smbd: Convert vfs_stat_smb_fname to synthetic_smb_fname
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobdcd2af23208806cc8511e4827f40c1bb36882100
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
59 files_struct *fsp,
60 const struct smb_filename *smb_fname,
61 uint32_t access_mask)
63 if (fsp) {
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
67 } else {
68 NTSTATUS status = smbd_check_access_rights(conn,
69 smb_fname,
70 false,
71 access_mask);
72 if (!NT_STATUS_IS_OK(status)) {
73 return status;
76 return NT_STATUS_OK;
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
93 return val;
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 uint64_t file_index;
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
110 return file_index;
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
126 SAMBA_XATTR_MARKER,
127 XATTR_NTACL_NAME,
128 NULL
131 int i;
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
135 return true;
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
139 return true;
141 return false;
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 } else {
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
171 attr_size = 65536;
172 goto again;
175 if (sizeret == -1) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
182 pea->flags = 0;
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 } else {
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
189 TALLOC_FREE(val);
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
194 return NT_STATUS_OK;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
205 char *p;
206 char **names, **tmp;
207 size_t num_names;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
223 if (names == NULL) {
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
240 ea_namelist_size);
241 } else {
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
243 ea_namelist_size);
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
249 else {
250 break;
254 if (sizeret == -1) {
255 TALLOC_FREE(names);
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
262 if (sizeret == 0) {
263 TALLOC_FREE(names);
264 if (pnames) {
265 *pnames = NULL;
267 *pnum_names = 0;
268 return NT_STATUS_OK;
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
276 TALLOC_FREE(names);
277 return NT_STATUS_INTERNAL_ERROR;
281 * count the names
283 num_names = 0;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
286 num_names += 1;
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 if (tmp == NULL) {
291 DEBUG(0, ("talloc failed\n"));
292 TALLOC_FREE(names);
293 return NT_STATUS_NO_MEMORY;
296 names = tmp;
297 num_names = 0;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
303 if (pnames) {
304 *pnames = names;
305 } else {
306 TALLOC_FREE(names);
308 *pnum_names = num_names;
309 return NT_STATUS_OK;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
320 size_t i, num_names;
321 char **names;
322 struct ea_list *ea_list_head = NULL;
323 NTSTATUS status;
325 *pea_total_len = 0;
326 *ea_list = NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 &names, &num_names);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 if (num_names == 0) {
336 *ea_list = NULL;
337 return NT_STATUS_OK;
340 for (i=0; i<num_names; i++) {
341 struct ea_list *listp;
342 fstring dos_ea_name;
344 if (strnequal(names[i], "system.", 7)
345 || samba_private_attr_name(names[i]))
346 continue;
348 listp = talloc(mem_ctx, struct ea_list);
349 if (listp == NULL) {
350 return NT_STATUS_NO_MEMORY;
353 status = get_ea_value(listp, conn, fsp,
354 fname, names[i],
355 &listp->ea);
357 if (!NT_STATUS_IS_OK(status)) {
358 TALLOC_FREE(listp);
359 return status;
362 if (listp->ea.value.length == 0) {
364 * We can never return a zero length EA.
365 * Windows reports the EA's as corrupted.
367 TALLOC_FREE(listp);
368 continue;
371 push_ascii_fstring(dos_ea_name, listp->ea.name);
373 *pea_total_len +=
374 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
376 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
377 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
378 (unsigned int)listp->ea.value.length));
380 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
384 /* Add on 4 for total length. */
385 if (*pea_total_len) {
386 *pea_total_len += 4;
389 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
390 (unsigned int)*pea_total_len));
392 *ea_list = ea_list_head;
393 return NT_STATUS_OK;
396 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
397 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
399 *pea_total_len = 0;
400 *ea_list = NULL;
402 if (!lp_ea_support(SNUM(conn))) {
403 return NT_STATUS_OK;
406 if (is_ntfs_stream_smb_fname(smb_fname)) {
407 return NT_STATUS_INVALID_PARAMETER;
410 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
413 /****************************************************************************
414 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
415 that was filled.
416 ****************************************************************************/
418 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
419 connection_struct *conn, struct ea_list *ea_list)
421 unsigned int ret_data_size = 4;
422 char *p = pdata;
424 SMB_ASSERT(total_data_size >= 4);
426 if (!lp_ea_support(SNUM(conn))) {
427 SIVAL(pdata,4,0);
428 return 4;
431 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
432 size_t dos_namelen;
433 fstring dos_ea_name;
434 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
435 dos_namelen = strlen(dos_ea_name);
436 if (dos_namelen > 255 || dos_namelen == 0) {
437 break;
439 if (ea_list->ea.value.length > 65535) {
440 break;
442 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
443 break;
446 /* We know we have room. */
447 SCVAL(p,0,ea_list->ea.flags);
448 SCVAL(p,1,dos_namelen);
449 SSVAL(p,2,ea_list->ea.value.length);
450 strlcpy(p+4, dos_ea_name, dos_namelen+1);
451 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
453 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
454 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
457 ret_data_size = PTR_DIFF(p, pdata);
458 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
459 SIVAL(pdata,0,ret_data_size);
460 return ret_data_size;
463 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
464 char *pdata,
465 unsigned int total_data_size,
466 unsigned int *ret_data_size,
467 connection_struct *conn,
468 struct ea_list *ea_list)
470 uint8_t *p = (uint8_t *)pdata;
471 uint8_t *last_start = NULL;
472 bool do_store_data = (pdata != NULL);
474 *ret_data_size = 0;
476 if (!lp_ea_support(SNUM(conn))) {
477 return NT_STATUS_NO_EAS_ON_FILE;
480 for (; ea_list; ea_list = ea_list->next) {
481 size_t dos_namelen;
482 fstring dos_ea_name;
483 size_t this_size;
484 size_t pad = 0;
486 if (last_start != NULL && do_store_data) {
487 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
489 last_start = p;
491 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
492 dos_namelen = strlen(dos_ea_name);
493 if (dos_namelen > 255 || dos_namelen == 0) {
494 return NT_STATUS_INTERNAL_ERROR;
496 if (ea_list->ea.value.length > 65535) {
497 return NT_STATUS_INTERNAL_ERROR;
500 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
502 if (ea_list->next) {
503 pad = (4 - (this_size % 4)) % 4;
504 this_size += pad;
507 if (do_store_data) {
508 if (this_size > total_data_size) {
509 return NT_STATUS_INFO_LENGTH_MISMATCH;
512 /* We know we have room. */
513 SIVAL(p, 0x00, 0); /* next offset */
514 SCVAL(p, 0x04, ea_list->ea.flags);
515 SCVAL(p, 0x05, dos_namelen);
516 SSVAL(p, 0x06, ea_list->ea.value.length);
517 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
518 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
519 if (pad) {
520 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
521 '\0',
522 pad);
524 total_data_size -= this_size;
527 p += this_size;
530 *ret_data_size = PTR_DIFF(p, pdata);
531 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
532 return NT_STATUS_OK;
535 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
537 size_t total_ea_len = 0;
538 TALLOC_CTX *mem_ctx;
539 struct ea_list *ea_list = NULL;
541 if (!lp_ea_support(SNUM(conn))) {
542 return 0;
544 mem_ctx = talloc_stackframe();
546 /* If this is a stream fsp, then we need to instead find the
547 * estimated ea len from the main file, not the stream
548 * (streams cannot have EAs), but the estimate isn't just 0 in
549 * this case! */
550 if (is_ntfs_stream_smb_fname(smb_fname)) {
551 fsp = NULL;
553 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
554 if(conn->sconn->using_smb2) {
555 NTSTATUS status;
556 unsigned int ret_data_size;
558 * We're going to be using fill_ea_chained_buffer() to
559 * marshall EA's - this size is significantly larger
560 * than the SMB1 buffer. Re-calculate the size without
561 * marshalling.
563 status = fill_ea_chained_buffer(mem_ctx,
564 NULL,
566 &ret_data_size,
567 conn,
568 ea_list);
569 if (!NT_STATUS_IS_OK(status)) {
570 ret_data_size = 0;
572 total_ea_len = ret_data_size;
574 TALLOC_FREE(mem_ctx);
575 return total_ea_len;
578 /****************************************************************************
579 Ensure the EA name is case insensitive by matching any existing EA name.
580 ****************************************************************************/
582 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
584 size_t total_ea_len;
585 TALLOC_CTX *mem_ctx = talloc_tos();
586 struct ea_list *ea_list;
587 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
588 if (!NT_STATUS_IS_OK(status)) {
589 return;
592 for (; ea_list; ea_list = ea_list->next) {
593 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
594 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
595 &unix_ea_name[5], ea_list->ea.name));
596 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
597 break;
602 /****************************************************************************
603 Set or delete an extended attribute.
604 ****************************************************************************/
606 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
607 const struct smb_filename *smb_fname, struct ea_list *ea_list)
609 NTSTATUS status;
610 char *fname = NULL;
612 if (!lp_ea_support(SNUM(conn))) {
613 return NT_STATUS_EAS_NOT_SUPPORTED;
616 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
617 if (!NT_STATUS_IS_OK(status)) {
618 return status;
621 /* Setting EAs on streams isn't supported. */
622 if (is_ntfs_stream_smb_fname(smb_fname)) {
623 return NT_STATUS_INVALID_PARAMETER;
626 fname = smb_fname->base_name;
628 for (;ea_list; ea_list = ea_list->next) {
629 int ret;
630 fstring unix_ea_name;
632 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
633 fstrcat(unix_ea_name, ea_list->ea.name);
635 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
637 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
639 if (samba_private_attr_name(unix_ea_name)) {
640 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
641 return NT_STATUS_ACCESS_DENIED;
644 if (ea_list->ea.value.length == 0) {
645 /* Remove the attribute. */
646 if (fsp && (fsp->fh->fd != -1)) {
647 DEBUG(10,("set_ea: deleting ea name %s on "
648 "file %s by file descriptor.\n",
649 unix_ea_name, fsp_str_dbg(fsp)));
650 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
651 } else {
652 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
653 unix_ea_name, fname));
654 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
656 #ifdef ENOATTR
657 /* Removing a non existent attribute always succeeds. */
658 if (ret == -1 && errno == ENOATTR) {
659 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
660 unix_ea_name));
661 ret = 0;
663 #endif
664 } else {
665 if (fsp && (fsp->fh->fd != -1)) {
666 DEBUG(10,("set_ea: setting ea name %s on file "
667 "%s by file descriptor.\n",
668 unix_ea_name, fsp_str_dbg(fsp)));
669 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
670 ea_list->ea.value.data, ea_list->ea.value.length, 0);
671 } else {
672 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
675 ea_list->ea.value.data, ea_list->ea.value.length, 0);
679 if (ret == -1) {
680 #ifdef ENOTSUP
681 if (errno == ENOTSUP) {
682 return NT_STATUS_EAS_NOT_SUPPORTED;
684 #endif
685 return map_nt_error_from_unix(errno);
689 return NT_STATUS_OK;
691 /****************************************************************************
692 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
693 ****************************************************************************/
695 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
697 struct ea_list *ea_list_head = NULL;
698 size_t converted_size, offset = 0;
700 while (offset + 2 < data_size) {
701 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
702 unsigned int namelen = CVAL(pdata,offset);
704 offset++; /* Go past the namelen byte. */
706 /* integer wrap paranioa. */
707 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
708 (offset > data_size) || (namelen > data_size) ||
709 (offset + namelen >= data_size)) {
710 break;
712 /* Ensure the name is null terminated. */
713 if (pdata[offset + namelen] != '\0') {
714 return NULL;
716 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
717 &converted_size)) {
718 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
719 "failed: %s", strerror(errno)));
721 if (!eal->ea.name) {
722 return NULL;
725 offset += (namelen + 1); /* Go past the name + terminating zero. */
726 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
727 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
730 return ea_list_head;
733 /****************************************************************************
734 Read one EA list entry from the buffer.
735 ****************************************************************************/
737 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
739 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
740 uint16 val_len;
741 unsigned int namelen;
742 size_t converted_size;
744 if (!eal) {
745 return NULL;
748 if (data_size < 6) {
749 return NULL;
752 eal->ea.flags = CVAL(pdata,0);
753 namelen = CVAL(pdata,1);
754 val_len = SVAL(pdata,2);
756 if (4 + namelen + 1 + val_len > data_size) {
757 return NULL;
760 /* Ensure the name is null terminated. */
761 if (pdata[namelen + 4] != '\0') {
762 return NULL;
764 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
765 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
766 strerror(errno)));
768 if (!eal->ea.name) {
769 return NULL;
772 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
773 if (!eal->ea.value.data) {
774 return NULL;
777 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
779 /* Ensure we're null terminated just in case we print the value. */
780 eal->ea.value.data[val_len] = '\0';
781 /* But don't count the null. */
782 eal->ea.value.length--;
784 if (pbytes_used) {
785 *pbytes_used = 4 + namelen + 1 + val_len;
788 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
789 dump_data(10, eal->ea.value.data, eal->ea.value.length);
791 return eal;
794 /****************************************************************************
795 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
796 ****************************************************************************/
798 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
800 struct ea_list *ea_list_head = NULL;
801 size_t offset = 0;
802 size_t bytes_used = 0;
804 while (offset < data_size) {
805 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
807 if (!eal) {
808 return NULL;
811 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
812 offset += bytes_used;
815 return ea_list_head;
818 /****************************************************************************
819 Count the total EA size needed.
820 ****************************************************************************/
822 static size_t ea_list_size(struct ea_list *ealist)
824 fstring dos_ea_name;
825 struct ea_list *listp;
826 size_t ret = 0;
828 for (listp = ealist; listp; listp = listp->next) {
829 push_ascii_fstring(dos_ea_name, listp->ea.name);
830 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
832 /* Add on 4 for total length. */
833 if (ret) {
834 ret += 4;
837 return ret;
840 /****************************************************************************
841 Return a union of EA's from a file list and a list of names.
842 The TALLOC context for the two lists *MUST* be identical as we steal
843 memory from one list to add to another. JRA.
844 ****************************************************************************/
846 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
848 struct ea_list *nlistp, *flistp;
850 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
851 for (flistp = file_list; flistp; flistp = flistp->next) {
852 if (strequal(nlistp->ea.name, flistp->ea.name)) {
853 break;
857 if (flistp) {
858 /* Copy the data from this entry. */
859 nlistp->ea.flags = flistp->ea.flags;
860 nlistp->ea.value = flistp->ea.value;
861 } else {
862 /* Null entry. */
863 nlistp->ea.flags = 0;
864 ZERO_STRUCT(nlistp->ea.value);
868 *total_ea_len = ea_list_size(name_list);
869 return name_list;
872 /****************************************************************************
873 Send the required number of replies back.
874 We assume all fields other than the data fields are
875 set correctly for the type of call.
876 HACK ! Always assumes smb_setup field is zero.
877 ****************************************************************************/
879 void send_trans2_replies(connection_struct *conn,
880 struct smb_request *req,
881 const char *params,
882 int paramsize,
883 const char *pdata,
884 int datasize,
885 int max_data_bytes)
887 /* As we are using a protocol > LANMAN1 then the max_send
888 variable must have been set in the sessetupX call.
889 This takes precedence over the max_xmit field in the
890 global struct. These different max_xmit variables should
891 be merged as this is now too confusing */
893 int data_to_send = datasize;
894 int params_to_send = paramsize;
895 int useable_space;
896 const char *pp = params;
897 const char *pd = pdata;
898 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
899 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
900 int data_alignment_offset = 0;
901 bool overflow = False;
902 struct smbd_server_connection *sconn = req->sconn;
903 int max_send = sconn->smb1.sessions.max_send;
905 /* Modify the data_to_send and datasize and set the error if
906 we're trying to send more than max_data_bytes. We still send
907 the part of the packet(s) that fit. Strange, but needed
908 for OS/2. */
910 if (max_data_bytes > 0 && datasize > max_data_bytes) {
911 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
912 max_data_bytes, datasize ));
913 datasize = data_to_send = max_data_bytes;
914 overflow = True;
917 /* If there genuinely are no parameters or data to send just send the empty packet */
919 if(params_to_send == 0 && data_to_send == 0) {
920 reply_outbuf(req, 10, 0);
921 show_msg((char *)req->outbuf);
922 if (!srv_send_smb(sconn,
923 (char *)req->outbuf,
924 true, req->seqnum+1,
925 IS_CONN_ENCRYPTED(conn),
926 &req->pcd)) {
927 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
929 TALLOC_FREE(req->outbuf);
930 return;
933 /* When sending params and data ensure that both are nicely aligned */
934 /* Only do this alignment when there is also data to send - else
935 can cause NT redirector problems. */
937 if (((params_to_send % 4) != 0) && (data_to_send != 0))
938 data_alignment_offset = 4 - (params_to_send % 4);
940 /* Space is bufsize minus Netbios over TCP header minus SMB header */
941 /* The alignment_offset is to align the param bytes on an even byte
942 boundary. NT 4.0 Beta needs this to work correctly. */
944 useable_space = max_send - (smb_size
945 + 2 * 10 /* wct */
946 + alignment_offset
947 + data_alignment_offset);
949 if (useable_space < 0) {
950 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
951 "= %d!!!", useable_space));
952 exit_server_cleanly("send_trans2_replies: Not enough space");
955 while (params_to_send || data_to_send) {
956 /* Calculate whether we will totally or partially fill this packet */
958 total_sent_thistime = params_to_send + data_to_send;
960 /* We can never send more than useable_space */
962 * Note that 'useable_space' does not include the alignment offsets,
963 * but we must include the alignment offsets in the calculation of
964 * the length of the data we send over the wire, as the alignment offsets
965 * are sent here. Fix from Marc_Jacobsen@hp.com.
968 total_sent_thistime = MIN(total_sent_thistime, useable_space);
970 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
971 + data_alignment_offset);
973 /* Set total params and data to be sent */
974 SSVAL(req->outbuf,smb_tprcnt,paramsize);
975 SSVAL(req->outbuf,smb_tdrcnt,datasize);
977 /* Calculate how many parameters and data we can fit into
978 * this packet. Parameters get precedence
981 params_sent_thistime = MIN(params_to_send,useable_space);
982 data_sent_thistime = useable_space - params_sent_thistime;
983 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
985 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
987 /* smb_proff is the offset from the start of the SMB header to the
988 parameter bytes, however the first 4 bytes of outbuf are
989 the Netbios over TCP header. Thus use smb_base() to subtract
990 them from the calculation */
992 SSVAL(req->outbuf,smb_proff,
993 ((smb_buf(req->outbuf)+alignment_offset)
994 - smb_base(req->outbuf)));
996 if(params_sent_thistime == 0)
997 SSVAL(req->outbuf,smb_prdisp,0);
998 else
999 /* Absolute displacement of param bytes sent in this packet */
1000 SSVAL(req->outbuf,smb_prdisp,pp - params);
1002 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1003 if(data_sent_thistime == 0) {
1004 SSVAL(req->outbuf,smb_droff,0);
1005 SSVAL(req->outbuf,smb_drdisp, 0);
1006 } else {
1007 /* The offset of the data bytes is the offset of the
1008 parameter bytes plus the number of parameters being sent this time */
1009 SSVAL(req->outbuf, smb_droff,
1010 ((smb_buf(req->outbuf)+alignment_offset)
1011 - smb_base(req->outbuf))
1012 + params_sent_thistime + data_alignment_offset);
1013 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1016 /* Initialize the padding for alignment */
1018 if (alignment_offset != 0) {
1019 memset(smb_buf(req->outbuf), 0, alignment_offset);
1022 /* Copy the param bytes into the packet */
1024 if(params_sent_thistime) {
1025 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1026 params_sent_thistime);
1029 /* Copy in the data bytes */
1030 if(data_sent_thistime) {
1031 if (data_alignment_offset != 0) {
1032 memset((smb_buf(req->outbuf)+alignment_offset+
1033 params_sent_thistime), 0,
1034 data_alignment_offset);
1036 memcpy(smb_buf(req->outbuf)+alignment_offset
1037 +params_sent_thistime+data_alignment_offset,
1038 pd,data_sent_thistime);
1041 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1042 params_sent_thistime, data_sent_thistime, useable_space));
1043 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1044 params_to_send, data_to_send, paramsize, datasize));
1046 if (overflow) {
1047 error_packet_set((char *)req->outbuf,
1048 ERRDOS,ERRbufferoverflow,
1049 STATUS_BUFFER_OVERFLOW,
1050 __LINE__,__FILE__);
1053 /* Send the packet */
1054 show_msg((char *)req->outbuf);
1055 if (!srv_send_smb(sconn,
1056 (char *)req->outbuf,
1057 true, req->seqnum+1,
1058 IS_CONN_ENCRYPTED(conn),
1059 &req->pcd))
1060 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1062 TALLOC_FREE(req->outbuf);
1064 pp += params_sent_thistime;
1065 pd += data_sent_thistime;
1067 params_to_send -= params_sent_thistime;
1068 data_to_send -= data_sent_thistime;
1070 /* Sanity check */
1071 if(params_to_send < 0 || data_to_send < 0) {
1072 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1073 params_to_send, data_to_send));
1074 return;
1078 return;
1081 /****************************************************************************
1082 Reply to a TRANSACT2_OPEN.
1083 ****************************************************************************/
1085 static void call_trans2open(connection_struct *conn,
1086 struct smb_request *req,
1087 char **pparams, int total_params,
1088 char **ppdata, int total_data,
1089 unsigned int max_data_bytes)
1091 struct smb_filename *smb_fname = NULL;
1092 char *params = *pparams;
1093 char *pdata = *ppdata;
1094 int deny_mode;
1095 int32 open_attr;
1096 bool oplock_request;
1097 #if 0
1098 bool return_additional_info;
1099 int16 open_sattr;
1100 time_t open_time;
1101 #endif
1102 int open_ofun;
1103 uint32 open_size;
1104 char *pname;
1105 char *fname = NULL;
1106 off_t size=0;
1107 int fattr=0,mtime=0;
1108 SMB_INO_T inode = 0;
1109 int smb_action = 0;
1110 files_struct *fsp;
1111 struct ea_list *ea_list = NULL;
1112 uint16 flags = 0;
1113 NTSTATUS status;
1114 uint32 access_mask;
1115 uint32 share_mode;
1116 uint32 create_disposition;
1117 uint32 create_options = 0;
1118 uint32_t private_flags = 0;
1119 TALLOC_CTX *ctx = talloc_tos();
1122 * Ensure we have enough parameters to perform the operation.
1125 if (total_params < 29) {
1126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1127 goto out;
1130 flags = SVAL(params, 0);
1131 deny_mode = SVAL(params, 2);
1132 open_attr = SVAL(params,6);
1133 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1134 if (oplock_request) {
1135 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1138 #if 0
1139 return_additional_info = BITSETW(params,0);
1140 open_sattr = SVAL(params, 4);
1141 open_time = make_unix_date3(params+8);
1142 #endif
1143 open_ofun = SVAL(params,12);
1144 open_size = IVAL(params,14);
1145 pname = &params[28];
1147 if (IS_IPC(conn)) {
1148 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1149 goto out;
1152 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1153 total_params - 28, STR_TERMINATE,
1154 &status);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 reply_nterror(req, status);
1157 goto out;
1160 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1161 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1162 (unsigned int)open_ofun, open_size));
1164 status = filename_convert(ctx,
1165 conn,
1166 req->flags2 & FLAGS2_DFS_PATHNAMES,
1167 fname,
1169 NULL,
1170 &smb_fname);
1171 if (!NT_STATUS_IS_OK(status)) {
1172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1173 reply_botherror(req,
1174 NT_STATUS_PATH_NOT_COVERED,
1175 ERRSRV, ERRbadpath);
1176 goto out;
1178 reply_nterror(req, status);
1179 goto out;
1182 if (open_ofun == 0) {
1183 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1184 goto out;
1187 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1188 open_ofun,
1189 &access_mask, &share_mode,
1190 &create_disposition,
1191 &create_options,
1192 &private_flags)) {
1193 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1194 goto out;
1197 /* Any data in this call is an EA list. */
1198 if (total_data && (total_data != 4)) {
1199 if (total_data < 10) {
1200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1201 goto out;
1204 if (IVAL(pdata,0) > total_data) {
1205 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1206 IVAL(pdata,0), (unsigned int)total_data));
1207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1208 goto out;
1211 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1212 total_data - 4);
1213 if (!ea_list) {
1214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1215 goto out;
1218 if (!lp_ea_support(SNUM(conn))) {
1219 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1220 goto out;
1224 status = SMB_VFS_CREATE_FILE(
1225 conn, /* conn */
1226 req, /* req */
1227 0, /* root_dir_fid */
1228 smb_fname, /* fname */
1229 access_mask, /* access_mask */
1230 share_mode, /* share_access */
1231 create_disposition, /* create_disposition*/
1232 create_options, /* create_options */
1233 open_attr, /* file_attributes */
1234 oplock_request, /* oplock_request */
1235 open_size, /* allocation_size */
1236 private_flags,
1237 NULL, /* sd */
1238 ea_list, /* ea_list */
1239 &fsp, /* result */
1240 &smb_action); /* psbuf */
1242 if (!NT_STATUS_IS_OK(status)) {
1243 if (open_was_deferred(req->sconn, req->mid)) {
1244 /* We have re-scheduled this call. */
1245 goto out;
1247 reply_openerror(req, status);
1248 goto out;
1251 size = get_file_size_stat(&smb_fname->st);
1252 fattr = dos_mode(conn, smb_fname);
1253 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1254 inode = smb_fname->st.st_ex_ino;
1255 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1256 close_file(req, fsp, ERROR_CLOSE);
1257 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1258 goto out;
1261 /* Realloc the size of parameters and data we will return */
1262 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1263 if(*pparams == NULL ) {
1264 reply_nterror(req, NT_STATUS_NO_MEMORY);
1265 goto out;
1267 params = *pparams;
1269 SSVAL(params,0,fsp->fnum);
1270 SSVAL(params,2,fattr);
1271 srv_put_dos_date2(params,4, mtime);
1272 SIVAL(params,8, (uint32)size);
1273 SSVAL(params,12,deny_mode);
1274 SSVAL(params,14,0); /* open_type - file or directory. */
1275 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1277 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1278 smb_action |= EXTENDED_OPLOCK_GRANTED;
1281 SSVAL(params,18,smb_action);
1284 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1286 SIVAL(params,20,inode);
1287 SSVAL(params,24,0); /* Padding. */
1288 if (flags & 8) {
1289 uint32 ea_size = estimate_ea_size(conn, fsp,
1290 smb_fname);
1291 SIVAL(params, 26, ea_size);
1292 } else {
1293 SIVAL(params, 26, 0);
1296 /* Send the required number of replies */
1297 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1298 out:
1299 TALLOC_FREE(smb_fname);
1302 /*********************************************************
1303 Routine to check if a given string matches exactly.
1304 as a special case a mask of "." does NOT match. That
1305 is required for correct wildcard semantics
1306 Case can be significant or not.
1307 **********************************************************/
1309 static bool exact_match(bool has_wild,
1310 bool case_sensitive,
1311 const char *str,
1312 const char *mask)
1314 if (mask[0] == '.' && mask[1] == 0) {
1315 return false;
1318 if (has_wild) {
1319 return false;
1322 if (case_sensitive) {
1323 return strcmp(str,mask)==0;
1324 } else {
1325 return strcasecmp_m(str,mask) == 0;
1329 /****************************************************************************
1330 Return the filetype for UNIX extensions.
1331 ****************************************************************************/
1333 static uint32 unix_filetype(mode_t mode)
1335 if(S_ISREG(mode))
1336 return UNIX_TYPE_FILE;
1337 else if(S_ISDIR(mode))
1338 return UNIX_TYPE_DIR;
1339 #ifdef S_ISLNK
1340 else if(S_ISLNK(mode))
1341 return UNIX_TYPE_SYMLINK;
1342 #endif
1343 #ifdef S_ISCHR
1344 else if(S_ISCHR(mode))
1345 return UNIX_TYPE_CHARDEV;
1346 #endif
1347 #ifdef S_ISBLK
1348 else if(S_ISBLK(mode))
1349 return UNIX_TYPE_BLKDEV;
1350 #endif
1351 #ifdef S_ISFIFO
1352 else if(S_ISFIFO(mode))
1353 return UNIX_TYPE_FIFO;
1354 #endif
1355 #ifdef S_ISSOCK
1356 else if(S_ISSOCK(mode))
1357 return UNIX_TYPE_SOCKET;
1358 #endif
1360 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1361 return UNIX_TYPE_UNKNOWN;
1364 /****************************************************************************
1365 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1366 ****************************************************************************/
1368 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1370 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1371 const SMB_STRUCT_STAT *psbuf,
1372 uint32 perms,
1373 enum perm_type ptype,
1374 mode_t *ret_perms)
1376 mode_t ret = 0;
1378 if (perms == SMB_MODE_NO_CHANGE) {
1379 if (!VALID_STAT(*psbuf)) {
1380 return NT_STATUS_INVALID_PARAMETER;
1381 } else {
1382 *ret_perms = psbuf->st_ex_mode;
1383 return NT_STATUS_OK;
1387 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1388 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1389 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1390 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1391 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1392 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1393 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1394 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1395 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1396 #ifdef S_ISVTX
1397 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1398 #endif
1399 #ifdef S_ISGID
1400 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1401 #endif
1402 #ifdef S_ISUID
1403 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1404 #endif
1406 switch (ptype) {
1407 case PERM_NEW_FILE:
1408 case PERM_EXISTING_FILE:
1409 /* Apply mode mask */
1410 ret &= lp_create_mask(SNUM(conn));
1411 /* Add in force bits */
1412 ret |= lp_force_create_mode(SNUM(conn));
1413 break;
1414 case PERM_NEW_DIR:
1415 case PERM_EXISTING_DIR:
1416 ret &= lp_dir_mask(SNUM(conn));
1417 /* Add in force bits */
1418 ret |= lp_force_dir_mode(SNUM(conn));
1419 break;
1422 *ret_perms = ret;
1423 return NT_STATUS_OK;
1426 /****************************************************************************
1427 Needed to show the msdfs symlinks as directories. Modifies psbuf
1428 to be a directory if it's a msdfs link.
1429 ****************************************************************************/
1431 static bool check_msdfs_link(connection_struct *conn,
1432 const char *pathname,
1433 SMB_STRUCT_STAT *psbuf)
1435 int saved_errno = errno;
1436 if(lp_host_msdfs() &&
1437 lp_msdfs_root(SNUM(conn)) &&
1438 is_msdfs_link(conn, pathname, psbuf)) {
1440 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1441 "as a directory\n",
1442 pathname));
1443 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1444 errno = saved_errno;
1445 return true;
1447 errno = saved_errno;
1448 return false;
1452 /****************************************************************************
1453 Get a level dependent lanman2 dir entry.
1454 ****************************************************************************/
1456 struct smbd_dirptr_lanman2_state {
1457 connection_struct *conn;
1458 uint32_t info_level;
1459 bool check_mangled_names;
1460 bool has_wild;
1461 bool got_exact_match;
1464 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1465 void *private_data,
1466 const char *dname,
1467 const char *mask,
1468 char **_fname)
1470 struct smbd_dirptr_lanman2_state *state =
1471 (struct smbd_dirptr_lanman2_state *)private_data;
1472 bool ok;
1473 char mangled_name[13]; /* mangled 8.3 name. */
1474 bool got_match;
1475 const char *fname;
1477 /* Mangle fname if it's an illegal name. */
1478 if (mangle_must_mangle(dname, state->conn->params)) {
1479 ok = name_to_8_3(dname, mangled_name,
1480 true, state->conn->params);
1481 if (!ok) {
1482 return false;
1484 fname = mangled_name;
1485 } else {
1486 fname = dname;
1489 got_match = exact_match(state->has_wild,
1490 state->conn->case_sensitive,
1491 fname, mask);
1492 state->got_exact_match = got_match;
1493 if (!got_match) {
1494 got_match = mask_match(fname, mask,
1495 state->conn->case_sensitive);
1498 if(!got_match && state->check_mangled_names &&
1499 !mangle_is_8_3(fname, false, state->conn->params)) {
1501 * It turns out that NT matches wildcards against
1502 * both long *and* short names. This may explain some
1503 * of the wildcard wierdness from old DOS clients
1504 * that some people have been seeing.... JRA.
1506 /* Force the mangling into 8.3. */
1507 ok = name_to_8_3(fname, mangled_name,
1508 false, state->conn->params);
1509 if (!ok) {
1510 return false;
1513 got_match = exact_match(state->has_wild,
1514 state->conn->case_sensitive,
1515 mangled_name, mask);
1516 state->got_exact_match = got_match;
1517 if (!got_match) {
1518 got_match = mask_match(mangled_name, mask,
1519 state->conn->case_sensitive);
1523 if (!got_match) {
1524 return false;
1527 *_fname = talloc_strdup(ctx, fname);
1528 if (*_fname == NULL) {
1529 return false;
1532 return true;
1535 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1536 void *private_data,
1537 struct smb_filename *smb_fname,
1538 uint32_t *_mode)
1540 struct smbd_dirptr_lanman2_state *state =
1541 (struct smbd_dirptr_lanman2_state *)private_data;
1542 bool ms_dfs_link = false;
1543 uint32_t mode = 0;
1545 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1546 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1547 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1548 "Couldn't lstat [%s] (%s)\n",
1549 smb_fname_str_dbg(smb_fname),
1550 strerror(errno)));
1551 return false;
1553 } else if (!VALID_STAT(smb_fname->st) &&
1554 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1555 /* Needed to show the msdfs symlinks as
1556 * directories */
1558 ms_dfs_link = check_msdfs_link(state->conn,
1559 smb_fname->base_name,
1560 &smb_fname->st);
1561 if (!ms_dfs_link) {
1562 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1563 "Couldn't stat [%s] (%s)\n",
1564 smb_fname_str_dbg(smb_fname),
1565 strerror(errno)));
1566 return false;
1570 if (ms_dfs_link) {
1571 mode = dos_mode_msdfs(state->conn, smb_fname);
1572 } else {
1573 mode = dos_mode(state->conn, smb_fname);
1576 *_mode = mode;
1577 return true;
1580 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1581 connection_struct *conn,
1582 uint16_t flags2,
1583 uint32_t info_level,
1584 struct ea_list *name_list,
1585 bool check_mangled_names,
1586 bool requires_resume_key,
1587 uint32_t mode,
1588 const char *fname,
1589 const struct smb_filename *smb_fname,
1590 int space_remaining,
1591 uint8_t align,
1592 bool do_pad,
1593 char *base_data,
1594 char **ppdata,
1595 char *end_data,
1596 bool *out_of_space,
1597 uint64_t *last_entry_off)
1599 char *p, *q, *pdata = *ppdata;
1600 uint32_t reskey=0;
1601 uint64_t file_size = 0;
1602 uint64_t allocation_size = 0;
1603 uint64_t file_index = 0;
1604 uint32_t len;
1605 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1606 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1607 char *nameptr;
1608 char *last_entry_ptr;
1609 bool was_8_3;
1610 int off;
1611 int pad = 0;
1613 *out_of_space = false;
1615 ZERO_STRUCT(mdate_ts);
1616 ZERO_STRUCT(adate_ts);
1617 ZERO_STRUCT(create_date_ts);
1618 ZERO_STRUCT(cdate_ts);
1620 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1621 file_size = get_file_size_stat(&smb_fname->st);
1623 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1625 file_index = get_FileIndex(conn, &smb_fname->st);
1627 mdate_ts = smb_fname->st.st_ex_mtime;
1628 adate_ts = smb_fname->st.st_ex_atime;
1629 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1630 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1632 if (lp_dos_filetime_resolution(SNUM(conn))) {
1633 dos_filetime_timespec(&create_date_ts);
1634 dos_filetime_timespec(&mdate_ts);
1635 dos_filetime_timespec(&adate_ts);
1636 dos_filetime_timespec(&cdate_ts);
1639 create_date = convert_timespec_to_time_t(create_date_ts);
1640 mdate = convert_timespec_to_time_t(mdate_ts);
1641 adate = convert_timespec_to_time_t(adate_ts);
1643 /* align the record */
1644 SMB_ASSERT(align >= 1);
1646 off = (int)PTR_DIFF(pdata, base_data);
1647 pad = (off + (align-1)) & ~(align-1);
1648 pad -= off;
1650 if (pad && pad > space_remaining) {
1651 *out_of_space = true;
1652 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1653 "for padding (wanted %u, had %d)\n",
1654 (unsigned int)pad,
1655 space_remaining ));
1656 return false; /* Not finished - just out of space */
1659 off += pad;
1660 /* initialize padding to 0 */
1661 if (pad) {
1662 memset(pdata, 0, pad);
1664 space_remaining -= pad;
1666 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1667 space_remaining ));
1669 pdata += pad;
1670 p = pdata;
1671 last_entry_ptr = p;
1673 pad = 0;
1674 off = 0;
1676 switch (info_level) {
1677 case SMB_FIND_INFO_STANDARD:
1678 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1679 if(requires_resume_key) {
1680 SIVAL(p,0,reskey);
1681 p += 4;
1683 srv_put_dos_date2(p,0,create_date);
1684 srv_put_dos_date2(p,4,adate);
1685 srv_put_dos_date2(p,8,mdate);
1686 SIVAL(p,12,(uint32)file_size);
1687 SIVAL(p,16,(uint32)allocation_size);
1688 SSVAL(p,20,mode);
1689 p += 23;
1690 nameptr = p;
1691 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1692 p += ucs2_align(base_data, p, 0);
1694 len = srvstr_push(base_data, flags2, p,
1695 fname, PTR_DIFF(end_data, p),
1696 STR_TERMINATE);
1697 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1698 if (len > 2) {
1699 SCVAL(nameptr, -1, len - 2);
1700 } else {
1701 SCVAL(nameptr, -1, 0);
1703 } else {
1704 if (len > 1) {
1705 SCVAL(nameptr, -1, len - 1);
1706 } else {
1707 SCVAL(nameptr, -1, 0);
1710 p += len;
1711 break;
1713 case SMB_FIND_EA_SIZE:
1714 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1715 if (requires_resume_key) {
1716 SIVAL(p,0,reskey);
1717 p += 4;
1719 srv_put_dos_date2(p,0,create_date);
1720 srv_put_dos_date2(p,4,adate);
1721 srv_put_dos_date2(p,8,mdate);
1722 SIVAL(p,12,(uint32)file_size);
1723 SIVAL(p,16,(uint32)allocation_size);
1724 SSVAL(p,20,mode);
1726 unsigned int ea_size = estimate_ea_size(conn, NULL,
1727 smb_fname);
1728 SIVAL(p,22,ea_size); /* Extended attributes */
1730 p += 27;
1731 nameptr = p - 1;
1732 len = srvstr_push(base_data, flags2,
1733 p, fname, PTR_DIFF(end_data, p),
1734 STR_TERMINATE | STR_NOALIGN);
1735 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1736 if (len > 2) {
1737 len -= 2;
1738 } else {
1739 len = 0;
1741 } else {
1742 if (len > 1) {
1743 len -= 1;
1744 } else {
1745 len = 0;
1748 SCVAL(nameptr,0,len);
1749 p += len;
1750 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1751 break;
1753 case SMB_FIND_EA_LIST:
1755 struct ea_list *file_list = NULL;
1756 size_t ea_len = 0;
1757 NTSTATUS status;
1759 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1760 if (!name_list) {
1761 return false;
1763 if (requires_resume_key) {
1764 SIVAL(p,0,reskey);
1765 p += 4;
1767 srv_put_dos_date2(p,0,create_date);
1768 srv_put_dos_date2(p,4,adate);
1769 srv_put_dos_date2(p,8,mdate);
1770 SIVAL(p,12,(uint32)file_size);
1771 SIVAL(p,16,(uint32)allocation_size);
1772 SSVAL(p,20,mode);
1773 p += 22; /* p now points to the EA area. */
1775 status = get_ea_list_from_file(ctx, conn, NULL,
1776 smb_fname,
1777 &ea_len, &file_list);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 file_list = NULL;
1781 name_list = ea_list_union(name_list, file_list, &ea_len);
1783 /* We need to determine if this entry will fit in the space available. */
1784 /* Max string size is 255 bytes. */
1785 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1786 *out_of_space = true;
1787 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1788 "(wanted %u, had %d)\n",
1789 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1790 space_remaining ));
1791 return False; /* Not finished - just out of space */
1794 /* Push the ea_data followed by the name. */
1795 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1796 nameptr = p;
1797 len = srvstr_push(base_data, flags2,
1798 p + 1, fname, PTR_DIFF(end_data, p+1),
1799 STR_TERMINATE | STR_NOALIGN);
1800 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1801 if (len > 2) {
1802 len -= 2;
1803 } else {
1804 len = 0;
1806 } else {
1807 if (len > 1) {
1808 len -= 1;
1809 } else {
1810 len = 0;
1813 SCVAL(nameptr,0,len);
1814 p += len + 1;
1815 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1816 break;
1819 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1820 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1821 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1822 p += 4;
1823 SIVAL(p,0,reskey); p += 4;
1824 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1827 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1828 SOFF_T(p,0,file_size); p += 8;
1829 SOFF_T(p,0,allocation_size); p += 8;
1830 SIVAL(p,0,mode); p += 4;
1831 q = p; p += 4; /* q is placeholder for name length. */
1833 unsigned int ea_size = estimate_ea_size(conn, NULL,
1834 smb_fname);
1835 SIVAL(p,0,ea_size); /* Extended attributes */
1836 p += 4;
1838 /* Clear the short name buffer. This is
1839 * IMPORTANT as not doing so will trigger
1840 * a Win2k client bug. JRA.
1842 if (!was_8_3 && check_mangled_names) {
1843 char mangled_name[13]; /* mangled 8.3 name. */
1844 if (!name_to_8_3(fname,mangled_name,True,
1845 conn->params)) {
1846 /* Error - mangle failed ! */
1847 memset(mangled_name,'\0',12);
1849 mangled_name[12] = 0;
1850 len = srvstr_push(base_data, flags2,
1851 p+2, mangled_name, 24,
1852 STR_UPPER|STR_UNICODE);
1853 if (len < 24) {
1854 memset(p + 2 + len,'\0',24 - len);
1856 SSVAL(p, 0, len);
1857 } else {
1858 memset(p,'\0',26);
1860 p += 2 + 24;
1861 len = srvstr_push(base_data, flags2, p,
1862 fname, PTR_DIFF(end_data, p),
1863 STR_TERMINATE_ASCII);
1864 SIVAL(q,0,len);
1865 p += len;
1867 len = PTR_DIFF(p, pdata);
1868 pad = (len + (align-1)) & ~(align-1);
1870 * offset to the next entry, the caller
1871 * will overwrite it for the last entry
1872 * that's why we always include the padding
1874 SIVAL(pdata,0,pad);
1876 * set padding to zero
1878 if (do_pad) {
1879 memset(p, 0, pad - len);
1880 p = pdata + pad;
1881 } else {
1882 p = pdata + len;
1884 break;
1886 case SMB_FIND_FILE_DIRECTORY_INFO:
1887 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1888 p += 4;
1889 SIVAL(p,0,reskey); p += 4;
1890 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1891 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1892 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1893 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1894 SOFF_T(p,0,file_size); p += 8;
1895 SOFF_T(p,0,allocation_size); p += 8;
1896 SIVAL(p,0,mode); p += 4;
1897 len = srvstr_push(base_data, flags2,
1898 p + 4, fname, PTR_DIFF(end_data, p+4),
1899 STR_TERMINATE_ASCII);
1900 SIVAL(p,0,len);
1901 p += 4 + len;
1903 len = PTR_DIFF(p, pdata);
1904 pad = (len + (align-1)) & ~(align-1);
1906 * offset to the next entry, the caller
1907 * will overwrite it for the last entry
1908 * that's why we always include the padding
1910 SIVAL(pdata,0,pad);
1912 * set padding to zero
1914 if (do_pad) {
1915 memset(p, 0, pad - len);
1916 p = pdata + pad;
1917 } else {
1918 p = pdata + len;
1920 break;
1922 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1923 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1924 p += 4;
1925 SIVAL(p,0,reskey); p += 4;
1926 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1927 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1930 SOFF_T(p,0,file_size); p += 8;
1931 SOFF_T(p,0,allocation_size); p += 8;
1932 SIVAL(p,0,mode); p += 4;
1933 q = p; p += 4; /* q is placeholder for name length. */
1935 unsigned int ea_size = estimate_ea_size(conn, NULL,
1936 smb_fname);
1937 SIVAL(p,0,ea_size); /* Extended attributes */
1938 p +=4;
1940 len = srvstr_push(base_data, flags2, p,
1941 fname, PTR_DIFF(end_data, p),
1942 STR_TERMINATE_ASCII);
1943 SIVAL(q, 0, len);
1944 p += len;
1946 len = PTR_DIFF(p, pdata);
1947 pad = (len + (align-1)) & ~(align-1);
1949 * offset to the next entry, the caller
1950 * will overwrite it for the last entry
1951 * that's why we always include the padding
1953 SIVAL(pdata,0,pad);
1955 * set padding to zero
1957 if (do_pad) {
1958 memset(p, 0, pad - len);
1959 p = pdata + pad;
1960 } else {
1961 p = pdata + len;
1963 break;
1965 case SMB_FIND_FILE_NAMES_INFO:
1966 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1967 p += 4;
1968 SIVAL(p,0,reskey); p += 4;
1969 p += 4;
1970 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1971 acl on a dir (tridge) */
1972 len = srvstr_push(base_data, flags2, p,
1973 fname, PTR_DIFF(end_data, p),
1974 STR_TERMINATE_ASCII);
1975 SIVAL(p, -4, len);
1976 p += len;
1978 len = PTR_DIFF(p, pdata);
1979 pad = (len + (align-1)) & ~(align-1);
1981 * offset to the next entry, the caller
1982 * will overwrite it for the last entry
1983 * that's why we always include the padding
1985 SIVAL(pdata,0,pad);
1987 * set padding to zero
1989 if (do_pad) {
1990 memset(p, 0, pad - len);
1991 p = pdata + pad;
1992 } else {
1993 p = pdata + len;
1995 break;
1997 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1998 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1999 p += 4;
2000 SIVAL(p,0,reskey); p += 4;
2001 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2002 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2003 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2004 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2005 SOFF_T(p,0,file_size); p += 8;
2006 SOFF_T(p,0,allocation_size); p += 8;
2007 SIVAL(p,0,mode); p += 4;
2008 q = p; p += 4; /* q is placeholder for name length. */
2010 unsigned int ea_size = estimate_ea_size(conn, NULL,
2011 smb_fname);
2012 SIVAL(p,0,ea_size); /* Extended attributes */
2013 p +=4;
2015 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2016 SBVAL(p,0,file_index); p += 8;
2017 len = srvstr_push(base_data, flags2, p,
2018 fname, PTR_DIFF(end_data, p),
2019 STR_TERMINATE_ASCII);
2020 SIVAL(q, 0, len);
2021 p += len;
2023 len = PTR_DIFF(p, pdata);
2024 pad = (len + (align-1)) & ~(align-1);
2026 * offset to the next entry, the caller
2027 * will overwrite it for the last entry
2028 * that's why we always include the padding
2030 SIVAL(pdata,0,pad);
2032 * set padding to zero
2034 if (do_pad) {
2035 memset(p, 0, pad - len);
2036 p = pdata + pad;
2037 } else {
2038 p = pdata + len;
2040 break;
2042 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2043 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2044 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2045 p += 4;
2046 SIVAL(p,0,reskey); p += 4;
2047 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2049 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2051 SOFF_T(p,0,file_size); p += 8;
2052 SOFF_T(p,0,allocation_size); p += 8;
2053 SIVAL(p,0,mode); p += 4;
2054 q = p; p += 4; /* q is placeholder for name length */
2056 unsigned int ea_size = estimate_ea_size(conn, NULL,
2057 smb_fname);
2058 SIVAL(p,0,ea_size); /* Extended attributes */
2059 p +=4;
2061 /* Clear the short name buffer. This is
2062 * IMPORTANT as not doing so will trigger
2063 * a Win2k client bug. JRA.
2065 if (!was_8_3 && check_mangled_names) {
2066 char mangled_name[13]; /* mangled 8.3 name. */
2067 if (!name_to_8_3(fname,mangled_name,True,
2068 conn->params)) {
2069 /* Error - mangle failed ! */
2070 memset(mangled_name,'\0',12);
2072 mangled_name[12] = 0;
2073 len = srvstr_push(base_data, flags2,
2074 p+2, mangled_name, 24,
2075 STR_UPPER|STR_UNICODE);
2076 SSVAL(p, 0, len);
2077 if (len < 24) {
2078 memset(p + 2 + len,'\0',24 - len);
2080 SSVAL(p, 0, len);
2081 } else {
2082 memset(p,'\0',26);
2084 p += 26;
2085 SSVAL(p,0,0); p += 2; /* Reserved ? */
2086 SBVAL(p,0,file_index); p += 8;
2087 len = srvstr_push(base_data, flags2, p,
2088 fname, PTR_DIFF(end_data, p),
2089 STR_TERMINATE_ASCII);
2090 SIVAL(q,0,len);
2091 p += len;
2093 len = PTR_DIFF(p, pdata);
2094 pad = (len + (align-1)) & ~(align-1);
2096 * offset to the next entry, the caller
2097 * will overwrite it for the last entry
2098 * that's why we always include the padding
2100 SIVAL(pdata,0,pad);
2102 * set padding to zero
2104 if (do_pad) {
2105 memset(p, 0, pad - len);
2106 p = pdata + pad;
2107 } else {
2108 p = pdata + len;
2110 break;
2112 /* CIFS UNIX Extension. */
2114 case SMB_FIND_FILE_UNIX:
2115 case SMB_FIND_FILE_UNIX_INFO2:
2116 p+= 4;
2117 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2119 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2121 if (info_level == SMB_FIND_FILE_UNIX) {
2122 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2123 p = store_file_unix_basic(conn, p,
2124 NULL, &smb_fname->st);
2125 len = srvstr_push(base_data, flags2, p,
2126 fname, PTR_DIFF(end_data, p),
2127 STR_TERMINATE);
2128 } else {
2129 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2130 p = store_file_unix_basic_info2(conn, p,
2131 NULL, &smb_fname->st);
2132 nameptr = p;
2133 p += 4;
2134 len = srvstr_push(base_data, flags2, p, fname,
2135 PTR_DIFF(end_data, p), 0);
2136 SIVAL(nameptr, 0, len);
2139 p += len;
2141 len = PTR_DIFF(p, pdata);
2142 pad = (len + (align-1)) & ~(align-1);
2144 * offset to the next entry, the caller
2145 * will overwrite it for the last entry
2146 * that's why we always include the padding
2148 SIVAL(pdata,0,pad);
2150 * set padding to zero
2152 if (do_pad) {
2153 memset(p, 0, pad - len);
2154 p = pdata + pad;
2155 } else {
2156 p = pdata + len;
2158 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2160 break;
2162 default:
2163 return false;
2166 if (PTR_DIFF(p,pdata) > space_remaining) {
2167 *out_of_space = true;
2168 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2169 "(wanted %u, had %d)\n",
2170 (unsigned int)PTR_DIFF(p,pdata),
2171 space_remaining ));
2172 return false; /* Not finished - just out of space */
2175 /* Setup the last entry pointer, as an offset from base_data */
2176 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2177 /* Advance the data pointer to the next slot */
2178 *ppdata = p;
2180 return true;
2183 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2184 connection_struct *conn,
2185 struct dptr_struct *dirptr,
2186 uint16 flags2,
2187 const char *path_mask,
2188 uint32 dirtype,
2189 int info_level,
2190 int requires_resume_key,
2191 bool dont_descend,
2192 bool ask_sharemode,
2193 uint8_t align,
2194 bool do_pad,
2195 char **ppdata,
2196 char *base_data,
2197 char *end_data,
2198 int space_remaining,
2199 bool *out_of_space,
2200 bool *got_exact_match,
2201 int *_last_entry_off,
2202 struct ea_list *name_list)
2204 const char *p;
2205 const char *mask = NULL;
2206 long prev_dirpos = 0;
2207 uint32_t mode = 0;
2208 char *fname = NULL;
2209 struct smb_filename *smb_fname = NULL;
2210 struct smbd_dirptr_lanman2_state state;
2211 bool ok;
2212 uint64_t last_entry_off = 0;
2214 ZERO_STRUCT(state);
2215 state.conn = conn;
2216 state.info_level = info_level;
2217 state.check_mangled_names = lp_manglednames(conn->params);
2218 state.has_wild = dptr_has_wild(dirptr);
2219 state.got_exact_match = false;
2221 *out_of_space = false;
2222 *got_exact_match = false;
2224 p = strrchr_m(path_mask,'/');
2225 if(p != NULL) {
2226 if(p[1] == '\0') {
2227 mask = "*.*";
2228 } else {
2229 mask = p+1;
2231 } else {
2232 mask = path_mask;
2235 ok = smbd_dirptr_get_entry(ctx,
2236 dirptr,
2237 mask,
2238 dirtype,
2239 dont_descend,
2240 ask_sharemode,
2241 smbd_dirptr_lanman2_match_fn,
2242 smbd_dirptr_lanman2_mode_fn,
2243 &state,
2244 &fname,
2245 &smb_fname,
2246 &mode,
2247 &prev_dirpos);
2248 if (!ok) {
2249 return false;
2252 *got_exact_match = state.got_exact_match;
2254 ok = smbd_marshall_dir_entry(ctx,
2255 conn,
2256 flags2,
2257 info_level,
2258 name_list,
2259 state.check_mangled_names,
2260 requires_resume_key,
2261 mode,
2262 fname,
2263 smb_fname,
2264 space_remaining,
2265 align,
2266 do_pad,
2267 base_data,
2268 ppdata,
2269 end_data,
2270 out_of_space,
2271 &last_entry_off);
2272 TALLOC_FREE(fname);
2273 TALLOC_FREE(smb_fname);
2274 if (*out_of_space) {
2275 dptr_SeekDir(dirptr, prev_dirpos);
2276 return false;
2278 if (!ok) {
2279 return false;
2282 *_last_entry_off = last_entry_off;
2283 return true;
2286 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2287 connection_struct *conn,
2288 struct dptr_struct *dirptr,
2289 uint16 flags2,
2290 const char *path_mask,
2291 uint32 dirtype,
2292 int info_level,
2293 bool requires_resume_key,
2294 bool dont_descend,
2295 bool ask_sharemode,
2296 char **ppdata,
2297 char *base_data,
2298 char *end_data,
2299 int space_remaining,
2300 bool *out_of_space,
2301 bool *got_exact_match,
2302 int *last_entry_off,
2303 struct ea_list *name_list)
2305 uint8_t align = 4;
2306 const bool do_pad = true;
2308 if (info_level >= 1 && info_level <= 3) {
2309 /* No alignment on earlier info levels. */
2310 align = 1;
2313 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2314 path_mask, dirtype, info_level,
2315 requires_resume_key, dont_descend, ask_sharemode,
2316 align, do_pad,
2317 ppdata, base_data, end_data,
2318 space_remaining,
2319 out_of_space, got_exact_match,
2320 last_entry_off, name_list);
2323 /****************************************************************************
2324 Reply to a TRANS2_FINDFIRST.
2325 ****************************************************************************/
2327 static void call_trans2findfirst(connection_struct *conn,
2328 struct smb_request *req,
2329 char **pparams, int total_params,
2330 char **ppdata, int total_data,
2331 unsigned int max_data_bytes)
2333 /* We must be careful here that we don't return more than the
2334 allowed number of data bytes. If this means returning fewer than
2335 maxentries then so be it. We assume that the redirector has
2336 enough room for the fixed number of parameter bytes it has
2337 requested. */
2338 struct smb_filename *smb_dname = NULL;
2339 char *params = *pparams;
2340 char *pdata = *ppdata;
2341 char *data_end;
2342 uint32 dirtype;
2343 int maxentries;
2344 uint16 findfirst_flags;
2345 bool close_after_first;
2346 bool close_if_end;
2347 bool requires_resume_key;
2348 int info_level;
2349 char *directory = NULL;
2350 char *mask = NULL;
2351 char *p;
2352 int last_entry_off=0;
2353 int dptr_num = -1;
2354 int numentries = 0;
2355 int i;
2356 bool finished = False;
2357 bool dont_descend = False;
2358 bool out_of_space = False;
2359 int space_remaining;
2360 bool mask_contains_wcard = False;
2361 struct ea_list *ea_list = NULL;
2362 NTSTATUS ntstatus = NT_STATUS_OK;
2363 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2364 TALLOC_CTX *ctx = talloc_tos();
2365 struct dptr_struct *dirptr = NULL;
2366 struct smbd_server_connection *sconn = req->sconn;
2367 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2368 bool backup_priv = false;
2370 if (total_params < 13) {
2371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2372 goto out;
2375 dirtype = SVAL(params,0);
2376 maxentries = SVAL(params,2);
2377 findfirst_flags = SVAL(params,4);
2378 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2379 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2380 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2381 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2382 security_token_has_privilege(get_current_nttok(conn),
2383 SEC_PRIV_BACKUP));
2385 info_level = SVAL(params,6);
2387 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2388 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2389 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2390 (int)backup_priv,
2391 info_level, max_data_bytes));
2393 if (!maxentries) {
2394 /* W2K3 seems to treat zero as 1. */
2395 maxentries = 1;
2398 switch (info_level) {
2399 case SMB_FIND_INFO_STANDARD:
2400 case SMB_FIND_EA_SIZE:
2401 case SMB_FIND_EA_LIST:
2402 case SMB_FIND_FILE_DIRECTORY_INFO:
2403 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_FILE_NAMES_INFO:
2405 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2406 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2407 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2408 break;
2409 case SMB_FIND_FILE_UNIX:
2410 case SMB_FIND_FILE_UNIX_INFO2:
2411 /* Always use filesystem for UNIX mtime query. */
2412 ask_sharemode = false;
2413 if (!lp_unix_extensions()) {
2414 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2415 goto out;
2417 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2418 break;
2419 default:
2420 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2421 goto out;
2424 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2425 params+12, total_params - 12,
2426 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2427 if (!NT_STATUS_IS_OK(ntstatus)) {
2428 reply_nterror(req, ntstatus);
2429 goto out;
2432 if (backup_priv) {
2433 become_root();
2434 ntstatus = filename_convert_with_privilege(ctx,
2435 conn,
2436 req,
2437 directory,
2438 ucf_flags,
2439 &mask_contains_wcard,
2440 &smb_dname);
2441 } else {
2442 ntstatus = filename_convert(ctx, conn,
2443 req->flags2 & FLAGS2_DFS_PATHNAMES,
2444 directory,
2445 ucf_flags,
2446 &mask_contains_wcard,
2447 &smb_dname);
2450 if (!NT_STATUS_IS_OK(ntstatus)) {
2451 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2452 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2453 ERRSRV, ERRbadpath);
2454 goto out;
2456 reply_nterror(req, ntstatus);
2457 goto out;
2460 mask = smb_dname->original_lcomp;
2462 directory = smb_dname->base_name;
2464 p = strrchr_m(directory,'/');
2465 if(p == NULL) {
2466 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2467 if((directory[0] == '.') && (directory[1] == '\0')) {
2468 mask = talloc_strdup(ctx,"*");
2469 if (!mask) {
2470 reply_nterror(req, NT_STATUS_NO_MEMORY);
2471 goto out;
2473 mask_contains_wcard = True;
2475 } else {
2476 *p = 0;
2479 if (p == NULL || p == directory) {
2480 /* Ensure we don't have a directory name of "". */
2481 directory = talloc_strdup(talloc_tos(), ".");
2482 if (!directory) {
2483 reply_nterror(req, NT_STATUS_NO_MEMORY);
2484 goto out;
2488 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2490 if (info_level == SMB_FIND_EA_LIST) {
2491 uint32 ea_size;
2493 if (total_data < 4) {
2494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2495 goto out;
2498 ea_size = IVAL(pdata,0);
2499 if (ea_size != total_data) {
2500 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2501 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2503 goto out;
2506 if (!lp_ea_support(SNUM(conn))) {
2507 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2508 goto out;
2511 /* Pull out the list of names. */
2512 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2513 if (!ea_list) {
2514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2515 goto out;
2519 *ppdata = (char *)SMB_REALLOC(
2520 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2521 if(*ppdata == NULL ) {
2522 reply_nterror(req, NT_STATUS_NO_MEMORY);
2523 goto out;
2525 pdata = *ppdata;
2526 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2528 /* Realloc the params space */
2529 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2530 if (*pparams == NULL) {
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2532 goto out;
2534 params = *pparams;
2536 /* Save the wildcard match and attribs we are using on this directory -
2537 needed as lanman2 assumes these are being saved between calls */
2539 ntstatus = dptr_create(conn,
2540 req,
2541 NULL, /* fsp */
2542 directory,
2543 False,
2544 True,
2545 req->smbpid,
2546 mask,
2547 mask_contains_wcard,
2548 dirtype,
2549 &dirptr);
2551 if (!NT_STATUS_IS_OK(ntstatus)) {
2552 reply_nterror(req, ntstatus);
2553 goto out;
2556 if (backup_priv) {
2557 /* Remember this in case we have
2558 to do a findnext. */
2559 dptr_set_priv(dirptr);
2562 dptr_num = dptr_dnum(dirptr);
2563 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2565 /* Initialize per TRANS2_FIND_FIRST operation data */
2566 dptr_init_search_op(dirptr);
2568 /* We don't need to check for VOL here as this is returned by
2569 a different TRANS2 call. */
2571 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2572 directory,lp_dontdescend(ctx, SNUM(conn))));
2573 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2574 dont_descend = True;
2576 p = pdata;
2577 space_remaining = max_data_bytes;
2578 out_of_space = False;
2580 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2581 bool got_exact_match = False;
2583 /* this is a heuristic to avoid seeking the dirptr except when
2584 absolutely necessary. It allows for a filename of about 40 chars */
2585 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2586 out_of_space = True;
2587 finished = False;
2588 } else {
2589 finished = !get_lanman2_dir_entry(ctx,
2590 conn,
2591 dirptr,
2592 req->flags2,
2593 mask,dirtype,info_level,
2594 requires_resume_key,dont_descend,
2595 ask_sharemode,
2596 &p,pdata,data_end,
2597 space_remaining, &out_of_space,
2598 &got_exact_match,
2599 &last_entry_off, ea_list);
2602 if (finished && out_of_space)
2603 finished = False;
2605 if (!finished && !out_of_space)
2606 numentries++;
2609 * As an optimisation if we know we aren't looking
2610 * for a wildcard name (ie. the name matches the wildcard exactly)
2611 * then we can finish on any (first) match.
2612 * This speeds up large directory searches. JRA.
2615 if(got_exact_match)
2616 finished = True;
2618 /* Ensure space_remaining never goes -ve. */
2619 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2620 space_remaining = 0;
2621 out_of_space = true;
2622 } else {
2623 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2627 /* Check if we can close the dirptr */
2628 if(close_after_first || (finished && close_if_end)) {
2629 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2630 dptr_close(sconn, &dptr_num);
2634 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2635 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2636 * the protocol level is less than NT1. Tested with smbclient. JRA.
2637 * This should fix the OS/2 client bug #2335.
2640 if(numentries == 0) {
2641 dptr_close(sconn, &dptr_num);
2642 if (get_Protocol() < PROTOCOL_NT1) {
2643 reply_force_doserror(req, ERRDOS, ERRnofiles);
2644 goto out;
2645 } else {
2646 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2647 ERRDOS, ERRbadfile);
2648 goto out;
2652 /* At this point pdata points to numentries directory entries. */
2654 /* Set up the return parameter block */
2655 SSVAL(params,0,dptr_num);
2656 SSVAL(params,2,numentries);
2657 SSVAL(params,4,finished);
2658 SSVAL(params,6,0); /* Never an EA error */
2659 SSVAL(params,8,last_entry_off);
2661 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2662 max_data_bytes);
2664 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2665 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2666 if (!directory) {
2667 reply_nterror(req, NT_STATUS_NO_MEMORY);
2671 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2672 smb_fn_name(req->cmd),
2673 mask, directory, dirtype, numentries ) );
2676 * Force a name mangle here to ensure that the
2677 * mask as an 8.3 name is top of the mangled cache.
2678 * The reasons for this are subtle. Don't remove
2679 * this code unless you know what you are doing
2680 * (see PR#13758). JRA.
2683 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2684 char mangled_name[13];
2685 name_to_8_3(mask, mangled_name, True, conn->params);
2687 out:
2689 if (backup_priv) {
2690 unbecome_root();
2693 TALLOC_FREE(smb_dname);
2694 return;
2697 /****************************************************************************
2698 Reply to a TRANS2_FINDNEXT.
2699 ****************************************************************************/
2701 static void call_trans2findnext(connection_struct *conn,
2702 struct smb_request *req,
2703 char **pparams, int total_params,
2704 char **ppdata, int total_data,
2705 unsigned int max_data_bytes)
2707 /* We must be careful here that we don't return more than the
2708 allowed number of data bytes. If this means returning fewer than
2709 maxentries then so be it. We assume that the redirector has
2710 enough room for the fixed number of parameter bytes it has
2711 requested. */
2712 char *params = *pparams;
2713 char *pdata = *ppdata;
2714 char *data_end;
2715 int dptr_num;
2716 int maxentries;
2717 uint16 info_level;
2718 uint32 resume_key;
2719 uint16 findnext_flags;
2720 bool close_after_request;
2721 bool close_if_end;
2722 bool requires_resume_key;
2723 bool continue_bit;
2724 bool mask_contains_wcard = False;
2725 char *resume_name = NULL;
2726 const char *mask = NULL;
2727 const char *directory = NULL;
2728 char *p = NULL;
2729 uint16 dirtype;
2730 int numentries = 0;
2731 int i, last_entry_off=0;
2732 bool finished = False;
2733 bool dont_descend = False;
2734 bool out_of_space = False;
2735 int space_remaining;
2736 struct ea_list *ea_list = NULL;
2737 NTSTATUS ntstatus = NT_STATUS_OK;
2738 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2739 TALLOC_CTX *ctx = talloc_tos();
2740 struct dptr_struct *dirptr;
2741 struct smbd_server_connection *sconn = req->sconn;
2742 bool backup_priv = false;
2744 if (total_params < 13) {
2745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2746 return;
2749 dptr_num = SVAL(params,0);
2750 maxentries = SVAL(params,2);
2751 info_level = SVAL(params,4);
2752 resume_key = IVAL(params,6);
2753 findnext_flags = SVAL(params,10);
2754 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2755 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2756 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2757 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2759 if (!continue_bit) {
2760 /* We only need resume_name if continue_bit is zero. */
2761 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2762 params+12,
2763 total_params - 12, STR_TERMINATE, &ntstatus,
2764 &mask_contains_wcard);
2765 if (!NT_STATUS_IS_OK(ntstatus)) {
2766 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2767 complain (it thinks we're asking for the directory above the shared
2768 path or an invalid name). Catch this as the resume name is only compared, never used in
2769 a file access. JRA. */
2770 srvstr_pull_talloc(ctx, params, req->flags2,
2771 &resume_name, params+12,
2772 total_params - 12,
2773 STR_TERMINATE);
2775 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2776 reply_nterror(req, ntstatus);
2777 return;
2782 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2783 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2784 resume_key = %d resume name = %s continue=%d level = %d\n",
2785 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2786 requires_resume_key, resume_key,
2787 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2789 if (!maxentries) {
2790 /* W2K3 seems to treat zero as 1. */
2791 maxentries = 1;
2794 switch (info_level) {
2795 case SMB_FIND_INFO_STANDARD:
2796 case SMB_FIND_EA_SIZE:
2797 case SMB_FIND_EA_LIST:
2798 case SMB_FIND_FILE_DIRECTORY_INFO:
2799 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_FILE_NAMES_INFO:
2801 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2802 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2803 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2804 break;
2805 case SMB_FIND_FILE_UNIX:
2806 case SMB_FIND_FILE_UNIX_INFO2:
2807 /* Always use filesystem for UNIX mtime query. */
2808 ask_sharemode = false;
2809 if (!lp_unix_extensions()) {
2810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2811 return;
2813 break;
2814 default:
2815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2816 return;
2819 if (info_level == SMB_FIND_EA_LIST) {
2820 uint32 ea_size;
2822 if (total_data < 4) {
2823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2824 return;
2827 ea_size = IVAL(pdata,0);
2828 if (ea_size != total_data) {
2829 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2830 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2832 return;
2835 if (!lp_ea_support(SNUM(conn))) {
2836 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2837 return;
2840 /* Pull out the list of names. */
2841 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2842 if (!ea_list) {
2843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2844 return;
2848 *ppdata = (char *)SMB_REALLOC(
2849 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2850 if(*ppdata == NULL) {
2851 reply_nterror(req, NT_STATUS_NO_MEMORY);
2852 return;
2855 pdata = *ppdata;
2856 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2858 /* Realloc the params space */
2859 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2860 if(*pparams == NULL ) {
2861 reply_nterror(req, NT_STATUS_NO_MEMORY);
2862 return;
2865 params = *pparams;
2867 /* Check that the dptr is valid */
2868 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2869 reply_nterror(req, STATUS_NO_MORE_FILES);
2870 return;
2873 directory = dptr_path(sconn, dptr_num);
2875 /* Get the wildcard mask from the dptr */
2876 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2877 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2878 reply_nterror(req, STATUS_NO_MORE_FILES);
2879 return;
2882 /* Get the attr mask from the dptr */
2883 dirtype = dptr_attr(sconn, dptr_num);
2885 backup_priv = dptr_get_priv(dirptr);
2887 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2888 "backup_priv = %d\n",
2889 dptr_num, mask, dirtype,
2890 (long)dirptr,
2891 dptr_TellDir(dirptr),
2892 (int)backup_priv));
2894 /* Initialize per TRANS2_FIND_NEXT operation data */
2895 dptr_init_search_op(dirptr);
2897 /* We don't need to check for VOL here as this is returned by
2898 a different TRANS2 call. */
2900 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2901 directory,lp_dontdescend(ctx, SNUM(conn))));
2902 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2903 dont_descend = True;
2905 p = pdata;
2906 space_remaining = max_data_bytes;
2907 out_of_space = False;
2909 if (backup_priv) {
2910 become_root();
2914 * Seek to the correct position. We no longer use the resume key but
2915 * depend on the last file name instead.
2918 if(!continue_bit && resume_name && *resume_name) {
2919 SMB_STRUCT_STAT st;
2921 long current_pos = 0;
2923 * Remember, name_to_8_3 is called by
2924 * get_lanman2_dir_entry(), so the resume name
2925 * could be mangled. Ensure we check the unmangled name.
2928 if (mangle_is_mangled(resume_name, conn->params)) {
2929 char *new_resume_name = NULL;
2930 mangle_lookup_name_from_8_3(ctx,
2931 resume_name,
2932 &new_resume_name,
2933 conn->params);
2934 if (new_resume_name) {
2935 resume_name = new_resume_name;
2940 * Fix for NT redirector problem triggered by resume key indexes
2941 * changing between directory scans. We now return a resume key of 0
2942 * and instead look for the filename to continue from (also given
2943 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2944 * findfirst/findnext (as is usual) then the directory pointer
2945 * should already be at the correct place.
2948 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2949 } /* end if resume_name && !continue_bit */
2951 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2952 bool got_exact_match = False;
2954 /* this is a heuristic to avoid seeking the dirptr except when
2955 absolutely necessary. It allows for a filename of about 40 chars */
2956 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2957 out_of_space = True;
2958 finished = False;
2959 } else {
2960 finished = !get_lanman2_dir_entry(ctx,
2961 conn,
2962 dirptr,
2963 req->flags2,
2964 mask,dirtype,info_level,
2965 requires_resume_key,dont_descend,
2966 ask_sharemode,
2967 &p,pdata,data_end,
2968 space_remaining, &out_of_space,
2969 &got_exact_match,
2970 &last_entry_off, ea_list);
2973 if (finished && out_of_space)
2974 finished = False;
2976 if (!finished && !out_of_space)
2977 numentries++;
2980 * As an optimisation if we know we aren't looking
2981 * for a wildcard name (ie. the name matches the wildcard exactly)
2982 * then we can finish on any (first) match.
2983 * This speeds up large directory searches. JRA.
2986 if(got_exact_match)
2987 finished = True;
2989 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2992 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2993 smb_fn_name(req->cmd),
2994 mask, directory, dirtype, numentries ) );
2996 /* Check if we can close the dirptr */
2997 if(close_after_request || (finished && close_if_end)) {
2998 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2999 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3002 if (backup_priv) {
3003 unbecome_root();
3006 /* Set up the return parameter block */
3007 SSVAL(params,0,numentries);
3008 SSVAL(params,2,finished);
3009 SSVAL(params,4,0); /* Never an EA error */
3010 SSVAL(params,6,last_entry_off);
3012 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3013 max_data_bytes);
3015 return;
3018 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3020 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3021 return objid;
3024 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3026 SMB_ASSERT(extended_info != NULL);
3028 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3029 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3030 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3031 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3032 #ifdef SAMBA_VERSION_REVISION
3033 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3034 #endif
3035 extended_info->samba_subversion = 0;
3036 #ifdef SAMBA_VERSION_RC_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3038 #else
3039 #ifdef SAMBA_VERSION_PRE_RELEASE
3040 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3041 #endif
3042 #endif
3043 #ifdef SAMBA_VERSION_VENDOR_PATCH
3044 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3045 #endif
3046 extended_info->samba_gitcommitdate = 0;
3047 #ifdef SAMBA_VERSION_COMMIT_TIME
3048 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3049 #endif
3051 memset(extended_info->samba_version_string, 0,
3052 sizeof(extended_info->samba_version_string));
3054 snprintf (extended_info->samba_version_string,
3055 sizeof(extended_info->samba_version_string),
3056 "%s", samba_version_string());
3059 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3060 TALLOC_CTX *mem_ctx,
3061 uint16_t info_level,
3062 uint16_t flags2,
3063 unsigned int max_data_bytes,
3064 struct smb_filename *fname,
3065 char **ppdata,
3066 int *ret_data_len)
3068 char *pdata, *end_data;
3069 int data_len = 0, len;
3070 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3071 int snum = SNUM(conn);
3072 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3073 char *filename = NULL;
3074 uint32 additional_flags = 0;
3075 struct smb_filename smb_fname;
3076 SMB_STRUCT_STAT st;
3078 if (fname == NULL || fname->base_name == NULL) {
3079 filename = ".";
3080 } else {
3081 filename = fname->base_name;
3084 if (IS_IPC(conn)) {
3085 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3086 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3087 "info level (0x%x) on IPC$.\n",
3088 (unsigned int)info_level));
3089 return NT_STATUS_ACCESS_DENIED;
3093 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3095 ZERO_STRUCT(smb_fname);
3096 smb_fname.base_name = discard_const_p(char, filename);
3098 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3099 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3100 return map_nt_error_from_unix(errno);
3103 st = smb_fname.st;
3105 *ppdata = (char *)SMB_REALLOC(
3106 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3107 if (*ppdata == NULL) {
3108 return NT_STATUS_NO_MEMORY;
3111 pdata = *ppdata;
3112 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3113 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3115 switch (info_level) {
3116 case SMB_INFO_ALLOCATION:
3118 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3119 data_len = 18;
3120 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3121 return map_nt_error_from_unix(errno);
3124 block_size = lp_block_size(snum);
3125 if (bsize < block_size) {
3126 uint64_t factor = block_size/bsize;
3127 bsize = block_size;
3128 dsize /= factor;
3129 dfree /= factor;
3131 if (bsize > block_size) {
3132 uint64_t factor = bsize/block_size;
3133 bsize = block_size;
3134 dsize *= factor;
3135 dfree *= factor;
3137 bytes_per_sector = 512;
3138 sectors_per_unit = bsize/bytes_per_sector;
3140 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3141 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3142 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3144 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3145 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3146 SIVAL(pdata,l1_cUnit,dsize);
3147 SIVAL(pdata,l1_cUnitAvail,dfree);
3148 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3149 break;
3152 case SMB_INFO_VOLUME:
3153 /* Return volume name */
3155 * Add volume serial number - hash of a combination of
3156 * the called hostname and the service name.
3158 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3160 * Win2k3 and previous mess this up by sending a name length
3161 * one byte short. I believe only older clients (OS/2 Win9x) use
3162 * this call so try fixing this by adding a terminating null to
3163 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3165 len = srvstr_push(
3166 pdata, flags2,
3167 pdata+l2_vol_szVolLabel, vname,
3168 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3169 STR_NOALIGN|STR_TERMINATE);
3170 SCVAL(pdata,l2_vol_cch,len);
3171 data_len = l2_vol_szVolLabel + len;
3172 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3173 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3174 len, vname));
3175 break;
3177 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3178 case SMB_FS_ATTRIBUTE_INFORMATION:
3180 additional_flags = 0;
3181 #if defined(HAVE_SYS_QUOTAS)
3182 additional_flags |= FILE_VOLUME_QUOTAS;
3183 #endif
3185 if(lp_nt_acl_support(SNUM(conn))) {
3186 additional_flags |= FILE_PERSISTENT_ACLS;
3189 /* Capabilities are filled in at connection time through STATVFS call */
3190 additional_flags |= conn->fs_capabilities;
3191 additional_flags |= lp_parm_int(conn->params->service,
3192 "share", "fake_fscaps",
3195 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3196 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3197 additional_flags); /* FS ATTRIBUTES */
3199 SIVAL(pdata,4,255); /* Max filename component length */
3200 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3201 and will think we can't do long filenames */
3202 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3203 PTR_DIFF(end_data, pdata+12),
3204 STR_UNICODE);
3205 SIVAL(pdata,8,len);
3206 data_len = 12 + len;
3207 break;
3209 case SMB_QUERY_FS_LABEL_INFO:
3210 case SMB_FS_LABEL_INFORMATION:
3211 len = srvstr_push(pdata, flags2, pdata+4, vname,
3212 PTR_DIFF(end_data, pdata+4), 0);
3213 data_len = 4 + len;
3214 SIVAL(pdata,0,len);
3215 break;
3217 case SMB_QUERY_FS_VOLUME_INFO:
3218 case SMB_FS_VOLUME_INFORMATION:
3221 * Add volume serial number - hash of a combination of
3222 * the called hostname and the service name.
3224 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3225 (str_checksum(get_local_machine_name())<<16));
3227 /* Max label len is 32 characters. */
3228 len = srvstr_push(pdata, flags2, pdata+18, vname,
3229 PTR_DIFF(end_data, pdata+18),
3230 STR_UNICODE);
3231 SIVAL(pdata,12,len);
3232 data_len = 18+len;
3234 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3235 (int)strlen(vname),vname,
3236 lp_servicename(talloc_tos(), snum)));
3237 break;
3239 case SMB_QUERY_FS_SIZE_INFO:
3240 case SMB_FS_SIZE_INFORMATION:
3242 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3243 data_len = 24;
3244 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3245 return map_nt_error_from_unix(errno);
3247 block_size = lp_block_size(snum);
3248 if (bsize < block_size) {
3249 uint64_t factor = block_size/bsize;
3250 bsize = block_size;
3251 dsize /= factor;
3252 dfree /= factor;
3254 if (bsize > block_size) {
3255 uint64_t factor = bsize/block_size;
3256 bsize = block_size;
3257 dsize *= factor;
3258 dfree *= factor;
3260 bytes_per_sector = 512;
3261 sectors_per_unit = bsize/bytes_per_sector;
3262 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3263 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3264 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3265 SBIG_UINT(pdata,0,dsize);
3266 SBIG_UINT(pdata,8,dfree);
3267 SIVAL(pdata,16,sectors_per_unit);
3268 SIVAL(pdata,20,bytes_per_sector);
3269 break;
3272 case SMB_FS_FULL_SIZE_INFORMATION:
3274 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3275 data_len = 32;
3276 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno);
3279 block_size = lp_block_size(snum);
3280 if (bsize < block_size) {
3281 uint64_t factor = block_size/bsize;
3282 bsize = block_size;
3283 dsize /= factor;
3284 dfree /= factor;
3286 if (bsize > block_size) {
3287 uint64_t factor = bsize/block_size;
3288 bsize = block_size;
3289 dsize *= factor;
3290 dfree *= factor;
3292 bytes_per_sector = 512;
3293 sectors_per_unit = bsize/bytes_per_sector;
3294 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3295 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3296 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3297 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3298 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3299 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3300 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3301 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3302 break;
3305 case SMB_QUERY_FS_DEVICE_INFO:
3306 case SMB_FS_DEVICE_INFORMATION:
3308 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3310 if (!CAN_WRITE(conn)) {
3311 characteristics |= FILE_READ_ONLY_DEVICE;
3313 data_len = 8;
3314 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3315 SIVAL(pdata,4,characteristics);
3316 break;
3319 #ifdef HAVE_SYS_QUOTAS
3320 case SMB_FS_QUOTA_INFORMATION:
3322 * what we have to send --metze:
3324 * Unknown1: 24 NULL bytes
3325 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3326 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3327 * Quota Flags: 2 byte :
3328 * Unknown3: 6 NULL bytes
3330 * 48 bytes total
3332 * details for Quota Flags:
3334 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3335 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3336 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3337 * 0x0001 Enable Quotas: enable quota for this fs
3341 /* we need to fake up a fsp here,
3342 * because its not send in this call
3344 files_struct fsp;
3345 SMB_NTQUOTA_STRUCT quotas;
3347 ZERO_STRUCT(fsp);
3348 ZERO_STRUCT(quotas);
3350 fsp.conn = conn;
3351 fsp.fnum = FNUM_FIELD_INVALID;
3353 /* access check */
3354 if (get_current_uid(conn) != 0) {
3355 DEBUG(0,("set_user_quota: access_denied "
3356 "service [%s] user [%s]\n",
3357 lp_servicename(talloc_tos(), SNUM(conn)),
3358 conn->session_info->unix_info->unix_name));
3359 return NT_STATUS_ACCESS_DENIED;
3362 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3363 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3364 return map_nt_error_from_unix(errno);
3367 data_len = 48;
3369 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3370 lp_servicename(talloc_tos(), SNUM(conn))));
3372 /* Unknown1 24 NULL bytes*/
3373 SBIG_UINT(pdata,0,(uint64_t)0);
3374 SBIG_UINT(pdata,8,(uint64_t)0);
3375 SBIG_UINT(pdata,16,(uint64_t)0);
3377 /* Default Soft Quota 8 bytes */
3378 SBIG_UINT(pdata,24,quotas.softlim);
3380 /* Default Hard Quota 8 bytes */
3381 SBIG_UINT(pdata,32,quotas.hardlim);
3383 /* Quota flag 2 bytes */
3384 SSVAL(pdata,40,quotas.qflags);
3386 /* Unknown3 6 NULL bytes */
3387 SSVAL(pdata,42,0);
3388 SIVAL(pdata,44,0);
3390 break;
3392 #endif /* HAVE_SYS_QUOTAS */
3393 case SMB_FS_OBJECTID_INFORMATION:
3395 unsigned char objid[16];
3396 struct smb_extended_info extended_info;
3397 memcpy(pdata,create_volume_objectid(conn, objid),16);
3398 samba_extended_info_version (&extended_info);
3399 SIVAL(pdata,16,extended_info.samba_magic);
3400 SIVAL(pdata,20,extended_info.samba_version);
3401 SIVAL(pdata,24,extended_info.samba_subversion);
3402 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3403 memcpy(pdata+36,extended_info.samba_version_string,28);
3404 data_len = 64;
3405 break;
3409 * Query the version and capabilities of the CIFS UNIX extensions
3410 * in use.
3413 case SMB_QUERY_CIFS_UNIX_INFO:
3415 bool large_write = lp_min_receive_file_size() &&
3416 !srv_is_signing_active(conn->sconn);
3417 bool large_read = !srv_is_signing_active(conn->sconn);
3418 int encrypt_caps = 0;
3420 if (!lp_unix_extensions()) {
3421 return NT_STATUS_INVALID_LEVEL;
3424 switch (conn->encrypt_level) {
3425 case SMB_SIGNING_OFF:
3426 encrypt_caps = 0;
3427 break;
3428 case SMB_SIGNING_IF_REQUIRED:
3429 case SMB_SIGNING_DEFAULT:
3430 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3431 break;
3432 case SMB_SIGNING_REQUIRED:
3433 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3434 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3435 large_write = false;
3436 large_read = false;
3437 break;
3440 data_len = 12;
3441 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3442 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3444 /* We have POSIX ACLs, pathname, encryption,
3445 * large read/write, and locking capability. */
3447 SBIG_UINT(pdata,4,((uint64_t)(
3448 CIFS_UNIX_POSIX_ACLS_CAP|
3449 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3450 CIFS_UNIX_FCNTL_LOCKS_CAP|
3451 CIFS_UNIX_EXTATTR_CAP|
3452 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3453 encrypt_caps|
3454 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3455 (large_write ?
3456 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3457 break;
3460 case SMB_QUERY_POSIX_FS_INFO:
3462 int rc;
3463 vfs_statvfs_struct svfs;
3465 if (!lp_unix_extensions()) {
3466 return NT_STATUS_INVALID_LEVEL;
3469 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3471 if (!rc) {
3472 data_len = 56;
3473 SIVAL(pdata,0,svfs.OptimalTransferSize);
3474 SIVAL(pdata,4,svfs.BlockSize);
3475 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3476 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3477 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3478 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3479 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3480 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3481 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3482 #ifdef EOPNOTSUPP
3483 } else if (rc == EOPNOTSUPP) {
3484 return NT_STATUS_INVALID_LEVEL;
3485 #endif /* EOPNOTSUPP */
3486 } else {
3487 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3488 return NT_STATUS_DOS(ERRSRV, ERRerror);
3490 break;
3493 case SMB_QUERY_POSIX_WHOAMI:
3495 uint32_t flags = 0;
3496 uint32_t sid_bytes;
3497 int i;
3499 if (!lp_unix_extensions()) {
3500 return NT_STATUS_INVALID_LEVEL;
3503 if (max_data_bytes < 40) {
3504 return NT_STATUS_BUFFER_TOO_SMALL;
3507 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3508 flags |= SMB_WHOAMI_GUEST;
3511 /* NOTE: 8 bytes for UID/GID, irrespective of native
3512 * platform size. This matches
3513 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3515 data_len = 4 /* flags */
3516 + 4 /* flag mask */
3517 + 8 /* uid */
3518 + 8 /* gid */
3519 + 4 /* ngroups */
3520 + 4 /* num_sids */
3521 + 4 /* SID bytes */
3522 + 4 /* pad/reserved */
3523 + (conn->session_info->unix_token->ngroups * 8)
3524 /* groups list */
3525 + (conn->session_info->security_token->num_sids *
3526 SID_MAX_SIZE)
3527 /* SID list */;
3529 SIVAL(pdata, 0, flags);
3530 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3531 SBIG_UINT(pdata, 8,
3532 (uint64_t)conn->session_info->unix_token->uid);
3533 SBIG_UINT(pdata, 16,
3534 (uint64_t)conn->session_info->unix_token->gid);
3537 if (data_len >= max_data_bytes) {
3538 /* Potential overflow, skip the GIDs and SIDs. */
3540 SIVAL(pdata, 24, 0); /* num_groups */
3541 SIVAL(pdata, 28, 0); /* num_sids */
3542 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3543 SIVAL(pdata, 36, 0); /* reserved */
3545 data_len = 40;
3546 break;
3549 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3550 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3552 /* We walk the SID list twice, but this call is fairly
3553 * infrequent, and I don't expect that it's performance
3554 * sensitive -- jpeach
3556 for (i = 0, sid_bytes = 0;
3557 i < conn->session_info->security_token->num_sids; ++i) {
3558 sid_bytes += ndr_size_dom_sid(
3559 &conn->session_info->security_token->sids[i],
3563 /* SID list byte count */
3564 SIVAL(pdata, 32, sid_bytes);
3566 /* 4 bytes pad/reserved - must be zero */
3567 SIVAL(pdata, 36, 0);
3568 data_len = 40;
3570 /* GID list */
3571 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3572 SBIG_UINT(pdata, data_len,
3573 (uint64_t)conn->session_info->unix_token->groups[i]);
3574 data_len += 8;
3577 /* SID list */
3578 for (i = 0;
3579 i < conn->session_info->security_token->num_sids; ++i) {
3580 int sid_len = ndr_size_dom_sid(
3581 &conn->session_info->security_token->sids[i],
3584 sid_linearize(pdata + data_len, sid_len,
3585 &conn->session_info->security_token->sids[i]);
3586 data_len += sid_len;
3589 break;
3592 case SMB_MAC_QUERY_FS_INFO:
3594 * Thursby MAC extension... ONLY on NTFS filesystems
3595 * once we do streams then we don't need this
3597 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3598 data_len = 88;
3599 SIVAL(pdata,84,0x100); /* Don't support mac... */
3600 break;
3602 /* drop through */
3603 default:
3604 return NT_STATUS_INVALID_LEVEL;
3607 *ret_data_len = data_len;
3608 return NT_STATUS_OK;
3611 /****************************************************************************
3612 Reply to a TRANS2_QFSINFO (query filesystem info).
3613 ****************************************************************************/
3615 static void call_trans2qfsinfo(connection_struct *conn,
3616 struct smb_request *req,
3617 char **pparams, int total_params,
3618 char **ppdata, int total_data,
3619 unsigned int max_data_bytes)
3621 char *params = *pparams;
3622 uint16_t info_level;
3623 int data_len = 0;
3624 NTSTATUS status;
3626 if (total_params < 2) {
3627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3628 return;
3631 info_level = SVAL(params,0);
3633 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3634 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3635 DEBUG(0,("call_trans2qfsinfo: encryption required "
3636 "and info level 0x%x sent.\n",
3637 (unsigned int)info_level));
3638 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3639 return;
3643 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3645 status = smbd_do_qfsinfo(conn, req,
3646 info_level,
3647 req->flags2,
3648 max_data_bytes,
3649 NULL,
3650 ppdata, &data_len);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 reply_nterror(req, status);
3653 return;
3656 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3657 max_data_bytes);
3659 DEBUG( 4, ( "%s info_level = %d\n",
3660 smb_fn_name(req->cmd), info_level) );
3662 return;
3665 /****************************************************************************
3666 Reply to a TRANS2_SETFSINFO (set filesystem info).
3667 ****************************************************************************/
3669 static void call_trans2setfsinfo(connection_struct *conn,
3670 struct smb_request *req,
3671 char **pparams, int total_params,
3672 char **ppdata, int total_data,
3673 unsigned int max_data_bytes)
3675 struct smbd_server_connection *sconn = req->sconn;
3676 char *pdata = *ppdata;
3677 char *params = *pparams;
3678 uint16 info_level;
3680 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3681 lp_servicename(talloc_tos(), SNUM(conn))));
3683 /* */
3684 if (total_params < 4) {
3685 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3686 total_params));
3687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3688 return;
3691 info_level = SVAL(params,2);
3693 if (IS_IPC(conn)) {
3694 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3695 info_level != SMB_SET_CIFS_UNIX_INFO) {
3696 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3697 "info level (0x%x) on IPC$.\n",
3698 (unsigned int)info_level));
3699 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3700 return;
3704 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3705 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3706 DEBUG(0,("call_trans2setfsinfo: encryption required "
3707 "and info level 0x%x sent.\n",
3708 (unsigned int)info_level));
3709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3710 return;
3714 switch(info_level) {
3715 case SMB_SET_CIFS_UNIX_INFO:
3716 if (!lp_unix_extensions()) {
3717 DEBUG(2,("call_trans2setfsinfo: "
3718 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3719 "unix extensions off\n"));
3720 reply_nterror(req,
3721 NT_STATUS_INVALID_LEVEL);
3722 return;
3725 /* There should be 12 bytes of capabilities set. */
3726 if (total_data < 12) {
3727 reply_nterror(
3728 req,
3729 NT_STATUS_INVALID_PARAMETER);
3730 return;
3732 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3733 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3734 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3735 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3736 /* Just print these values for now. */
3737 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3738 "major = %u, minor = %u cap_low = 0x%x, "
3739 "cap_high = 0x%xn",
3740 (unsigned int)sconn->
3741 smb1.unix_info.client_major,
3742 (unsigned int)sconn->
3743 smb1.unix_info.client_minor,
3744 (unsigned int)sconn->
3745 smb1.unix_info.client_cap_low,
3746 (unsigned int)sconn->
3747 smb1.unix_info.client_cap_high));
3749 /* Here is where we must switch to posix pathname processing... */
3750 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3751 lp_set_posix_pathnames();
3752 mangle_change_to_posix();
3755 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3756 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3757 /* Client that knows how to do posix locks,
3758 * but not posix open/mkdir operations. Set a
3759 * default type for read/write checks. */
3761 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3764 break;
3766 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3768 NTSTATUS status;
3769 size_t param_len = 0;
3770 size_t data_len = total_data;
3772 if (!lp_unix_extensions()) {
3773 reply_nterror(
3774 req,
3775 NT_STATUS_INVALID_LEVEL);
3776 return;
3779 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3780 reply_nterror(
3781 req,
3782 NT_STATUS_NOT_SUPPORTED);
3783 return;
3786 if (req->sconn->smb1.echo_handler.trusted_fde) {
3787 DEBUG( 2,("call_trans2setfsinfo: "
3788 "request transport encryption disabled"
3789 "with 'fork echo handler = yes'\n"));
3790 reply_nterror(
3791 req,
3792 NT_STATUS_NOT_SUPPORTED);
3793 return;
3796 DEBUG( 4,("call_trans2setfsinfo: "
3797 "request transport encryption.\n"));
3799 status = srv_request_encryption_setup(conn,
3800 (unsigned char **)ppdata,
3801 &data_len,
3802 (unsigned char **)pparams,
3803 &param_len);
3805 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3806 !NT_STATUS_IS_OK(status)) {
3807 reply_nterror(req, status);
3808 return;
3811 send_trans2_replies(conn, req,
3812 *pparams,
3813 param_len,
3814 *ppdata,
3815 data_len,
3816 max_data_bytes);
3818 if (NT_STATUS_IS_OK(status)) {
3819 /* Server-side transport
3820 * encryption is now *on*. */
3821 status = srv_encryption_start(conn);
3822 if (!NT_STATUS_IS_OK(status)) {
3823 char *reason = talloc_asprintf(talloc_tos(),
3824 "Failure in setting "
3825 "up encrypted transport: %s",
3826 nt_errstr(status));
3827 exit_server_cleanly(reason);
3830 return;
3833 case SMB_FS_QUOTA_INFORMATION:
3835 files_struct *fsp = NULL;
3836 SMB_NTQUOTA_STRUCT quotas;
3838 ZERO_STRUCT(quotas);
3840 /* access check */
3841 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3842 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3843 lp_servicename(talloc_tos(), SNUM(conn)),
3844 conn->session_info->unix_info->unix_name));
3845 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3846 return;
3849 /* note: normaly there're 48 bytes,
3850 * but we didn't use the last 6 bytes for now
3851 * --metze
3853 fsp = file_fsp(req, SVAL(params,0));
3855 if (!check_fsp_ntquota_handle(conn, req,
3856 fsp)) {
3857 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3858 reply_nterror(
3859 req, NT_STATUS_INVALID_HANDLE);
3860 return;
3863 if (total_data < 42) {
3864 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3865 total_data));
3866 reply_nterror(
3867 req,
3868 NT_STATUS_INVALID_PARAMETER);
3869 return;
3872 /* unknown_1 24 NULL bytes in pdata*/
3874 /* the soft quotas 8 bytes (uint64_t)*/
3875 quotas.softlim = BVAL(pdata,24);
3877 /* the hard quotas 8 bytes (uint64_t)*/
3878 quotas.hardlim = BVAL(pdata,32);
3880 /* quota_flags 2 bytes **/
3881 quotas.qflags = SVAL(pdata,40);
3883 /* unknown_2 6 NULL bytes follow*/
3885 /* now set the quotas */
3886 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3887 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3888 reply_nterror(req, map_nt_error_from_unix(errno));
3889 return;
3892 break;
3894 default:
3895 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3896 info_level));
3897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3898 return;
3899 break;
3903 * sending this reply works fine,
3904 * but I'm not sure it's the same
3905 * like windows do...
3906 * --metze
3908 reply_outbuf(req, 10, 0);
3911 #if defined(HAVE_POSIX_ACLS)
3912 /****************************************************************************
3913 Utility function to count the number of entries in a POSIX acl.
3914 ****************************************************************************/
3916 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3918 unsigned int ace_count = 0;
3919 int entry_id = SMB_ACL_FIRST_ENTRY;
3920 SMB_ACL_ENTRY_T entry;
3922 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3923 /* get_next... */
3924 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3925 entry_id = SMB_ACL_NEXT_ENTRY;
3927 ace_count++;
3929 return ace_count;
3932 /****************************************************************************
3933 Utility function to marshall a POSIX acl into wire format.
3934 ****************************************************************************/
3936 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3938 int entry_id = SMB_ACL_FIRST_ENTRY;
3939 SMB_ACL_ENTRY_T entry;
3941 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3942 SMB_ACL_TAG_T tagtype;
3943 SMB_ACL_PERMSET_T permset;
3944 unsigned char perms = 0;
3945 unsigned int own_grp;
3947 /* get_next... */
3948 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3949 entry_id = SMB_ACL_NEXT_ENTRY;
3952 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3953 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3954 return False;
3957 if (sys_acl_get_permset(entry, &permset) == -1) {
3958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3959 return False;
3962 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3963 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3964 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3966 SCVAL(pdata,1,perms);
3968 switch (tagtype) {
3969 case SMB_ACL_USER_OBJ:
3970 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3971 own_grp = (unsigned int)pst->st_ex_uid;
3972 SIVAL(pdata,2,own_grp);
3973 SIVAL(pdata,6,0);
3974 break;
3975 case SMB_ACL_USER:
3977 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3978 if (!puid) {
3979 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3980 return False;
3982 own_grp = (unsigned int)*puid;
3983 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3984 SIVAL(pdata,2,own_grp);
3985 SIVAL(pdata,6,0);
3986 break;
3988 case SMB_ACL_GROUP_OBJ:
3989 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3990 own_grp = (unsigned int)pst->st_ex_gid;
3991 SIVAL(pdata,2,own_grp);
3992 SIVAL(pdata,6,0);
3993 break;
3994 case SMB_ACL_GROUP:
3996 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3997 if (!pgid) {
3998 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3999 return False;
4001 own_grp = (unsigned int)*pgid;
4002 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4003 SIVAL(pdata,2,own_grp);
4004 SIVAL(pdata,6,0);
4005 break;
4007 case SMB_ACL_MASK:
4008 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4009 SIVAL(pdata,2,0xFFFFFFFF);
4010 SIVAL(pdata,6,0xFFFFFFFF);
4011 break;
4012 case SMB_ACL_OTHER:
4013 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4014 SIVAL(pdata,2,0xFFFFFFFF);
4015 SIVAL(pdata,6,0xFFFFFFFF);
4016 break;
4017 default:
4018 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4019 return False;
4021 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4024 return True;
4026 #endif
4028 /****************************************************************************
4029 Store the FILE_UNIX_BASIC info.
4030 ****************************************************************************/
4032 static char *store_file_unix_basic(connection_struct *conn,
4033 char *pdata,
4034 files_struct *fsp,
4035 const SMB_STRUCT_STAT *psbuf)
4037 uint64_t file_index = get_FileIndex(conn, psbuf);
4038 dev_t devno;
4040 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4041 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4043 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4044 pdata += 8;
4046 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4047 pdata += 8;
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4050 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4051 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4052 pdata += 24;
4054 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4055 SIVAL(pdata,4,0);
4056 pdata += 8;
4058 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4059 SIVAL(pdata,4,0);
4060 pdata += 8;
4062 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4063 pdata += 4;
4065 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4066 devno = psbuf->st_ex_rdev;
4067 } else {
4068 devno = psbuf->st_ex_dev;
4071 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4072 SIVAL(pdata,4,0);
4073 pdata += 8;
4075 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4076 SIVAL(pdata,4,0);
4077 pdata += 8;
4079 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4080 pdata += 8;
4082 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4083 SIVAL(pdata,4,0);
4084 pdata += 8;
4086 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4087 SIVAL(pdata,4,0);
4088 pdata += 8;
4090 return pdata;
4093 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4094 * the chflags(2) (or equivalent) flags.
4096 * XXX: this really should be behind the VFS interface. To do this, we would
4097 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4098 * Each VFS module could then implement its own mapping as appropriate for the
4099 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4101 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4102 info2_flags_map[] =
4104 #ifdef UF_NODUMP
4105 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4106 #endif
4108 #ifdef UF_IMMUTABLE
4109 { UF_IMMUTABLE, EXT_IMMUTABLE },
4110 #endif
4112 #ifdef UF_APPEND
4113 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4114 #endif
4116 #ifdef UF_HIDDEN
4117 { UF_HIDDEN, EXT_HIDDEN },
4118 #endif
4120 /* Do not remove. We need to guarantee that this array has at least one
4121 * entry to build on HP-UX.
4123 { 0, 0 }
4127 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4128 uint32 *smb_fflags, uint32 *smb_fmask)
4130 int i;
4132 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4133 *smb_fmask |= info2_flags_map[i].smb_fflag;
4134 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4135 *smb_fflags |= info2_flags_map[i].smb_fflag;
4140 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4141 const uint32 smb_fflags,
4142 const uint32 smb_fmask,
4143 int *stat_fflags)
4145 uint32 max_fmask = 0;
4146 int i;
4148 *stat_fflags = psbuf->st_ex_flags;
4150 /* For each flags requested in smb_fmask, check the state of the
4151 * corresponding flag in smb_fflags and set or clear the matching
4152 * stat flag.
4155 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4156 max_fmask |= info2_flags_map[i].smb_fflag;
4157 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4158 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4159 *stat_fflags |= info2_flags_map[i].stat_fflag;
4160 } else {
4161 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4166 /* If smb_fmask is asking to set any bits that are not supported by
4167 * our flag mappings, we should fail.
4169 if ((smb_fmask & max_fmask) != smb_fmask) {
4170 return False;
4173 return True;
4177 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4178 * of file flags and birth (create) time.
4180 static char *store_file_unix_basic_info2(connection_struct *conn,
4181 char *pdata,
4182 files_struct *fsp,
4183 const SMB_STRUCT_STAT *psbuf)
4185 uint32 file_flags = 0;
4186 uint32 flags_mask = 0;
4188 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4190 /* Create (birth) time 64 bit */
4191 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4192 pdata += 8;
4194 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4195 SIVAL(pdata, 0, file_flags); /* flags */
4196 SIVAL(pdata, 4, flags_mask); /* mask */
4197 pdata += 8;
4199 return pdata;
4202 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4203 const struct stream_struct *streams,
4204 char *data,
4205 unsigned int max_data_bytes,
4206 unsigned int *data_size)
4208 unsigned int i;
4209 unsigned int ofs = 0;
4211 for (i = 0; i < num_streams; i++) {
4212 unsigned int next_offset;
4213 size_t namelen;
4214 smb_ucs2_t *namebuf;
4216 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4217 streams[i].name, &namelen) ||
4218 namelen <= 2)
4220 return NT_STATUS_INVALID_PARAMETER;
4224 * name_buf is now null-terminated, we need to marshall as not
4225 * terminated
4228 namelen -= 2;
4231 * We cannot overflow ...
4233 if ((ofs + 24 + namelen) > max_data_bytes) {
4234 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4235 i));
4236 TALLOC_FREE(namebuf);
4237 return STATUS_BUFFER_OVERFLOW;
4240 SIVAL(data, ofs+4, namelen);
4241 SOFF_T(data, ofs+8, streams[i].size);
4242 SOFF_T(data, ofs+16, streams[i].alloc_size);
4243 memcpy(data+ofs+24, namebuf, namelen);
4244 TALLOC_FREE(namebuf);
4246 next_offset = ofs + 24 + namelen;
4248 if (i == num_streams-1) {
4249 SIVAL(data, ofs, 0);
4251 else {
4252 unsigned int align = ndr_align_size(next_offset, 8);
4254 if ((next_offset + align) > max_data_bytes) {
4255 DEBUG(10, ("refusing to overflow align "
4256 "reply at stream %u\n",
4257 i));
4258 TALLOC_FREE(namebuf);
4259 return STATUS_BUFFER_OVERFLOW;
4262 memset(data+next_offset, 0, align);
4263 next_offset += align;
4265 SIVAL(data, ofs, next_offset - ofs);
4266 ofs = next_offset;
4269 ofs = next_offset;
4272 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4274 *data_size = ofs;
4276 return NT_STATUS_OK;
4279 /****************************************************************************
4280 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4281 ****************************************************************************/
4283 static void call_trans2qpipeinfo(connection_struct *conn,
4284 struct smb_request *req,
4285 unsigned int tran_call,
4286 char **pparams, int total_params,
4287 char **ppdata, int total_data,
4288 unsigned int max_data_bytes)
4290 char *params = *pparams;
4291 char *pdata = *ppdata;
4292 unsigned int data_size = 0;
4293 unsigned int param_size = 2;
4294 uint16 info_level;
4295 files_struct *fsp;
4297 if (!params) {
4298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4299 return;
4302 if (total_params < 4) {
4303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4304 return;
4307 fsp = file_fsp(req, SVAL(params,0));
4308 if (!fsp_is_np(fsp)) {
4309 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4310 return;
4313 info_level = SVAL(params,2);
4315 *pparams = (char *)SMB_REALLOC(*pparams,2);
4316 if (*pparams == NULL) {
4317 reply_nterror(req, NT_STATUS_NO_MEMORY);
4318 return;
4320 params = *pparams;
4321 SSVAL(params,0,0);
4322 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4323 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4324 if (*ppdata == NULL ) {
4325 reply_nterror(req, NT_STATUS_NO_MEMORY);
4326 return;
4328 pdata = *ppdata;
4330 switch (info_level) {
4331 case SMB_FILE_STANDARD_INFORMATION:
4332 memset(pdata,0,24);
4333 SOFF_T(pdata,0,4096LL);
4334 SIVAL(pdata,16,1);
4335 SIVAL(pdata,20,1);
4336 data_size = 24;
4337 break;
4339 default:
4340 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4341 return;
4344 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4345 max_data_bytes);
4347 return;
4350 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4351 TALLOC_CTX *mem_ctx,
4352 uint16_t info_level,
4353 files_struct *fsp,
4354 struct smb_filename *smb_fname,
4355 bool delete_pending,
4356 struct timespec write_time_ts,
4357 struct ea_list *ea_list,
4358 int lock_data_count,
4359 char *lock_data,
4360 uint16_t flags2,
4361 unsigned int max_data_bytes,
4362 char **ppdata,
4363 unsigned int *pdata_size)
4365 char *pdata = *ppdata;
4366 char *dstart, *dend;
4367 unsigned int data_size;
4368 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4369 time_t create_time, mtime, atime, c_time;
4370 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4371 char *p;
4372 char *base_name;
4373 char *dos_fname;
4374 int mode;
4375 int nlink;
4376 NTSTATUS status;
4377 uint64_t file_size = 0;
4378 uint64_t pos = 0;
4379 uint64_t allocation_size = 0;
4380 uint64_t file_index = 0;
4381 uint32_t access_mask = 0;
4383 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4384 return NT_STATUS_INVALID_LEVEL;
4387 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4388 smb_fname_str_dbg(smb_fname),
4389 fsp_fnum_dbg(fsp),
4390 info_level, max_data_bytes));
4392 mode = dos_mode(conn, smb_fname);
4393 nlink = psbuf->st_ex_nlink;
4395 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4396 nlink = 1;
4399 if ((nlink > 0) && delete_pending) {
4400 nlink -= 1;
4403 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4404 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4405 if (*ppdata == NULL) {
4406 return NT_STATUS_NO_MEMORY;
4408 pdata = *ppdata;
4409 dstart = pdata;
4410 dend = dstart + data_size - 1;
4412 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4413 update_stat_ex_mtime(psbuf, write_time_ts);
4416 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4417 mtime_ts = psbuf->st_ex_mtime;
4418 atime_ts = psbuf->st_ex_atime;
4419 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4421 if (lp_dos_filetime_resolution(SNUM(conn))) {
4422 dos_filetime_timespec(&create_time_ts);
4423 dos_filetime_timespec(&mtime_ts);
4424 dos_filetime_timespec(&atime_ts);
4425 dos_filetime_timespec(&ctime_ts);
4428 create_time = convert_timespec_to_time_t(create_time_ts);
4429 mtime = convert_timespec_to_time_t(mtime_ts);
4430 atime = convert_timespec_to_time_t(atime_ts);
4431 c_time = convert_timespec_to_time_t(ctime_ts);
4433 p = strrchr_m(smb_fname->base_name,'/');
4434 if (!p)
4435 base_name = smb_fname->base_name;
4436 else
4437 base_name = p+1;
4439 /* NT expects the name to be in an exact form of the *full*
4440 filename. See the trans2 torture test */
4441 if (ISDOT(base_name)) {
4442 dos_fname = talloc_strdup(mem_ctx, "\\");
4443 if (!dos_fname) {
4444 return NT_STATUS_NO_MEMORY;
4446 } else {
4447 dos_fname = talloc_asprintf(mem_ctx,
4448 "\\%s",
4449 smb_fname->base_name);
4450 if (!dos_fname) {
4451 return NT_STATUS_NO_MEMORY;
4453 if (is_ntfs_stream_smb_fname(smb_fname)) {
4454 dos_fname = talloc_asprintf(dos_fname, "%s",
4455 smb_fname->stream_name);
4456 if (!dos_fname) {
4457 return NT_STATUS_NO_MEMORY;
4461 string_replace(dos_fname, '/', '\\');
4464 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4466 if (!fsp) {
4467 /* Do we have this path open ? */
4468 files_struct *fsp1;
4469 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4470 fsp1 = file_find_di_first(conn->sconn, fileid);
4471 if (fsp1 && fsp1->initial_allocation_size) {
4472 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4476 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4477 file_size = get_file_size_stat(psbuf);
4480 if (fsp) {
4481 pos = fsp->fh->position_information;
4484 if (fsp) {
4485 access_mask = fsp->access_mask;
4486 } else {
4487 /* GENERIC_EXECUTE mapping from Windows */
4488 access_mask = 0x12019F;
4491 /* This should be an index number - looks like
4492 dev/ino to me :-)
4494 I think this causes us to fail the IFSKIT
4495 BasicFileInformationTest. -tpot */
4496 file_index = get_FileIndex(conn, psbuf);
4498 switch (info_level) {
4499 case SMB_INFO_STANDARD:
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4501 data_size = 22;
4502 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4503 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4504 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4505 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4506 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4507 SSVAL(pdata,l1_attrFile,mode);
4508 break;
4510 case SMB_INFO_QUERY_EA_SIZE:
4512 unsigned int ea_size =
4513 estimate_ea_size(conn, fsp,
4514 smb_fname);
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4516 data_size = 26;
4517 srv_put_dos_date2(pdata,0,create_time);
4518 srv_put_dos_date2(pdata,4,atime);
4519 srv_put_dos_date2(pdata,8,mtime); /* write time */
4520 SIVAL(pdata,12,(uint32)file_size);
4521 SIVAL(pdata,16,(uint32)allocation_size);
4522 SSVAL(pdata,20,mode);
4523 SIVAL(pdata,22,ea_size);
4524 break;
4527 case SMB_INFO_IS_NAME_VALID:
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4529 if (fsp) {
4530 /* os/2 needs this ? really ?*/
4531 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4533 /* This is only reached for qpathinfo */
4534 data_size = 0;
4535 break;
4537 case SMB_INFO_QUERY_EAS_FROM_LIST:
4539 size_t total_ea_len = 0;
4540 struct ea_list *ea_file_list = NULL;
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4543 status =
4544 get_ea_list_from_file(mem_ctx, conn, fsp,
4545 smb_fname,
4546 &total_ea_len, &ea_file_list);
4547 if (!NT_STATUS_IS_OK(status)) {
4548 return status;
4551 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4553 if (!ea_list || (total_ea_len > data_size)) {
4554 data_size = 4;
4555 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4556 break;
4559 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4560 break;
4563 case SMB_INFO_QUERY_ALL_EAS:
4565 /* We have data_size bytes to put EA's into. */
4566 size_t total_ea_len = 0;
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4569 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4570 smb_fname,
4571 &total_ea_len, &ea_list);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 return status;
4576 if (!ea_list || (total_ea_len > data_size)) {
4577 data_size = 4;
4578 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4579 break;
4582 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4583 break;
4586 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4588 /* This is FileFullEaInformation - 0xF which maps to
4589 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4591 /* We have data_size bytes to put EA's into. */
4592 size_t total_ea_len = 0;
4593 struct ea_list *ea_file_list = NULL;
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4597 /*TODO: add filtering and index handling */
4599 status =
4600 get_ea_list_from_file(mem_ctx, conn, fsp,
4601 smb_fname,
4602 &total_ea_len, &ea_file_list);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 return status;
4606 if (!ea_file_list) {
4607 return NT_STATUS_NO_EAS_ON_FILE;
4610 status = fill_ea_chained_buffer(mem_ctx,
4611 pdata,
4612 data_size,
4613 &data_size,
4614 conn, ea_file_list);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 return status;
4618 break;
4621 case SMB_FILE_BASIC_INFORMATION:
4622 case SMB_QUERY_FILE_BASIC_INFO:
4624 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4626 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4627 } else {
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4629 data_size = 40;
4630 SIVAL(pdata,36,0);
4632 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4633 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4634 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4635 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4636 SIVAL(pdata,32,mode);
4638 DEBUG(5,("SMB_QFBI - "));
4639 DEBUG(5,("create: %s ", ctime(&create_time)));
4640 DEBUG(5,("access: %s ", ctime(&atime)));
4641 DEBUG(5,("write: %s ", ctime(&mtime)));
4642 DEBUG(5,("change: %s ", ctime(&c_time)));
4643 DEBUG(5,("mode: %x\n", mode));
4644 break;
4646 case SMB_FILE_STANDARD_INFORMATION:
4647 case SMB_QUERY_FILE_STANDARD_INFO:
4649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4650 data_size = 24;
4651 SOFF_T(pdata,0,allocation_size);
4652 SOFF_T(pdata,8,file_size);
4653 SIVAL(pdata,16,nlink);
4654 SCVAL(pdata,20,delete_pending?1:0);
4655 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4656 SSVAL(pdata,22,0); /* Padding. */
4657 break;
4659 case SMB_FILE_EA_INFORMATION:
4660 case SMB_QUERY_FILE_EA_INFO:
4662 unsigned int ea_size =
4663 estimate_ea_size(conn, fsp, smb_fname);
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4665 data_size = 4;
4666 SIVAL(pdata,0,ea_size);
4667 break;
4670 /* Get the 8.3 name - used if NT SMB was negotiated. */
4671 case SMB_QUERY_FILE_ALT_NAME_INFO:
4672 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4674 int len;
4675 char mangled_name[13];
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4677 if (!name_to_8_3(base_name,mangled_name,
4678 True,conn->params)) {
4679 return NT_STATUS_NO_MEMORY;
4681 len = srvstr_push(dstart, flags2,
4682 pdata+4, mangled_name,
4683 PTR_DIFF(dend, pdata+4),
4684 STR_UNICODE);
4685 data_size = 4 + len;
4686 SIVAL(pdata,0,len);
4687 break;
4690 case SMB_QUERY_FILE_NAME_INFO:
4692 int len;
4694 this must be *exactly* right for ACLs on mapped drives to work
4696 len = srvstr_push(dstart, flags2,
4697 pdata+4, dos_fname,
4698 PTR_DIFF(dend, pdata+4),
4699 STR_UNICODE);
4700 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4701 data_size = 4 + len;
4702 SIVAL(pdata,0,len);
4703 break;
4706 case SMB_FILE_ALLOCATION_INFORMATION:
4707 case SMB_QUERY_FILE_ALLOCATION_INFO:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4709 data_size = 8;
4710 SOFF_T(pdata,0,allocation_size);
4711 break;
4713 case SMB_FILE_END_OF_FILE_INFORMATION:
4714 case SMB_QUERY_FILE_END_OF_FILEINFO:
4715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4716 data_size = 8;
4717 SOFF_T(pdata,0,file_size);
4718 break;
4720 case SMB_QUERY_FILE_ALL_INFO:
4721 case SMB_FILE_ALL_INFORMATION:
4723 int len;
4724 unsigned int ea_size =
4725 estimate_ea_size(conn, fsp, smb_fname);
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4727 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4728 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4729 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4730 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4731 SIVAL(pdata,32,mode);
4732 SIVAL(pdata,36,0); /* padding. */
4733 pdata += 40;
4734 SOFF_T(pdata,0,allocation_size);
4735 SOFF_T(pdata,8,file_size);
4736 SIVAL(pdata,16,nlink);
4737 SCVAL(pdata,20,delete_pending);
4738 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4739 SSVAL(pdata,22,0);
4740 pdata += 24;
4741 SIVAL(pdata,0,ea_size);
4742 pdata += 4; /* EA info */
4743 len = srvstr_push(dstart, flags2,
4744 pdata+4, dos_fname,
4745 PTR_DIFF(dend, pdata+4),
4746 STR_UNICODE);
4747 SIVAL(pdata,0,len);
4748 pdata += 4 + len;
4749 data_size = PTR_DIFF(pdata,(*ppdata));
4750 break;
4753 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4755 int len;
4756 unsigned int ea_size =
4757 estimate_ea_size(conn, fsp, smb_fname);
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4759 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4760 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4761 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4762 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4763 SIVAL(pdata, 0x20, mode);
4764 SIVAL(pdata, 0x24, 0); /* padding. */
4765 SBVAL(pdata, 0x28, allocation_size);
4766 SBVAL(pdata, 0x30, file_size);
4767 SIVAL(pdata, 0x38, nlink);
4768 SCVAL(pdata, 0x3C, delete_pending);
4769 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4770 SSVAL(pdata, 0x3E, 0); /* padding */
4771 SBVAL(pdata, 0x40, file_index);
4772 SIVAL(pdata, 0x48, ea_size);
4773 SIVAL(pdata, 0x4C, access_mask);
4774 SBVAL(pdata, 0x50, pos);
4775 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4776 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4778 pdata += 0x60;
4780 len = srvstr_push(dstart, flags2,
4781 pdata+4, dos_fname,
4782 PTR_DIFF(dend, pdata+4),
4783 STR_UNICODE);
4784 SIVAL(pdata,0,len);
4785 pdata += 4 + len;
4786 data_size = PTR_DIFF(pdata,(*ppdata));
4787 break;
4789 case SMB_FILE_INTERNAL_INFORMATION:
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4792 SBVAL(pdata, 0, file_index);
4793 data_size = 8;
4794 break;
4796 case SMB_FILE_ACCESS_INFORMATION:
4797 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4798 SIVAL(pdata, 0, access_mask);
4799 data_size = 4;
4800 break;
4802 case SMB_FILE_NAME_INFORMATION:
4803 /* Pathname with leading '\'. */
4805 size_t byte_len;
4806 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4807 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4808 SIVAL(pdata,0,byte_len);
4809 data_size = 4 + byte_len;
4810 break;
4813 case SMB_FILE_DISPOSITION_INFORMATION:
4814 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4815 data_size = 1;
4816 SCVAL(pdata,0,delete_pending);
4817 break;
4819 case SMB_FILE_POSITION_INFORMATION:
4820 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4821 data_size = 8;
4822 SOFF_T(pdata,0,pos);
4823 break;
4825 case SMB_FILE_MODE_INFORMATION:
4826 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4827 SIVAL(pdata,0,mode);
4828 data_size = 4;
4829 break;
4831 case SMB_FILE_ALIGNMENT_INFORMATION:
4832 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4833 SIVAL(pdata,0,0); /* No alignment needed. */
4834 data_size = 4;
4835 break;
4838 * NT4 server just returns "invalid query" to this - if we try
4839 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4840 * want this. JRA.
4842 /* The first statement above is false - verified using Thursby
4843 * client against NT4 -- gcolley.
4845 case SMB_QUERY_FILE_STREAM_INFO:
4846 case SMB_FILE_STREAM_INFORMATION: {
4847 unsigned int num_streams = 0;
4848 struct stream_struct *streams = NULL;
4850 DEBUG(10,("smbd_do_qfilepathinfo: "
4851 "SMB_FILE_STREAM_INFORMATION\n"));
4853 if (is_ntfs_stream_smb_fname(smb_fname)) {
4854 return NT_STATUS_INVALID_PARAMETER;
4857 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4858 talloc_tos(), &num_streams, &streams);
4860 if (!NT_STATUS_IS_OK(status)) {
4861 DEBUG(10, ("could not get stream info: %s\n",
4862 nt_errstr(status)));
4863 return status;
4866 status = marshall_stream_info(num_streams, streams,
4867 pdata, max_data_bytes,
4868 &data_size);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 DEBUG(10, ("marshall_stream_info failed: %s\n",
4872 nt_errstr(status)));
4873 TALLOC_FREE(streams);
4874 return status;
4877 TALLOC_FREE(streams);
4879 break;
4881 case SMB_QUERY_COMPRESSION_INFO:
4882 case SMB_FILE_COMPRESSION_INFORMATION:
4883 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4884 SOFF_T(pdata,0,file_size);
4885 SIVAL(pdata,8,0); /* ??? */
4886 SIVAL(pdata,12,0); /* ??? */
4887 data_size = 16;
4888 break;
4890 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4892 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4893 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4894 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4895 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4896 SOFF_T(pdata,32,allocation_size);
4897 SOFF_T(pdata,40,file_size);
4898 SIVAL(pdata,48,mode);
4899 SIVAL(pdata,52,0); /* ??? */
4900 data_size = 56;
4901 break;
4903 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4904 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4905 SIVAL(pdata,0,mode);
4906 SIVAL(pdata,4,0);
4907 data_size = 8;
4908 break;
4911 * CIFS UNIX Extensions.
4914 case SMB_QUERY_FILE_UNIX_BASIC:
4916 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4917 data_size = PTR_DIFF(pdata,(*ppdata));
4919 DEBUG(4,("smbd_do_qfilepathinfo: "
4920 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4921 dump_data(4, (uint8_t *)(*ppdata), data_size);
4923 break;
4925 case SMB_QUERY_FILE_UNIX_INFO2:
4927 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4928 data_size = PTR_DIFF(pdata,(*ppdata));
4931 int i;
4932 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4934 for (i=0; i<100; i++)
4935 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4936 DEBUG(4,("\n"));
4939 break;
4941 case SMB_QUERY_FILE_UNIX_LINK:
4943 int len;
4944 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4946 if (!buffer) {
4947 return NT_STATUS_NO_MEMORY;
4950 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4951 #ifdef S_ISLNK
4952 if(!S_ISLNK(psbuf->st_ex_mode)) {
4953 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4955 #else
4956 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4957 #endif
4958 len = SMB_VFS_READLINK(conn,
4959 smb_fname->base_name,
4960 buffer, PATH_MAX);
4961 if (len == -1) {
4962 return map_nt_error_from_unix(errno);
4964 buffer[len] = 0;
4965 len = srvstr_push(dstart, flags2,
4966 pdata, buffer,
4967 PTR_DIFF(dend, pdata),
4968 STR_TERMINATE);
4969 pdata += len;
4970 data_size = PTR_DIFF(pdata,(*ppdata));
4972 break;
4975 #if defined(HAVE_POSIX_ACLS)
4976 case SMB_QUERY_POSIX_ACL:
4978 SMB_ACL_T file_acl = NULL;
4979 SMB_ACL_T def_acl = NULL;
4980 uint16 num_file_acls = 0;
4981 uint16 num_def_acls = 0;
4983 if (fsp && fsp->fh->fd != -1) {
4984 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4985 talloc_tos());
4986 } else {
4987 file_acl =
4988 SMB_VFS_SYS_ACL_GET_FILE(conn,
4989 smb_fname->base_name,
4990 SMB_ACL_TYPE_ACCESS,
4991 talloc_tos());
4994 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4995 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4996 "not implemented on "
4997 "filesystem containing %s\n",
4998 smb_fname->base_name));
4999 return NT_STATUS_NOT_IMPLEMENTED;
5002 if (S_ISDIR(psbuf->st_ex_mode)) {
5003 if (fsp && fsp->is_directory) {
5004 def_acl =
5005 SMB_VFS_SYS_ACL_GET_FILE(
5006 conn,
5007 fsp->fsp_name->base_name,
5008 SMB_ACL_TYPE_DEFAULT,
5009 talloc_tos());
5010 } else {
5011 def_acl =
5012 SMB_VFS_SYS_ACL_GET_FILE(
5013 conn,
5014 smb_fname->base_name,
5015 SMB_ACL_TYPE_DEFAULT,
5016 talloc_tos());
5018 def_acl = free_empty_sys_acl(conn, def_acl);
5021 num_file_acls = count_acl_entries(conn, file_acl);
5022 num_def_acls = count_acl_entries(conn, def_acl);
5024 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5025 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5026 data_size,
5027 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5028 SMB_POSIX_ACL_HEADER_SIZE) ));
5029 if (file_acl) {
5030 TALLOC_FREE(file_acl);
5032 if (def_acl) {
5033 TALLOC_FREE(def_acl);
5035 return NT_STATUS_BUFFER_TOO_SMALL;
5038 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5039 SSVAL(pdata,2,num_file_acls);
5040 SSVAL(pdata,4,num_def_acls);
5041 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5042 if (file_acl) {
5043 TALLOC_FREE(file_acl);
5045 if (def_acl) {
5046 TALLOC_FREE(def_acl);
5048 return NT_STATUS_INTERNAL_ERROR;
5050 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5051 if (file_acl) {
5052 TALLOC_FREE(file_acl);
5054 if (def_acl) {
5055 TALLOC_FREE(def_acl);
5057 return NT_STATUS_INTERNAL_ERROR;
5060 if (file_acl) {
5061 TALLOC_FREE(file_acl);
5063 if (def_acl) {
5064 TALLOC_FREE(def_acl);
5066 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5067 break;
5069 #endif
5072 case SMB_QUERY_POSIX_LOCK:
5074 uint64_t count;
5075 uint64_t offset;
5076 uint64_t smblctx;
5077 enum brl_type lock_type;
5079 /* We need an open file with a real fd for this. */
5080 if (!fsp || fsp->fh->fd == -1) {
5081 return NT_STATUS_INVALID_LEVEL;
5084 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5085 return NT_STATUS_INVALID_PARAMETER;
5088 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5089 case POSIX_LOCK_TYPE_READ:
5090 lock_type = READ_LOCK;
5091 break;
5092 case POSIX_LOCK_TYPE_WRITE:
5093 lock_type = WRITE_LOCK;
5094 break;
5095 case POSIX_LOCK_TYPE_UNLOCK:
5096 default:
5097 /* There's no point in asking for an unlock... */
5098 return NT_STATUS_INVALID_PARAMETER;
5101 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5102 #if defined(HAVE_LONGLONG)
5103 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5104 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5105 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5106 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5107 #else /* HAVE_LONGLONG */
5108 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5109 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5110 #endif /* HAVE_LONGLONG */
5112 status = query_lock(fsp,
5113 &smblctx,
5114 &count,
5115 &offset,
5116 &lock_type,
5117 POSIX_LOCK);
5119 if (ERROR_WAS_LOCK_DENIED(status)) {
5120 /* Here we need to report who has it locked... */
5121 data_size = POSIX_LOCK_DATA_SIZE;
5123 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5124 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5125 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5126 #if defined(HAVE_LONGLONG)
5127 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5128 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5129 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5130 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5131 #else /* HAVE_LONGLONG */
5132 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5133 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5134 #endif /* HAVE_LONGLONG */
5136 } else if (NT_STATUS_IS_OK(status)) {
5137 /* For success we just return a copy of what we sent
5138 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5139 data_size = POSIX_LOCK_DATA_SIZE;
5140 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5141 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5142 } else {
5143 return status;
5145 break;
5148 default:
5149 return NT_STATUS_INVALID_LEVEL;
5152 *pdata_size = data_size;
5153 return NT_STATUS_OK;
5156 /****************************************************************************
5157 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5158 file name or file id).
5159 ****************************************************************************/
5161 static void call_trans2qfilepathinfo(connection_struct *conn,
5162 struct smb_request *req,
5163 unsigned int tran_call,
5164 char **pparams, int total_params,
5165 char **ppdata, int total_data,
5166 unsigned int max_data_bytes)
5168 char *params = *pparams;
5169 char *pdata = *ppdata;
5170 uint16 info_level;
5171 unsigned int data_size = 0;
5172 unsigned int param_size = 2;
5173 struct smb_filename *smb_fname = NULL;
5174 bool delete_pending = False;
5175 struct timespec write_time_ts;
5176 files_struct *fsp = NULL;
5177 struct file_id fileid;
5178 struct ea_list *ea_list = NULL;
5179 int lock_data_count = 0;
5180 char *lock_data = NULL;
5181 NTSTATUS status = NT_STATUS_OK;
5183 if (!params) {
5184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5185 return;
5188 ZERO_STRUCT(write_time_ts);
5190 if (tran_call == TRANSACT2_QFILEINFO) {
5191 if (total_params < 4) {
5192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5193 return;
5196 if (IS_IPC(conn)) {
5197 call_trans2qpipeinfo(conn, req, tran_call,
5198 pparams, total_params,
5199 ppdata, total_data,
5200 max_data_bytes);
5201 return;
5204 fsp = file_fsp(req, SVAL(params,0));
5205 info_level = SVAL(params,2);
5207 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5209 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5210 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5211 return;
5214 /* Initial check for valid fsp ptr. */
5215 if (!check_fsp_open(conn, req, fsp)) {
5216 return;
5219 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5220 if (smb_fname == NULL) {
5221 reply_nterror(req, NT_STATUS_NO_MEMORY);
5222 return;
5225 if(fsp->fake_file_handle) {
5227 * This is actually for the QUOTA_FAKE_FILE --metze
5230 /* We know this name is ok, it's already passed the checks. */
5232 } else if(fsp->fh->fd == -1) {
5234 * This is actually a QFILEINFO on a directory
5235 * handle (returned from an NT SMB). NT5.0 seems
5236 * to do this call. JRA.
5239 if (INFO_LEVEL_IS_UNIX(info_level)) {
5240 /* Always do lstat for UNIX calls. */
5241 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5242 DEBUG(3,("call_trans2qfilepathinfo: "
5243 "SMB_VFS_LSTAT of %s failed "
5244 "(%s)\n",
5245 smb_fname_str_dbg(smb_fname),
5246 strerror(errno)));
5247 reply_nterror(req,
5248 map_nt_error_from_unix(errno));
5249 return;
5251 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5252 DEBUG(3,("call_trans2qfilepathinfo: "
5253 "SMB_VFS_STAT of %s failed (%s)\n",
5254 smb_fname_str_dbg(smb_fname),
5255 strerror(errno)));
5256 reply_nterror(req,
5257 map_nt_error_from_unix(errno));
5258 return;
5261 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5262 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5263 } else {
5265 * Original code - this is an open file.
5267 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5268 DEBUG(3, ("fstat of %s failed (%s)\n",
5269 fsp_fnum_dbg(fsp), strerror(errno)));
5270 reply_nterror(req,
5271 map_nt_error_from_unix(errno));
5272 return;
5274 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5275 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5278 } else {
5279 uint32_t name_hash;
5280 char *fname = NULL;
5281 uint32_t ucf_flags = 0;
5283 /* qpathinfo */
5284 if (total_params < 7) {
5285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5286 return;
5289 info_level = SVAL(params,0);
5291 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5293 if (INFO_LEVEL_IS_UNIX(info_level)) {
5294 if (!lp_unix_extensions()) {
5295 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5296 return;
5298 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5299 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5300 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5301 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5305 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5306 total_params - 6,
5307 STR_TERMINATE, &status);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 reply_nterror(req, status);
5310 return;
5313 status = filename_convert(req,
5314 conn,
5315 req->flags2 & FLAGS2_DFS_PATHNAMES,
5316 fname,
5317 ucf_flags,
5318 NULL,
5319 &smb_fname);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5322 reply_botherror(req,
5323 NT_STATUS_PATH_NOT_COVERED,
5324 ERRSRV, ERRbadpath);
5325 return;
5327 reply_nterror(req, status);
5328 return;
5331 /* If this is a stream, check if there is a delete_pending. */
5332 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5333 && is_ntfs_stream_smb_fname(smb_fname)) {
5334 struct smb_filename *smb_fname_base = NULL;
5336 /* Create an smb_filename with stream_name == NULL. */
5337 status =
5338 create_synthetic_smb_fname(talloc_tos(),
5339 smb_fname->base_name,
5340 NULL, NULL,
5341 &smb_fname_base);
5342 if (!NT_STATUS_IS_OK(status)) {
5343 reply_nterror(req, status);
5344 return;
5347 if (INFO_LEVEL_IS_UNIX(info_level)) {
5348 /* Always do lstat for UNIX calls. */
5349 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5350 DEBUG(3,("call_trans2qfilepathinfo: "
5351 "SMB_VFS_LSTAT of %s failed "
5352 "(%s)\n",
5353 smb_fname_str_dbg(smb_fname_base),
5354 strerror(errno)));
5355 TALLOC_FREE(smb_fname_base);
5356 reply_nterror(req,
5357 map_nt_error_from_unix(errno));
5358 return;
5360 } else {
5361 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5362 DEBUG(3,("call_trans2qfilepathinfo: "
5363 "fileinfo of %s failed "
5364 "(%s)\n",
5365 smb_fname_str_dbg(smb_fname_base),
5366 strerror(errno)));
5367 TALLOC_FREE(smb_fname_base);
5368 reply_nterror(req,
5369 map_nt_error_from_unix(errno));
5370 return;
5374 status = file_name_hash(conn,
5375 smb_fname_str_dbg(smb_fname_base),
5376 &name_hash);
5377 if (!NT_STATUS_IS_OK(status)) {
5378 TALLOC_FREE(smb_fname_base);
5379 reply_nterror(req, status);
5380 return;
5383 fileid = vfs_file_id_from_sbuf(conn,
5384 &smb_fname_base->st);
5385 TALLOC_FREE(smb_fname_base);
5386 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5387 if (delete_pending) {
5388 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5389 return;
5393 if (INFO_LEVEL_IS_UNIX(info_level)) {
5394 /* Always do lstat for UNIX calls. */
5395 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5396 DEBUG(3,("call_trans2qfilepathinfo: "
5397 "SMB_VFS_LSTAT of %s failed (%s)\n",
5398 smb_fname_str_dbg(smb_fname),
5399 strerror(errno)));
5400 reply_nterror(req,
5401 map_nt_error_from_unix(errno));
5402 return;
5405 } else {
5406 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5407 DEBUG(3,("call_trans2qfilepathinfo: "
5408 "SMB_VFS_STAT of %s failed (%s)\n",
5409 smb_fname_str_dbg(smb_fname),
5410 strerror(errno)));
5411 reply_nterror(req,
5412 map_nt_error_from_unix(errno));
5413 return;
5417 status = file_name_hash(conn,
5418 smb_fname_str_dbg(smb_fname),
5419 &name_hash);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 reply_nterror(req, status);
5422 return;
5425 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5426 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5427 if (delete_pending) {
5428 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5429 return;
5433 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5434 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5435 fsp_fnum_dbg(fsp),
5436 info_level,tran_call,total_data));
5438 /* Pull out any data sent here before we realloc. */
5439 switch (info_level) {
5440 case SMB_INFO_QUERY_EAS_FROM_LIST:
5442 /* Pull any EA list from the data portion. */
5443 uint32 ea_size;
5445 if (total_data < 4) {
5446 reply_nterror(
5447 req, NT_STATUS_INVALID_PARAMETER);
5448 return;
5450 ea_size = IVAL(pdata,0);
5452 if (total_data > 0 && ea_size != total_data) {
5453 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5454 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5455 reply_nterror(
5456 req, NT_STATUS_INVALID_PARAMETER);
5457 return;
5460 if (!lp_ea_support(SNUM(conn))) {
5461 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5462 return;
5465 /* Pull out the list of names. */
5466 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5467 if (!ea_list) {
5468 reply_nterror(
5469 req, NT_STATUS_INVALID_PARAMETER);
5470 return;
5472 break;
5475 case SMB_QUERY_POSIX_LOCK:
5477 if (fsp == NULL || fsp->fh->fd == -1) {
5478 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5479 return;
5482 if (total_data != POSIX_LOCK_DATA_SIZE) {
5483 reply_nterror(
5484 req, NT_STATUS_INVALID_PARAMETER);
5485 return;
5488 /* Copy the lock range data. */
5489 lock_data = (char *)talloc_memdup(
5490 req, pdata, total_data);
5491 if (!lock_data) {
5492 reply_nterror(req, NT_STATUS_NO_MEMORY);
5493 return;
5495 lock_data_count = total_data;
5497 default:
5498 break;
5501 *pparams = (char *)SMB_REALLOC(*pparams,2);
5502 if (*pparams == NULL) {
5503 reply_nterror(req, NT_STATUS_NO_MEMORY);
5504 return;
5506 params = *pparams;
5507 SSVAL(params,0,0);
5510 * draft-leach-cifs-v1-spec-02.txt
5511 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5512 * says:
5514 * The requested information is placed in the Data portion of the
5515 * transaction response. For the information levels greater than 0x100,
5516 * the transaction response has 1 parameter word which should be
5517 * ignored by the client.
5519 * However Windows only follows this rule for the IS_NAME_VALID call.
5521 switch (info_level) {
5522 case SMB_INFO_IS_NAME_VALID:
5523 param_size = 0;
5524 break;
5527 if ((info_level & 0xFF00) == 0xFF00) {
5529 * We use levels that start with 0xFF00
5530 * internally to represent SMB2 specific levels
5532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5533 return;
5536 status = smbd_do_qfilepathinfo(conn, req, info_level,
5537 fsp, smb_fname,
5538 delete_pending, write_time_ts,
5539 ea_list,
5540 lock_data_count, lock_data,
5541 req->flags2, max_data_bytes,
5542 ppdata, &data_size);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 reply_nterror(req, status);
5545 return;
5548 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5549 max_data_bytes);
5551 return;
5554 /****************************************************************************
5555 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5556 code.
5557 ****************************************************************************/
5559 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5560 connection_struct *conn,
5561 struct smb_request *req,
5562 bool overwrite_if_exists,
5563 const struct smb_filename *smb_fname_old,
5564 struct smb_filename *smb_fname_new)
5566 NTSTATUS status = NT_STATUS_OK;
5568 /* source must already exist. */
5569 if (!VALID_STAT(smb_fname_old->st)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5573 if (VALID_STAT(smb_fname_new->st)) {
5574 if (overwrite_if_exists) {
5575 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5576 return NT_STATUS_FILE_IS_A_DIRECTORY;
5578 status = unlink_internals(conn,
5579 req,
5580 FILE_ATTRIBUTE_NORMAL,
5581 smb_fname_new,
5582 false);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 return status;
5586 } else {
5587 /* Disallow if newname already exists. */
5588 return NT_STATUS_OBJECT_NAME_COLLISION;
5592 /* No links from a directory. */
5593 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5594 return NT_STATUS_FILE_IS_A_DIRECTORY;
5597 /* Setting a hardlink to/from a stream isn't currently supported. */
5598 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5599 is_ntfs_stream_smb_fname(smb_fname_new)) {
5600 return NT_STATUS_INVALID_PARAMETER;
5603 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5604 smb_fname_old->base_name, smb_fname_new->base_name));
5606 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5607 smb_fname_new->base_name) != 0) {
5608 status = map_nt_error_from_unix(errno);
5609 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5610 nt_errstr(status), smb_fname_old->base_name,
5611 smb_fname_new->base_name));
5613 return status;
5616 /****************************************************************************
5617 Deal with setting the time from any of the setfilepathinfo functions.
5618 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5619 calling this function.
5620 ****************************************************************************/
5622 NTSTATUS smb_set_file_time(connection_struct *conn,
5623 files_struct *fsp,
5624 const struct smb_filename *smb_fname,
5625 struct smb_file_time *ft,
5626 bool setting_write_time)
5628 struct smb_filename smb_fname_base;
5629 uint32 action =
5630 FILE_NOTIFY_CHANGE_LAST_ACCESS
5631 |FILE_NOTIFY_CHANGE_LAST_WRITE
5632 |FILE_NOTIFY_CHANGE_CREATION;
5634 if (!VALID_STAT(smb_fname->st)) {
5635 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5638 /* get some defaults (no modifications) if any info is zero or -1. */
5639 if (null_timespec(ft->create_time)) {
5640 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5643 if (null_timespec(ft->atime)) {
5644 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5647 if (null_timespec(ft->mtime)) {
5648 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5651 if (!setting_write_time) {
5652 /* ft->mtime comes from change time, not write time. */
5653 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5656 /* Ensure the resolution is the correct for
5657 * what we can store on this filesystem. */
5659 round_timespec(conn->ts_res, &ft->create_time);
5660 round_timespec(conn->ts_res, &ft->ctime);
5661 round_timespec(conn->ts_res, &ft->atime);
5662 round_timespec(conn->ts_res, &ft->mtime);
5664 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5665 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5666 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5667 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5668 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5669 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5670 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5671 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5673 if (setting_write_time) {
5675 * This was a Windows setfileinfo on an open file.
5676 * NT does this a lot. We also need to
5677 * set the time here, as it can be read by
5678 * FindFirst/FindNext and with the patch for bug #2045
5679 * in smbd/fileio.c it ensures that this timestamp is
5680 * kept sticky even after a write. We save the request
5681 * away and will set it on file close and after a write. JRA.
5684 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5685 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5687 if (fsp != NULL) {
5688 if (fsp->base_fsp) {
5689 set_sticky_write_time_fsp(fsp->base_fsp,
5690 ft->mtime);
5691 } else {
5692 set_sticky_write_time_fsp(fsp, ft->mtime);
5694 } else {
5695 set_sticky_write_time_path(
5696 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5697 ft->mtime);
5701 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5703 /* Always call ntimes on the base, even if a stream was passed in. */
5704 smb_fname_base = *smb_fname;
5705 smb_fname_base.stream_name = NULL;
5707 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5708 return map_nt_error_from_unix(errno);
5711 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5712 smb_fname->base_name);
5713 return NT_STATUS_OK;
5716 /****************************************************************************
5717 Deal with setting the dosmode from any of the setfilepathinfo functions.
5718 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5719 done before calling this function.
5720 ****************************************************************************/
5722 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5723 const struct smb_filename *smb_fname,
5724 uint32 dosmode)
5726 struct smb_filename *smb_fname_base = NULL;
5727 NTSTATUS status;
5729 if (!VALID_STAT(smb_fname->st)) {
5730 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5733 /* Always operate on the base_name, even if a stream was passed in. */
5734 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5735 NULL, &smb_fname->st,
5736 &smb_fname_base);
5737 if (!NT_STATUS_IS_OK(status)) {
5738 return status;
5741 if (dosmode) {
5742 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5743 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5744 } else {
5745 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5749 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5751 /* check the mode isn't different, before changing it */
5752 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5753 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5754 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5755 (unsigned int)dosmode));
5757 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5758 false)) {
5759 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5760 "%s failed (%s)\n",
5761 smb_fname_str_dbg(smb_fname_base),
5762 strerror(errno)));
5763 status = map_nt_error_from_unix(errno);
5764 goto out;
5767 status = NT_STATUS_OK;
5768 out:
5769 TALLOC_FREE(smb_fname_base);
5770 return status;
5773 /****************************************************************************
5774 Deal with setting the size from any of the setfilepathinfo functions.
5775 ****************************************************************************/
5777 static NTSTATUS smb_set_file_size(connection_struct *conn,
5778 struct smb_request *req,
5779 files_struct *fsp,
5780 const struct smb_filename *smb_fname,
5781 const SMB_STRUCT_STAT *psbuf,
5782 off_t size,
5783 bool fail_after_createfile)
5785 NTSTATUS status = NT_STATUS_OK;
5786 struct smb_filename *smb_fname_tmp = NULL;
5787 files_struct *new_fsp = NULL;
5789 if (!VALID_STAT(*psbuf)) {
5790 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5793 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5795 if (size == get_file_size_stat(psbuf)) {
5796 return NT_STATUS_OK;
5799 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5800 smb_fname_str_dbg(smb_fname), (double)size));
5802 if (fsp && fsp->fh->fd != -1) {
5803 /* Handle based call. */
5804 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5805 return NT_STATUS_ACCESS_DENIED;
5808 if (vfs_set_filelen(fsp, size) == -1) {
5809 return map_nt_error_from_unix(errno);
5811 trigger_write_time_update_immediate(fsp);
5812 return NT_STATUS_OK;
5815 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5816 if (smb_fname_tmp == NULL) {
5817 return NT_STATUS_NO_MEMORY;
5820 smb_fname_tmp->st = *psbuf;
5822 status = SMB_VFS_CREATE_FILE(
5823 conn, /* conn */
5824 req, /* req */
5825 0, /* root_dir_fid */
5826 smb_fname_tmp, /* fname */
5827 FILE_WRITE_DATA, /* access_mask */
5828 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5829 FILE_SHARE_DELETE),
5830 FILE_OPEN, /* create_disposition*/
5831 0, /* create_options */
5832 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5833 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5834 0, /* allocation_size */
5835 0, /* private_flags */
5836 NULL, /* sd */
5837 NULL, /* ea_list */
5838 &new_fsp, /* result */
5839 NULL); /* pinfo */
5841 TALLOC_FREE(smb_fname_tmp);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 /* NB. We check for open_was_deferred in the caller. */
5845 return status;
5848 /* See RAW-SFILEINFO-END-OF-FILE */
5849 if (fail_after_createfile) {
5850 close_file(req, new_fsp,NORMAL_CLOSE);
5851 return NT_STATUS_INVALID_LEVEL;
5854 if (vfs_set_filelen(new_fsp, size) == -1) {
5855 status = map_nt_error_from_unix(errno);
5856 close_file(req, new_fsp,NORMAL_CLOSE);
5857 return status;
5860 trigger_write_time_update_immediate(new_fsp);
5861 close_file(req, new_fsp,NORMAL_CLOSE);
5862 return NT_STATUS_OK;
5865 /****************************************************************************
5866 Deal with SMB_INFO_SET_EA.
5867 ****************************************************************************/
5869 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5870 const char *pdata,
5871 int total_data,
5872 files_struct *fsp,
5873 const struct smb_filename *smb_fname)
5875 struct ea_list *ea_list = NULL;
5876 TALLOC_CTX *ctx = NULL;
5877 NTSTATUS status = NT_STATUS_OK;
5879 if (total_data < 10) {
5881 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5882 length. They seem to have no effect. Bug #3212. JRA */
5884 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5885 /* We're done. We only get EA info in this call. */
5886 return NT_STATUS_OK;
5889 return NT_STATUS_INVALID_PARAMETER;
5892 if (IVAL(pdata,0) > total_data) {
5893 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5894 IVAL(pdata,0), (unsigned int)total_data));
5895 return NT_STATUS_INVALID_PARAMETER;
5898 ctx = talloc_tos();
5899 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5900 if (!ea_list) {
5901 return NT_STATUS_INVALID_PARAMETER;
5904 status = set_ea(conn, fsp, smb_fname, ea_list);
5906 return status;
5909 /****************************************************************************
5910 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5911 ****************************************************************************/
5913 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5914 const char *pdata,
5915 int total_data,
5916 files_struct *fsp)
5918 struct ea_list *ea_list = NULL;
5919 NTSTATUS status;
5921 if (!fsp) {
5922 return NT_STATUS_INVALID_HANDLE;
5925 if (!lp_ea_support(SNUM(conn))) {
5926 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5927 "EA's not supported.\n",
5928 (unsigned int)total_data));
5929 return NT_STATUS_EAS_NOT_SUPPORTED;
5932 if (total_data < 10) {
5933 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5934 "too small.\n",
5935 (unsigned int)total_data));
5936 return NT_STATUS_INVALID_PARAMETER;
5939 ea_list = read_nttrans_ea_list(talloc_tos(),
5940 pdata,
5941 total_data);
5943 if (!ea_list) {
5944 return NT_STATUS_INVALID_PARAMETER;
5947 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5949 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5950 smb_fname_str_dbg(fsp->fsp_name),
5951 nt_errstr(status) ));
5953 return status;
5957 /****************************************************************************
5958 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5959 ****************************************************************************/
5961 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5962 const char *pdata,
5963 int total_data,
5964 files_struct *fsp,
5965 struct smb_filename *smb_fname)
5967 NTSTATUS status = NT_STATUS_OK;
5968 bool delete_on_close;
5969 uint32 dosmode = 0;
5971 if (total_data < 1) {
5972 return NT_STATUS_INVALID_PARAMETER;
5975 if (fsp == NULL) {
5976 return NT_STATUS_INVALID_HANDLE;
5979 delete_on_close = (CVAL(pdata,0) ? True : False);
5980 dosmode = dos_mode(conn, smb_fname);
5982 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5983 "delete_on_close = %u\n",
5984 smb_fname_str_dbg(smb_fname),
5985 (unsigned int)dosmode,
5986 (unsigned int)delete_on_close ));
5988 if (delete_on_close) {
5989 status = can_set_delete_on_close(fsp, dosmode);
5990 if (!NT_STATUS_IS_OK(status)) {
5991 return status;
5995 /* The set is across all open files on this dev/inode pair. */
5996 if (!set_delete_on_close(fsp, delete_on_close,
5997 conn->session_info->security_token,
5998 conn->session_info->unix_token)) {
5999 return NT_STATUS_ACCESS_DENIED;
6001 return NT_STATUS_OK;
6004 /****************************************************************************
6005 Deal with SMB_FILE_POSITION_INFORMATION.
6006 ****************************************************************************/
6008 static NTSTATUS smb_file_position_information(connection_struct *conn,
6009 const char *pdata,
6010 int total_data,
6011 files_struct *fsp)
6013 uint64_t position_information;
6015 if (total_data < 8) {
6016 return NT_STATUS_INVALID_PARAMETER;
6019 if (fsp == NULL) {
6020 /* Ignore on pathname based set. */
6021 return NT_STATUS_OK;
6024 position_information = (uint64_t)IVAL(pdata,0);
6025 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6027 DEBUG(10,("smb_file_position_information: Set file position "
6028 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6029 (double)position_information));
6030 fsp->fh->position_information = position_information;
6031 return NT_STATUS_OK;
6034 /****************************************************************************
6035 Deal with SMB_FILE_MODE_INFORMATION.
6036 ****************************************************************************/
6038 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6039 const char *pdata,
6040 int total_data)
6042 uint32 mode;
6044 if (total_data < 4) {
6045 return NT_STATUS_INVALID_PARAMETER;
6047 mode = IVAL(pdata,0);
6048 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6049 return NT_STATUS_INVALID_PARAMETER;
6051 return NT_STATUS_OK;
6054 /****************************************************************************
6055 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6056 ****************************************************************************/
6058 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6059 struct smb_request *req,
6060 const char *pdata,
6061 int total_data,
6062 const struct smb_filename *smb_fname)
6064 char *link_target = NULL;
6065 const char *newname = smb_fname->base_name;
6066 TALLOC_CTX *ctx = talloc_tos();
6068 /* Set a symbolic link. */
6069 /* Don't allow this if follow links is false. */
6071 if (total_data == 0) {
6072 return NT_STATUS_INVALID_PARAMETER;
6075 if (!lp_symlinks(SNUM(conn))) {
6076 return NT_STATUS_ACCESS_DENIED;
6079 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6080 total_data, STR_TERMINATE);
6082 if (!link_target) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6087 newname, link_target ));
6089 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6090 return map_nt_error_from_unix(errno);
6093 return NT_STATUS_OK;
6096 /****************************************************************************
6097 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6098 ****************************************************************************/
6100 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6101 struct smb_request *req,
6102 const char *pdata, int total_data,
6103 struct smb_filename *smb_fname_new)
6105 char *oldname = NULL;
6106 struct smb_filename *smb_fname_old = NULL;
6107 TALLOC_CTX *ctx = talloc_tos();
6108 NTSTATUS status = NT_STATUS_OK;
6110 /* Set a hard link. */
6111 if (total_data == 0) {
6112 return NT_STATUS_INVALID_PARAMETER;
6115 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6116 total_data, STR_TERMINATE, &status);
6117 if (!NT_STATUS_IS_OK(status)) {
6118 return status;
6121 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6122 smb_fname_str_dbg(smb_fname_new), oldname));
6124 status = filename_convert(ctx,
6125 conn,
6126 req->flags2 & FLAGS2_DFS_PATHNAMES,
6127 oldname,
6129 NULL,
6130 &smb_fname_old);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 return status;
6135 return hardlink_internals(ctx, conn, req, false,
6136 smb_fname_old, smb_fname_new);
6139 /****************************************************************************
6140 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6141 ****************************************************************************/
6143 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6144 struct smb_request *req,
6145 const char *pdata,
6146 int total_data,
6147 files_struct *fsp,
6148 struct smb_filename *smb_fname_src)
6150 bool overwrite;
6151 uint32_t len;
6152 char *newname = NULL;
6153 struct smb_filename *smb_fname_dst = NULL;
6154 NTSTATUS status = NT_STATUS_OK;
6155 TALLOC_CTX *ctx = talloc_tos();
6157 if (!fsp) {
6158 return NT_STATUS_INVALID_HANDLE;
6161 if (total_data < 20) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 overwrite = (CVAL(pdata,0) ? True : False);
6166 len = IVAL(pdata,16);
6168 if (len > (total_data - 20) || (len == 0)) {
6169 return NT_STATUS_INVALID_PARAMETER;
6172 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6173 &pdata[20], len, STR_TERMINATE,
6174 &status);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 return status;
6179 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6180 newname));
6182 status = filename_convert(ctx,
6183 conn,
6184 req->flags2 & FLAGS2_DFS_PATHNAMES,
6185 newname,
6186 UCF_SAVE_LCOMP,
6187 NULL,
6188 &smb_fname_dst);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 return status;
6193 if (fsp->base_fsp) {
6194 /* newname must be a stream name. */
6195 if (newname[0] != ':') {
6196 return NT_STATUS_NOT_SUPPORTED;
6199 /* Create an smb_fname to call rename_internals_fsp() with. */
6200 status = create_synthetic_smb_fname(talloc_tos(),
6201 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6202 &smb_fname_dst);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 goto out;
6208 * Set the original last component, since
6209 * rename_internals_fsp() requires it.
6211 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6212 newname);
6213 if (smb_fname_dst->original_lcomp == NULL) {
6214 status = NT_STATUS_NO_MEMORY;
6215 goto out;
6220 DEBUG(10,("smb2_file_rename_information: "
6221 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6222 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6223 smb_fname_str_dbg(smb_fname_dst)));
6224 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6225 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6226 overwrite);
6228 out:
6229 TALLOC_FREE(smb_fname_dst);
6230 return status;
6233 static NTSTATUS smb_file_link_information(connection_struct *conn,
6234 struct smb_request *req,
6235 const char *pdata,
6236 int total_data,
6237 files_struct *fsp,
6238 struct smb_filename *smb_fname_src)
6240 bool overwrite;
6241 uint32_t len;
6242 char *newname = NULL;
6243 struct smb_filename *smb_fname_dst = NULL;
6244 NTSTATUS status = NT_STATUS_OK;
6245 TALLOC_CTX *ctx = talloc_tos();
6247 if (!fsp) {
6248 return NT_STATUS_INVALID_HANDLE;
6251 if (total_data < 20) {
6252 return NT_STATUS_INVALID_PARAMETER;
6255 overwrite = (CVAL(pdata,0) ? true : false);
6256 len = IVAL(pdata,16);
6258 if (len > (total_data - 20) || (len == 0)) {
6259 return NT_STATUS_INVALID_PARAMETER;
6262 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6263 &pdata[20], len, STR_TERMINATE,
6264 &status);
6265 if (!NT_STATUS_IS_OK(status)) {
6266 return status;
6269 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6270 newname));
6272 status = filename_convert(ctx,
6273 conn,
6274 req->flags2 & FLAGS2_DFS_PATHNAMES,
6275 newname,
6276 UCF_SAVE_LCOMP,
6277 NULL,
6278 &smb_fname_dst);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 return status;
6283 if (fsp->base_fsp) {
6284 /* No stream names. */
6285 return NT_STATUS_NOT_SUPPORTED;
6288 DEBUG(10,("smb_file_link_information: "
6289 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6290 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6291 smb_fname_str_dbg(smb_fname_dst)));
6292 status = hardlink_internals(ctx,
6293 conn,
6294 req,
6295 overwrite,
6296 fsp->fsp_name,
6297 smb_fname_dst);
6299 TALLOC_FREE(smb_fname_dst);
6300 return status;
6303 /****************************************************************************
6304 Deal with SMB_FILE_RENAME_INFORMATION.
6305 ****************************************************************************/
6307 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6308 struct smb_request *req,
6309 const char *pdata,
6310 int total_data,
6311 files_struct *fsp,
6312 struct smb_filename *smb_fname_src)
6314 bool overwrite;
6315 uint32 root_fid;
6316 uint32 len;
6317 char *newname = NULL;
6318 struct smb_filename *smb_fname_dst = NULL;
6319 bool dest_has_wcard = False;
6320 NTSTATUS status = NT_STATUS_OK;
6321 char *p;
6322 TALLOC_CTX *ctx = talloc_tos();
6324 if (total_data < 13) {
6325 return NT_STATUS_INVALID_PARAMETER;
6328 overwrite = (CVAL(pdata,0) ? True : False);
6329 root_fid = IVAL(pdata,4);
6330 len = IVAL(pdata,8);
6332 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6333 return NT_STATUS_INVALID_PARAMETER;
6336 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6337 len, 0, &status,
6338 &dest_has_wcard);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 return status;
6343 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6344 newname));
6346 status = resolve_dfspath_wcard(ctx, conn,
6347 req->flags2 & FLAGS2_DFS_PATHNAMES,
6348 newname,
6349 true,
6350 !conn->sconn->using_smb2,
6351 &newname,
6352 &dest_has_wcard);
6353 if (!NT_STATUS_IS_OK(status)) {
6354 return status;
6357 /* Check the new name has no '/' characters. */
6358 if (strchr_m(newname, '/')) {
6359 return NT_STATUS_NOT_SUPPORTED;
6362 if (fsp && fsp->base_fsp) {
6363 /* newname must be a stream name. */
6364 if (newname[0] != ':') {
6365 return NT_STATUS_NOT_SUPPORTED;
6368 /* Create an smb_fname to call rename_internals_fsp() with. */
6369 status = create_synthetic_smb_fname(talloc_tos(),
6370 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6371 &smb_fname_dst);
6372 if (!NT_STATUS_IS_OK(status)) {
6373 goto out;
6377 * Set the original last component, since
6378 * rename_internals_fsp() requires it.
6380 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6381 newname);
6382 if (smb_fname_dst->original_lcomp == NULL) {
6383 status = NT_STATUS_NO_MEMORY;
6384 goto out;
6387 } else {
6389 * Build up an smb_fname_dst based on the filename passed in.
6390 * We basically just strip off the last component, and put on
6391 * the newname instead.
6393 char *base_name = NULL;
6395 /* newname must *not* be a stream name. */
6396 if (newname[0] == ':') {
6397 return NT_STATUS_NOT_SUPPORTED;
6401 * Strip off the last component (filename) of the path passed
6402 * in.
6404 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6405 if (!base_name) {
6406 return NT_STATUS_NO_MEMORY;
6408 p = strrchr_m(base_name, '/');
6409 if (p) {
6410 p[1] = '\0';
6411 } else {
6412 base_name = talloc_strdup(ctx, "");
6413 if (!base_name) {
6414 return NT_STATUS_NO_MEMORY;
6417 /* Append the new name. */
6418 base_name = talloc_asprintf_append(base_name,
6419 "%s",
6420 newname);
6421 if (!base_name) {
6422 return NT_STATUS_NO_MEMORY;
6425 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6426 (UCF_SAVE_LCOMP |
6427 (dest_has_wcard ?
6428 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6429 0)));
6431 /* If an error we expect this to be
6432 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6434 if (!NT_STATUS_IS_OK(status)) {
6435 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6436 status)) {
6437 goto out;
6439 /* Create an smb_fname to call rename_internals_fsp() */
6440 status = create_synthetic_smb_fname(ctx,
6441 base_name, NULL,
6442 NULL,
6443 &smb_fname_dst);
6444 if (!NT_STATUS_IS_OK(status)) {
6445 goto out;
6450 if (fsp) {
6451 DEBUG(10,("smb_file_rename_information: "
6452 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6453 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6454 smb_fname_str_dbg(smb_fname_dst)));
6455 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6456 overwrite);
6457 } else {
6458 DEBUG(10,("smb_file_rename_information: "
6459 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6460 smb_fname_str_dbg(smb_fname_src),
6461 smb_fname_str_dbg(smb_fname_dst)));
6462 status = rename_internals(ctx, conn, req, smb_fname_src,
6463 smb_fname_dst, 0, overwrite, false,
6464 dest_has_wcard,
6465 FILE_WRITE_ATTRIBUTES);
6467 out:
6468 TALLOC_FREE(smb_fname_dst);
6469 return status;
6472 /****************************************************************************
6473 Deal with SMB_SET_POSIX_ACL.
6474 ****************************************************************************/
6476 #if defined(HAVE_POSIX_ACLS)
6477 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6478 const char *pdata,
6479 int total_data,
6480 files_struct *fsp,
6481 const struct smb_filename *smb_fname)
6483 uint16 posix_acl_version;
6484 uint16 num_file_acls;
6485 uint16 num_def_acls;
6486 bool valid_file_acls = True;
6487 bool valid_def_acls = True;
6489 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6490 return NT_STATUS_INVALID_PARAMETER;
6492 posix_acl_version = SVAL(pdata,0);
6493 num_file_acls = SVAL(pdata,2);
6494 num_def_acls = SVAL(pdata,4);
6496 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6497 valid_file_acls = False;
6498 num_file_acls = 0;
6501 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6502 valid_def_acls = False;
6503 num_def_acls = 0;
6506 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6507 return NT_STATUS_INVALID_PARAMETER;
6510 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6511 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6512 return NT_STATUS_INVALID_PARAMETER;
6515 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6516 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6517 (unsigned int)num_file_acls,
6518 (unsigned int)num_def_acls));
6520 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6521 smb_fname->base_name, num_file_acls,
6522 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6523 return map_nt_error_from_unix(errno);
6526 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6527 smb_fname->base_name, &smb_fname->st, num_def_acls,
6528 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6529 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6530 return map_nt_error_from_unix(errno);
6532 return NT_STATUS_OK;
6534 #endif
6536 /****************************************************************************
6537 Deal with SMB_SET_POSIX_LOCK.
6538 ****************************************************************************/
6540 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6541 struct smb_request *req,
6542 const char *pdata,
6543 int total_data,
6544 files_struct *fsp)
6546 uint64_t count;
6547 uint64_t offset;
6548 uint64_t smblctx;
6549 bool blocking_lock = False;
6550 enum brl_type lock_type;
6552 NTSTATUS status = NT_STATUS_OK;
6554 if (fsp == NULL || fsp->fh->fd == -1) {
6555 return NT_STATUS_INVALID_HANDLE;
6558 if (total_data != POSIX_LOCK_DATA_SIZE) {
6559 return NT_STATUS_INVALID_PARAMETER;
6562 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6563 case POSIX_LOCK_TYPE_READ:
6564 lock_type = READ_LOCK;
6565 break;
6566 case POSIX_LOCK_TYPE_WRITE:
6567 /* Return the right POSIX-mappable error code for files opened read-only. */
6568 if (!fsp->can_write) {
6569 return NT_STATUS_INVALID_HANDLE;
6571 lock_type = WRITE_LOCK;
6572 break;
6573 case POSIX_LOCK_TYPE_UNLOCK:
6574 lock_type = UNLOCK_LOCK;
6575 break;
6576 default:
6577 return NT_STATUS_INVALID_PARAMETER;
6580 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6581 blocking_lock = False;
6582 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6583 blocking_lock = True;
6584 } else {
6585 return NT_STATUS_INVALID_PARAMETER;
6588 if (!lp_blocking_locks(SNUM(conn))) {
6589 blocking_lock = False;
6592 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6593 #if defined(HAVE_LONGLONG)
6594 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6595 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6596 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6597 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6598 #else /* HAVE_LONGLONG */
6599 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6600 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6601 #endif /* HAVE_LONGLONG */
6603 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6604 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6605 fsp_str_dbg(fsp),
6606 (unsigned int)lock_type,
6607 (unsigned long long)smblctx,
6608 (double)count,
6609 (double)offset ));
6611 if (lock_type == UNLOCK_LOCK) {
6612 status = do_unlock(req->sconn->msg_ctx,
6613 fsp,
6614 smblctx,
6615 count,
6616 offset,
6617 POSIX_LOCK);
6618 } else {
6619 uint64_t block_smblctx;
6621 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6622 fsp,
6623 smblctx,
6624 count,
6625 offset,
6626 lock_type,
6627 POSIX_LOCK,
6628 blocking_lock,
6629 &status,
6630 &block_smblctx,
6631 NULL);
6633 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6635 * A blocking lock was requested. Package up
6636 * this smb into a queued request and push it
6637 * onto the blocking lock queue.
6639 if(push_blocking_lock_request(br_lck,
6640 req,
6641 fsp,
6642 -1, /* infinite timeout. */
6644 smblctx,
6645 lock_type,
6646 POSIX_LOCK,
6647 offset,
6648 count,
6649 block_smblctx)) {
6650 TALLOC_FREE(br_lck);
6651 return status;
6654 TALLOC_FREE(br_lck);
6657 return status;
6660 /****************************************************************************
6661 Deal with SMB_SET_FILE_BASIC_INFO.
6662 ****************************************************************************/
6664 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6665 const char *pdata,
6666 int total_data,
6667 files_struct *fsp,
6668 const struct smb_filename *smb_fname)
6670 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6671 struct smb_file_time ft;
6672 uint32 dosmode = 0;
6673 NTSTATUS status = NT_STATUS_OK;
6675 ZERO_STRUCT(ft);
6677 if (total_data < 36) {
6678 return NT_STATUS_INVALID_PARAMETER;
6681 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 return status;
6686 /* Set the attributes */
6687 dosmode = IVAL(pdata,32);
6688 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 return status;
6693 /* create time */
6694 ft.create_time = interpret_long_date(pdata);
6696 /* access time */
6697 ft.atime = interpret_long_date(pdata+8);
6699 /* write time. */
6700 ft.mtime = interpret_long_date(pdata+16);
6702 /* change time. */
6703 ft.ctime = interpret_long_date(pdata+24);
6705 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6706 smb_fname_str_dbg(smb_fname)));
6708 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6709 true);
6712 /****************************************************************************
6713 Deal with SMB_INFO_STANDARD.
6714 ****************************************************************************/
6716 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6717 const char *pdata,
6718 int total_data,
6719 files_struct *fsp,
6720 const struct smb_filename *smb_fname)
6722 NTSTATUS status;
6723 struct smb_file_time ft;
6725 ZERO_STRUCT(ft);
6727 if (total_data < 12) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 /* create time */
6732 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6733 /* access time */
6734 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6735 /* write time */
6736 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6738 DEBUG(10,("smb_set_info_standard: file %s\n",
6739 smb_fname_str_dbg(smb_fname)));
6741 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 return status;
6746 return smb_set_file_time(conn,
6747 fsp,
6748 smb_fname,
6749 &ft,
6750 true);
6753 /****************************************************************************
6754 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6755 ****************************************************************************/
6757 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6758 struct smb_request *req,
6759 const char *pdata,
6760 int total_data,
6761 files_struct *fsp,
6762 struct smb_filename *smb_fname)
6764 uint64_t allocation_size = 0;
6765 NTSTATUS status = NT_STATUS_OK;
6766 files_struct *new_fsp = NULL;
6768 if (!VALID_STAT(smb_fname->st)) {
6769 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6772 if (total_data < 8) {
6773 return NT_STATUS_INVALID_PARAMETER;
6776 allocation_size = (uint64_t)IVAL(pdata,0);
6777 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6778 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6779 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6780 (double)allocation_size));
6782 if (allocation_size) {
6783 allocation_size = smb_roundup(conn, allocation_size);
6786 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6787 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6788 (double)allocation_size));
6790 if (fsp && fsp->fh->fd != -1) {
6791 /* Open file handle. */
6792 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6793 return NT_STATUS_ACCESS_DENIED;
6796 /* Only change if needed. */
6797 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6798 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6799 return map_nt_error_from_unix(errno);
6802 /* But always update the time. */
6804 * This is equivalent to a write. Ensure it's seen immediately
6805 * if there are no pending writes.
6807 trigger_write_time_update_immediate(fsp);
6808 return NT_STATUS_OK;
6811 /* Pathname or stat or directory file. */
6812 status = SMB_VFS_CREATE_FILE(
6813 conn, /* conn */
6814 req, /* req */
6815 0, /* root_dir_fid */
6816 smb_fname, /* fname */
6817 FILE_WRITE_DATA, /* access_mask */
6818 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6819 FILE_SHARE_DELETE),
6820 FILE_OPEN, /* create_disposition*/
6821 0, /* create_options */
6822 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6823 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6824 0, /* allocation_size */
6825 0, /* private_flags */
6826 NULL, /* sd */
6827 NULL, /* ea_list */
6828 &new_fsp, /* result */
6829 NULL); /* pinfo */
6831 if (!NT_STATUS_IS_OK(status)) {
6832 /* NB. We check for open_was_deferred in the caller. */
6833 return status;
6836 /* Only change if needed. */
6837 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6838 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6839 status = map_nt_error_from_unix(errno);
6840 close_file(req, new_fsp, NORMAL_CLOSE);
6841 return status;
6845 /* Changing the allocation size should set the last mod time. */
6847 * This is equivalent to a write. Ensure it's seen immediately
6848 * if there are no pending writes.
6850 trigger_write_time_update_immediate(new_fsp);
6852 close_file(req, new_fsp, NORMAL_CLOSE);
6853 return NT_STATUS_OK;
6856 /****************************************************************************
6857 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6858 ****************************************************************************/
6860 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6861 struct smb_request *req,
6862 const char *pdata,
6863 int total_data,
6864 files_struct *fsp,
6865 const struct smb_filename *smb_fname,
6866 bool fail_after_createfile)
6868 off_t size;
6870 if (total_data < 8) {
6871 return NT_STATUS_INVALID_PARAMETER;
6874 size = IVAL(pdata,0);
6875 size |= (((off_t)IVAL(pdata,4)) << 32);
6876 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6877 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6878 (double)size));
6880 return smb_set_file_size(conn, req,
6881 fsp,
6882 smb_fname,
6883 &smb_fname->st,
6884 size,
6885 fail_after_createfile);
6888 /****************************************************************************
6889 Allow a UNIX info mknod.
6890 ****************************************************************************/
6892 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6893 const char *pdata,
6894 int total_data,
6895 const struct smb_filename *smb_fname)
6897 uint32 file_type = IVAL(pdata,56);
6898 #if defined(HAVE_MAKEDEV)
6899 uint32 dev_major = IVAL(pdata,60);
6900 uint32 dev_minor = IVAL(pdata,68);
6901 #endif
6902 SMB_DEV_T dev = (SMB_DEV_T)0;
6903 uint32 raw_unixmode = IVAL(pdata,84);
6904 NTSTATUS status;
6905 mode_t unixmode;
6907 if (total_data < 100) {
6908 return NT_STATUS_INVALID_PARAMETER;
6911 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6912 PERM_NEW_FILE, &unixmode);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 return status;
6917 #if defined(HAVE_MAKEDEV)
6918 dev = makedev(dev_major, dev_minor);
6919 #endif
6921 switch (file_type) {
6922 #if defined(S_IFIFO)
6923 case UNIX_TYPE_FIFO:
6924 unixmode |= S_IFIFO;
6925 break;
6926 #endif
6927 #if defined(S_IFSOCK)
6928 case UNIX_TYPE_SOCKET:
6929 unixmode |= S_IFSOCK;
6930 break;
6931 #endif
6932 #if defined(S_IFCHR)
6933 case UNIX_TYPE_CHARDEV:
6934 unixmode |= S_IFCHR;
6935 break;
6936 #endif
6937 #if defined(S_IFBLK)
6938 case UNIX_TYPE_BLKDEV:
6939 unixmode |= S_IFBLK;
6940 break;
6941 #endif
6942 default:
6943 return NT_STATUS_INVALID_PARAMETER;
6946 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6947 "%.0f mode 0%o for file %s\n", (double)dev,
6948 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6950 /* Ok - do the mknod. */
6951 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6952 return map_nt_error_from_unix(errno);
6955 /* If any of the other "set" calls fail we
6956 * don't want to end up with a half-constructed mknod.
6959 if (lp_inherit_perms(SNUM(conn))) {
6960 char *parent;
6961 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6962 &parent, NULL)) {
6963 return NT_STATUS_NO_MEMORY;
6965 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6966 unixmode);
6967 TALLOC_FREE(parent);
6970 return NT_STATUS_OK;
6973 /****************************************************************************
6974 Deal with SMB_SET_FILE_UNIX_BASIC.
6975 ****************************************************************************/
6977 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6978 struct smb_request *req,
6979 const char *pdata,
6980 int total_data,
6981 files_struct *fsp,
6982 const struct smb_filename *smb_fname)
6984 struct smb_file_time ft;
6985 uint32 raw_unixmode;
6986 mode_t unixmode;
6987 off_t size = 0;
6988 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6989 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6990 NTSTATUS status = NT_STATUS_OK;
6991 bool delete_on_fail = False;
6992 enum perm_type ptype;
6993 files_struct *all_fsps = NULL;
6994 bool modify_mtime = true;
6995 struct file_id id;
6996 struct smb_filename *smb_fname_tmp = NULL;
6997 SMB_STRUCT_STAT sbuf;
6999 ZERO_STRUCT(ft);
7001 if (total_data < 100) {
7002 return NT_STATUS_INVALID_PARAMETER;
7005 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7006 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7007 size=IVAL(pdata,0); /* first 8 Bytes are size */
7008 size |= (((off_t)IVAL(pdata,4)) << 32);
7011 ft.atime = interpret_long_date(pdata+24); /* access_time */
7012 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7013 set_owner = (uid_t)IVAL(pdata,40);
7014 set_grp = (gid_t)IVAL(pdata,48);
7015 raw_unixmode = IVAL(pdata,84);
7017 if (VALID_STAT(smb_fname->st)) {
7018 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7019 ptype = PERM_EXISTING_DIR;
7020 } else {
7021 ptype = PERM_EXISTING_FILE;
7023 } else {
7024 ptype = PERM_NEW_FILE;
7027 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7028 ptype, &unixmode);
7029 if (!NT_STATUS_IS_OK(status)) {
7030 return status;
7033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7034 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7035 smb_fname_str_dbg(smb_fname), (double)size,
7036 (unsigned int)set_owner, (unsigned int)set_grp,
7037 (int)raw_unixmode));
7039 sbuf = smb_fname->st;
7041 if (!VALID_STAT(sbuf)) {
7043 * The only valid use of this is to create character and block
7044 * devices, and named pipes. This is deprecated (IMHO) and
7045 * a new info level should be used for mknod. JRA.
7048 status = smb_unix_mknod(conn,
7049 pdata,
7050 total_data,
7051 smb_fname);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return status;
7056 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7057 if (smb_fname_tmp == NULL) {
7058 return NT_STATUS_NO_MEMORY;
7061 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7062 status = map_nt_error_from_unix(errno);
7063 TALLOC_FREE(smb_fname_tmp);
7064 SMB_VFS_UNLINK(conn, smb_fname);
7065 return status;
7068 sbuf = smb_fname_tmp->st;
7069 smb_fname = smb_fname_tmp;
7071 /* Ensure we don't try and change anything else. */
7072 raw_unixmode = SMB_MODE_NO_CHANGE;
7073 size = get_file_size_stat(&sbuf);
7074 ft.atime = sbuf.st_ex_atime;
7075 ft.mtime = sbuf.st_ex_mtime;
7077 * We continue here as we might want to change the
7078 * owner uid/gid.
7080 delete_on_fail = True;
7083 #if 1
7084 /* Horrible backwards compatibility hack as an old server bug
7085 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7086 * */
7088 if (!size) {
7089 size = get_file_size_stat(&sbuf);
7091 #endif
7094 * Deal with the UNIX specific mode set.
7097 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7099 "setting mode 0%o for file %s\n",
7100 (unsigned int)unixmode,
7101 smb_fname_str_dbg(smb_fname)));
7102 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7103 return map_nt_error_from_unix(errno);
7108 * Deal with the UNIX specific uid set.
7111 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7112 (sbuf.st_ex_uid != set_owner)) {
7113 int ret;
7115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7116 "changing owner %u for path %s\n",
7117 (unsigned int)set_owner,
7118 smb_fname_str_dbg(smb_fname)));
7120 if (S_ISLNK(sbuf.st_ex_mode)) {
7121 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7122 set_owner, (gid_t)-1);
7123 } else {
7124 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7125 set_owner, (gid_t)-1);
7128 if (ret != 0) {
7129 status = map_nt_error_from_unix(errno);
7130 if (delete_on_fail) {
7131 SMB_VFS_UNLINK(conn, smb_fname);
7133 return status;
7138 * Deal with the UNIX specific gid set.
7141 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7142 (sbuf.st_ex_gid != set_grp)) {
7143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7144 "changing group %u for file %s\n",
7145 (unsigned int)set_owner,
7146 smb_fname_str_dbg(smb_fname)));
7147 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7148 set_grp) != 0) {
7149 status = map_nt_error_from_unix(errno);
7150 if (delete_on_fail) {
7151 SMB_VFS_UNLINK(conn, smb_fname);
7153 return status;
7157 /* Deal with any size changes. */
7159 status = smb_set_file_size(conn, req,
7160 fsp,
7161 smb_fname,
7162 &sbuf,
7163 size,
7164 false);
7165 if (!NT_STATUS_IS_OK(status)) {
7166 return status;
7169 /* Deal with any time changes. */
7170 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7171 /* No change, don't cancel anything. */
7172 return status;
7175 id = vfs_file_id_from_sbuf(conn, &sbuf);
7176 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7177 all_fsps = file_find_di_next(all_fsps)) {
7179 * We're setting the time explicitly for UNIX.
7180 * Cancel any pending changes over all handles.
7182 all_fsps->update_write_time_on_close = false;
7183 TALLOC_FREE(all_fsps->update_write_time_event);
7187 * Override the "setting_write_time"
7188 * parameter here as it almost does what
7189 * we need. Just remember if we modified
7190 * mtime and send the notify ourselves.
7192 if (null_timespec(ft.mtime)) {
7193 modify_mtime = false;
7196 status = smb_set_file_time(conn,
7197 fsp,
7198 smb_fname,
7199 &ft,
7200 false);
7201 if (modify_mtime) {
7202 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7203 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7205 return status;
7208 /****************************************************************************
7209 Deal with SMB_SET_FILE_UNIX_INFO2.
7210 ****************************************************************************/
7212 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7213 struct smb_request *req,
7214 const char *pdata,
7215 int total_data,
7216 files_struct *fsp,
7217 const struct smb_filename *smb_fname)
7219 NTSTATUS status;
7220 uint32 smb_fflags;
7221 uint32 smb_fmask;
7223 if (total_data < 116) {
7224 return NT_STATUS_INVALID_PARAMETER;
7227 /* Start by setting all the fields that are common between UNIX_BASIC
7228 * and UNIX_INFO2.
7230 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7231 fsp, smb_fname);
7232 if (!NT_STATUS_IS_OK(status)) {
7233 return status;
7236 smb_fflags = IVAL(pdata, 108);
7237 smb_fmask = IVAL(pdata, 112);
7239 /* NB: We should only attempt to alter the file flags if the client
7240 * sends a non-zero mask.
7242 if (smb_fmask != 0) {
7243 int stat_fflags = 0;
7245 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7246 smb_fmask, &stat_fflags)) {
7247 /* Client asked to alter a flag we don't understand. */
7248 return NT_STATUS_INVALID_PARAMETER;
7251 if (fsp && fsp->fh->fd != -1) {
7252 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7253 return NT_STATUS_NOT_SUPPORTED;
7254 } else {
7255 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7256 stat_fflags) != 0) {
7257 return map_nt_error_from_unix(errno);
7262 /* XXX: need to add support for changing the create_time here. You
7263 * can do this for paths on Darwin with setattrlist(2). The right way
7264 * to hook this up is probably by extending the VFS utimes interface.
7267 return NT_STATUS_OK;
7270 /****************************************************************************
7271 Create a directory with POSIX semantics.
7272 ****************************************************************************/
7274 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7275 struct smb_request *req,
7276 char **ppdata,
7277 int total_data,
7278 struct smb_filename *smb_fname,
7279 int *pdata_return_size)
7281 NTSTATUS status = NT_STATUS_OK;
7282 uint32 raw_unixmode = 0;
7283 uint32 mod_unixmode = 0;
7284 mode_t unixmode = (mode_t)0;
7285 files_struct *fsp = NULL;
7286 uint16 info_level_return = 0;
7287 int info;
7288 char *pdata = *ppdata;
7290 if (total_data < 18) {
7291 return NT_STATUS_INVALID_PARAMETER;
7294 raw_unixmode = IVAL(pdata,8);
7295 /* Next 4 bytes are not yet defined. */
7297 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7298 PERM_NEW_DIR, &unixmode);
7299 if (!NT_STATUS_IS_OK(status)) {
7300 return status;
7303 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7305 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7306 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7308 status = SMB_VFS_CREATE_FILE(
7309 conn, /* conn */
7310 req, /* req */
7311 0, /* root_dir_fid */
7312 smb_fname, /* fname */
7313 FILE_READ_ATTRIBUTES, /* access_mask */
7314 FILE_SHARE_NONE, /* share_access */
7315 FILE_CREATE, /* create_disposition*/
7316 FILE_DIRECTORY_FILE, /* create_options */
7317 mod_unixmode, /* file_attributes */
7318 0, /* oplock_request */
7319 0, /* allocation_size */
7320 0, /* private_flags */
7321 NULL, /* sd */
7322 NULL, /* ea_list */
7323 &fsp, /* result */
7324 &info); /* pinfo */
7326 if (NT_STATUS_IS_OK(status)) {
7327 close_file(req, fsp, NORMAL_CLOSE);
7330 info_level_return = SVAL(pdata,16);
7332 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7333 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7334 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7335 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7336 } else {
7337 *pdata_return_size = 12;
7340 /* Realloc the data size */
7341 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7342 if (*ppdata == NULL) {
7343 *pdata_return_size = 0;
7344 return NT_STATUS_NO_MEMORY;
7346 pdata = *ppdata;
7348 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7349 SSVAL(pdata,2,0); /* No fnum. */
7350 SIVAL(pdata,4,info); /* Was directory created. */
7352 switch (info_level_return) {
7353 case SMB_QUERY_FILE_UNIX_BASIC:
7354 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7355 SSVAL(pdata,10,0); /* Padding. */
7356 store_file_unix_basic(conn, pdata + 12, fsp,
7357 &smb_fname->st);
7358 break;
7359 case SMB_QUERY_FILE_UNIX_INFO2:
7360 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7361 SSVAL(pdata,10,0); /* Padding. */
7362 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7363 &smb_fname->st);
7364 break;
7365 default:
7366 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7367 SSVAL(pdata,10,0); /* Padding. */
7368 break;
7371 return status;
7374 /****************************************************************************
7375 Open/Create a file with POSIX semantics.
7376 ****************************************************************************/
7378 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7379 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7381 static NTSTATUS smb_posix_open(connection_struct *conn,
7382 struct smb_request *req,
7383 char **ppdata,
7384 int total_data,
7385 struct smb_filename *smb_fname,
7386 int *pdata_return_size)
7388 bool extended_oplock_granted = False;
7389 char *pdata = *ppdata;
7390 uint32 flags = 0;
7391 uint32 wire_open_mode = 0;
7392 uint32 raw_unixmode = 0;
7393 uint32 mod_unixmode = 0;
7394 uint32 create_disp = 0;
7395 uint32 access_mask = 0;
7396 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7397 NTSTATUS status = NT_STATUS_OK;
7398 mode_t unixmode = (mode_t)0;
7399 files_struct *fsp = NULL;
7400 int oplock_request = 0;
7401 int info = 0;
7402 uint16 info_level_return = 0;
7404 if (total_data < 18) {
7405 return NT_STATUS_INVALID_PARAMETER;
7408 flags = IVAL(pdata,0);
7409 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7410 if (oplock_request) {
7411 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7414 wire_open_mode = IVAL(pdata,4);
7416 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7417 return smb_posix_mkdir(conn, req,
7418 ppdata,
7419 total_data,
7420 smb_fname,
7421 pdata_return_size);
7424 switch (wire_open_mode & SMB_ACCMODE) {
7425 case SMB_O_RDONLY:
7426 access_mask = SMB_O_RDONLY_MAPPING;
7427 break;
7428 case SMB_O_WRONLY:
7429 access_mask = SMB_O_WRONLY_MAPPING;
7430 break;
7431 case SMB_O_RDWR:
7432 access_mask = (SMB_O_RDONLY_MAPPING|
7433 SMB_O_WRONLY_MAPPING);
7434 break;
7435 default:
7436 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7437 (unsigned int)wire_open_mode ));
7438 return NT_STATUS_INVALID_PARAMETER;
7441 wire_open_mode &= ~SMB_ACCMODE;
7443 /* First take care of O_CREAT|O_EXCL interactions. */
7444 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7445 case (SMB_O_CREAT | SMB_O_EXCL):
7446 /* File exists fail. File not exist create. */
7447 create_disp = FILE_CREATE;
7448 break;
7449 case SMB_O_CREAT:
7450 /* File exists open. File not exist create. */
7451 create_disp = FILE_OPEN_IF;
7452 break;
7453 case SMB_O_EXCL:
7454 /* O_EXCL on its own without O_CREAT is undefined.
7455 We deliberately ignore it as some versions of
7456 Linux CIFSFS can send a bare O_EXCL on the
7457 wire which other filesystems in the kernel
7458 ignore. See bug 9519 for details. */
7460 /* Fallthrough. */
7462 case 0:
7463 /* File exists open. File not exist fail. */
7464 create_disp = FILE_OPEN;
7465 break;
7466 default:
7467 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7468 (unsigned int)wire_open_mode ));
7469 return NT_STATUS_INVALID_PARAMETER;
7472 /* Next factor in the effects of O_TRUNC. */
7473 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7475 if (wire_open_mode & SMB_O_TRUNC) {
7476 switch (create_disp) {
7477 case FILE_CREATE:
7478 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7479 /* Leave create_disp alone as
7480 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7482 /* File exists fail. File not exist create. */
7483 break;
7484 case FILE_OPEN_IF:
7485 /* SMB_O_CREAT | SMB_O_TRUNC */
7486 /* File exists overwrite. File not exist create. */
7487 create_disp = FILE_OVERWRITE_IF;
7488 break;
7489 case FILE_OPEN:
7490 /* SMB_O_TRUNC */
7491 /* File exists overwrite. File not exist fail. */
7492 create_disp = FILE_OVERWRITE;
7493 break;
7494 default:
7495 /* Cannot get here. */
7496 smb_panic("smb_posix_open: logic error");
7497 return NT_STATUS_INVALID_PARAMETER;
7501 raw_unixmode = IVAL(pdata,8);
7502 /* Next 4 bytes are not yet defined. */
7504 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7505 (VALID_STAT(smb_fname->st) ?
7506 PERM_EXISTING_FILE : PERM_NEW_FILE),
7507 &unixmode);
7509 if (!NT_STATUS_IS_OK(status)) {
7510 return status;
7513 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7515 if (wire_open_mode & SMB_O_SYNC) {
7516 create_options |= FILE_WRITE_THROUGH;
7518 if (wire_open_mode & SMB_O_APPEND) {
7519 access_mask |= FILE_APPEND_DATA;
7521 if (wire_open_mode & SMB_O_DIRECT) {
7522 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7525 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7526 VALID_STAT_OF_DIR(smb_fname->st)) {
7527 if (access_mask != SMB_O_RDONLY_MAPPING) {
7528 return NT_STATUS_FILE_IS_A_DIRECTORY;
7530 create_options &= ~FILE_NON_DIRECTORY_FILE;
7531 create_options |= FILE_DIRECTORY_FILE;
7534 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7535 smb_fname_str_dbg(smb_fname),
7536 (unsigned int)wire_open_mode,
7537 (unsigned int)unixmode ));
7539 status = SMB_VFS_CREATE_FILE(
7540 conn, /* conn */
7541 req, /* req */
7542 0, /* root_dir_fid */
7543 smb_fname, /* fname */
7544 access_mask, /* access_mask */
7545 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7546 FILE_SHARE_DELETE),
7547 create_disp, /* create_disposition*/
7548 create_options, /* create_options */
7549 mod_unixmode, /* file_attributes */
7550 oplock_request, /* oplock_request */
7551 0, /* allocation_size */
7552 0, /* private_flags */
7553 NULL, /* sd */
7554 NULL, /* ea_list */
7555 &fsp, /* result */
7556 &info); /* pinfo */
7558 if (!NT_STATUS_IS_OK(status)) {
7559 return status;
7562 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7563 extended_oplock_granted = True;
7566 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7567 extended_oplock_granted = True;
7570 info_level_return = SVAL(pdata,16);
7572 /* Allocate the correct return size. */
7574 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7575 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7576 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7577 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7578 } else {
7579 *pdata_return_size = 12;
7582 /* Realloc the data size */
7583 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7584 if (*ppdata == NULL) {
7585 close_file(req, fsp, ERROR_CLOSE);
7586 *pdata_return_size = 0;
7587 return NT_STATUS_NO_MEMORY;
7589 pdata = *ppdata;
7591 if (extended_oplock_granted) {
7592 if (flags & REQUEST_BATCH_OPLOCK) {
7593 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7594 } else {
7595 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7597 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7598 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7599 } else {
7600 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7603 SSVAL(pdata,2,fsp->fnum);
7604 SIVAL(pdata,4,info); /* Was file created etc. */
7606 switch (info_level_return) {
7607 case SMB_QUERY_FILE_UNIX_BASIC:
7608 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7609 SSVAL(pdata,10,0); /* padding. */
7610 store_file_unix_basic(conn, pdata + 12, fsp,
7611 &smb_fname->st);
7612 break;
7613 case SMB_QUERY_FILE_UNIX_INFO2:
7614 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7615 SSVAL(pdata,10,0); /* padding. */
7616 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7617 &smb_fname->st);
7618 break;
7619 default:
7620 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7621 SSVAL(pdata,10,0); /* padding. */
7622 break;
7624 return NT_STATUS_OK;
7627 /****************************************************************************
7628 Delete a file with POSIX semantics.
7629 ****************************************************************************/
7631 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7632 struct smb_request *req,
7633 const char *pdata,
7634 int total_data,
7635 struct smb_filename *smb_fname)
7637 NTSTATUS status = NT_STATUS_OK;
7638 files_struct *fsp = NULL;
7639 uint16 flags = 0;
7640 char del = 1;
7641 int info = 0;
7642 int create_options = 0;
7643 int i;
7644 struct share_mode_lock *lck = NULL;
7646 if (total_data < 2) {
7647 return NT_STATUS_INVALID_PARAMETER;
7650 flags = SVAL(pdata,0);
7652 if (!VALID_STAT(smb_fname->st)) {
7653 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7656 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7657 !VALID_STAT_OF_DIR(smb_fname->st)) {
7658 return NT_STATUS_NOT_A_DIRECTORY;
7661 DEBUG(10,("smb_posix_unlink: %s %s\n",
7662 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7663 smb_fname_str_dbg(smb_fname)));
7665 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7666 create_options |= FILE_DIRECTORY_FILE;
7669 status = SMB_VFS_CREATE_FILE(
7670 conn, /* conn */
7671 req, /* req */
7672 0, /* root_dir_fid */
7673 smb_fname, /* fname */
7674 DELETE_ACCESS, /* access_mask */
7675 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7676 FILE_SHARE_DELETE),
7677 FILE_OPEN, /* create_disposition*/
7678 create_options, /* create_options */
7679 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7680 0, /* oplock_request */
7681 0, /* allocation_size */
7682 0, /* private_flags */
7683 NULL, /* sd */
7684 NULL, /* ea_list */
7685 &fsp, /* result */
7686 &info); /* pinfo */
7688 if (!NT_STATUS_IS_OK(status)) {
7689 return status;
7693 * Don't lie to client. If we can't really delete due to
7694 * non-POSIX opens return SHARING_VIOLATION.
7697 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7698 if (lck == NULL) {
7699 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7700 "lock for file %s\n", fsp_str_dbg(fsp)));
7701 close_file(req, fsp, NORMAL_CLOSE);
7702 return NT_STATUS_INVALID_PARAMETER;
7706 * See if others still have the file open. If this is the case, then
7707 * don't delete. If all opens are POSIX delete we can set the delete
7708 * on close disposition.
7710 for (i=0; i<lck->data->num_share_modes; i++) {
7711 struct share_mode_entry *e = &lck->data->share_modes[i];
7712 if (is_valid_share_mode_entry(e)) {
7713 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7714 continue;
7716 if (share_mode_stale_pid(lck->data, i)) {
7717 continue;
7719 /* Fail with sharing violation. */
7720 TALLOC_FREE(lck);
7721 close_file(req, fsp, NORMAL_CLOSE);
7722 return NT_STATUS_SHARING_VIOLATION;
7727 * Set the delete on close.
7729 status = smb_set_file_disposition_info(conn,
7730 &del,
7732 fsp,
7733 smb_fname);
7735 TALLOC_FREE(lck);
7737 if (!NT_STATUS_IS_OK(status)) {
7738 close_file(req, fsp, NORMAL_CLOSE);
7739 return status;
7741 return close_file(req, fsp, NORMAL_CLOSE);
7744 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7745 struct smb_request *req,
7746 TALLOC_CTX *mem_ctx,
7747 uint16_t info_level,
7748 files_struct *fsp,
7749 struct smb_filename *smb_fname,
7750 char **ppdata, int total_data,
7751 int *ret_data_size)
7753 char *pdata = *ppdata;
7754 NTSTATUS status = NT_STATUS_OK;
7755 int data_return_size = 0;
7757 *ret_data_size = 0;
7759 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7760 return NT_STATUS_INVALID_LEVEL;
7763 if (!CAN_WRITE(conn)) {
7764 /* Allow POSIX opens. The open path will deny
7765 * any non-readonly opens. */
7766 if (info_level != SMB_POSIX_PATH_OPEN) {
7767 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7771 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7772 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7773 fsp_fnum_dbg(fsp),
7774 info_level, total_data));
7776 switch (info_level) {
7778 case SMB_INFO_STANDARD:
7780 status = smb_set_info_standard(conn,
7781 pdata,
7782 total_data,
7783 fsp,
7784 smb_fname);
7785 break;
7788 case SMB_INFO_SET_EA:
7790 status = smb_info_set_ea(conn,
7791 pdata,
7792 total_data,
7793 fsp,
7794 smb_fname);
7795 break;
7798 case SMB_SET_FILE_BASIC_INFO:
7799 case SMB_FILE_BASIC_INFORMATION:
7801 status = smb_set_file_basic_info(conn,
7802 pdata,
7803 total_data,
7804 fsp,
7805 smb_fname);
7806 break;
7809 case SMB_FILE_ALLOCATION_INFORMATION:
7810 case SMB_SET_FILE_ALLOCATION_INFO:
7812 status = smb_set_file_allocation_info(conn, req,
7813 pdata,
7814 total_data,
7815 fsp,
7816 smb_fname);
7817 break;
7820 case SMB_FILE_END_OF_FILE_INFORMATION:
7821 case SMB_SET_FILE_END_OF_FILE_INFO:
7824 * XP/Win7 both fail after the createfile with
7825 * SMB_SET_FILE_END_OF_FILE_INFO but not
7826 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7827 * The level is known here, so pass it down
7828 * appropriately.
7830 bool should_fail =
7831 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7833 status = smb_set_file_end_of_file_info(conn, req,
7834 pdata,
7835 total_data,
7836 fsp,
7837 smb_fname,
7838 should_fail);
7839 break;
7842 case SMB_FILE_DISPOSITION_INFORMATION:
7843 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7845 #if 0
7846 /* JRA - We used to just ignore this on a path ?
7847 * Shouldn't this be invalid level on a pathname
7848 * based call ?
7850 if (tran_call != TRANSACT2_SETFILEINFO) {
7851 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7853 #endif
7854 status = smb_set_file_disposition_info(conn,
7855 pdata,
7856 total_data,
7857 fsp,
7858 smb_fname);
7859 break;
7862 case SMB_FILE_POSITION_INFORMATION:
7864 status = smb_file_position_information(conn,
7865 pdata,
7866 total_data,
7867 fsp);
7868 break;
7871 case SMB_FILE_FULL_EA_INFORMATION:
7873 status = smb_set_file_full_ea_info(conn,
7874 pdata,
7875 total_data,
7876 fsp);
7877 break;
7880 /* From tridge Samba4 :
7881 * MODE_INFORMATION in setfileinfo (I have no
7882 * idea what "mode information" on a file is - it takes a value of 0,
7883 * 2, 4 or 6. What could it be?).
7886 case SMB_FILE_MODE_INFORMATION:
7888 status = smb_file_mode_information(conn,
7889 pdata,
7890 total_data);
7891 break;
7895 * CIFS UNIX extensions.
7898 case SMB_SET_FILE_UNIX_BASIC:
7900 status = smb_set_file_unix_basic(conn, req,
7901 pdata,
7902 total_data,
7903 fsp,
7904 smb_fname);
7905 break;
7908 case SMB_SET_FILE_UNIX_INFO2:
7910 status = smb_set_file_unix_info2(conn, req,
7911 pdata,
7912 total_data,
7913 fsp,
7914 smb_fname);
7915 break;
7918 case SMB_SET_FILE_UNIX_LINK:
7920 if (fsp) {
7921 /* We must have a pathname for this. */
7922 return NT_STATUS_INVALID_LEVEL;
7924 status = smb_set_file_unix_link(conn, req, pdata,
7925 total_data, smb_fname);
7926 break;
7929 case SMB_SET_FILE_UNIX_HLINK:
7931 if (fsp) {
7932 /* We must have a pathname for this. */
7933 return NT_STATUS_INVALID_LEVEL;
7935 status = smb_set_file_unix_hlink(conn, req,
7936 pdata, total_data,
7937 smb_fname);
7938 break;
7941 case SMB_FILE_RENAME_INFORMATION:
7943 status = smb_file_rename_information(conn, req,
7944 pdata, total_data,
7945 fsp, smb_fname);
7946 break;
7949 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7951 /* SMB2 rename information. */
7952 status = smb2_file_rename_information(conn, req,
7953 pdata, total_data,
7954 fsp, smb_fname);
7955 break;
7958 case SMB_FILE_LINK_INFORMATION:
7960 status = smb_file_link_information(conn, req,
7961 pdata, total_data,
7962 fsp, smb_fname);
7963 break;
7966 #if defined(HAVE_POSIX_ACLS)
7967 case SMB_SET_POSIX_ACL:
7969 status = smb_set_posix_acl(conn,
7970 pdata,
7971 total_data,
7972 fsp,
7973 smb_fname);
7974 break;
7976 #endif
7978 case SMB_SET_POSIX_LOCK:
7980 if (!fsp) {
7981 return NT_STATUS_INVALID_LEVEL;
7983 status = smb_set_posix_lock(conn, req,
7984 pdata, total_data, fsp);
7985 break;
7988 case SMB_POSIX_PATH_OPEN:
7990 if (fsp) {
7991 /* We must have a pathname for this. */
7992 return NT_STATUS_INVALID_LEVEL;
7995 status = smb_posix_open(conn, req,
7996 ppdata,
7997 total_data,
7998 smb_fname,
7999 &data_return_size);
8000 break;
8003 case SMB_POSIX_PATH_UNLINK:
8005 if (fsp) {
8006 /* We must have a pathname for this. */
8007 return NT_STATUS_INVALID_LEVEL;
8010 status = smb_posix_unlink(conn, req,
8011 pdata,
8012 total_data,
8013 smb_fname);
8014 break;
8017 default:
8018 return NT_STATUS_INVALID_LEVEL;
8021 if (!NT_STATUS_IS_OK(status)) {
8022 return status;
8025 *ret_data_size = data_return_size;
8026 return NT_STATUS_OK;
8029 /****************************************************************************
8030 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8031 ****************************************************************************/
8033 static void call_trans2setfilepathinfo(connection_struct *conn,
8034 struct smb_request *req,
8035 unsigned int tran_call,
8036 char **pparams, int total_params,
8037 char **ppdata, int total_data,
8038 unsigned int max_data_bytes)
8040 char *params = *pparams;
8041 char *pdata = *ppdata;
8042 uint16 info_level;
8043 struct smb_filename *smb_fname = NULL;
8044 files_struct *fsp = NULL;
8045 NTSTATUS status = NT_STATUS_OK;
8046 int data_return_size = 0;
8048 if (!params) {
8049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8050 return;
8053 if (tran_call == TRANSACT2_SETFILEINFO) {
8054 if (total_params < 4) {
8055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8056 return;
8059 fsp = file_fsp(req, SVAL(params,0));
8060 /* Basic check for non-null fsp. */
8061 if (!check_fsp_open(conn, req, fsp)) {
8062 return;
8064 info_level = SVAL(params,2);
8066 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8067 if (smb_fname == NULL) {
8068 reply_nterror(req, NT_STATUS_NO_MEMORY);
8069 return;
8072 if(fsp->fh->fd == -1) {
8074 * This is actually a SETFILEINFO on a directory
8075 * handle (returned from an NT SMB). NT5.0 seems
8076 * to do this call. JRA.
8078 if (INFO_LEVEL_IS_UNIX(info_level)) {
8079 /* Always do lstat for UNIX calls. */
8080 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8081 DEBUG(3,("call_trans2setfilepathinfo: "
8082 "SMB_VFS_LSTAT of %s failed "
8083 "(%s)\n",
8084 smb_fname_str_dbg(smb_fname),
8085 strerror(errno)));
8086 reply_nterror(req, map_nt_error_from_unix(errno));
8087 return;
8089 } else {
8090 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8091 DEBUG(3,("call_trans2setfilepathinfo: "
8092 "fileinfo of %s failed (%s)\n",
8093 smb_fname_str_dbg(smb_fname),
8094 strerror(errno)));
8095 reply_nterror(req, map_nt_error_from_unix(errno));
8096 return;
8099 } else if (fsp->print_file) {
8101 * Doing a DELETE_ON_CLOSE should cancel a print job.
8103 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8104 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8106 DEBUG(3,("call_trans2setfilepathinfo: "
8107 "Cancelling print job (%s)\n",
8108 fsp_str_dbg(fsp)));
8110 SSVAL(params,0,0);
8111 send_trans2_replies(conn, req, params, 2,
8112 *ppdata, 0,
8113 max_data_bytes);
8114 return;
8115 } else {
8116 reply_nterror(req,
8117 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8118 return;
8120 } else {
8122 * Original code - this is an open file.
8124 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8125 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8126 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8127 strerror(errno)));
8128 reply_nterror(req, map_nt_error_from_unix(errno));
8129 return;
8132 } else {
8133 char *fname = NULL;
8134 uint32_t ucf_flags = 0;
8136 /* set path info */
8137 if (total_params < 7) {
8138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8139 return;
8142 info_level = SVAL(params,0);
8143 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8144 total_params - 6, STR_TERMINATE,
8145 &status);
8146 if (!NT_STATUS_IS_OK(status)) {
8147 reply_nterror(req, status);
8148 return;
8151 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8152 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8153 info_level == SMB_FILE_RENAME_INFORMATION ||
8154 info_level == SMB_POSIX_PATH_UNLINK) {
8155 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8158 status = filename_convert(req, conn,
8159 req->flags2 & FLAGS2_DFS_PATHNAMES,
8160 fname,
8161 ucf_flags,
8162 NULL,
8163 &smb_fname);
8164 if (!NT_STATUS_IS_OK(status)) {
8165 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8166 reply_botherror(req,
8167 NT_STATUS_PATH_NOT_COVERED,
8168 ERRSRV, ERRbadpath);
8169 return;
8171 reply_nterror(req, status);
8172 return;
8175 if (INFO_LEVEL_IS_UNIX(info_level)) {
8177 * For CIFS UNIX extensions the target name may not exist.
8180 /* Always do lstat for UNIX calls. */
8181 SMB_VFS_LSTAT(conn, smb_fname);
8183 } else if (!VALID_STAT(smb_fname->st) &&
8184 SMB_VFS_STAT(conn, smb_fname)) {
8185 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8186 "%s failed (%s)\n",
8187 smb_fname_str_dbg(smb_fname),
8188 strerror(errno)));
8189 reply_nterror(req, map_nt_error_from_unix(errno));
8190 return;
8194 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8195 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8196 fsp_fnum_dbg(fsp),
8197 info_level,total_data));
8199 /* Realloc the parameter size */
8200 *pparams = (char *)SMB_REALLOC(*pparams,2);
8201 if (*pparams == NULL) {
8202 reply_nterror(req, NT_STATUS_NO_MEMORY);
8203 return;
8205 params = *pparams;
8207 SSVAL(params,0,0);
8209 status = smbd_do_setfilepathinfo(conn, req, req,
8210 info_level,
8211 fsp,
8212 smb_fname,
8213 ppdata, total_data,
8214 &data_return_size);
8215 if (!NT_STATUS_IS_OK(status)) {
8216 if (open_was_deferred(req->sconn, req->mid)) {
8217 /* We have re-scheduled this call. */
8218 return;
8220 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8221 /* We have re-scheduled this call. */
8222 return;
8224 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8225 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8226 ERRSRV, ERRbadpath);
8227 return;
8229 if (info_level == SMB_POSIX_PATH_OPEN) {
8230 reply_openerror(req, status);
8231 return;
8234 reply_nterror(req, status);
8235 return;
8238 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8239 max_data_bytes);
8241 return;
8244 /****************************************************************************
8245 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8246 ****************************************************************************/
8248 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8249 char **pparams, int total_params,
8250 char **ppdata, int total_data,
8251 unsigned int max_data_bytes)
8253 struct smb_filename *smb_dname = NULL;
8254 char *params = *pparams;
8255 char *pdata = *ppdata;
8256 char *directory = NULL;
8257 NTSTATUS status = NT_STATUS_OK;
8258 struct ea_list *ea_list = NULL;
8259 TALLOC_CTX *ctx = talloc_tos();
8261 if (!CAN_WRITE(conn)) {
8262 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8263 return;
8266 if (total_params < 5) {
8267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8268 return;
8271 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8272 total_params - 4, STR_TERMINATE,
8273 &status);
8274 if (!NT_STATUS_IS_OK(status)) {
8275 reply_nterror(req, status);
8276 return;
8279 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8281 status = filename_convert(ctx,
8282 conn,
8283 req->flags2 & FLAGS2_DFS_PATHNAMES,
8284 directory,
8286 NULL,
8287 &smb_dname);
8289 if (!NT_STATUS_IS_OK(status)) {
8290 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8291 reply_botherror(req,
8292 NT_STATUS_PATH_NOT_COVERED,
8293 ERRSRV, ERRbadpath);
8294 return;
8296 reply_nterror(req, status);
8297 return;
8301 * OS/2 workplace shell seems to send SET_EA requests of "null"
8302 * length (4 bytes containing IVAL 4).
8303 * They seem to have no effect. Bug #3212. JRA.
8306 if (total_data && (total_data != 4)) {
8307 /* Any data in this call is an EA list. */
8308 if (total_data < 10) {
8309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8310 goto out;
8313 if (IVAL(pdata,0) > total_data) {
8314 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8315 IVAL(pdata,0), (unsigned int)total_data));
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8317 goto out;
8320 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8321 total_data - 4);
8322 if (!ea_list) {
8323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8324 goto out;
8327 if (!lp_ea_support(SNUM(conn))) {
8328 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8329 goto out;
8332 /* If total_data == 4 Windows doesn't care what values
8333 * are placed in that field, it just ignores them.
8334 * The System i QNTC IBM SMB client puts bad values here,
8335 * so ignore them. */
8337 status = create_directory(conn, req, smb_dname);
8339 if (!NT_STATUS_IS_OK(status)) {
8340 reply_nterror(req, status);
8341 goto out;
8344 /* Try and set any given EA. */
8345 if (ea_list) {
8346 status = set_ea(conn, NULL, smb_dname, ea_list);
8347 if (!NT_STATUS_IS_OK(status)) {
8348 reply_nterror(req, status);
8349 goto out;
8353 /* Realloc the parameter and data sizes */
8354 *pparams = (char *)SMB_REALLOC(*pparams,2);
8355 if(*pparams == NULL) {
8356 reply_nterror(req, NT_STATUS_NO_MEMORY);
8357 goto out;
8359 params = *pparams;
8361 SSVAL(params,0,0);
8363 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8365 out:
8366 TALLOC_FREE(smb_dname);
8367 return;
8370 /****************************************************************************
8371 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8372 We don't actually do this - we just send a null response.
8373 ****************************************************************************/
8375 static void call_trans2findnotifyfirst(connection_struct *conn,
8376 struct smb_request *req,
8377 char **pparams, int total_params,
8378 char **ppdata, int total_data,
8379 unsigned int max_data_bytes)
8381 char *params = *pparams;
8382 uint16 info_level;
8384 if (total_params < 6) {
8385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8386 return;
8389 info_level = SVAL(params,4);
8390 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8392 switch (info_level) {
8393 case 1:
8394 case 2:
8395 break;
8396 default:
8397 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8398 return;
8401 /* Realloc the parameter and data sizes */
8402 *pparams = (char *)SMB_REALLOC(*pparams,6);
8403 if (*pparams == NULL) {
8404 reply_nterror(req, NT_STATUS_NO_MEMORY);
8405 return;
8407 params = *pparams;
8409 SSVAL(params,0,fnf_handle);
8410 SSVAL(params,2,0); /* No changes */
8411 SSVAL(params,4,0); /* No EA errors */
8413 fnf_handle++;
8415 if(fnf_handle == 0)
8416 fnf_handle = 257;
8418 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8420 return;
8423 /****************************************************************************
8424 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8425 changes). Currently this does nothing.
8426 ****************************************************************************/
8428 static void call_trans2findnotifynext(connection_struct *conn,
8429 struct smb_request *req,
8430 char **pparams, int total_params,
8431 char **ppdata, int total_data,
8432 unsigned int max_data_bytes)
8434 char *params = *pparams;
8436 DEBUG(3,("call_trans2findnotifynext\n"));
8438 /* Realloc the parameter and data sizes */
8439 *pparams = (char *)SMB_REALLOC(*pparams,4);
8440 if (*pparams == NULL) {
8441 reply_nterror(req, NT_STATUS_NO_MEMORY);
8442 return;
8444 params = *pparams;
8446 SSVAL(params,0,0); /* No changes */
8447 SSVAL(params,2,0); /* No EA errors */
8449 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8451 return;
8454 /****************************************************************************
8455 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8456 ****************************************************************************/
8458 static void call_trans2getdfsreferral(connection_struct *conn,
8459 struct smb_request *req,
8460 char **pparams, int total_params,
8461 char **ppdata, int total_data,
8462 unsigned int max_data_bytes)
8464 char *params = *pparams;
8465 char *pathname = NULL;
8466 int reply_size = 0;
8467 int max_referral_level;
8468 NTSTATUS status = NT_STATUS_OK;
8469 TALLOC_CTX *ctx = talloc_tos();
8471 DEBUG(10,("call_trans2getdfsreferral\n"));
8473 if (total_params < 3) {
8474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8475 return;
8478 max_referral_level = SVAL(params,0);
8480 if(!lp_host_msdfs()) {
8481 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8482 return;
8485 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8486 total_params - 2, STR_TERMINATE);
8487 if (!pathname) {
8488 reply_nterror(req, NT_STATUS_NOT_FOUND);
8489 return;
8491 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8492 ppdata,&status)) < 0) {
8493 reply_nterror(req, status);
8494 return;
8497 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8498 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8499 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8501 return;
8504 #define LMCAT_SPL 0x53
8505 #define LMFUNC_GETJOBID 0x60
8507 /****************************************************************************
8508 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8509 ****************************************************************************/
8511 static void call_trans2ioctl(connection_struct *conn,
8512 struct smb_request *req,
8513 char **pparams, int total_params,
8514 char **ppdata, int total_data,
8515 unsigned int max_data_bytes)
8517 char *pdata = *ppdata;
8518 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8520 /* check for an invalid fid before proceeding */
8522 if (!fsp) {
8523 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8524 return;
8527 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8528 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8529 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8530 if (*ppdata == NULL) {
8531 reply_nterror(req, NT_STATUS_NO_MEMORY);
8532 return;
8534 pdata = *ppdata;
8536 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8537 CAN ACCEPT THIS IN UNICODE. JRA. */
8539 /* Job number */
8540 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8542 srvstr_push(pdata, req->flags2, pdata + 2,
8543 lp_netbios_name(), 15,
8544 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8545 srvstr_push(pdata, req->flags2, pdata+18,
8546 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8547 STR_ASCII|STR_TERMINATE); /* Service name */
8548 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8549 max_data_bytes);
8550 return;
8553 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8554 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8557 /****************************************************************************
8558 Reply to a SMBfindclose (stop trans2 directory search).
8559 ****************************************************************************/
8561 void reply_findclose(struct smb_request *req)
8563 int dptr_num;
8564 struct smbd_server_connection *sconn = req->sconn;
8566 START_PROFILE(SMBfindclose);
8568 if (req->wct < 1) {
8569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8570 END_PROFILE(SMBfindclose);
8571 return;
8574 dptr_num = SVALS(req->vwv+0, 0);
8576 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8578 dptr_close(sconn, &dptr_num);
8580 reply_outbuf(req, 0, 0);
8582 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8584 END_PROFILE(SMBfindclose);
8585 return;
8588 /****************************************************************************
8589 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8590 ****************************************************************************/
8592 void reply_findnclose(struct smb_request *req)
8594 int dptr_num;
8596 START_PROFILE(SMBfindnclose);
8598 if (req->wct < 1) {
8599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8600 END_PROFILE(SMBfindnclose);
8601 return;
8604 dptr_num = SVAL(req->vwv+0, 0);
8606 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8608 /* We never give out valid handles for a
8609 findnotifyfirst - so any dptr_num is ok here.
8610 Just ignore it. */
8612 reply_outbuf(req, 0, 0);
8614 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8616 END_PROFILE(SMBfindnclose);
8617 return;
8620 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8621 struct trans_state *state)
8623 if (get_Protocol() >= PROTOCOL_NT1) {
8624 req->flags2 |= 0x40; /* IS_LONG_NAME */
8625 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8628 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8629 if (state->call != TRANSACT2_QFSINFO &&
8630 state->call != TRANSACT2_SETFSINFO) {
8631 DEBUG(0,("handle_trans2: encryption required "
8632 "with call 0x%x\n",
8633 (unsigned int)state->call));
8634 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8635 return;
8639 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8641 /* Now we must call the relevant TRANS2 function */
8642 switch(state->call) {
8643 case TRANSACT2_OPEN:
8645 START_PROFILE(Trans2_open);
8646 call_trans2open(conn, req,
8647 &state->param, state->total_param,
8648 &state->data, state->total_data,
8649 state->max_data_return);
8650 END_PROFILE(Trans2_open);
8651 break;
8654 case TRANSACT2_FINDFIRST:
8656 START_PROFILE(Trans2_findfirst);
8657 call_trans2findfirst(conn, req,
8658 &state->param, state->total_param,
8659 &state->data, state->total_data,
8660 state->max_data_return);
8661 END_PROFILE(Trans2_findfirst);
8662 break;
8665 case TRANSACT2_FINDNEXT:
8667 START_PROFILE(Trans2_findnext);
8668 call_trans2findnext(conn, req,
8669 &state->param, state->total_param,
8670 &state->data, state->total_data,
8671 state->max_data_return);
8672 END_PROFILE(Trans2_findnext);
8673 break;
8676 case TRANSACT2_QFSINFO:
8678 START_PROFILE(Trans2_qfsinfo);
8679 call_trans2qfsinfo(conn, req,
8680 &state->param, state->total_param,
8681 &state->data, state->total_data,
8682 state->max_data_return);
8683 END_PROFILE(Trans2_qfsinfo);
8684 break;
8687 case TRANSACT2_SETFSINFO:
8689 START_PROFILE(Trans2_setfsinfo);
8690 call_trans2setfsinfo(conn, req,
8691 &state->param, state->total_param,
8692 &state->data, state->total_data,
8693 state->max_data_return);
8694 END_PROFILE(Trans2_setfsinfo);
8695 break;
8698 case TRANSACT2_QPATHINFO:
8699 case TRANSACT2_QFILEINFO:
8701 START_PROFILE(Trans2_qpathinfo);
8702 call_trans2qfilepathinfo(conn, req, state->call,
8703 &state->param, state->total_param,
8704 &state->data, state->total_data,
8705 state->max_data_return);
8706 END_PROFILE(Trans2_qpathinfo);
8707 break;
8710 case TRANSACT2_SETPATHINFO:
8711 case TRANSACT2_SETFILEINFO:
8713 START_PROFILE(Trans2_setpathinfo);
8714 call_trans2setfilepathinfo(conn, req, state->call,
8715 &state->param, state->total_param,
8716 &state->data, state->total_data,
8717 state->max_data_return);
8718 END_PROFILE(Trans2_setpathinfo);
8719 break;
8722 case TRANSACT2_FINDNOTIFYFIRST:
8724 START_PROFILE(Trans2_findnotifyfirst);
8725 call_trans2findnotifyfirst(conn, req,
8726 &state->param, state->total_param,
8727 &state->data, state->total_data,
8728 state->max_data_return);
8729 END_PROFILE(Trans2_findnotifyfirst);
8730 break;
8733 case TRANSACT2_FINDNOTIFYNEXT:
8735 START_PROFILE(Trans2_findnotifynext);
8736 call_trans2findnotifynext(conn, req,
8737 &state->param, state->total_param,
8738 &state->data, state->total_data,
8739 state->max_data_return);
8740 END_PROFILE(Trans2_findnotifynext);
8741 break;
8744 case TRANSACT2_MKDIR:
8746 START_PROFILE(Trans2_mkdir);
8747 call_trans2mkdir(conn, req,
8748 &state->param, state->total_param,
8749 &state->data, state->total_data,
8750 state->max_data_return);
8751 END_PROFILE(Trans2_mkdir);
8752 break;
8755 case TRANSACT2_GET_DFS_REFERRAL:
8757 START_PROFILE(Trans2_get_dfs_referral);
8758 call_trans2getdfsreferral(conn, req,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_get_dfs_referral);
8763 break;
8766 case TRANSACT2_IOCTL:
8768 START_PROFILE(Trans2_ioctl);
8769 call_trans2ioctl(conn, req,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_ioctl);
8774 break;
8777 default:
8778 /* Error in request */
8779 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8780 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8784 /****************************************************************************
8785 Reply to a SMBtrans2.
8786 ****************************************************************************/
8788 void reply_trans2(struct smb_request *req)
8790 connection_struct *conn = req->conn;
8791 unsigned int dsoff;
8792 unsigned int dscnt;
8793 unsigned int psoff;
8794 unsigned int pscnt;
8795 unsigned int tran_call;
8796 struct trans_state *state;
8797 NTSTATUS result;
8799 START_PROFILE(SMBtrans2);
8801 if (req->wct < 14) {
8802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8803 END_PROFILE(SMBtrans2);
8804 return;
8807 dsoff = SVAL(req->vwv+12, 0);
8808 dscnt = SVAL(req->vwv+11, 0);
8809 psoff = SVAL(req->vwv+10, 0);
8810 pscnt = SVAL(req->vwv+9, 0);
8811 tran_call = SVAL(req->vwv+14, 0);
8813 result = allow_new_trans(conn->pending_trans, req->mid);
8814 if (!NT_STATUS_IS_OK(result)) {
8815 DEBUG(2, ("Got invalid trans2 request: %s\n",
8816 nt_errstr(result)));
8817 reply_nterror(req, result);
8818 END_PROFILE(SMBtrans2);
8819 return;
8822 if (IS_IPC(conn)) {
8823 switch (tran_call) {
8824 /* List the allowed trans2 calls on IPC$ */
8825 case TRANSACT2_OPEN:
8826 case TRANSACT2_GET_DFS_REFERRAL:
8827 case TRANSACT2_QFILEINFO:
8828 case TRANSACT2_QFSINFO:
8829 case TRANSACT2_SETFSINFO:
8830 break;
8831 default:
8832 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8833 END_PROFILE(SMBtrans2);
8834 return;
8838 if ((state = talloc(conn, struct trans_state)) == NULL) {
8839 DEBUG(0, ("talloc failed\n"));
8840 reply_nterror(req, NT_STATUS_NO_MEMORY);
8841 END_PROFILE(SMBtrans2);
8842 return;
8845 state->cmd = SMBtrans2;
8847 state->mid = req->mid;
8848 state->vuid = req->vuid;
8849 state->setup_count = SVAL(req->vwv+13, 0);
8850 state->setup = NULL;
8851 state->total_param = SVAL(req->vwv+0, 0);
8852 state->param = NULL;
8853 state->total_data = SVAL(req->vwv+1, 0);
8854 state->data = NULL;
8855 state->max_param_return = SVAL(req->vwv+2, 0);
8856 state->max_data_return = SVAL(req->vwv+3, 0);
8857 state->max_setup_return = SVAL(req->vwv+4, 0);
8858 state->close_on_completion = BITSETW(req->vwv+5, 0);
8859 state->one_way = BITSETW(req->vwv+5, 1);
8861 state->call = tran_call;
8863 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8864 is so as a sanity check */
8865 if (state->setup_count != 1) {
8867 * Need to have rc=0 for ioctl to get job id for OS/2.
8868 * Network printing will fail if function is not successful.
8869 * Similar function in reply.c will be used if protocol
8870 * is LANMAN1.0 instead of LM1.2X002.
8871 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8872 * outbuf doesn't have to be set(only job id is used).
8874 if ( (state->setup_count == 4)
8875 && (tran_call == TRANSACT2_IOCTL)
8876 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8877 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8878 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8879 } else {
8880 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8881 DEBUG(2,("Transaction is %d\n",tran_call));
8882 TALLOC_FREE(state);
8883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8884 END_PROFILE(SMBtrans2);
8885 return;
8889 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8890 goto bad_param;
8892 if (state->total_data) {
8894 if (trans_oob(state->total_data, 0, dscnt)
8895 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8896 goto bad_param;
8899 /* Can't use talloc here, the core routines do realloc on the
8900 * params and data. */
8901 state->data = (char *)SMB_MALLOC(state->total_data);
8902 if (state->data == NULL) {
8903 DEBUG(0,("reply_trans2: data malloc fail for %u "
8904 "bytes !\n", (unsigned int)state->total_data));
8905 TALLOC_FREE(state);
8906 reply_nterror(req, NT_STATUS_NO_MEMORY);
8907 END_PROFILE(SMBtrans2);
8908 return;
8911 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8914 if (state->total_param) {
8916 if (trans_oob(state->total_param, 0, pscnt)
8917 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8918 goto bad_param;
8921 /* Can't use talloc here, the core routines do realloc on the
8922 * params and data. */
8923 state->param = (char *)SMB_MALLOC(state->total_param);
8924 if (state->param == NULL) {
8925 DEBUG(0,("reply_trans: param malloc fail for %u "
8926 "bytes !\n", (unsigned int)state->total_param));
8927 SAFE_FREE(state->data);
8928 TALLOC_FREE(state);
8929 reply_nterror(req, NT_STATUS_NO_MEMORY);
8930 END_PROFILE(SMBtrans2);
8931 return;
8934 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8937 state->received_data = dscnt;
8938 state->received_param = pscnt;
8940 if ((state->received_param == state->total_param) &&
8941 (state->received_data == state->total_data)) {
8943 handle_trans2(conn, req, state);
8945 SAFE_FREE(state->data);
8946 SAFE_FREE(state->param);
8947 TALLOC_FREE(state);
8948 END_PROFILE(SMBtrans2);
8949 return;
8952 DLIST_ADD(conn->pending_trans, state);
8954 /* We need to send an interim response then receive the rest
8955 of the parameter/data bytes */
8956 reply_outbuf(req, 0, 0);
8957 show_msg((char *)req->outbuf);
8958 END_PROFILE(SMBtrans2);
8959 return;
8961 bad_param:
8963 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8964 SAFE_FREE(state->data);
8965 SAFE_FREE(state->param);
8966 TALLOC_FREE(state);
8967 END_PROFILE(SMBtrans2);
8968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8972 /****************************************************************************
8973 Reply to a SMBtranss2
8974 ****************************************************************************/
8976 void reply_transs2(struct smb_request *req)
8978 connection_struct *conn = req->conn;
8979 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8980 struct trans_state *state;
8982 START_PROFILE(SMBtranss2);
8984 show_msg((const char *)req->inbuf);
8986 /* Windows clients expect all replies to
8987 a transact secondary (SMBtranss2 0x33)
8988 to have a command code of transact
8989 (SMBtrans2 0x32). See bug #8989
8990 and also [MS-CIFS] section 2.2.4.47.2
8991 for details.
8993 req->cmd = SMBtrans2;
8995 if (req->wct < 8) {
8996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8997 END_PROFILE(SMBtranss2);
8998 return;
9001 for (state = conn->pending_trans; state != NULL;
9002 state = state->next) {
9003 if (state->mid == req->mid) {
9004 break;
9008 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9010 END_PROFILE(SMBtranss2);
9011 return;
9014 /* Revise state->total_param and state->total_data in case they have
9015 changed downwards */
9017 if (SVAL(req->vwv+0, 0) < state->total_param)
9018 state->total_param = SVAL(req->vwv+0, 0);
9019 if (SVAL(req->vwv+1, 0) < state->total_data)
9020 state->total_data = SVAL(req->vwv+1, 0);
9022 pcnt = SVAL(req->vwv+2, 0);
9023 poff = SVAL(req->vwv+3, 0);
9024 pdisp = SVAL(req->vwv+4, 0);
9026 dcnt = SVAL(req->vwv+5, 0);
9027 doff = SVAL(req->vwv+6, 0);
9028 ddisp = SVAL(req->vwv+7, 0);
9030 state->received_param += pcnt;
9031 state->received_data += dcnt;
9033 if ((state->received_data > state->total_data) ||
9034 (state->received_param > state->total_param))
9035 goto bad_param;
9037 if (pcnt) {
9038 if (trans_oob(state->total_param, pdisp, pcnt)
9039 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9040 goto bad_param;
9042 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9045 if (dcnt) {
9046 if (trans_oob(state->total_data, ddisp, dcnt)
9047 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9048 goto bad_param;
9050 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9053 if ((state->received_param < state->total_param) ||
9054 (state->received_data < state->total_data)) {
9055 END_PROFILE(SMBtranss2);
9056 return;
9059 handle_trans2(conn, req, state);
9061 DLIST_REMOVE(conn->pending_trans, state);
9062 SAFE_FREE(state->data);
9063 SAFE_FREE(state->param);
9064 TALLOC_FREE(state);
9066 END_PROFILE(SMBtranss2);
9067 return;
9069 bad_param:
9071 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9072 DLIST_REMOVE(conn->pending_trans, state);
9073 SAFE_FREE(state->data);
9074 SAFE_FREE(state->param);
9075 TALLOC_FREE(state);
9076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9077 END_PROFILE(SMBtranss2);
9078 return;