Ensure set_ea cannot set invalid Windows EA names.
[Samba.git] / source3 / smbd / trans2.c
blobff7bc3e0afac06c56cdb4cdfc68bd311cd6e4be6
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 access_mask);
71 if (!NT_STATUS_IS_OK(status)) {
72 return status;
75 return NT_STATUS_OK;
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
92 return val;
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
103 uint64_t file_index;
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
109 return file_index;
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
125 SAMBA_XATTR_MARKER,
126 XATTR_NTACL_NAME,
127 NULL
130 int i;
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
134 return true;
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
138 return true;
140 return false;
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
153 char *val = NULL;
154 ssize_t sizeret;
156 again:
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
159 if (!val) {
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 } else {
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
170 attr_size = 65536;
171 goto again;
174 if (sizeret == -1) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
181 pea->flags = 0;
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
184 } else {
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
188 TALLOC_FREE(val);
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
193 return NT_STATUS_OK;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
204 char *p;
205 char **names, **tmp;
206 size_t num_names;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
214 return NT_STATUS_OK;
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
222 if (names == NULL) {
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
233 TALLOC_FREE(names);
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
239 ea_namelist_size);
240 } else {
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
242 ea_namelist_size);
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
248 else {
249 break;
253 if (sizeret == -1) {
254 TALLOC_FREE(names);
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
261 if (sizeret == 0) {
262 TALLOC_FREE(names);
263 if (pnames) {
264 *pnames = NULL;
266 *pnum_names = 0;
267 return NT_STATUS_OK;
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
275 TALLOC_FREE(names);
276 return NT_STATUS_INTERNAL_ERROR;
280 * count the names
282 num_names = 0;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
285 num_names += 1;
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
289 if (tmp == NULL) {
290 DEBUG(0, ("talloc failed\n"));
291 TALLOC_FREE(names);
292 return NT_STATUS_NO_MEMORY;
295 names = tmp;
296 num_names = 0;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
302 if (pnames) {
303 *pnames = names;
304 } else {
305 TALLOC_FREE(names);
307 *pnum_names = num_names;
308 return NT_STATUS_OK;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
318 /* Get a list of all xattrs. Max namesize is 64k. */
319 size_t i, num_names;
320 char **names;
321 struct ea_list *ea_list_head = NULL;
322 NTSTATUS status;
324 *pea_total_len = 0;
325 *ea_list = NULL;
327 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
328 &names, &num_names);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (num_names == 0) {
335 *ea_list = NULL;
336 return NT_STATUS_OK;
339 for (i=0; i<num_names; i++) {
340 struct ea_list *listp;
341 fstring dos_ea_name;
343 if (strnequal(names[i], "system.", 7)
344 || samba_private_attr_name(names[i]))
345 continue;
347 listp = talloc(mem_ctx, struct ea_list);
348 if (listp == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 status = get_ea_value(listp, conn, fsp,
353 fname, names[i],
354 &listp->ea);
356 if (!NT_STATUS_IS_OK(status)) {
357 TALLOC_FREE(listp);
358 return status;
361 if (listp->ea.value.length == 0) {
363 * We can never return a zero length EA.
364 * Windows reports the EA's as corrupted.
366 TALLOC_FREE(listp);
367 continue;
370 push_ascii_fstring(dos_ea_name, listp->ea.name);
372 *pea_total_len +=
373 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
375 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
376 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
377 (unsigned int)listp->ea.value.length));
379 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
383 /* Add on 4 for total length. */
384 if (*pea_total_len) {
385 *pea_total_len += 4;
388 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
389 (unsigned int)*pea_total_len));
391 *ea_list = ea_list_head;
392 return NT_STATUS_OK;
395 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
396 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
398 *pea_total_len = 0;
399 *ea_list = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
402 return NT_STATUS_OK;
405 if (is_ntfs_stream_smb_fname(smb_fname)) {
406 return NT_STATUS_INVALID_PARAMETER;
409 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
412 /****************************************************************************
413 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
414 that was filled.
415 ****************************************************************************/
417 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
418 connection_struct *conn, struct ea_list *ea_list)
420 unsigned int ret_data_size = 4;
421 char *p = pdata;
423 SMB_ASSERT(total_data_size >= 4);
425 if (!lp_ea_support(SNUM(conn))) {
426 SIVAL(pdata,4,0);
427 return 4;
430 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
431 size_t dos_namelen;
432 fstring dos_ea_name;
433 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
434 dos_namelen = strlen(dos_ea_name);
435 if (dos_namelen > 255 || dos_namelen == 0) {
436 break;
438 if (ea_list->ea.value.length > 65535) {
439 break;
441 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
442 break;
445 /* We know we have room. */
446 SCVAL(p,0,ea_list->ea.flags);
447 SCVAL(p,1,dos_namelen);
448 SSVAL(p,2,ea_list->ea.value.length);
449 strlcpy(p+4, dos_ea_name, dos_namelen+1);
450 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
452 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
453 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
456 ret_data_size = PTR_DIFF(p, pdata);
457 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
458 SIVAL(pdata,0,ret_data_size);
459 return ret_data_size;
462 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
463 char *pdata,
464 unsigned int total_data_size,
465 unsigned int *ret_data_size,
466 connection_struct *conn,
467 struct ea_list *ea_list)
469 uint8_t *p = (uint8_t *)pdata;
470 uint8_t *last_start = NULL;
471 bool do_store_data = (pdata != NULL);
473 *ret_data_size = 0;
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_NO_EAS_ON_FILE;
479 for (; ea_list; ea_list = ea_list->next) {
480 size_t dos_namelen;
481 fstring dos_ea_name;
482 size_t this_size;
483 size_t pad = 0;
485 if (last_start != NULL && do_store_data) {
486 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
488 last_start = p;
490 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
491 dos_namelen = strlen(dos_ea_name);
492 if (dos_namelen > 255 || dos_namelen == 0) {
493 return NT_STATUS_INTERNAL_ERROR;
495 if (ea_list->ea.value.length > 65535) {
496 return NT_STATUS_INTERNAL_ERROR;
499 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
501 if (ea_list->next) {
502 pad = (4 - (this_size % 4)) % 4;
503 this_size += pad;
506 if (do_store_data) {
507 if (this_size > total_data_size) {
508 return NT_STATUS_INFO_LENGTH_MISMATCH;
511 /* We know we have room. */
512 SIVAL(p, 0x00, 0); /* next offset */
513 SCVAL(p, 0x04, ea_list->ea.flags);
514 SCVAL(p, 0x05, dos_namelen);
515 SSVAL(p, 0x06, ea_list->ea.value.length);
516 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
517 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
518 if (pad) {
519 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
520 '\0',
521 pad);
523 total_data_size -= this_size;
526 p += this_size;
529 *ret_data_size = PTR_DIFF(p, pdata);
530 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
531 return NT_STATUS_OK;
534 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
536 size_t total_ea_len = 0;
537 TALLOC_CTX *mem_ctx;
538 struct ea_list *ea_list = NULL;
540 if (!lp_ea_support(SNUM(conn))) {
541 return 0;
543 mem_ctx = talloc_stackframe();
545 /* If this is a stream fsp, then we need to instead find the
546 * estimated ea len from the main file, not the stream
547 * (streams cannot have EAs), but the estimate isn't just 0 in
548 * this case! */
549 if (is_ntfs_stream_smb_fname(smb_fname)) {
550 fsp = NULL;
552 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
553 if(conn->sconn->using_smb2) {
554 NTSTATUS status;
555 unsigned int ret_data_size;
557 * We're going to be using fill_ea_chained_buffer() to
558 * marshall EA's - this size is significantly larger
559 * than the SMB1 buffer. Re-calculate the size without
560 * marshalling.
562 status = fill_ea_chained_buffer(mem_ctx,
563 NULL,
565 &ret_data_size,
566 conn,
567 ea_list);
568 if (!NT_STATUS_IS_OK(status)) {
569 ret_data_size = 0;
571 total_ea_len = ret_data_size;
573 TALLOC_FREE(mem_ctx);
574 return total_ea_len;
577 /****************************************************************************
578 Ensure the EA name is case insensitive by matching any existing EA name.
579 ****************************************************************************/
581 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
583 size_t total_ea_len;
584 TALLOC_CTX *mem_ctx = talloc_tos();
585 struct ea_list *ea_list;
586 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
587 if (!NT_STATUS_IS_OK(status)) {
588 return;
591 for (; ea_list; ea_list = ea_list->next) {
592 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
593 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
594 &unix_ea_name[5], ea_list->ea.name));
595 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
596 break;
601 /****************************************************************************
602 Set or delete an extended attribute.
603 ****************************************************************************/
605 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
606 const struct smb_filename *smb_fname, struct ea_list *ea_list)
608 NTSTATUS status;
609 char *fname = NULL;
611 if (!lp_ea_support(SNUM(conn))) {
612 return NT_STATUS_EAS_NOT_SUPPORTED;
615 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
616 if (!NT_STATUS_IS_OK(status)) {
617 return status;
620 /* Setting EAs on streams isn't supported. */
621 if (is_ntfs_stream_smb_fname(smb_fname)) {
622 return NT_STATUS_INVALID_PARAMETER;
626 * Filter out invalid Windows EA names - before
627 * we set *any* of them.
630 if (ea_list_has_invalid_name(ea_list)) {
631 return STATUS_INVALID_EA_NAME;
634 fname = smb_fname->base_name;
636 for (;ea_list; ea_list = ea_list->next) {
637 int ret;
638 fstring unix_ea_name;
640 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
641 fstrcat(unix_ea_name, ea_list->ea.name);
643 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
645 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
647 if (samba_private_attr_name(unix_ea_name)) {
648 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
649 return NT_STATUS_ACCESS_DENIED;
652 if (ea_list->ea.value.length == 0) {
653 /* Remove the attribute. */
654 if (fsp && (fsp->fh->fd != -1)) {
655 DEBUG(10,("set_ea: deleting ea name %s on "
656 "file %s by file descriptor.\n",
657 unix_ea_name, fsp_str_dbg(fsp)));
658 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
659 } else {
660 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
661 unix_ea_name, fname));
662 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
664 #ifdef ENOATTR
665 /* Removing a non existent attribute always succeeds. */
666 if (ret == -1 && errno == ENOATTR) {
667 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
668 unix_ea_name));
669 ret = 0;
671 #endif
672 } else {
673 if (fsp && (fsp->fh->fd != -1)) {
674 DEBUG(10,("set_ea: setting ea name %s on file "
675 "%s by file descriptor.\n",
676 unix_ea_name, fsp_str_dbg(fsp)));
677 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
678 ea_list->ea.value.data, ea_list->ea.value.length, 0);
679 } else {
680 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
681 unix_ea_name, fname));
682 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
683 ea_list->ea.value.data, ea_list->ea.value.length, 0);
687 if (ret == -1) {
688 #ifdef ENOTSUP
689 if (errno == ENOTSUP) {
690 return NT_STATUS_EAS_NOT_SUPPORTED;
692 #endif
693 return map_nt_error_from_unix(errno);
697 return NT_STATUS_OK;
699 /****************************************************************************
700 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
701 ****************************************************************************/
703 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
705 struct ea_list *ea_list_head = NULL;
706 size_t converted_size, offset = 0;
708 while (offset + 2 < data_size) {
709 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
710 unsigned int namelen = CVAL(pdata,offset);
712 offset++; /* Go past the namelen byte. */
714 /* integer wrap paranioa. */
715 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
716 (offset > data_size) || (namelen > data_size) ||
717 (offset + namelen >= data_size)) {
718 break;
720 /* Ensure the name is null terminated. */
721 if (pdata[offset + namelen] != '\0') {
722 return NULL;
724 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
725 &converted_size)) {
726 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
727 "failed: %s", strerror(errno)));
729 if (!eal->ea.name) {
730 return NULL;
733 offset += (namelen + 1); /* Go past the name + terminating zero. */
734 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
735 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
738 return ea_list_head;
741 /****************************************************************************
742 Read one EA list entry from the buffer.
743 ****************************************************************************/
745 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
747 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
748 uint16 val_len;
749 unsigned int namelen;
750 size_t converted_size;
752 if (!eal) {
753 return NULL;
756 if (data_size < 6) {
757 return NULL;
760 eal->ea.flags = CVAL(pdata,0);
761 namelen = CVAL(pdata,1);
762 val_len = SVAL(pdata,2);
764 if (4 + namelen + 1 + val_len > data_size) {
765 return NULL;
768 /* Ensure the name is null terminated. */
769 if (pdata[namelen + 4] != '\0') {
770 return NULL;
772 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
773 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
774 strerror(errno)));
776 if (!eal->ea.name) {
777 return NULL;
780 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
781 if (!eal->ea.value.data) {
782 return NULL;
785 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
787 /* Ensure we're null terminated just in case we print the value. */
788 eal->ea.value.data[val_len] = '\0';
789 /* But don't count the null. */
790 eal->ea.value.length--;
792 if (pbytes_used) {
793 *pbytes_used = 4 + namelen + 1 + val_len;
796 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
797 dump_data(10, eal->ea.value.data, eal->ea.value.length);
799 return eal;
802 /****************************************************************************
803 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
804 ****************************************************************************/
806 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
808 struct ea_list *ea_list_head = NULL;
809 size_t offset = 0;
810 size_t bytes_used = 0;
812 while (offset < data_size) {
813 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
815 if (!eal) {
816 return NULL;
819 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
820 offset += bytes_used;
823 return ea_list_head;
826 /****************************************************************************
827 Count the total EA size needed.
828 ****************************************************************************/
830 static size_t ea_list_size(struct ea_list *ealist)
832 fstring dos_ea_name;
833 struct ea_list *listp;
834 size_t ret = 0;
836 for (listp = ealist; listp; listp = listp->next) {
837 push_ascii_fstring(dos_ea_name, listp->ea.name);
838 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
840 /* Add on 4 for total length. */
841 if (ret) {
842 ret += 4;
845 return ret;
848 /****************************************************************************
849 Return a union of EA's from a file list and a list of names.
850 The TALLOC context for the two lists *MUST* be identical as we steal
851 memory from one list to add to another. JRA.
852 ****************************************************************************/
854 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
856 struct ea_list *nlistp, *flistp;
858 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
859 for (flistp = file_list; flistp; flistp = flistp->next) {
860 if (strequal(nlistp->ea.name, flistp->ea.name)) {
861 break;
865 if (flistp) {
866 /* Copy the data from this entry. */
867 nlistp->ea.flags = flistp->ea.flags;
868 nlistp->ea.value = flistp->ea.value;
869 } else {
870 /* Null entry. */
871 nlistp->ea.flags = 0;
872 ZERO_STRUCT(nlistp->ea.value);
876 *total_ea_len = ea_list_size(name_list);
877 return name_list;
880 /****************************************************************************
881 Send the required number of replies back.
882 We assume all fields other than the data fields are
883 set correctly for the type of call.
884 HACK ! Always assumes smb_setup field is zero.
885 ****************************************************************************/
887 void send_trans2_replies(connection_struct *conn,
888 struct smb_request *req,
889 const char *params,
890 int paramsize,
891 const char *pdata,
892 int datasize,
893 int max_data_bytes)
895 /* As we are using a protocol > LANMAN1 then the max_send
896 variable must have been set in the sessetupX call.
897 This takes precedence over the max_xmit field in the
898 global struct. These different max_xmit variables should
899 be merged as this is now too confusing */
901 int data_to_send = datasize;
902 int params_to_send = paramsize;
903 int useable_space;
904 const char *pp = params;
905 const char *pd = pdata;
906 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
907 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
908 int data_alignment_offset = 0;
909 bool overflow = False;
910 struct smbd_server_connection *sconn = req->sconn;
911 int max_send = sconn->smb1.sessions.max_send;
913 /* Modify the data_to_send and datasize and set the error if
914 we're trying to send more than max_data_bytes. We still send
915 the part of the packet(s) that fit. Strange, but needed
916 for OS/2. */
918 if (max_data_bytes > 0 && datasize > max_data_bytes) {
919 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
920 max_data_bytes, datasize ));
921 datasize = data_to_send = max_data_bytes;
922 overflow = True;
925 /* If there genuinely are no parameters or data to send just send the empty packet */
927 if(params_to_send == 0 && data_to_send == 0) {
928 reply_outbuf(req, 10, 0);
929 show_msg((char *)req->outbuf);
930 if (!srv_send_smb(sconn,
931 (char *)req->outbuf,
932 true, req->seqnum+1,
933 IS_CONN_ENCRYPTED(conn),
934 &req->pcd)) {
935 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
937 TALLOC_FREE(req->outbuf);
938 return;
941 /* When sending params and data ensure that both are nicely aligned */
942 /* Only do this alignment when there is also data to send - else
943 can cause NT redirector problems. */
945 if (((params_to_send % 4) != 0) && (data_to_send != 0))
946 data_alignment_offset = 4 - (params_to_send % 4);
948 /* Space is bufsize minus Netbios over TCP header minus SMB header */
949 /* The alignment_offset is to align the param bytes on an even byte
950 boundary. NT 4.0 Beta needs this to work correctly. */
952 useable_space = max_send - (smb_size
953 + 2 * 10 /* wct */
954 + alignment_offset
955 + data_alignment_offset);
957 if (useable_space < 0) {
958 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
959 "= %d!!!", useable_space));
960 exit_server_cleanly("send_trans2_replies: Not enough space");
963 while (params_to_send || data_to_send) {
964 /* Calculate whether we will totally or partially fill this packet */
966 total_sent_thistime = params_to_send + data_to_send;
968 /* We can never send more than useable_space */
970 * Note that 'useable_space' does not include the alignment offsets,
971 * but we must include the alignment offsets in the calculation of
972 * the length of the data we send over the wire, as the alignment offsets
973 * are sent here. Fix from Marc_Jacobsen@hp.com.
976 total_sent_thistime = MIN(total_sent_thistime, useable_space);
978 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
979 + data_alignment_offset);
981 /* Set total params and data to be sent */
982 SSVAL(req->outbuf,smb_tprcnt,paramsize);
983 SSVAL(req->outbuf,smb_tdrcnt,datasize);
985 /* Calculate how many parameters and data we can fit into
986 * this packet. Parameters get precedence
989 params_sent_thistime = MIN(params_to_send,useable_space);
990 data_sent_thistime = useable_space - params_sent_thistime;
991 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
993 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
995 /* smb_proff is the offset from the start of the SMB header to the
996 parameter bytes, however the first 4 bytes of outbuf are
997 the Netbios over TCP header. Thus use smb_base() to subtract
998 them from the calculation */
1000 SSVAL(req->outbuf,smb_proff,
1001 ((smb_buf(req->outbuf)+alignment_offset)
1002 - smb_base(req->outbuf)));
1004 if(params_sent_thistime == 0)
1005 SSVAL(req->outbuf,smb_prdisp,0);
1006 else
1007 /* Absolute displacement of param bytes sent in this packet */
1008 SSVAL(req->outbuf,smb_prdisp,pp - params);
1010 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1011 if(data_sent_thistime == 0) {
1012 SSVAL(req->outbuf,smb_droff,0);
1013 SSVAL(req->outbuf,smb_drdisp, 0);
1014 } else {
1015 /* The offset of the data bytes is the offset of the
1016 parameter bytes plus the number of parameters being sent this time */
1017 SSVAL(req->outbuf, smb_droff,
1018 ((smb_buf(req->outbuf)+alignment_offset)
1019 - smb_base(req->outbuf))
1020 + params_sent_thistime + data_alignment_offset);
1021 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1024 /* Initialize the padding for alignment */
1026 if (alignment_offset != 0) {
1027 memset(smb_buf(req->outbuf), 0, alignment_offset);
1030 /* Copy the param bytes into the packet */
1032 if(params_sent_thistime) {
1033 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1034 params_sent_thistime);
1037 /* Copy in the data bytes */
1038 if(data_sent_thistime) {
1039 if (data_alignment_offset != 0) {
1040 memset((smb_buf(req->outbuf)+alignment_offset+
1041 params_sent_thistime), 0,
1042 data_alignment_offset);
1044 memcpy(smb_buf(req->outbuf)+alignment_offset
1045 +params_sent_thistime+data_alignment_offset,
1046 pd,data_sent_thistime);
1049 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1050 params_sent_thistime, data_sent_thistime, useable_space));
1051 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1052 params_to_send, data_to_send, paramsize, datasize));
1054 if (overflow) {
1055 error_packet_set((char *)req->outbuf,
1056 ERRDOS,ERRbufferoverflow,
1057 STATUS_BUFFER_OVERFLOW,
1058 __LINE__,__FILE__);
1061 /* Send the packet */
1062 show_msg((char *)req->outbuf);
1063 if (!srv_send_smb(sconn,
1064 (char *)req->outbuf,
1065 true, req->seqnum+1,
1066 IS_CONN_ENCRYPTED(conn),
1067 &req->pcd))
1068 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1070 TALLOC_FREE(req->outbuf);
1072 pp += params_sent_thistime;
1073 pd += data_sent_thistime;
1075 params_to_send -= params_sent_thistime;
1076 data_to_send -= data_sent_thistime;
1078 /* Sanity check */
1079 if(params_to_send < 0 || data_to_send < 0) {
1080 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1081 params_to_send, data_to_send));
1082 return;
1086 return;
1089 /****************************************************************************
1090 Reply to a TRANSACT2_OPEN.
1091 ****************************************************************************/
1093 static void call_trans2open(connection_struct *conn,
1094 struct smb_request *req,
1095 char **pparams, int total_params,
1096 char **ppdata, int total_data,
1097 unsigned int max_data_bytes)
1099 struct smb_filename *smb_fname = NULL;
1100 char *params = *pparams;
1101 char *pdata = *ppdata;
1102 int deny_mode;
1103 int32 open_attr;
1104 bool oplock_request;
1105 #if 0
1106 bool return_additional_info;
1107 int16 open_sattr;
1108 time_t open_time;
1109 #endif
1110 int open_ofun;
1111 uint32 open_size;
1112 char *pname;
1113 char *fname = NULL;
1114 off_t size=0;
1115 int fattr=0,mtime=0;
1116 SMB_INO_T inode = 0;
1117 int smb_action = 0;
1118 files_struct *fsp;
1119 struct ea_list *ea_list = NULL;
1120 uint16 flags = 0;
1121 NTSTATUS status;
1122 uint32 access_mask;
1123 uint32 share_mode;
1124 uint32 create_disposition;
1125 uint32 create_options = 0;
1126 uint32_t private_flags = 0;
1127 TALLOC_CTX *ctx = talloc_tos();
1130 * Ensure we have enough parameters to perform the operation.
1133 if (total_params < 29) {
1134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1135 goto out;
1138 flags = SVAL(params, 0);
1139 deny_mode = SVAL(params, 2);
1140 open_attr = SVAL(params,6);
1141 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1142 if (oplock_request) {
1143 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1146 #if 0
1147 return_additional_info = BITSETW(params,0);
1148 open_sattr = SVAL(params, 4);
1149 open_time = make_unix_date3(params+8);
1150 #endif
1151 open_ofun = SVAL(params,12);
1152 open_size = IVAL(params,14);
1153 pname = &params[28];
1155 if (IS_IPC(conn)) {
1156 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1157 goto out;
1160 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1161 total_params - 28, STR_TERMINATE,
1162 &status);
1163 if (!NT_STATUS_IS_OK(status)) {
1164 reply_nterror(req, status);
1165 goto out;
1168 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1169 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1170 (unsigned int)open_ofun, open_size));
1172 status = filename_convert(ctx,
1173 conn,
1174 req->flags2 & FLAGS2_DFS_PATHNAMES,
1175 fname,
1177 NULL,
1178 &smb_fname);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1181 reply_botherror(req,
1182 NT_STATUS_PATH_NOT_COVERED,
1183 ERRSRV, ERRbadpath);
1184 goto out;
1186 reply_nterror(req, status);
1187 goto out;
1190 if (open_ofun == 0) {
1191 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1192 goto out;
1195 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1196 open_ofun,
1197 &access_mask, &share_mode,
1198 &create_disposition,
1199 &create_options,
1200 &private_flags)) {
1201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1202 goto out;
1205 /* Any data in this call is an EA list. */
1206 if (total_data && (total_data != 4)) {
1207 if (total_data < 10) {
1208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1209 goto out;
1212 if (IVAL(pdata,0) > total_data) {
1213 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1214 IVAL(pdata,0), (unsigned int)total_data));
1215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1216 goto out;
1219 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1220 total_data - 4);
1221 if (!ea_list) {
1222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1223 goto out;
1226 if (!lp_ea_support(SNUM(conn))) {
1227 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1228 goto out;
1232 status = SMB_VFS_CREATE_FILE(
1233 conn, /* conn */
1234 req, /* req */
1235 0, /* root_dir_fid */
1236 smb_fname, /* fname */
1237 access_mask, /* access_mask */
1238 share_mode, /* share_access */
1239 create_disposition, /* create_disposition*/
1240 create_options, /* create_options */
1241 open_attr, /* file_attributes */
1242 oplock_request, /* oplock_request */
1243 open_size, /* allocation_size */
1244 private_flags,
1245 NULL, /* sd */
1246 ea_list, /* ea_list */
1247 &fsp, /* result */
1248 &smb_action); /* psbuf */
1250 if (!NT_STATUS_IS_OK(status)) {
1251 if (open_was_deferred(req->sconn, req->mid)) {
1252 /* We have re-scheduled this call. */
1253 goto out;
1255 reply_openerror(req, status);
1256 goto out;
1259 size = get_file_size_stat(&smb_fname->st);
1260 fattr = dos_mode(conn, smb_fname);
1261 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1262 inode = smb_fname->st.st_ex_ino;
1263 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1264 close_file(req, fsp, ERROR_CLOSE);
1265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1266 goto out;
1269 /* Realloc the size of parameters and data we will return */
1270 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1271 if(*pparams == NULL ) {
1272 reply_nterror(req, NT_STATUS_NO_MEMORY);
1273 goto out;
1275 params = *pparams;
1277 SSVAL(params,0,fsp->fnum);
1278 SSVAL(params,2,fattr);
1279 srv_put_dos_date2(params,4, mtime);
1280 SIVAL(params,8, (uint32)size);
1281 SSVAL(params,12,deny_mode);
1282 SSVAL(params,14,0); /* open_type - file or directory. */
1283 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1285 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1286 smb_action |= EXTENDED_OPLOCK_GRANTED;
1289 SSVAL(params,18,smb_action);
1292 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1294 SIVAL(params,20,inode);
1295 SSVAL(params,24,0); /* Padding. */
1296 if (flags & 8) {
1297 uint32 ea_size = estimate_ea_size(conn, fsp,
1298 smb_fname);
1299 SIVAL(params, 26, ea_size);
1300 } else {
1301 SIVAL(params, 26, 0);
1304 /* Send the required number of replies */
1305 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1306 out:
1307 TALLOC_FREE(smb_fname);
1310 /*********************************************************
1311 Routine to check if a given string matches exactly.
1312 as a special case a mask of "." does NOT match. That
1313 is required for correct wildcard semantics
1314 Case can be significant or not.
1315 **********************************************************/
1317 static bool exact_match(bool has_wild,
1318 bool case_sensitive,
1319 const char *str,
1320 const char *mask)
1322 if (mask[0] == '.' && mask[1] == 0) {
1323 return false;
1326 if (has_wild) {
1327 return false;
1330 if (case_sensitive) {
1331 return strcmp(str,mask)==0;
1332 } else {
1333 return strcasecmp_m(str,mask) == 0;
1337 /****************************************************************************
1338 Return the filetype for UNIX extensions.
1339 ****************************************************************************/
1341 static uint32 unix_filetype(mode_t mode)
1343 if(S_ISREG(mode))
1344 return UNIX_TYPE_FILE;
1345 else if(S_ISDIR(mode))
1346 return UNIX_TYPE_DIR;
1347 #ifdef S_ISLNK
1348 else if(S_ISLNK(mode))
1349 return UNIX_TYPE_SYMLINK;
1350 #endif
1351 #ifdef S_ISCHR
1352 else if(S_ISCHR(mode))
1353 return UNIX_TYPE_CHARDEV;
1354 #endif
1355 #ifdef S_ISBLK
1356 else if(S_ISBLK(mode))
1357 return UNIX_TYPE_BLKDEV;
1358 #endif
1359 #ifdef S_ISFIFO
1360 else if(S_ISFIFO(mode))
1361 return UNIX_TYPE_FIFO;
1362 #endif
1363 #ifdef S_ISSOCK
1364 else if(S_ISSOCK(mode))
1365 return UNIX_TYPE_SOCKET;
1366 #endif
1368 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1369 return UNIX_TYPE_UNKNOWN;
1372 /****************************************************************************
1373 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1374 ****************************************************************************/
1376 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1378 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1379 const SMB_STRUCT_STAT *psbuf,
1380 uint32 perms,
1381 enum perm_type ptype,
1382 mode_t *ret_perms)
1384 mode_t ret = 0;
1386 if (perms == SMB_MODE_NO_CHANGE) {
1387 if (!VALID_STAT(*psbuf)) {
1388 return NT_STATUS_INVALID_PARAMETER;
1389 } else {
1390 *ret_perms = psbuf->st_ex_mode;
1391 return NT_STATUS_OK;
1395 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1396 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1397 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1398 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1399 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1400 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1401 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1402 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1403 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1404 #ifdef S_ISVTX
1405 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1406 #endif
1407 #ifdef S_ISGID
1408 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1409 #endif
1410 #ifdef S_ISUID
1411 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1412 #endif
1414 switch (ptype) {
1415 case PERM_NEW_FILE:
1416 case PERM_EXISTING_FILE:
1417 /* Apply mode mask */
1418 ret &= lp_create_mask(SNUM(conn));
1419 /* Add in force bits */
1420 ret |= lp_force_create_mode(SNUM(conn));
1421 break;
1422 case PERM_NEW_DIR:
1423 case PERM_EXISTING_DIR:
1424 ret &= lp_dir_mask(SNUM(conn));
1425 /* Add in force bits */
1426 ret |= lp_force_dir_mode(SNUM(conn));
1427 break;
1430 *ret_perms = ret;
1431 return NT_STATUS_OK;
1434 /****************************************************************************
1435 Needed to show the msdfs symlinks as directories. Modifies psbuf
1436 to be a directory if it's a msdfs link.
1437 ****************************************************************************/
1439 static bool check_msdfs_link(connection_struct *conn,
1440 const char *pathname,
1441 SMB_STRUCT_STAT *psbuf)
1443 int saved_errno = errno;
1444 if(lp_host_msdfs() &&
1445 lp_msdfs_root(SNUM(conn)) &&
1446 is_msdfs_link(conn, pathname, psbuf)) {
1448 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1449 "as a directory\n",
1450 pathname));
1451 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1452 errno = saved_errno;
1453 return true;
1455 errno = saved_errno;
1456 return false;
1460 /****************************************************************************
1461 Get a level dependent lanman2 dir entry.
1462 ****************************************************************************/
1464 struct smbd_dirptr_lanman2_state {
1465 connection_struct *conn;
1466 uint32_t info_level;
1467 bool check_mangled_names;
1468 bool has_wild;
1469 bool got_exact_match;
1472 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1473 void *private_data,
1474 const char *dname,
1475 const char *mask,
1476 char **_fname)
1478 struct smbd_dirptr_lanman2_state *state =
1479 (struct smbd_dirptr_lanman2_state *)private_data;
1480 bool ok;
1481 char mangled_name[13]; /* mangled 8.3 name. */
1482 bool got_match;
1483 const char *fname;
1485 /* Mangle fname if it's an illegal name. */
1486 if (mangle_must_mangle(dname, state->conn->params)) {
1487 ok = name_to_8_3(dname, mangled_name,
1488 true, state->conn->params);
1489 if (!ok) {
1490 return false;
1492 fname = mangled_name;
1493 } else {
1494 fname = dname;
1497 got_match = exact_match(state->has_wild,
1498 state->conn->case_sensitive,
1499 fname, mask);
1500 state->got_exact_match = got_match;
1501 if (!got_match) {
1502 got_match = mask_match(fname, mask,
1503 state->conn->case_sensitive);
1506 if(!got_match && state->check_mangled_names &&
1507 !mangle_is_8_3(fname, false, state->conn->params)) {
1509 * It turns out that NT matches wildcards against
1510 * both long *and* short names. This may explain some
1511 * of the wildcard wierdness from old DOS clients
1512 * that some people have been seeing.... JRA.
1514 /* Force the mangling into 8.3. */
1515 ok = name_to_8_3(fname, mangled_name,
1516 false, state->conn->params);
1517 if (!ok) {
1518 return false;
1521 got_match = exact_match(state->has_wild,
1522 state->conn->case_sensitive,
1523 mangled_name, mask);
1524 state->got_exact_match = got_match;
1525 if (!got_match) {
1526 got_match = mask_match(mangled_name, mask,
1527 state->conn->case_sensitive);
1531 if (!got_match) {
1532 return false;
1535 *_fname = talloc_strdup(ctx, fname);
1536 if (*_fname == NULL) {
1537 return false;
1540 return true;
1543 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1544 void *private_data,
1545 struct smb_filename *smb_fname,
1546 uint32_t *_mode)
1548 struct smbd_dirptr_lanman2_state *state =
1549 (struct smbd_dirptr_lanman2_state *)private_data;
1550 bool ms_dfs_link = false;
1551 uint32_t mode = 0;
1553 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1554 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1555 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1556 "Couldn't lstat [%s] (%s)\n",
1557 smb_fname_str_dbg(smb_fname),
1558 strerror(errno)));
1559 return false;
1561 } else if (!VALID_STAT(smb_fname->st) &&
1562 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1563 /* Needed to show the msdfs symlinks as
1564 * directories */
1566 ms_dfs_link = check_msdfs_link(state->conn,
1567 smb_fname->base_name,
1568 &smb_fname->st);
1569 if (!ms_dfs_link) {
1570 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1571 "Couldn't stat [%s] (%s)\n",
1572 smb_fname_str_dbg(smb_fname),
1573 strerror(errno)));
1574 return false;
1578 if (ms_dfs_link) {
1579 mode = dos_mode_msdfs(state->conn, smb_fname);
1580 } else {
1581 mode = dos_mode(state->conn, smb_fname);
1584 *_mode = mode;
1585 return true;
1588 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1589 connection_struct *conn,
1590 uint16_t flags2,
1591 uint32_t info_level,
1592 struct ea_list *name_list,
1593 bool check_mangled_names,
1594 bool requires_resume_key,
1595 uint32_t mode,
1596 const char *fname,
1597 const struct smb_filename *smb_fname,
1598 int space_remaining,
1599 uint8_t align,
1600 bool do_pad,
1601 char *base_data,
1602 char **ppdata,
1603 char *end_data,
1604 bool *out_of_space,
1605 uint64_t *last_entry_off)
1607 char *p, *q, *pdata = *ppdata;
1608 uint32_t reskey=0;
1609 uint64_t file_size = 0;
1610 uint64_t allocation_size = 0;
1611 uint64_t file_index = 0;
1612 uint32_t len;
1613 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1614 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1615 char *nameptr;
1616 char *last_entry_ptr;
1617 bool was_8_3;
1618 int off;
1619 int pad = 0;
1621 *out_of_space = false;
1623 ZERO_STRUCT(mdate_ts);
1624 ZERO_STRUCT(adate_ts);
1625 ZERO_STRUCT(create_date_ts);
1626 ZERO_STRUCT(cdate_ts);
1628 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1629 file_size = get_file_size_stat(&smb_fname->st);
1631 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1633 file_index = get_FileIndex(conn, &smb_fname->st);
1635 mdate_ts = smb_fname->st.st_ex_mtime;
1636 adate_ts = smb_fname->st.st_ex_atime;
1637 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1638 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1640 if (lp_dos_filetime_resolution(SNUM(conn))) {
1641 dos_filetime_timespec(&create_date_ts);
1642 dos_filetime_timespec(&mdate_ts);
1643 dos_filetime_timespec(&adate_ts);
1644 dos_filetime_timespec(&cdate_ts);
1647 create_date = convert_timespec_to_time_t(create_date_ts);
1648 mdate = convert_timespec_to_time_t(mdate_ts);
1649 adate = convert_timespec_to_time_t(adate_ts);
1651 /* align the record */
1652 SMB_ASSERT(align >= 1);
1654 off = (int)PTR_DIFF(pdata, base_data);
1655 pad = (off + (align-1)) & ~(align-1);
1656 pad -= off;
1658 if (pad && pad > space_remaining) {
1659 *out_of_space = true;
1660 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1661 "for padding (wanted %u, had %d)\n",
1662 (unsigned int)pad,
1663 space_remaining ));
1664 return false; /* Not finished - just out of space */
1667 off += pad;
1668 /* initialize padding to 0 */
1669 if (pad) {
1670 memset(pdata, 0, pad);
1672 space_remaining -= pad;
1674 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1675 space_remaining ));
1677 pdata += pad;
1678 p = pdata;
1679 last_entry_ptr = p;
1681 pad = 0;
1682 off = 0;
1684 switch (info_level) {
1685 case SMB_FIND_INFO_STANDARD:
1686 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1687 if(requires_resume_key) {
1688 SIVAL(p,0,reskey);
1689 p += 4;
1691 srv_put_dos_date2(p,0,create_date);
1692 srv_put_dos_date2(p,4,adate);
1693 srv_put_dos_date2(p,8,mdate);
1694 SIVAL(p,12,(uint32)file_size);
1695 SIVAL(p,16,(uint32)allocation_size);
1696 SSVAL(p,20,mode);
1697 p += 23;
1698 nameptr = p;
1699 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1700 p += ucs2_align(base_data, p, 0);
1702 len = srvstr_push(base_data, flags2, p,
1703 fname, PTR_DIFF(end_data, p),
1704 STR_TERMINATE);
1705 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1706 if (len > 2) {
1707 SCVAL(nameptr, -1, len - 2);
1708 } else {
1709 SCVAL(nameptr, -1, 0);
1711 } else {
1712 if (len > 1) {
1713 SCVAL(nameptr, -1, len - 1);
1714 } else {
1715 SCVAL(nameptr, -1, 0);
1718 p += len;
1719 break;
1721 case SMB_FIND_EA_SIZE:
1722 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1723 if (requires_resume_key) {
1724 SIVAL(p,0,reskey);
1725 p += 4;
1727 srv_put_dos_date2(p,0,create_date);
1728 srv_put_dos_date2(p,4,adate);
1729 srv_put_dos_date2(p,8,mdate);
1730 SIVAL(p,12,(uint32)file_size);
1731 SIVAL(p,16,(uint32)allocation_size);
1732 SSVAL(p,20,mode);
1734 unsigned int ea_size = estimate_ea_size(conn, NULL,
1735 smb_fname);
1736 SIVAL(p,22,ea_size); /* Extended attributes */
1738 p += 27;
1739 nameptr = p - 1;
1740 len = srvstr_push(base_data, flags2,
1741 p, fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE | STR_NOALIGN);
1743 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1744 if (len > 2) {
1745 len -= 2;
1746 } else {
1747 len = 0;
1749 } else {
1750 if (len > 1) {
1751 len -= 1;
1752 } else {
1753 len = 0;
1756 SCVAL(nameptr,0,len);
1757 p += len;
1758 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1759 break;
1761 case SMB_FIND_EA_LIST:
1763 struct ea_list *file_list = NULL;
1764 size_t ea_len = 0;
1765 NTSTATUS status;
1767 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1768 if (!name_list) {
1769 return false;
1771 if (requires_resume_key) {
1772 SIVAL(p,0,reskey);
1773 p += 4;
1775 srv_put_dos_date2(p,0,create_date);
1776 srv_put_dos_date2(p,4,adate);
1777 srv_put_dos_date2(p,8,mdate);
1778 SIVAL(p,12,(uint32)file_size);
1779 SIVAL(p,16,(uint32)allocation_size);
1780 SSVAL(p,20,mode);
1781 p += 22; /* p now points to the EA area. */
1783 status = get_ea_list_from_file(ctx, conn, NULL,
1784 smb_fname,
1785 &ea_len, &file_list);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 file_list = NULL;
1789 name_list = ea_list_union(name_list, file_list, &ea_len);
1791 /* We need to determine if this entry will fit in the space available. */
1792 /* Max string size is 255 bytes. */
1793 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1794 *out_of_space = true;
1795 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1796 "(wanted %u, had %d)\n",
1797 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1798 space_remaining ));
1799 return False; /* Not finished - just out of space */
1802 /* Push the ea_data followed by the name. */
1803 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1804 nameptr = p;
1805 len = srvstr_push(base_data, flags2,
1806 p + 1, fname, PTR_DIFF(end_data, p+1),
1807 STR_TERMINATE | STR_NOALIGN);
1808 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1809 if (len > 2) {
1810 len -= 2;
1811 } else {
1812 len = 0;
1814 } else {
1815 if (len > 1) {
1816 len -= 1;
1817 } else {
1818 len = 0;
1821 SCVAL(nameptr,0,len);
1822 p += len + 1;
1823 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1824 break;
1827 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1828 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1829 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1830 p += 4;
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1844 p += 4;
1846 /* Clear the short name buffer. This is
1847 * IMPORTANT as not doing so will trigger
1848 * a Win2k client bug. JRA.
1850 if (!was_8_3 && check_mangled_names) {
1851 char mangled_name[13]; /* mangled 8.3 name. */
1852 if (!name_to_8_3(fname,mangled_name,True,
1853 conn->params)) {
1854 /* Error - mangle failed ! */
1855 memset(mangled_name,'\0',12);
1857 mangled_name[12] = 0;
1858 len = srvstr_push(base_data, flags2,
1859 p+2, mangled_name, 24,
1860 STR_UPPER|STR_UNICODE);
1861 if (len < 24) {
1862 memset(p + 2 + len,'\0',24 - len);
1864 SSVAL(p, 0, len);
1865 } else {
1866 memset(p,'\0',26);
1868 p += 2 + 24;
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1872 SIVAL(q,0,len);
1873 p += len;
1875 len = PTR_DIFF(p, pdata);
1876 pad = (len + (align-1)) & ~(align-1);
1878 * offset to the next entry, the caller
1879 * will overwrite it for the last entry
1880 * that's why we always include the padding
1882 SIVAL(pdata,0,pad);
1884 * set padding to zero
1886 if (do_pad) {
1887 memset(p, 0, pad - len);
1888 p = pdata + pad;
1889 } else {
1890 p = pdata + len;
1892 break;
1894 case SMB_FIND_FILE_DIRECTORY_INFO:
1895 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1896 p += 4;
1897 SIVAL(p,0,reskey); p += 4;
1898 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1899 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1900 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1901 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1902 SOFF_T(p,0,file_size); p += 8;
1903 SOFF_T(p,0,allocation_size); p += 8;
1904 SIVAL(p,0,mode); p += 4;
1905 len = srvstr_push(base_data, flags2,
1906 p + 4, fname, PTR_DIFF(end_data, p+4),
1907 STR_TERMINATE_ASCII);
1908 SIVAL(p,0,len);
1909 p += 4 + len;
1911 len = PTR_DIFF(p, pdata);
1912 pad = (len + (align-1)) & ~(align-1);
1914 * offset to the next entry, the caller
1915 * will overwrite it for the last entry
1916 * that's why we always include the padding
1918 SIVAL(pdata,0,pad);
1920 * set padding to zero
1922 if (do_pad) {
1923 memset(p, 0, pad - len);
1924 p = pdata + pad;
1925 } else {
1926 p = pdata + len;
1928 break;
1930 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1931 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1932 p += 4;
1933 SIVAL(p,0,reskey); p += 4;
1934 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1937 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1938 SOFF_T(p,0,file_size); p += 8;
1939 SOFF_T(p,0,allocation_size); p += 8;
1940 SIVAL(p,0,mode); p += 4;
1941 q = p; p += 4; /* q is placeholder for name length. */
1943 unsigned int ea_size = estimate_ea_size(conn, NULL,
1944 smb_fname);
1945 SIVAL(p,0,ea_size); /* Extended attributes */
1946 p +=4;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q, 0, len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 case SMB_FIND_FILE_NAMES_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1975 p += 4;
1976 SIVAL(p,0,reskey); p += 4;
1977 p += 4;
1978 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1979 acl on a dir (tridge) */
1980 len = srvstr_push(base_data, flags2, p,
1981 fname, PTR_DIFF(end_data, p),
1982 STR_TERMINATE_ASCII);
1983 SIVAL(p, -4, len);
1984 p += len;
1986 len = PTR_DIFF(p, pdata);
1987 pad = (len + (align-1)) & ~(align-1);
1989 * offset to the next entry, the caller
1990 * will overwrite it for the last entry
1991 * that's why we always include the padding
1993 SIVAL(pdata,0,pad);
1995 * set padding to zero
1997 if (do_pad) {
1998 memset(p, 0, pad - len);
1999 p = pdata + pad;
2000 } else {
2001 p = pdata + len;
2003 break;
2005 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2006 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2007 p += 4;
2008 SIVAL(p,0,reskey); p += 4;
2009 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2010 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2011 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2012 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2013 SOFF_T(p,0,file_size); p += 8;
2014 SOFF_T(p,0,allocation_size); p += 8;
2015 SIVAL(p,0,mode); p += 4;
2016 q = p; p += 4; /* q is placeholder for name length. */
2018 unsigned int ea_size = estimate_ea_size(conn, NULL,
2019 smb_fname);
2020 SIVAL(p,0,ea_size); /* Extended attributes */
2021 p +=4;
2023 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2024 SBVAL(p,0,file_index); p += 8;
2025 len = srvstr_push(base_data, flags2, p,
2026 fname, PTR_DIFF(end_data, p),
2027 STR_TERMINATE_ASCII);
2028 SIVAL(q, 0, len);
2029 p += len;
2031 len = PTR_DIFF(p, pdata);
2032 pad = (len + (align-1)) & ~(align-1);
2034 * offset to the next entry, the caller
2035 * will overwrite it for the last entry
2036 * that's why we always include the padding
2038 SIVAL(pdata,0,pad);
2040 * set padding to zero
2042 if (do_pad) {
2043 memset(p, 0, pad - len);
2044 p = pdata + pad;
2045 } else {
2046 p = pdata + len;
2048 break;
2050 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2051 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2052 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2053 p += 4;
2054 SIVAL(p,0,reskey); p += 4;
2055 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2056 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2057 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2058 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2059 SOFF_T(p,0,file_size); p += 8;
2060 SOFF_T(p,0,allocation_size); p += 8;
2061 SIVAL(p,0,mode); p += 4;
2062 q = p; p += 4; /* q is placeholder for name length */
2064 unsigned int ea_size = estimate_ea_size(conn, NULL,
2065 smb_fname);
2066 SIVAL(p,0,ea_size); /* Extended attributes */
2067 p +=4;
2069 /* Clear the short name buffer. This is
2070 * IMPORTANT as not doing so will trigger
2071 * a Win2k client bug. JRA.
2073 if (!was_8_3 && check_mangled_names) {
2074 char mangled_name[13]; /* mangled 8.3 name. */
2075 if (!name_to_8_3(fname,mangled_name,True,
2076 conn->params)) {
2077 /* Error - mangle failed ! */
2078 memset(mangled_name,'\0',12);
2080 mangled_name[12] = 0;
2081 len = srvstr_push(base_data, flags2,
2082 p+2, mangled_name, 24,
2083 STR_UPPER|STR_UNICODE);
2084 SSVAL(p, 0, len);
2085 if (len < 24) {
2086 memset(p + 2 + len,'\0',24 - len);
2088 SSVAL(p, 0, len);
2089 } else {
2090 memset(p,'\0',26);
2092 p += 26;
2093 SSVAL(p,0,0); p += 2; /* Reserved ? */
2094 SBVAL(p,0,file_index); p += 8;
2095 len = srvstr_push(base_data, flags2, p,
2096 fname, PTR_DIFF(end_data, p),
2097 STR_TERMINATE_ASCII);
2098 SIVAL(q,0,len);
2099 p += len;
2101 len = PTR_DIFF(p, pdata);
2102 pad = (len + (align-1)) & ~(align-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2108 SIVAL(pdata,0,pad);
2110 * set padding to zero
2112 if (do_pad) {
2113 memset(p, 0, pad - len);
2114 p = pdata + pad;
2115 } else {
2116 p = pdata + len;
2118 break;
2120 /* CIFS UNIX Extension. */
2122 case SMB_FIND_FILE_UNIX:
2123 case SMB_FIND_FILE_UNIX_INFO2:
2124 p+= 4;
2125 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2127 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2129 if (info_level == SMB_FIND_FILE_UNIX) {
2130 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2131 p = store_file_unix_basic(conn, p,
2132 NULL, &smb_fname->st);
2133 len = srvstr_push(base_data, flags2, p,
2134 fname, PTR_DIFF(end_data, p),
2135 STR_TERMINATE);
2136 } else {
2137 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2138 p = store_file_unix_basic_info2(conn, p,
2139 NULL, &smb_fname->st);
2140 nameptr = p;
2141 p += 4;
2142 len = srvstr_push(base_data, flags2, p, fname,
2143 PTR_DIFF(end_data, p), 0);
2144 SIVAL(nameptr, 0, len);
2147 p += len;
2149 len = PTR_DIFF(p, pdata);
2150 pad = (len + (align-1)) & ~(align-1);
2152 * offset to the next entry, the caller
2153 * will overwrite it for the last entry
2154 * that's why we always include the padding
2156 SIVAL(pdata,0,pad);
2158 * set padding to zero
2160 if (do_pad) {
2161 memset(p, 0, pad - len);
2162 p = pdata + pad;
2163 } else {
2164 p = pdata + len;
2166 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2168 break;
2170 default:
2171 return false;
2174 if (PTR_DIFF(p,pdata) > space_remaining) {
2175 *out_of_space = true;
2176 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2177 "(wanted %u, had %d)\n",
2178 (unsigned int)PTR_DIFF(p,pdata),
2179 space_remaining ));
2180 return false; /* Not finished - just out of space */
2183 /* Setup the last entry pointer, as an offset from base_data */
2184 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2185 /* Advance the data pointer to the next slot */
2186 *ppdata = p;
2188 return true;
2191 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2192 connection_struct *conn,
2193 struct dptr_struct *dirptr,
2194 uint16 flags2,
2195 const char *path_mask,
2196 uint32 dirtype,
2197 int info_level,
2198 int requires_resume_key,
2199 bool dont_descend,
2200 bool ask_sharemode,
2201 uint8_t align,
2202 bool do_pad,
2203 char **ppdata,
2204 char *base_data,
2205 char *end_data,
2206 int space_remaining,
2207 bool *out_of_space,
2208 bool *got_exact_match,
2209 int *_last_entry_off,
2210 struct ea_list *name_list)
2212 const char *p;
2213 const char *mask = NULL;
2214 long prev_dirpos = 0;
2215 uint32_t mode = 0;
2216 char *fname = NULL;
2217 struct smb_filename *smb_fname = NULL;
2218 struct smbd_dirptr_lanman2_state state;
2219 bool ok;
2220 uint64_t last_entry_off = 0;
2222 ZERO_STRUCT(state);
2223 state.conn = conn;
2224 state.info_level = info_level;
2225 state.check_mangled_names = lp_manglednames(conn->params);
2226 state.has_wild = dptr_has_wild(dirptr);
2227 state.got_exact_match = false;
2229 *out_of_space = false;
2230 *got_exact_match = false;
2232 p = strrchr_m(path_mask,'/');
2233 if(p != NULL) {
2234 if(p[1] == '\0') {
2235 mask = "*.*";
2236 } else {
2237 mask = p+1;
2239 } else {
2240 mask = path_mask;
2243 ok = smbd_dirptr_get_entry(ctx,
2244 dirptr,
2245 mask,
2246 dirtype,
2247 dont_descend,
2248 ask_sharemode,
2249 smbd_dirptr_lanman2_match_fn,
2250 smbd_dirptr_lanman2_mode_fn,
2251 &state,
2252 &fname,
2253 &smb_fname,
2254 &mode,
2255 &prev_dirpos);
2256 if (!ok) {
2257 return false;
2260 *got_exact_match = state.got_exact_match;
2262 ok = smbd_marshall_dir_entry(ctx,
2263 conn,
2264 flags2,
2265 info_level,
2266 name_list,
2267 state.check_mangled_names,
2268 requires_resume_key,
2269 mode,
2270 fname,
2271 smb_fname,
2272 space_remaining,
2273 align,
2274 do_pad,
2275 base_data,
2276 ppdata,
2277 end_data,
2278 out_of_space,
2279 &last_entry_off);
2280 TALLOC_FREE(fname);
2281 TALLOC_FREE(smb_fname);
2282 if (*out_of_space) {
2283 dptr_SeekDir(dirptr, prev_dirpos);
2284 return false;
2286 if (!ok) {
2287 return false;
2290 *_last_entry_off = last_entry_off;
2291 return true;
2294 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2295 connection_struct *conn,
2296 struct dptr_struct *dirptr,
2297 uint16 flags2,
2298 const char *path_mask,
2299 uint32 dirtype,
2300 int info_level,
2301 bool requires_resume_key,
2302 bool dont_descend,
2303 bool ask_sharemode,
2304 char **ppdata,
2305 char *base_data,
2306 char *end_data,
2307 int space_remaining,
2308 bool *out_of_space,
2309 bool *got_exact_match,
2310 int *last_entry_off,
2311 struct ea_list *name_list)
2313 uint8_t align = 4;
2314 const bool do_pad = true;
2316 if (info_level >= 1 && info_level <= 3) {
2317 /* No alignment on earlier info levels. */
2318 align = 1;
2321 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2322 path_mask, dirtype, info_level,
2323 requires_resume_key, dont_descend, ask_sharemode,
2324 align, do_pad,
2325 ppdata, base_data, end_data,
2326 space_remaining,
2327 out_of_space, got_exact_match,
2328 last_entry_off, name_list);
2331 /****************************************************************************
2332 Reply to a TRANS2_FINDFIRST.
2333 ****************************************************************************/
2335 static void call_trans2findfirst(connection_struct *conn,
2336 struct smb_request *req,
2337 char **pparams, int total_params,
2338 char **ppdata, int total_data,
2339 unsigned int max_data_bytes)
2341 /* We must be careful here that we don't return more than the
2342 allowed number of data bytes. If this means returning fewer than
2343 maxentries then so be it. We assume that the redirector has
2344 enough room for the fixed number of parameter bytes it has
2345 requested. */
2346 struct smb_filename *smb_dname = NULL;
2347 char *params = *pparams;
2348 char *pdata = *ppdata;
2349 char *data_end;
2350 uint32 dirtype;
2351 int maxentries;
2352 uint16 findfirst_flags;
2353 bool close_after_first;
2354 bool close_if_end;
2355 bool requires_resume_key;
2356 int info_level;
2357 char *directory = NULL;
2358 char *mask = NULL;
2359 char *p;
2360 int last_entry_off=0;
2361 int dptr_num = -1;
2362 int numentries = 0;
2363 int i;
2364 bool finished = False;
2365 bool dont_descend = False;
2366 bool out_of_space = False;
2367 int space_remaining;
2368 bool mask_contains_wcard = False;
2369 struct ea_list *ea_list = NULL;
2370 NTSTATUS ntstatus = NT_STATUS_OK;
2371 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2372 TALLOC_CTX *ctx = talloc_tos();
2373 struct dptr_struct *dirptr = NULL;
2374 struct smbd_server_connection *sconn = req->sconn;
2375 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2376 bool backup_priv = false;
2378 if (total_params < 13) {
2379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2380 goto out;
2383 dirtype = SVAL(params,0);
2384 maxentries = SVAL(params,2);
2385 findfirst_flags = SVAL(params,4);
2386 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2387 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2388 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2389 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2390 security_token_has_privilege(get_current_nttok(conn),
2391 SEC_PRIV_BACKUP));
2393 info_level = SVAL(params,6);
2395 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2396 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2397 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2398 (int)backup_priv,
2399 info_level, max_data_bytes));
2401 if (!maxentries) {
2402 /* W2K3 seems to treat zero as 1. */
2403 maxentries = 1;
2406 switch (info_level) {
2407 case SMB_FIND_INFO_STANDARD:
2408 case SMB_FIND_EA_SIZE:
2409 case SMB_FIND_EA_LIST:
2410 case SMB_FIND_FILE_DIRECTORY_INFO:
2411 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2412 case SMB_FIND_FILE_NAMES_INFO:
2413 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2414 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2415 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2416 break;
2417 case SMB_FIND_FILE_UNIX:
2418 case SMB_FIND_FILE_UNIX_INFO2:
2419 /* Always use filesystem for UNIX mtime query. */
2420 ask_sharemode = false;
2421 if (!lp_unix_extensions()) {
2422 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2423 goto out;
2425 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2426 break;
2427 default:
2428 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2429 goto out;
2432 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2433 params+12, total_params - 12,
2434 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2435 if (!NT_STATUS_IS_OK(ntstatus)) {
2436 reply_nterror(req, ntstatus);
2437 goto out;
2440 if (backup_priv) {
2441 become_root();
2442 ntstatus = filename_convert_with_privilege(ctx,
2443 conn,
2444 req,
2445 directory,
2446 ucf_flags,
2447 &mask_contains_wcard,
2448 &smb_dname);
2449 } else {
2450 ntstatus = filename_convert(ctx, conn,
2451 req->flags2 & FLAGS2_DFS_PATHNAMES,
2452 directory,
2453 ucf_flags,
2454 &mask_contains_wcard,
2455 &smb_dname);
2458 if (!NT_STATUS_IS_OK(ntstatus)) {
2459 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2460 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2461 ERRSRV, ERRbadpath);
2462 goto out;
2464 reply_nterror(req, ntstatus);
2465 goto out;
2468 mask = smb_dname->original_lcomp;
2470 directory = smb_dname->base_name;
2472 p = strrchr_m(directory,'/');
2473 if(p == NULL) {
2474 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2475 if((directory[0] == '.') && (directory[1] == '\0')) {
2476 mask = talloc_strdup(ctx,"*");
2477 if (!mask) {
2478 reply_nterror(req, NT_STATUS_NO_MEMORY);
2479 goto out;
2481 mask_contains_wcard = True;
2483 } else {
2484 *p = 0;
2487 if (p == NULL || p == directory) {
2488 /* Ensure we don't have a directory name of "". */
2489 directory = talloc_strdup(talloc_tos(), ".");
2490 if (!directory) {
2491 reply_nterror(req, NT_STATUS_NO_MEMORY);
2492 goto out;
2496 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2498 if (info_level == SMB_FIND_EA_LIST) {
2499 uint32 ea_size;
2501 if (total_data < 4) {
2502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2503 goto out;
2506 ea_size = IVAL(pdata,0);
2507 if (ea_size != total_data) {
2508 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2509 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2511 goto out;
2514 if (!lp_ea_support(SNUM(conn))) {
2515 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2516 goto out;
2519 /* Pull out the list of names. */
2520 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2521 if (!ea_list) {
2522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2523 goto out;
2527 *ppdata = (char *)SMB_REALLOC(
2528 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2529 if(*ppdata == NULL ) {
2530 reply_nterror(req, NT_STATUS_NO_MEMORY);
2531 goto out;
2533 pdata = *ppdata;
2534 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2536 /* Realloc the params space */
2537 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2538 if (*pparams == NULL) {
2539 reply_nterror(req, NT_STATUS_NO_MEMORY);
2540 goto out;
2542 params = *pparams;
2544 /* Save the wildcard match and attribs we are using on this directory -
2545 needed as lanman2 assumes these are being saved between calls */
2547 ntstatus = dptr_create(conn,
2548 req,
2549 NULL, /* fsp */
2550 directory,
2551 False,
2552 True,
2553 req->smbpid,
2554 mask,
2555 mask_contains_wcard,
2556 dirtype,
2557 &dirptr);
2559 if (!NT_STATUS_IS_OK(ntstatus)) {
2560 reply_nterror(req, ntstatus);
2561 goto out;
2564 if (backup_priv) {
2565 /* Remember this in case we have
2566 to do a findnext. */
2567 dptr_set_priv(dirptr);
2570 dptr_num = dptr_dnum(dirptr);
2571 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2573 /* Initialize per TRANS2_FIND_FIRST operation data */
2574 dptr_init_search_op(dirptr);
2576 /* We don't need to check for VOL here as this is returned by
2577 a different TRANS2 call. */
2579 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2580 directory,lp_dontdescend(ctx, SNUM(conn))));
2581 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2582 dont_descend = True;
2584 p = pdata;
2585 space_remaining = max_data_bytes;
2586 out_of_space = False;
2588 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2589 bool got_exact_match = False;
2591 /* this is a heuristic to avoid seeking the dirptr except when
2592 absolutely necessary. It allows for a filename of about 40 chars */
2593 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2594 out_of_space = True;
2595 finished = False;
2596 } else {
2597 finished = !get_lanman2_dir_entry(ctx,
2598 conn,
2599 dirptr,
2600 req->flags2,
2601 mask,dirtype,info_level,
2602 requires_resume_key,dont_descend,
2603 ask_sharemode,
2604 &p,pdata,data_end,
2605 space_remaining, &out_of_space,
2606 &got_exact_match,
2607 &last_entry_off, ea_list);
2610 if (finished && out_of_space)
2611 finished = False;
2613 if (!finished && !out_of_space)
2614 numentries++;
2617 * As an optimisation if we know we aren't looking
2618 * for a wildcard name (ie. the name matches the wildcard exactly)
2619 * then we can finish on any (first) match.
2620 * This speeds up large directory searches. JRA.
2623 if(got_exact_match)
2624 finished = True;
2626 /* Ensure space_remaining never goes -ve. */
2627 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2628 space_remaining = 0;
2629 out_of_space = true;
2630 } else {
2631 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2635 /* Check if we can close the dirptr */
2636 if(close_after_first || (finished && close_if_end)) {
2637 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2638 dptr_close(sconn, &dptr_num);
2642 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2643 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2644 * the protocol level is less than NT1. Tested with smbclient. JRA.
2645 * This should fix the OS/2 client bug #2335.
2648 if(numentries == 0) {
2649 dptr_close(sconn, &dptr_num);
2650 if (get_Protocol() < PROTOCOL_NT1) {
2651 reply_force_doserror(req, ERRDOS, ERRnofiles);
2652 goto out;
2653 } else {
2654 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2655 ERRDOS, ERRbadfile);
2656 goto out;
2660 /* At this point pdata points to numentries directory entries. */
2662 /* Set up the return parameter block */
2663 SSVAL(params,0,dptr_num);
2664 SSVAL(params,2,numentries);
2665 SSVAL(params,4,finished);
2666 SSVAL(params,6,0); /* Never an EA error */
2667 SSVAL(params,8,last_entry_off);
2669 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2670 max_data_bytes);
2672 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2673 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2674 if (!directory) {
2675 reply_nterror(req, NT_STATUS_NO_MEMORY);
2679 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2680 smb_fn_name(req->cmd),
2681 mask, directory, dirtype, numentries ) );
2684 * Force a name mangle here to ensure that the
2685 * mask as an 8.3 name is top of the mangled cache.
2686 * The reasons for this are subtle. Don't remove
2687 * this code unless you know what you are doing
2688 * (see PR#13758). JRA.
2691 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2692 char mangled_name[13];
2693 name_to_8_3(mask, mangled_name, True, conn->params);
2695 out:
2697 if (backup_priv) {
2698 unbecome_root();
2701 TALLOC_FREE(smb_dname);
2702 return;
2705 /****************************************************************************
2706 Reply to a TRANS2_FINDNEXT.
2707 ****************************************************************************/
2709 static void call_trans2findnext(connection_struct *conn,
2710 struct smb_request *req,
2711 char **pparams, int total_params,
2712 char **ppdata, int total_data,
2713 unsigned int max_data_bytes)
2715 /* We must be careful here that we don't return more than the
2716 allowed number of data bytes. If this means returning fewer than
2717 maxentries then so be it. We assume that the redirector has
2718 enough room for the fixed number of parameter bytes it has
2719 requested. */
2720 char *params = *pparams;
2721 char *pdata = *ppdata;
2722 char *data_end;
2723 int dptr_num;
2724 int maxentries;
2725 uint16 info_level;
2726 uint32 resume_key;
2727 uint16 findnext_flags;
2728 bool close_after_request;
2729 bool close_if_end;
2730 bool requires_resume_key;
2731 bool continue_bit;
2732 bool mask_contains_wcard = False;
2733 char *resume_name = NULL;
2734 const char *mask = NULL;
2735 const char *directory = NULL;
2736 char *p = NULL;
2737 uint16 dirtype;
2738 int numentries = 0;
2739 int i, last_entry_off=0;
2740 bool finished = False;
2741 bool dont_descend = False;
2742 bool out_of_space = False;
2743 int space_remaining;
2744 struct ea_list *ea_list = NULL;
2745 NTSTATUS ntstatus = NT_STATUS_OK;
2746 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2747 TALLOC_CTX *ctx = talloc_tos();
2748 struct dptr_struct *dirptr;
2749 struct smbd_server_connection *sconn = req->sconn;
2750 bool backup_priv = false;
2752 if (total_params < 13) {
2753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2754 return;
2757 dptr_num = SVAL(params,0);
2758 maxentries = SVAL(params,2);
2759 info_level = SVAL(params,4);
2760 resume_key = IVAL(params,6);
2761 findnext_flags = SVAL(params,10);
2762 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2763 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2764 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2765 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2767 if (!continue_bit) {
2768 /* We only need resume_name if continue_bit is zero. */
2769 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2770 params+12,
2771 total_params - 12, STR_TERMINATE, &ntstatus,
2772 &mask_contains_wcard);
2773 if (!NT_STATUS_IS_OK(ntstatus)) {
2774 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2775 complain (it thinks we're asking for the directory above the shared
2776 path or an invalid name). Catch this as the resume name is only compared, never used in
2777 a file access. JRA. */
2778 srvstr_pull_talloc(ctx, params, req->flags2,
2779 &resume_name, params+12,
2780 total_params - 12,
2781 STR_TERMINATE);
2783 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2784 reply_nterror(req, ntstatus);
2785 return;
2790 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2791 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2792 resume_key = %d resume name = %s continue=%d level = %d\n",
2793 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2794 requires_resume_key, resume_key,
2795 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2797 if (!maxentries) {
2798 /* W2K3 seems to treat zero as 1. */
2799 maxentries = 1;
2802 switch (info_level) {
2803 case SMB_FIND_INFO_STANDARD:
2804 case SMB_FIND_EA_SIZE:
2805 case SMB_FIND_EA_LIST:
2806 case SMB_FIND_FILE_DIRECTORY_INFO:
2807 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2808 case SMB_FIND_FILE_NAMES_INFO:
2809 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2810 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2811 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2812 break;
2813 case SMB_FIND_FILE_UNIX:
2814 case SMB_FIND_FILE_UNIX_INFO2:
2815 /* Always use filesystem for UNIX mtime query. */
2816 ask_sharemode = false;
2817 if (!lp_unix_extensions()) {
2818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2819 return;
2821 break;
2822 default:
2823 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2824 return;
2827 if (info_level == SMB_FIND_EA_LIST) {
2828 uint32 ea_size;
2830 if (total_data < 4) {
2831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2832 return;
2835 ea_size = IVAL(pdata,0);
2836 if (ea_size != total_data) {
2837 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2838 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2840 return;
2843 if (!lp_ea_support(SNUM(conn))) {
2844 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2845 return;
2848 /* Pull out the list of names. */
2849 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2850 if (!ea_list) {
2851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2852 return;
2856 *ppdata = (char *)SMB_REALLOC(
2857 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2858 if(*ppdata == NULL) {
2859 reply_nterror(req, NT_STATUS_NO_MEMORY);
2860 return;
2863 pdata = *ppdata;
2864 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2866 /* Realloc the params space */
2867 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2868 if(*pparams == NULL ) {
2869 reply_nterror(req, NT_STATUS_NO_MEMORY);
2870 return;
2873 params = *pparams;
2875 /* Check that the dptr is valid */
2876 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2877 reply_nterror(req, STATUS_NO_MORE_FILES);
2878 return;
2881 directory = dptr_path(sconn, dptr_num);
2883 /* Get the wildcard mask from the dptr */
2884 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2885 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2886 reply_nterror(req, STATUS_NO_MORE_FILES);
2887 return;
2890 /* Get the attr mask from the dptr */
2891 dirtype = dptr_attr(sconn, dptr_num);
2893 backup_priv = dptr_get_priv(dirptr);
2895 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2896 "backup_priv = %d\n",
2897 dptr_num, mask, dirtype,
2898 (long)dirptr,
2899 dptr_TellDir(dirptr),
2900 (int)backup_priv));
2902 /* Initialize per TRANS2_FIND_NEXT operation data */
2903 dptr_init_search_op(dirptr);
2905 /* We don't need to check for VOL here as this is returned by
2906 a different TRANS2 call. */
2908 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2909 directory,lp_dontdescend(ctx, SNUM(conn))));
2910 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2911 dont_descend = True;
2913 p = pdata;
2914 space_remaining = max_data_bytes;
2915 out_of_space = False;
2917 if (backup_priv) {
2918 become_root();
2922 * Seek to the correct position. We no longer use the resume key but
2923 * depend on the last file name instead.
2926 if(!continue_bit && resume_name && *resume_name) {
2927 SMB_STRUCT_STAT st;
2929 long current_pos = 0;
2931 * Remember, name_to_8_3 is called by
2932 * get_lanman2_dir_entry(), so the resume name
2933 * could be mangled. Ensure we check the unmangled name.
2936 if (mangle_is_mangled(resume_name, conn->params)) {
2937 char *new_resume_name = NULL;
2938 mangle_lookup_name_from_8_3(ctx,
2939 resume_name,
2940 &new_resume_name,
2941 conn->params);
2942 if (new_resume_name) {
2943 resume_name = new_resume_name;
2948 * Fix for NT redirector problem triggered by resume key indexes
2949 * changing between directory scans. We now return a resume key of 0
2950 * and instead look for the filename to continue from (also given
2951 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2952 * findfirst/findnext (as is usual) then the directory pointer
2953 * should already be at the correct place.
2956 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2957 } /* end if resume_name && !continue_bit */
2959 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2960 bool got_exact_match = False;
2962 /* this is a heuristic to avoid seeking the dirptr except when
2963 absolutely necessary. It allows for a filename of about 40 chars */
2964 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2965 out_of_space = True;
2966 finished = False;
2967 } else {
2968 finished = !get_lanman2_dir_entry(ctx,
2969 conn,
2970 dirptr,
2971 req->flags2,
2972 mask,dirtype,info_level,
2973 requires_resume_key,dont_descend,
2974 ask_sharemode,
2975 &p,pdata,data_end,
2976 space_remaining, &out_of_space,
2977 &got_exact_match,
2978 &last_entry_off, ea_list);
2981 if (finished && out_of_space)
2982 finished = False;
2984 if (!finished && !out_of_space)
2985 numentries++;
2988 * As an optimisation if we know we aren't looking
2989 * for a wildcard name (ie. the name matches the wildcard exactly)
2990 * then we can finish on any (first) match.
2991 * This speeds up large directory searches. JRA.
2994 if(got_exact_match)
2995 finished = True;
2997 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3000 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3001 smb_fn_name(req->cmd),
3002 mask, directory, dirtype, numentries ) );
3004 /* Check if we can close the dirptr */
3005 if(close_after_request || (finished && close_if_end)) {
3006 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3007 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3010 if (backup_priv) {
3011 unbecome_root();
3014 /* Set up the return parameter block */
3015 SSVAL(params,0,numentries);
3016 SSVAL(params,2,finished);
3017 SSVAL(params,4,0); /* Never an EA error */
3018 SSVAL(params,6,last_entry_off);
3020 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3021 max_data_bytes);
3023 return;
3026 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3028 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3029 return objid;
3032 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3034 SMB_ASSERT(extended_info != NULL);
3036 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3037 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3038 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3039 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3040 #ifdef SAMBA_VERSION_REVISION
3041 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3042 #endif
3043 extended_info->samba_subversion = 0;
3044 #ifdef SAMBA_VERSION_RC_RELEASE
3045 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3046 #else
3047 #ifdef SAMBA_VERSION_PRE_RELEASE
3048 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3049 #endif
3050 #endif
3051 #ifdef SAMBA_VERSION_VENDOR_PATCH
3052 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3053 #endif
3054 extended_info->samba_gitcommitdate = 0;
3055 #ifdef SAMBA_VERSION_COMMIT_TIME
3056 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3057 #endif
3059 memset(extended_info->samba_version_string, 0,
3060 sizeof(extended_info->samba_version_string));
3062 snprintf (extended_info->samba_version_string,
3063 sizeof(extended_info->samba_version_string),
3064 "%s", samba_version_string());
3067 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3068 TALLOC_CTX *mem_ctx,
3069 uint16_t info_level,
3070 uint16_t flags2,
3071 unsigned int max_data_bytes,
3072 struct smb_filename *fname,
3073 char **ppdata,
3074 int *ret_data_len)
3076 char *pdata, *end_data;
3077 int data_len = 0, len;
3078 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3079 int snum = SNUM(conn);
3080 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3081 char *filename = NULL;
3082 uint32 additional_flags = 0;
3083 struct smb_filename smb_fname;
3084 SMB_STRUCT_STAT st;
3086 if (fname == NULL || fname->base_name == NULL) {
3087 filename = ".";
3088 } else {
3089 filename = fname->base_name;
3092 if (IS_IPC(conn)) {
3093 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3094 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3095 "info level (0x%x) on IPC$.\n",
3096 (unsigned int)info_level));
3097 return NT_STATUS_ACCESS_DENIED;
3101 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3103 ZERO_STRUCT(smb_fname);
3104 smb_fname.base_name = discard_const_p(char, filename);
3106 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3107 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3108 return map_nt_error_from_unix(errno);
3111 st = smb_fname.st;
3113 *ppdata = (char *)SMB_REALLOC(
3114 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3115 if (*ppdata == NULL) {
3116 return NT_STATUS_NO_MEMORY;
3119 pdata = *ppdata;
3120 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3121 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3123 switch (info_level) {
3124 case SMB_INFO_ALLOCATION:
3126 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3127 data_len = 18;
3128 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3129 return map_nt_error_from_unix(errno);
3132 block_size = lp_block_size(snum);
3133 if (bsize < block_size) {
3134 uint64_t factor = block_size/bsize;
3135 bsize = block_size;
3136 dsize /= factor;
3137 dfree /= factor;
3139 if (bsize > block_size) {
3140 uint64_t factor = bsize/block_size;
3141 bsize = block_size;
3142 dsize *= factor;
3143 dfree *= factor;
3145 bytes_per_sector = 512;
3146 sectors_per_unit = bsize/bytes_per_sector;
3148 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3149 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3150 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3153 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3154 SIVAL(pdata,l1_cUnit,dsize);
3155 SIVAL(pdata,l1_cUnitAvail,dfree);
3156 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3157 break;
3160 case SMB_INFO_VOLUME:
3161 /* Return volume name */
3163 * Add volume serial number - hash of a combination of
3164 * the called hostname and the service name.
3166 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3168 * Win2k3 and previous mess this up by sending a name length
3169 * one byte short. I believe only older clients (OS/2 Win9x) use
3170 * this call so try fixing this by adding a terminating null to
3171 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3173 len = srvstr_push(
3174 pdata, flags2,
3175 pdata+l2_vol_szVolLabel, vname,
3176 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3177 STR_NOALIGN|STR_TERMINATE);
3178 SCVAL(pdata,l2_vol_cch,len);
3179 data_len = l2_vol_szVolLabel + len;
3180 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3181 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3182 len, vname));
3183 break;
3185 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3186 case SMB_FS_ATTRIBUTE_INFORMATION:
3188 additional_flags = 0;
3189 #if defined(HAVE_SYS_QUOTAS)
3190 additional_flags |= FILE_VOLUME_QUOTAS;
3191 #endif
3193 if(lp_nt_acl_support(SNUM(conn))) {
3194 additional_flags |= FILE_PERSISTENT_ACLS;
3197 /* Capabilities are filled in at connection time through STATVFS call */
3198 additional_flags |= conn->fs_capabilities;
3199 additional_flags |= lp_parm_int(conn->params->service,
3200 "share", "fake_fscaps",
3203 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3204 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3205 additional_flags); /* FS ATTRIBUTES */
3207 SIVAL(pdata,4,255); /* Max filename component length */
3208 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3209 and will think we can't do long filenames */
3210 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3211 PTR_DIFF(end_data, pdata+12),
3212 STR_UNICODE);
3213 SIVAL(pdata,8,len);
3214 data_len = 12 + len;
3215 break;
3217 case SMB_QUERY_FS_LABEL_INFO:
3218 case SMB_FS_LABEL_INFORMATION:
3219 len = srvstr_push(pdata, flags2, pdata+4, vname,
3220 PTR_DIFF(end_data, pdata+4), 0);
3221 data_len = 4 + len;
3222 SIVAL(pdata,0,len);
3223 break;
3225 case SMB_QUERY_FS_VOLUME_INFO:
3226 case SMB_FS_VOLUME_INFORMATION:
3229 * Add volume serial number - hash of a combination of
3230 * the called hostname and the service name.
3232 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3233 (str_checksum(get_local_machine_name())<<16));
3235 /* Max label len is 32 characters. */
3236 len = srvstr_push(pdata, flags2, pdata+18, vname,
3237 PTR_DIFF(end_data, pdata+18),
3238 STR_UNICODE);
3239 SIVAL(pdata,12,len);
3240 data_len = 18+len;
3242 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3243 (int)strlen(vname),vname,
3244 lp_servicename(talloc_tos(), snum)));
3245 break;
3247 case SMB_QUERY_FS_SIZE_INFO:
3248 case SMB_FS_SIZE_INFORMATION:
3250 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3251 data_len = 24;
3252 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3253 return map_nt_error_from_unix(errno);
3255 block_size = lp_block_size(snum);
3256 if (bsize < block_size) {
3257 uint64_t factor = block_size/bsize;
3258 bsize = block_size;
3259 dsize /= factor;
3260 dfree /= factor;
3262 if (bsize > block_size) {
3263 uint64_t factor = bsize/block_size;
3264 bsize = block_size;
3265 dsize *= factor;
3266 dfree *= factor;
3268 bytes_per_sector = 512;
3269 sectors_per_unit = bsize/bytes_per_sector;
3270 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3271 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3272 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3273 SBIG_UINT(pdata,0,dsize);
3274 SBIG_UINT(pdata,8,dfree);
3275 SIVAL(pdata,16,sectors_per_unit);
3276 SIVAL(pdata,20,bytes_per_sector);
3277 break;
3280 case SMB_FS_FULL_SIZE_INFORMATION:
3282 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3283 data_len = 32;
3284 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3285 return map_nt_error_from_unix(errno);
3287 block_size = lp_block_size(snum);
3288 if (bsize < block_size) {
3289 uint64_t factor = block_size/bsize;
3290 bsize = block_size;
3291 dsize /= factor;
3292 dfree /= factor;
3294 if (bsize > block_size) {
3295 uint64_t factor = bsize/block_size;
3296 bsize = block_size;
3297 dsize *= factor;
3298 dfree *= factor;
3300 bytes_per_sector = 512;
3301 sectors_per_unit = bsize/bytes_per_sector;
3302 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3304 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3305 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3306 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3307 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3308 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3309 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3310 break;
3313 case SMB_QUERY_FS_DEVICE_INFO:
3314 case SMB_FS_DEVICE_INFORMATION:
3316 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3318 if (!CAN_WRITE(conn)) {
3319 characteristics |= FILE_READ_ONLY_DEVICE;
3321 data_len = 8;
3322 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3323 SIVAL(pdata,4,characteristics);
3324 break;
3327 #ifdef HAVE_SYS_QUOTAS
3328 case SMB_FS_QUOTA_INFORMATION:
3330 * what we have to send --metze:
3332 * Unknown1: 24 NULL bytes
3333 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3334 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3335 * Quota Flags: 2 byte :
3336 * Unknown3: 6 NULL bytes
3338 * 48 bytes total
3340 * details for Quota Flags:
3342 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3343 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3344 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3345 * 0x0001 Enable Quotas: enable quota for this fs
3349 /* we need to fake up a fsp here,
3350 * because its not send in this call
3352 files_struct fsp;
3353 SMB_NTQUOTA_STRUCT quotas;
3355 ZERO_STRUCT(fsp);
3356 ZERO_STRUCT(quotas);
3358 fsp.conn = conn;
3359 fsp.fnum = FNUM_FIELD_INVALID;
3361 /* access check */
3362 if (get_current_uid(conn) != 0) {
3363 DEBUG(0,("set_user_quota: access_denied "
3364 "service [%s] user [%s]\n",
3365 lp_servicename(talloc_tos(), SNUM(conn)),
3366 conn->session_info->unix_info->unix_name));
3367 return NT_STATUS_ACCESS_DENIED;
3370 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3371 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3372 return map_nt_error_from_unix(errno);
3375 data_len = 48;
3377 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3378 lp_servicename(talloc_tos(), SNUM(conn))));
3380 /* Unknown1 24 NULL bytes*/
3381 SBIG_UINT(pdata,0,(uint64_t)0);
3382 SBIG_UINT(pdata,8,(uint64_t)0);
3383 SBIG_UINT(pdata,16,(uint64_t)0);
3385 /* Default Soft Quota 8 bytes */
3386 SBIG_UINT(pdata,24,quotas.softlim);
3388 /* Default Hard Quota 8 bytes */
3389 SBIG_UINT(pdata,32,quotas.hardlim);
3391 /* Quota flag 2 bytes */
3392 SSVAL(pdata,40,quotas.qflags);
3394 /* Unknown3 6 NULL bytes */
3395 SSVAL(pdata,42,0);
3396 SIVAL(pdata,44,0);
3398 break;
3400 #endif /* HAVE_SYS_QUOTAS */
3401 case SMB_FS_OBJECTID_INFORMATION:
3403 unsigned char objid[16];
3404 struct smb_extended_info extended_info;
3405 memcpy(pdata,create_volume_objectid(conn, objid),16);
3406 samba_extended_info_version (&extended_info);
3407 SIVAL(pdata,16,extended_info.samba_magic);
3408 SIVAL(pdata,20,extended_info.samba_version);
3409 SIVAL(pdata,24,extended_info.samba_subversion);
3410 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3411 memcpy(pdata+36,extended_info.samba_version_string,28);
3412 data_len = 64;
3413 break;
3417 * Query the version and capabilities of the CIFS UNIX extensions
3418 * in use.
3421 case SMB_QUERY_CIFS_UNIX_INFO:
3423 bool large_write = lp_min_receive_file_size() &&
3424 !srv_is_signing_active(conn->sconn);
3425 bool large_read = !srv_is_signing_active(conn->sconn);
3426 int encrypt_caps = 0;
3428 if (!lp_unix_extensions()) {
3429 return NT_STATUS_INVALID_LEVEL;
3432 switch (conn->encrypt_level) {
3433 case SMB_SIGNING_OFF:
3434 encrypt_caps = 0;
3435 break;
3436 case SMB_SIGNING_IF_REQUIRED:
3437 case SMB_SIGNING_DEFAULT:
3438 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3439 break;
3440 case SMB_SIGNING_REQUIRED:
3441 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3442 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3443 large_write = false;
3444 large_read = false;
3445 break;
3448 data_len = 12;
3449 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3450 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3452 /* We have POSIX ACLs, pathname, encryption,
3453 * large read/write, and locking capability. */
3455 SBIG_UINT(pdata,4,((uint64_t)(
3456 CIFS_UNIX_POSIX_ACLS_CAP|
3457 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3458 CIFS_UNIX_FCNTL_LOCKS_CAP|
3459 CIFS_UNIX_EXTATTR_CAP|
3460 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3461 encrypt_caps|
3462 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3463 (large_write ?
3464 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3465 break;
3468 case SMB_QUERY_POSIX_FS_INFO:
3470 int rc;
3471 vfs_statvfs_struct svfs;
3473 if (!lp_unix_extensions()) {
3474 return NT_STATUS_INVALID_LEVEL;
3477 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3479 if (!rc) {
3480 data_len = 56;
3481 SIVAL(pdata,0,svfs.OptimalTransferSize);
3482 SIVAL(pdata,4,svfs.BlockSize);
3483 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3484 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3485 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3486 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3487 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3488 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3489 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3490 #ifdef EOPNOTSUPP
3491 } else if (rc == EOPNOTSUPP) {
3492 return NT_STATUS_INVALID_LEVEL;
3493 #endif /* EOPNOTSUPP */
3494 } else {
3495 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3496 return NT_STATUS_DOS(ERRSRV, ERRerror);
3498 break;
3501 case SMB_QUERY_POSIX_WHOAMI:
3503 uint32_t flags = 0;
3504 uint32_t sid_bytes;
3505 int i;
3507 if (!lp_unix_extensions()) {
3508 return NT_STATUS_INVALID_LEVEL;
3511 if (max_data_bytes < 40) {
3512 return NT_STATUS_BUFFER_TOO_SMALL;
3515 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3516 flags |= SMB_WHOAMI_GUEST;
3519 /* NOTE: 8 bytes for UID/GID, irrespective of native
3520 * platform size. This matches
3521 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3523 data_len = 4 /* flags */
3524 + 4 /* flag mask */
3525 + 8 /* uid */
3526 + 8 /* gid */
3527 + 4 /* ngroups */
3528 + 4 /* num_sids */
3529 + 4 /* SID bytes */
3530 + 4 /* pad/reserved */
3531 + (conn->session_info->unix_token->ngroups * 8)
3532 /* groups list */
3533 + (conn->session_info->security_token->num_sids *
3534 SID_MAX_SIZE)
3535 /* SID list */;
3537 SIVAL(pdata, 0, flags);
3538 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3539 SBIG_UINT(pdata, 8,
3540 (uint64_t)conn->session_info->unix_token->uid);
3541 SBIG_UINT(pdata, 16,
3542 (uint64_t)conn->session_info->unix_token->gid);
3545 if (data_len >= max_data_bytes) {
3546 /* Potential overflow, skip the GIDs and SIDs. */
3548 SIVAL(pdata, 24, 0); /* num_groups */
3549 SIVAL(pdata, 28, 0); /* num_sids */
3550 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3551 SIVAL(pdata, 36, 0); /* reserved */
3553 data_len = 40;
3554 break;
3557 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3558 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3560 /* We walk the SID list twice, but this call is fairly
3561 * infrequent, and I don't expect that it's performance
3562 * sensitive -- jpeach
3564 for (i = 0, sid_bytes = 0;
3565 i < conn->session_info->security_token->num_sids; ++i) {
3566 sid_bytes += ndr_size_dom_sid(
3567 &conn->session_info->security_token->sids[i],
3571 /* SID list byte count */
3572 SIVAL(pdata, 32, sid_bytes);
3574 /* 4 bytes pad/reserved - must be zero */
3575 SIVAL(pdata, 36, 0);
3576 data_len = 40;
3578 /* GID list */
3579 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3580 SBIG_UINT(pdata, data_len,
3581 (uint64_t)conn->session_info->unix_token->groups[i]);
3582 data_len += 8;
3585 /* SID list */
3586 for (i = 0;
3587 i < conn->session_info->security_token->num_sids; ++i) {
3588 int sid_len = ndr_size_dom_sid(
3589 &conn->session_info->security_token->sids[i],
3592 sid_linearize(pdata + data_len, sid_len,
3593 &conn->session_info->security_token->sids[i]);
3594 data_len += sid_len;
3597 break;
3600 case SMB_MAC_QUERY_FS_INFO:
3602 * Thursby MAC extension... ONLY on NTFS filesystems
3603 * once we do streams then we don't need this
3605 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3606 data_len = 88;
3607 SIVAL(pdata,84,0x100); /* Don't support mac... */
3608 break;
3610 /* drop through */
3611 default:
3612 return NT_STATUS_INVALID_LEVEL;
3615 *ret_data_len = data_len;
3616 return NT_STATUS_OK;
3619 /****************************************************************************
3620 Reply to a TRANS2_QFSINFO (query filesystem info).
3621 ****************************************************************************/
3623 static void call_trans2qfsinfo(connection_struct *conn,
3624 struct smb_request *req,
3625 char **pparams, int total_params,
3626 char **ppdata, int total_data,
3627 unsigned int max_data_bytes)
3629 char *params = *pparams;
3630 uint16_t info_level;
3631 int data_len = 0;
3632 NTSTATUS status;
3634 if (total_params < 2) {
3635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3636 return;
3639 info_level = SVAL(params,0);
3641 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3642 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3643 DEBUG(0,("call_trans2qfsinfo: encryption required "
3644 "and info level 0x%x sent.\n",
3645 (unsigned int)info_level));
3646 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3647 return;
3651 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3653 status = smbd_do_qfsinfo(conn, req,
3654 info_level,
3655 req->flags2,
3656 max_data_bytes,
3657 NULL,
3658 ppdata, &data_len);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 reply_nterror(req, status);
3661 return;
3664 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3665 max_data_bytes);
3667 DEBUG( 4, ( "%s info_level = %d\n",
3668 smb_fn_name(req->cmd), info_level) );
3670 return;
3673 /****************************************************************************
3674 Reply to a TRANS2_SETFSINFO (set filesystem info).
3675 ****************************************************************************/
3677 static void call_trans2setfsinfo(connection_struct *conn,
3678 struct smb_request *req,
3679 char **pparams, int total_params,
3680 char **ppdata, int total_data,
3681 unsigned int max_data_bytes)
3683 struct smbd_server_connection *sconn = req->sconn;
3684 char *pdata = *ppdata;
3685 char *params = *pparams;
3686 uint16 info_level;
3688 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3689 lp_servicename(talloc_tos(), SNUM(conn))));
3691 /* */
3692 if (total_params < 4) {
3693 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3694 total_params));
3695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3696 return;
3699 info_level = SVAL(params,2);
3701 if (IS_IPC(conn)) {
3702 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3703 info_level != SMB_SET_CIFS_UNIX_INFO) {
3704 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3705 "info level (0x%x) on IPC$.\n",
3706 (unsigned int)info_level));
3707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3708 return;
3712 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3713 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3714 DEBUG(0,("call_trans2setfsinfo: encryption required "
3715 "and info level 0x%x sent.\n",
3716 (unsigned int)info_level));
3717 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3718 return;
3722 switch(info_level) {
3723 case SMB_SET_CIFS_UNIX_INFO:
3724 if (!lp_unix_extensions()) {
3725 DEBUG(2,("call_trans2setfsinfo: "
3726 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3727 "unix extensions off\n"));
3728 reply_nterror(req,
3729 NT_STATUS_INVALID_LEVEL);
3730 return;
3733 /* There should be 12 bytes of capabilities set. */
3734 if (total_data < 12) {
3735 reply_nterror(
3736 req,
3737 NT_STATUS_INVALID_PARAMETER);
3738 return;
3740 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3741 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3742 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3743 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3744 /* Just print these values for now. */
3745 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3746 "major = %u, minor = %u cap_low = 0x%x, "
3747 "cap_high = 0x%xn",
3748 (unsigned int)sconn->
3749 smb1.unix_info.client_major,
3750 (unsigned int)sconn->
3751 smb1.unix_info.client_minor,
3752 (unsigned int)sconn->
3753 smb1.unix_info.client_cap_low,
3754 (unsigned int)sconn->
3755 smb1.unix_info.client_cap_high));
3757 /* Here is where we must switch to posix pathname processing... */
3758 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3759 lp_set_posix_pathnames();
3760 mangle_change_to_posix();
3763 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3764 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3765 /* Client that knows how to do posix locks,
3766 * but not posix open/mkdir operations. Set a
3767 * default type for read/write checks. */
3769 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3772 break;
3774 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3776 NTSTATUS status;
3777 size_t param_len = 0;
3778 size_t data_len = total_data;
3780 if (!lp_unix_extensions()) {
3781 reply_nterror(
3782 req,
3783 NT_STATUS_INVALID_LEVEL);
3784 return;
3787 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3788 reply_nterror(
3789 req,
3790 NT_STATUS_NOT_SUPPORTED);
3791 return;
3794 if (req->sconn->smb1.echo_handler.trusted_fde) {
3795 DEBUG( 2,("call_trans2setfsinfo: "
3796 "request transport encryption disabled"
3797 "with 'fork echo handler = yes'\n"));
3798 reply_nterror(
3799 req,
3800 NT_STATUS_NOT_SUPPORTED);
3801 return;
3804 DEBUG( 4,("call_trans2setfsinfo: "
3805 "request transport encryption.\n"));
3807 status = srv_request_encryption_setup(conn,
3808 (unsigned char **)ppdata,
3809 &data_len,
3810 (unsigned char **)pparams,
3811 &param_len);
3813 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3814 !NT_STATUS_IS_OK(status)) {
3815 reply_nterror(req, status);
3816 return;
3819 send_trans2_replies(conn, req,
3820 *pparams,
3821 param_len,
3822 *ppdata,
3823 data_len,
3824 max_data_bytes);
3826 if (NT_STATUS_IS_OK(status)) {
3827 /* Server-side transport
3828 * encryption is now *on*. */
3829 status = srv_encryption_start(conn);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 char *reason = talloc_asprintf(talloc_tos(),
3832 "Failure in setting "
3833 "up encrypted transport: %s",
3834 nt_errstr(status));
3835 exit_server_cleanly(reason);
3838 return;
3841 case SMB_FS_QUOTA_INFORMATION:
3843 files_struct *fsp = NULL;
3844 SMB_NTQUOTA_STRUCT quotas;
3846 ZERO_STRUCT(quotas);
3848 /* access check */
3849 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3850 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3851 lp_servicename(talloc_tos(), SNUM(conn)),
3852 conn->session_info->unix_info->unix_name));
3853 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3854 return;
3857 /* note: normaly there're 48 bytes,
3858 * but we didn't use the last 6 bytes for now
3859 * --metze
3861 fsp = file_fsp(req, SVAL(params,0));
3863 if (!check_fsp_ntquota_handle(conn, req,
3864 fsp)) {
3865 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3866 reply_nterror(
3867 req, NT_STATUS_INVALID_HANDLE);
3868 return;
3871 if (total_data < 42) {
3872 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3873 total_data));
3874 reply_nterror(
3875 req,
3876 NT_STATUS_INVALID_PARAMETER);
3877 return;
3880 /* unknown_1 24 NULL bytes in pdata*/
3882 /* the soft quotas 8 bytes (uint64_t)*/
3883 quotas.softlim = BVAL(pdata,24);
3885 /* the hard quotas 8 bytes (uint64_t)*/
3886 quotas.hardlim = BVAL(pdata,32);
3888 /* quota_flags 2 bytes **/
3889 quotas.qflags = SVAL(pdata,40);
3891 /* unknown_2 6 NULL bytes follow*/
3893 /* now set the quotas */
3894 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3895 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3896 reply_nterror(req, map_nt_error_from_unix(errno));
3897 return;
3900 break;
3902 default:
3903 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3904 info_level));
3905 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3906 return;
3907 break;
3911 * sending this reply works fine,
3912 * but I'm not sure it's the same
3913 * like windows do...
3914 * --metze
3916 reply_outbuf(req, 10, 0);
3919 #if defined(HAVE_POSIX_ACLS)
3920 /****************************************************************************
3921 Utility function to count the number of entries in a POSIX acl.
3922 ****************************************************************************/
3924 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3926 unsigned int ace_count = 0;
3927 int entry_id = SMB_ACL_FIRST_ENTRY;
3928 SMB_ACL_ENTRY_T entry;
3930 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3931 /* get_next... */
3932 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3933 entry_id = SMB_ACL_NEXT_ENTRY;
3935 ace_count++;
3937 return ace_count;
3940 /****************************************************************************
3941 Utility function to marshall a POSIX acl into wire format.
3942 ****************************************************************************/
3944 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3946 int entry_id = SMB_ACL_FIRST_ENTRY;
3947 SMB_ACL_ENTRY_T entry;
3949 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3950 SMB_ACL_TAG_T tagtype;
3951 SMB_ACL_PERMSET_T permset;
3952 unsigned char perms = 0;
3953 unsigned int own_grp;
3955 /* get_next... */
3956 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3957 entry_id = SMB_ACL_NEXT_ENTRY;
3960 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3961 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3962 return False;
3965 if (sys_acl_get_permset(entry, &permset) == -1) {
3966 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3967 return False;
3970 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3971 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3972 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3974 SCVAL(pdata,1,perms);
3976 switch (tagtype) {
3977 case SMB_ACL_USER_OBJ:
3978 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3979 own_grp = (unsigned int)pst->st_ex_uid;
3980 SIVAL(pdata,2,own_grp);
3981 SIVAL(pdata,6,0);
3982 break;
3983 case SMB_ACL_USER:
3985 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3986 if (!puid) {
3987 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3988 return False;
3990 own_grp = (unsigned int)*puid;
3991 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3992 SIVAL(pdata,2,own_grp);
3993 SIVAL(pdata,6,0);
3994 break;
3996 case SMB_ACL_GROUP_OBJ:
3997 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3998 own_grp = (unsigned int)pst->st_ex_gid;
3999 SIVAL(pdata,2,own_grp);
4000 SIVAL(pdata,6,0);
4001 break;
4002 case SMB_ACL_GROUP:
4004 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4005 if (!pgid) {
4006 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4007 return False;
4009 own_grp = (unsigned int)*pgid;
4010 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4011 SIVAL(pdata,2,own_grp);
4012 SIVAL(pdata,6,0);
4013 break;
4015 case SMB_ACL_MASK:
4016 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4017 SIVAL(pdata,2,0xFFFFFFFF);
4018 SIVAL(pdata,6,0xFFFFFFFF);
4019 break;
4020 case SMB_ACL_OTHER:
4021 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4022 SIVAL(pdata,2,0xFFFFFFFF);
4023 SIVAL(pdata,6,0xFFFFFFFF);
4024 break;
4025 default:
4026 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4027 return False;
4029 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4032 return True;
4034 #endif
4036 /****************************************************************************
4037 Store the FILE_UNIX_BASIC info.
4038 ****************************************************************************/
4040 static char *store_file_unix_basic(connection_struct *conn,
4041 char *pdata,
4042 files_struct *fsp,
4043 const SMB_STRUCT_STAT *psbuf)
4045 uint64_t file_index = get_FileIndex(conn, psbuf);
4046 dev_t devno;
4048 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4049 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4051 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4052 pdata += 8;
4054 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4055 pdata += 8;
4057 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4058 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4059 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4060 pdata += 24;
4062 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4063 SIVAL(pdata,4,0);
4064 pdata += 8;
4066 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4067 SIVAL(pdata,4,0);
4068 pdata += 8;
4070 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4071 pdata += 4;
4073 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4074 devno = psbuf->st_ex_rdev;
4075 } else {
4076 devno = psbuf->st_ex_dev;
4079 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4080 SIVAL(pdata,4,0);
4081 pdata += 8;
4083 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4084 SIVAL(pdata,4,0);
4085 pdata += 8;
4087 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4088 pdata += 8;
4090 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4091 SIVAL(pdata,4,0);
4092 pdata += 8;
4094 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4095 SIVAL(pdata,4,0);
4096 pdata += 8;
4098 return pdata;
4101 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4102 * the chflags(2) (or equivalent) flags.
4104 * XXX: this really should be behind the VFS interface. To do this, we would
4105 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4106 * Each VFS module could then implement its own mapping as appropriate for the
4107 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4109 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4110 info2_flags_map[] =
4112 #ifdef UF_NODUMP
4113 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4114 #endif
4116 #ifdef UF_IMMUTABLE
4117 { UF_IMMUTABLE, EXT_IMMUTABLE },
4118 #endif
4120 #ifdef UF_APPEND
4121 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4122 #endif
4124 #ifdef UF_HIDDEN
4125 { UF_HIDDEN, EXT_HIDDEN },
4126 #endif
4128 /* Do not remove. We need to guarantee that this array has at least one
4129 * entry to build on HP-UX.
4131 { 0, 0 }
4135 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4136 uint32 *smb_fflags, uint32 *smb_fmask)
4138 int i;
4140 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4141 *smb_fmask |= info2_flags_map[i].smb_fflag;
4142 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4143 *smb_fflags |= info2_flags_map[i].smb_fflag;
4148 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4149 const uint32 smb_fflags,
4150 const uint32 smb_fmask,
4151 int *stat_fflags)
4153 uint32 max_fmask = 0;
4154 int i;
4156 *stat_fflags = psbuf->st_ex_flags;
4158 /* For each flags requested in smb_fmask, check the state of the
4159 * corresponding flag in smb_fflags and set or clear the matching
4160 * stat flag.
4163 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4164 max_fmask |= info2_flags_map[i].smb_fflag;
4165 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4166 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4167 *stat_fflags |= info2_flags_map[i].stat_fflag;
4168 } else {
4169 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4174 /* If smb_fmask is asking to set any bits that are not supported by
4175 * our flag mappings, we should fail.
4177 if ((smb_fmask & max_fmask) != smb_fmask) {
4178 return False;
4181 return True;
4185 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4186 * of file flags and birth (create) time.
4188 static char *store_file_unix_basic_info2(connection_struct *conn,
4189 char *pdata,
4190 files_struct *fsp,
4191 const SMB_STRUCT_STAT *psbuf)
4193 uint32 file_flags = 0;
4194 uint32 flags_mask = 0;
4196 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4198 /* Create (birth) time 64 bit */
4199 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4200 pdata += 8;
4202 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4203 SIVAL(pdata, 0, file_flags); /* flags */
4204 SIVAL(pdata, 4, flags_mask); /* mask */
4205 pdata += 8;
4207 return pdata;
4210 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4211 const struct stream_struct *streams,
4212 char *data,
4213 unsigned int max_data_bytes,
4214 unsigned int *data_size)
4216 unsigned int i;
4217 unsigned int ofs = 0;
4219 for (i = 0; i < num_streams; i++) {
4220 unsigned int next_offset;
4221 size_t namelen;
4222 smb_ucs2_t *namebuf;
4224 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4225 streams[i].name, &namelen) ||
4226 namelen <= 2)
4228 return NT_STATUS_INVALID_PARAMETER;
4232 * name_buf is now null-terminated, we need to marshall as not
4233 * terminated
4236 namelen -= 2;
4239 * We cannot overflow ...
4241 if ((ofs + 24 + namelen) > max_data_bytes) {
4242 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4243 i));
4244 TALLOC_FREE(namebuf);
4245 return STATUS_BUFFER_OVERFLOW;
4248 SIVAL(data, ofs+4, namelen);
4249 SOFF_T(data, ofs+8, streams[i].size);
4250 SOFF_T(data, ofs+16, streams[i].alloc_size);
4251 memcpy(data+ofs+24, namebuf, namelen);
4252 TALLOC_FREE(namebuf);
4254 next_offset = ofs + 24 + namelen;
4256 if (i == num_streams-1) {
4257 SIVAL(data, ofs, 0);
4259 else {
4260 unsigned int align = ndr_align_size(next_offset, 8);
4262 if ((next_offset + align) > max_data_bytes) {
4263 DEBUG(10, ("refusing to overflow align "
4264 "reply at stream %u\n",
4265 i));
4266 TALLOC_FREE(namebuf);
4267 return STATUS_BUFFER_OVERFLOW;
4270 memset(data+next_offset, 0, align);
4271 next_offset += align;
4273 SIVAL(data, ofs, next_offset - ofs);
4274 ofs = next_offset;
4277 ofs = next_offset;
4280 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4282 *data_size = ofs;
4284 return NT_STATUS_OK;
4287 /****************************************************************************
4288 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4289 ****************************************************************************/
4291 static void call_trans2qpipeinfo(connection_struct *conn,
4292 struct smb_request *req,
4293 unsigned int tran_call,
4294 char **pparams, int total_params,
4295 char **ppdata, int total_data,
4296 unsigned int max_data_bytes)
4298 char *params = *pparams;
4299 char *pdata = *ppdata;
4300 unsigned int data_size = 0;
4301 unsigned int param_size = 2;
4302 uint16 info_level;
4303 files_struct *fsp;
4305 if (!params) {
4306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4307 return;
4310 if (total_params < 4) {
4311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4312 return;
4315 fsp = file_fsp(req, SVAL(params,0));
4316 if (!fsp_is_np(fsp)) {
4317 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4318 return;
4321 info_level = SVAL(params,2);
4323 *pparams = (char *)SMB_REALLOC(*pparams,2);
4324 if (*pparams == NULL) {
4325 reply_nterror(req, NT_STATUS_NO_MEMORY);
4326 return;
4328 params = *pparams;
4329 SSVAL(params,0,0);
4330 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4331 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4332 if (*ppdata == NULL ) {
4333 reply_nterror(req, NT_STATUS_NO_MEMORY);
4334 return;
4336 pdata = *ppdata;
4338 switch (info_level) {
4339 case SMB_FILE_STANDARD_INFORMATION:
4340 memset(pdata,0,24);
4341 SOFF_T(pdata,0,4096LL);
4342 SIVAL(pdata,16,1);
4343 SIVAL(pdata,20,1);
4344 data_size = 24;
4345 break;
4347 default:
4348 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4349 return;
4352 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4353 max_data_bytes);
4355 return;
4358 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4359 TALLOC_CTX *mem_ctx,
4360 uint16_t info_level,
4361 files_struct *fsp,
4362 struct smb_filename *smb_fname,
4363 bool delete_pending,
4364 struct timespec write_time_ts,
4365 struct ea_list *ea_list,
4366 int lock_data_count,
4367 char *lock_data,
4368 uint16_t flags2,
4369 unsigned int max_data_bytes,
4370 char **ppdata,
4371 unsigned int *pdata_size)
4373 char *pdata = *ppdata;
4374 char *dstart, *dend;
4375 unsigned int data_size;
4376 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4377 time_t create_time, mtime, atime, c_time;
4378 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4379 char *p;
4380 char *base_name;
4381 char *dos_fname;
4382 int mode;
4383 int nlink;
4384 NTSTATUS status;
4385 uint64_t file_size = 0;
4386 uint64_t pos = 0;
4387 uint64_t allocation_size = 0;
4388 uint64_t file_index = 0;
4389 uint32_t access_mask = 0;
4391 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4392 return NT_STATUS_INVALID_LEVEL;
4395 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4396 smb_fname_str_dbg(smb_fname),
4397 fsp_fnum_dbg(fsp),
4398 info_level, max_data_bytes));
4400 mode = dos_mode(conn, smb_fname);
4401 nlink = psbuf->st_ex_nlink;
4403 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4404 nlink = 1;
4407 if ((nlink > 0) && delete_pending) {
4408 nlink -= 1;
4411 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4412 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4413 if (*ppdata == NULL) {
4414 return NT_STATUS_NO_MEMORY;
4416 pdata = *ppdata;
4417 dstart = pdata;
4418 dend = dstart + data_size - 1;
4420 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4421 update_stat_ex_mtime(psbuf, write_time_ts);
4424 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4425 mtime_ts = psbuf->st_ex_mtime;
4426 atime_ts = psbuf->st_ex_atime;
4427 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4429 if (lp_dos_filetime_resolution(SNUM(conn))) {
4430 dos_filetime_timespec(&create_time_ts);
4431 dos_filetime_timespec(&mtime_ts);
4432 dos_filetime_timespec(&atime_ts);
4433 dos_filetime_timespec(&ctime_ts);
4436 create_time = convert_timespec_to_time_t(create_time_ts);
4437 mtime = convert_timespec_to_time_t(mtime_ts);
4438 atime = convert_timespec_to_time_t(atime_ts);
4439 c_time = convert_timespec_to_time_t(ctime_ts);
4441 p = strrchr_m(smb_fname->base_name,'/');
4442 if (!p)
4443 base_name = smb_fname->base_name;
4444 else
4445 base_name = p+1;
4447 /* NT expects the name to be in an exact form of the *full*
4448 filename. See the trans2 torture test */
4449 if (ISDOT(base_name)) {
4450 dos_fname = talloc_strdup(mem_ctx, "\\");
4451 if (!dos_fname) {
4452 return NT_STATUS_NO_MEMORY;
4454 } else {
4455 dos_fname = talloc_asprintf(mem_ctx,
4456 "\\%s",
4457 smb_fname->base_name);
4458 if (!dos_fname) {
4459 return NT_STATUS_NO_MEMORY;
4461 if (is_ntfs_stream_smb_fname(smb_fname)) {
4462 dos_fname = talloc_asprintf(dos_fname, "%s",
4463 smb_fname->stream_name);
4464 if (!dos_fname) {
4465 return NT_STATUS_NO_MEMORY;
4469 string_replace(dos_fname, '/', '\\');
4472 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4474 if (!fsp) {
4475 /* Do we have this path open ? */
4476 files_struct *fsp1;
4477 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4478 fsp1 = file_find_di_first(conn->sconn, fileid);
4479 if (fsp1 && fsp1->initial_allocation_size) {
4480 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4484 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4485 file_size = get_file_size_stat(psbuf);
4488 if (fsp) {
4489 pos = fsp->fh->position_information;
4492 if (fsp) {
4493 access_mask = fsp->access_mask;
4494 } else {
4495 /* GENERIC_EXECUTE mapping from Windows */
4496 access_mask = 0x12019F;
4499 /* This should be an index number - looks like
4500 dev/ino to me :-)
4502 I think this causes us to fail the IFSKIT
4503 BasicFileInformationTest. -tpot */
4504 file_index = get_FileIndex(conn, psbuf);
4506 switch (info_level) {
4507 case SMB_INFO_STANDARD:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4509 data_size = 22;
4510 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4511 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4512 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4513 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4514 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4515 SSVAL(pdata,l1_attrFile,mode);
4516 break;
4518 case SMB_INFO_QUERY_EA_SIZE:
4520 unsigned int ea_size =
4521 estimate_ea_size(conn, fsp,
4522 smb_fname);
4523 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4524 data_size = 26;
4525 srv_put_dos_date2(pdata,0,create_time);
4526 srv_put_dos_date2(pdata,4,atime);
4527 srv_put_dos_date2(pdata,8,mtime); /* write time */
4528 SIVAL(pdata,12,(uint32)file_size);
4529 SIVAL(pdata,16,(uint32)allocation_size);
4530 SSVAL(pdata,20,mode);
4531 SIVAL(pdata,22,ea_size);
4532 break;
4535 case SMB_INFO_IS_NAME_VALID:
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4537 if (fsp) {
4538 /* os/2 needs this ? really ?*/
4539 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4541 /* This is only reached for qpathinfo */
4542 data_size = 0;
4543 break;
4545 case SMB_INFO_QUERY_EAS_FROM_LIST:
4547 size_t total_ea_len = 0;
4548 struct ea_list *ea_file_list = NULL;
4549 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4551 status =
4552 get_ea_list_from_file(mem_ctx, conn, fsp,
4553 smb_fname,
4554 &total_ea_len, &ea_file_list);
4555 if (!NT_STATUS_IS_OK(status)) {
4556 return status;
4559 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4561 if (!ea_list || (total_ea_len > data_size)) {
4562 data_size = 4;
4563 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4564 break;
4567 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4568 break;
4571 case SMB_INFO_QUERY_ALL_EAS:
4573 /* We have data_size bytes to put EA's into. */
4574 size_t total_ea_len = 0;
4575 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4577 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4578 smb_fname,
4579 &total_ea_len, &ea_list);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 return status;
4584 if (!ea_list || (total_ea_len > data_size)) {
4585 data_size = 4;
4586 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4587 break;
4590 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4591 break;
4594 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4596 /* This is FileFullEaInformation - 0xF which maps to
4597 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4599 /* We have data_size bytes to put EA's into. */
4600 size_t total_ea_len = 0;
4601 struct ea_list *ea_file_list = NULL;
4603 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4605 /*TODO: add filtering and index handling */
4607 status =
4608 get_ea_list_from_file(mem_ctx, conn, fsp,
4609 smb_fname,
4610 &total_ea_len, &ea_file_list);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 return status;
4614 if (!ea_file_list) {
4615 return NT_STATUS_NO_EAS_ON_FILE;
4618 status = fill_ea_chained_buffer(mem_ctx,
4619 pdata,
4620 data_size,
4621 &data_size,
4622 conn, ea_file_list);
4623 if (!NT_STATUS_IS_OK(status)) {
4624 return status;
4626 break;
4629 case SMB_FILE_BASIC_INFORMATION:
4630 case SMB_QUERY_FILE_BASIC_INFO:
4632 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4634 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4635 } else {
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4637 data_size = 40;
4638 SIVAL(pdata,36,0);
4640 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4641 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4642 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4643 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4644 SIVAL(pdata,32,mode);
4646 DEBUG(5,("SMB_QFBI - "));
4647 DEBUG(5,("create: %s ", ctime(&create_time)));
4648 DEBUG(5,("access: %s ", ctime(&atime)));
4649 DEBUG(5,("write: %s ", ctime(&mtime)));
4650 DEBUG(5,("change: %s ", ctime(&c_time)));
4651 DEBUG(5,("mode: %x\n", mode));
4652 break;
4654 case SMB_FILE_STANDARD_INFORMATION:
4655 case SMB_QUERY_FILE_STANDARD_INFO:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4658 data_size = 24;
4659 SOFF_T(pdata,0,allocation_size);
4660 SOFF_T(pdata,8,file_size);
4661 SIVAL(pdata,16,nlink);
4662 SCVAL(pdata,20,delete_pending?1:0);
4663 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4664 SSVAL(pdata,22,0); /* Padding. */
4665 break;
4667 case SMB_FILE_EA_INFORMATION:
4668 case SMB_QUERY_FILE_EA_INFO:
4670 unsigned int ea_size =
4671 estimate_ea_size(conn, fsp, smb_fname);
4672 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4673 data_size = 4;
4674 SIVAL(pdata,0,ea_size);
4675 break;
4678 /* Get the 8.3 name - used if NT SMB was negotiated. */
4679 case SMB_QUERY_FILE_ALT_NAME_INFO:
4680 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4682 int len;
4683 char mangled_name[13];
4684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4685 if (!name_to_8_3(base_name,mangled_name,
4686 True,conn->params)) {
4687 return NT_STATUS_NO_MEMORY;
4689 len = srvstr_push(dstart, flags2,
4690 pdata+4, mangled_name,
4691 PTR_DIFF(dend, pdata+4),
4692 STR_UNICODE);
4693 data_size = 4 + len;
4694 SIVAL(pdata,0,len);
4695 break;
4698 case SMB_QUERY_FILE_NAME_INFO:
4700 int len;
4702 this must be *exactly* right for ACLs on mapped drives to work
4704 len = srvstr_push(dstart, flags2,
4705 pdata+4, dos_fname,
4706 PTR_DIFF(dend, pdata+4),
4707 STR_UNICODE);
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4709 data_size = 4 + len;
4710 SIVAL(pdata,0,len);
4711 break;
4714 case SMB_FILE_ALLOCATION_INFORMATION:
4715 case SMB_QUERY_FILE_ALLOCATION_INFO:
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4717 data_size = 8;
4718 SOFF_T(pdata,0,allocation_size);
4719 break;
4721 case SMB_FILE_END_OF_FILE_INFORMATION:
4722 case SMB_QUERY_FILE_END_OF_FILEINFO:
4723 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4724 data_size = 8;
4725 SOFF_T(pdata,0,file_size);
4726 break;
4728 case SMB_QUERY_FILE_ALL_INFO:
4729 case SMB_FILE_ALL_INFORMATION:
4731 int len;
4732 unsigned int ea_size =
4733 estimate_ea_size(conn, fsp, smb_fname);
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4735 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4736 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4737 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4738 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4739 SIVAL(pdata,32,mode);
4740 SIVAL(pdata,36,0); /* padding. */
4741 pdata += 40;
4742 SOFF_T(pdata,0,allocation_size);
4743 SOFF_T(pdata,8,file_size);
4744 SIVAL(pdata,16,nlink);
4745 SCVAL(pdata,20,delete_pending);
4746 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4747 SSVAL(pdata,22,0);
4748 pdata += 24;
4749 SIVAL(pdata,0,ea_size);
4750 pdata += 4; /* EA info */
4751 len = srvstr_push(dstart, flags2,
4752 pdata+4, dos_fname,
4753 PTR_DIFF(dend, pdata+4),
4754 STR_UNICODE);
4755 SIVAL(pdata,0,len);
4756 pdata += 4 + len;
4757 data_size = PTR_DIFF(pdata,(*ppdata));
4758 break;
4761 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4763 int len;
4764 unsigned int ea_size =
4765 estimate_ea_size(conn, fsp, smb_fname);
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4767 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4768 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4769 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4770 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4771 SIVAL(pdata, 0x20, mode);
4772 SIVAL(pdata, 0x24, 0); /* padding. */
4773 SBVAL(pdata, 0x28, allocation_size);
4774 SBVAL(pdata, 0x30, file_size);
4775 SIVAL(pdata, 0x38, nlink);
4776 SCVAL(pdata, 0x3C, delete_pending);
4777 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4778 SSVAL(pdata, 0x3E, 0); /* padding */
4779 SBVAL(pdata, 0x40, file_index);
4780 SIVAL(pdata, 0x48, ea_size);
4781 SIVAL(pdata, 0x4C, access_mask);
4782 SBVAL(pdata, 0x50, pos);
4783 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4784 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4786 pdata += 0x60;
4788 len = srvstr_push(dstart, flags2,
4789 pdata+4, dos_fname,
4790 PTR_DIFF(dend, pdata+4),
4791 STR_UNICODE);
4792 SIVAL(pdata,0,len);
4793 pdata += 4 + len;
4794 data_size = PTR_DIFF(pdata,(*ppdata));
4795 break;
4797 case SMB_FILE_INTERNAL_INFORMATION:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4800 SBVAL(pdata, 0, file_index);
4801 data_size = 8;
4802 break;
4804 case SMB_FILE_ACCESS_INFORMATION:
4805 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4806 SIVAL(pdata, 0, access_mask);
4807 data_size = 4;
4808 break;
4810 case SMB_FILE_NAME_INFORMATION:
4811 /* Pathname with leading '\'. */
4813 size_t byte_len;
4814 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4815 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4816 SIVAL(pdata,0,byte_len);
4817 data_size = 4 + byte_len;
4818 break;
4821 case SMB_FILE_DISPOSITION_INFORMATION:
4822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4823 data_size = 1;
4824 SCVAL(pdata,0,delete_pending);
4825 break;
4827 case SMB_FILE_POSITION_INFORMATION:
4828 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4829 data_size = 8;
4830 SOFF_T(pdata,0,pos);
4831 break;
4833 case SMB_FILE_MODE_INFORMATION:
4834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4835 SIVAL(pdata,0,mode);
4836 data_size = 4;
4837 break;
4839 case SMB_FILE_ALIGNMENT_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4841 SIVAL(pdata,0,0); /* No alignment needed. */
4842 data_size = 4;
4843 break;
4846 * NT4 server just returns "invalid query" to this - if we try
4847 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4848 * want this. JRA.
4850 /* The first statement above is false - verified using Thursby
4851 * client against NT4 -- gcolley.
4853 case SMB_QUERY_FILE_STREAM_INFO:
4854 case SMB_FILE_STREAM_INFORMATION: {
4855 unsigned int num_streams = 0;
4856 struct stream_struct *streams = NULL;
4858 DEBUG(10,("smbd_do_qfilepathinfo: "
4859 "SMB_FILE_STREAM_INFORMATION\n"));
4861 if (is_ntfs_stream_smb_fname(smb_fname)) {
4862 return NT_STATUS_INVALID_PARAMETER;
4865 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4866 talloc_tos(), &num_streams, &streams);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 DEBUG(10, ("could not get stream info: %s\n",
4870 nt_errstr(status)));
4871 return status;
4874 status = marshall_stream_info(num_streams, streams,
4875 pdata, max_data_bytes,
4876 &data_size);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 DEBUG(10, ("marshall_stream_info failed: %s\n",
4880 nt_errstr(status)));
4881 TALLOC_FREE(streams);
4882 return status;
4885 TALLOC_FREE(streams);
4887 break;
4889 case SMB_QUERY_COMPRESSION_INFO:
4890 case SMB_FILE_COMPRESSION_INFORMATION:
4891 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4892 SOFF_T(pdata,0,file_size);
4893 SIVAL(pdata,8,0); /* ??? */
4894 SIVAL(pdata,12,0); /* ??? */
4895 data_size = 16;
4896 break;
4898 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4899 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4900 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4901 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4902 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4903 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4904 SOFF_T(pdata,32,allocation_size);
4905 SOFF_T(pdata,40,file_size);
4906 SIVAL(pdata,48,mode);
4907 SIVAL(pdata,52,0); /* ??? */
4908 data_size = 56;
4909 break;
4911 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4912 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4913 SIVAL(pdata,0,mode);
4914 SIVAL(pdata,4,0);
4915 data_size = 8;
4916 break;
4919 * CIFS UNIX Extensions.
4922 case SMB_QUERY_FILE_UNIX_BASIC:
4924 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4925 data_size = PTR_DIFF(pdata,(*ppdata));
4927 DEBUG(4,("smbd_do_qfilepathinfo: "
4928 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4929 dump_data(4, (uint8_t *)(*ppdata), data_size);
4931 break;
4933 case SMB_QUERY_FILE_UNIX_INFO2:
4935 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4936 data_size = PTR_DIFF(pdata,(*ppdata));
4939 int i;
4940 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4942 for (i=0; i<100; i++)
4943 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4944 DEBUG(4,("\n"));
4947 break;
4949 case SMB_QUERY_FILE_UNIX_LINK:
4951 int len;
4952 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4954 if (!buffer) {
4955 return NT_STATUS_NO_MEMORY;
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4959 #ifdef S_ISLNK
4960 if(!S_ISLNK(psbuf->st_ex_mode)) {
4961 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4963 #else
4964 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4965 #endif
4966 len = SMB_VFS_READLINK(conn,
4967 smb_fname->base_name,
4968 buffer, PATH_MAX);
4969 if (len == -1) {
4970 return map_nt_error_from_unix(errno);
4972 buffer[len] = 0;
4973 len = srvstr_push(dstart, flags2,
4974 pdata, buffer,
4975 PTR_DIFF(dend, pdata),
4976 STR_TERMINATE);
4977 pdata += len;
4978 data_size = PTR_DIFF(pdata,(*ppdata));
4980 break;
4983 #if defined(HAVE_POSIX_ACLS)
4984 case SMB_QUERY_POSIX_ACL:
4986 SMB_ACL_T file_acl = NULL;
4987 SMB_ACL_T def_acl = NULL;
4988 uint16 num_file_acls = 0;
4989 uint16 num_def_acls = 0;
4991 if (fsp && fsp->fh->fd != -1) {
4992 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4993 talloc_tos());
4994 } else {
4995 file_acl =
4996 SMB_VFS_SYS_ACL_GET_FILE(conn,
4997 smb_fname->base_name,
4998 SMB_ACL_TYPE_ACCESS,
4999 talloc_tos());
5002 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5003 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5004 "not implemented on "
5005 "filesystem containing %s\n",
5006 smb_fname->base_name));
5007 return NT_STATUS_NOT_IMPLEMENTED;
5010 if (S_ISDIR(psbuf->st_ex_mode)) {
5011 if (fsp && fsp->is_directory) {
5012 def_acl =
5013 SMB_VFS_SYS_ACL_GET_FILE(
5014 conn,
5015 fsp->fsp_name->base_name,
5016 SMB_ACL_TYPE_DEFAULT,
5017 talloc_tos());
5018 } else {
5019 def_acl =
5020 SMB_VFS_SYS_ACL_GET_FILE(
5021 conn,
5022 smb_fname->base_name,
5023 SMB_ACL_TYPE_DEFAULT,
5024 talloc_tos());
5026 def_acl = free_empty_sys_acl(conn, def_acl);
5029 num_file_acls = count_acl_entries(conn, file_acl);
5030 num_def_acls = count_acl_entries(conn, def_acl);
5032 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5033 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5034 data_size,
5035 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5036 SMB_POSIX_ACL_HEADER_SIZE) ));
5037 if (file_acl) {
5038 TALLOC_FREE(file_acl);
5040 if (def_acl) {
5041 TALLOC_FREE(def_acl);
5043 return NT_STATUS_BUFFER_TOO_SMALL;
5046 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5047 SSVAL(pdata,2,num_file_acls);
5048 SSVAL(pdata,4,num_def_acls);
5049 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5050 if (file_acl) {
5051 TALLOC_FREE(file_acl);
5053 if (def_acl) {
5054 TALLOC_FREE(def_acl);
5056 return NT_STATUS_INTERNAL_ERROR;
5058 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5059 if (file_acl) {
5060 TALLOC_FREE(file_acl);
5062 if (def_acl) {
5063 TALLOC_FREE(def_acl);
5065 return NT_STATUS_INTERNAL_ERROR;
5068 if (file_acl) {
5069 TALLOC_FREE(file_acl);
5071 if (def_acl) {
5072 TALLOC_FREE(def_acl);
5074 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5075 break;
5077 #endif
5080 case SMB_QUERY_POSIX_LOCK:
5082 uint64_t count;
5083 uint64_t offset;
5084 uint64_t smblctx;
5085 enum brl_type lock_type;
5087 /* We need an open file with a real fd for this. */
5088 if (!fsp || fsp->fh->fd == -1) {
5089 return NT_STATUS_INVALID_LEVEL;
5092 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5093 return NT_STATUS_INVALID_PARAMETER;
5096 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5097 case POSIX_LOCK_TYPE_READ:
5098 lock_type = READ_LOCK;
5099 break;
5100 case POSIX_LOCK_TYPE_WRITE:
5101 lock_type = WRITE_LOCK;
5102 break;
5103 case POSIX_LOCK_TYPE_UNLOCK:
5104 default:
5105 /* There's no point in asking for an unlock... */
5106 return NT_STATUS_INVALID_PARAMETER;
5109 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5110 #if defined(HAVE_LONGLONG)
5111 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5112 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5113 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5114 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5115 #else /* HAVE_LONGLONG */
5116 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5117 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5118 #endif /* HAVE_LONGLONG */
5120 status = query_lock(fsp,
5121 &smblctx,
5122 &count,
5123 &offset,
5124 &lock_type,
5125 POSIX_LOCK);
5127 if (ERROR_WAS_LOCK_DENIED(status)) {
5128 /* Here we need to report who has it locked... */
5129 data_size = POSIX_LOCK_DATA_SIZE;
5131 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5132 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5133 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5134 #if defined(HAVE_LONGLONG)
5135 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5136 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5137 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5138 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5139 #else /* HAVE_LONGLONG */
5140 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5141 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5142 #endif /* HAVE_LONGLONG */
5144 } else if (NT_STATUS_IS_OK(status)) {
5145 /* For success we just return a copy of what we sent
5146 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5147 data_size = POSIX_LOCK_DATA_SIZE;
5148 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5149 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5150 } else {
5151 return status;
5153 break;
5156 default:
5157 return NT_STATUS_INVALID_LEVEL;
5160 *pdata_size = data_size;
5161 return NT_STATUS_OK;
5164 /****************************************************************************
5165 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5166 file name or file id).
5167 ****************************************************************************/
5169 static void call_trans2qfilepathinfo(connection_struct *conn,
5170 struct smb_request *req,
5171 unsigned int tran_call,
5172 char **pparams, int total_params,
5173 char **ppdata, int total_data,
5174 unsigned int max_data_bytes)
5176 char *params = *pparams;
5177 char *pdata = *ppdata;
5178 uint16 info_level;
5179 unsigned int data_size = 0;
5180 unsigned int param_size = 2;
5181 struct smb_filename *smb_fname = NULL;
5182 bool delete_pending = False;
5183 struct timespec write_time_ts;
5184 files_struct *fsp = NULL;
5185 struct file_id fileid;
5186 struct ea_list *ea_list = NULL;
5187 int lock_data_count = 0;
5188 char *lock_data = NULL;
5189 NTSTATUS status = NT_STATUS_OK;
5191 if (!params) {
5192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5193 return;
5196 ZERO_STRUCT(write_time_ts);
5198 if (tran_call == TRANSACT2_QFILEINFO) {
5199 if (total_params < 4) {
5200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5201 return;
5204 if (IS_IPC(conn)) {
5205 call_trans2qpipeinfo(conn, req, tran_call,
5206 pparams, total_params,
5207 ppdata, total_data,
5208 max_data_bytes);
5209 return;
5212 fsp = file_fsp(req, SVAL(params,0));
5213 info_level = SVAL(params,2);
5215 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5217 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5218 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5219 return;
5222 /* Initial check for valid fsp ptr. */
5223 if (!check_fsp_open(conn, req, fsp)) {
5224 return;
5227 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5228 &smb_fname);
5229 if (!NT_STATUS_IS_OK(status)) {
5230 reply_nterror(req, status);
5231 return;
5234 if(fsp->fake_file_handle) {
5236 * This is actually for the QUOTA_FAKE_FILE --metze
5239 /* We know this name is ok, it's already passed the checks. */
5241 } else if(fsp->fh->fd == -1) {
5243 * This is actually a QFILEINFO on a directory
5244 * handle (returned from an NT SMB). NT5.0 seems
5245 * to do this call. JRA.
5248 if (INFO_LEVEL_IS_UNIX(info_level)) {
5249 /* Always do lstat for UNIX calls. */
5250 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5251 DEBUG(3,("call_trans2qfilepathinfo: "
5252 "SMB_VFS_LSTAT of %s failed "
5253 "(%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;
5260 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5261 DEBUG(3,("call_trans2qfilepathinfo: "
5262 "SMB_VFS_STAT of %s failed (%s)\n",
5263 smb_fname_str_dbg(smb_fname),
5264 strerror(errno)));
5265 reply_nterror(req,
5266 map_nt_error_from_unix(errno));
5267 return;
5270 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5271 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5272 } else {
5274 * Original code - this is an open file.
5276 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5277 DEBUG(3, ("fstat of %s failed (%s)\n",
5278 fsp_fnum_dbg(fsp), strerror(errno)));
5279 reply_nterror(req,
5280 map_nt_error_from_unix(errno));
5281 return;
5283 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5284 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5287 } else {
5288 uint32_t name_hash;
5289 char *fname = NULL;
5290 uint32_t ucf_flags = 0;
5292 /* qpathinfo */
5293 if (total_params < 7) {
5294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5295 return;
5298 info_level = SVAL(params,0);
5300 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5302 if (INFO_LEVEL_IS_UNIX(info_level)) {
5303 if (!lp_unix_extensions()) {
5304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5305 return;
5307 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5308 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5309 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5310 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5314 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5315 total_params - 6,
5316 STR_TERMINATE, &status);
5317 if (!NT_STATUS_IS_OK(status)) {
5318 reply_nterror(req, status);
5319 return;
5322 status = filename_convert(req,
5323 conn,
5324 req->flags2 & FLAGS2_DFS_PATHNAMES,
5325 fname,
5326 ucf_flags,
5327 NULL,
5328 &smb_fname);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5331 reply_botherror(req,
5332 NT_STATUS_PATH_NOT_COVERED,
5333 ERRSRV, ERRbadpath);
5334 return;
5336 reply_nterror(req, status);
5337 return;
5340 /* If this is a stream, check if there is a delete_pending. */
5341 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5342 && is_ntfs_stream_smb_fname(smb_fname)) {
5343 struct smb_filename *smb_fname_base = NULL;
5345 /* Create an smb_filename with stream_name == NULL. */
5346 status =
5347 create_synthetic_smb_fname(talloc_tos(),
5348 smb_fname->base_name,
5349 NULL, NULL,
5350 &smb_fname_base);
5351 if (!NT_STATUS_IS_OK(status)) {
5352 reply_nterror(req, status);
5353 return;
5356 if (INFO_LEVEL_IS_UNIX(info_level)) {
5357 /* Always do lstat for UNIX calls. */
5358 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5359 DEBUG(3,("call_trans2qfilepathinfo: "
5360 "SMB_VFS_LSTAT of %s failed "
5361 "(%s)\n",
5362 smb_fname_str_dbg(smb_fname_base),
5363 strerror(errno)));
5364 TALLOC_FREE(smb_fname_base);
5365 reply_nterror(req,
5366 map_nt_error_from_unix(errno));
5367 return;
5369 } else {
5370 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5371 DEBUG(3,("call_trans2qfilepathinfo: "
5372 "fileinfo of %s failed "
5373 "(%s)\n",
5374 smb_fname_str_dbg(smb_fname_base),
5375 strerror(errno)));
5376 TALLOC_FREE(smb_fname_base);
5377 reply_nterror(req,
5378 map_nt_error_from_unix(errno));
5379 return;
5383 status = file_name_hash(conn,
5384 smb_fname_str_dbg(smb_fname_base),
5385 &name_hash);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 TALLOC_FREE(smb_fname_base);
5388 reply_nterror(req, status);
5389 return;
5392 fileid = vfs_file_id_from_sbuf(conn,
5393 &smb_fname_base->st);
5394 TALLOC_FREE(smb_fname_base);
5395 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5396 if (delete_pending) {
5397 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5398 return;
5402 if (INFO_LEVEL_IS_UNIX(info_level)) {
5403 /* Always do lstat for UNIX calls. */
5404 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5405 DEBUG(3,("call_trans2qfilepathinfo: "
5406 "SMB_VFS_LSTAT of %s failed (%s)\n",
5407 smb_fname_str_dbg(smb_fname),
5408 strerror(errno)));
5409 reply_nterror(req,
5410 map_nt_error_from_unix(errno));
5411 return;
5414 } else {
5415 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5416 DEBUG(3,("call_trans2qfilepathinfo: "
5417 "SMB_VFS_STAT of %s failed (%s)\n",
5418 smb_fname_str_dbg(smb_fname),
5419 strerror(errno)));
5420 reply_nterror(req,
5421 map_nt_error_from_unix(errno));
5422 return;
5426 status = file_name_hash(conn,
5427 smb_fname_str_dbg(smb_fname),
5428 &name_hash);
5429 if (!NT_STATUS_IS_OK(status)) {
5430 reply_nterror(req, status);
5431 return;
5434 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5435 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5436 if (delete_pending) {
5437 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5438 return;
5442 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5443 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5444 fsp_fnum_dbg(fsp),
5445 info_level,tran_call,total_data));
5447 /* Pull out any data sent here before we realloc. */
5448 switch (info_level) {
5449 case SMB_INFO_QUERY_EAS_FROM_LIST:
5451 /* Pull any EA list from the data portion. */
5452 uint32 ea_size;
5454 if (total_data < 4) {
5455 reply_nterror(
5456 req, NT_STATUS_INVALID_PARAMETER);
5457 return;
5459 ea_size = IVAL(pdata,0);
5461 if (total_data > 0 && ea_size != total_data) {
5462 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5463 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5464 reply_nterror(
5465 req, NT_STATUS_INVALID_PARAMETER);
5466 return;
5469 if (!lp_ea_support(SNUM(conn))) {
5470 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5471 return;
5474 /* Pull out the list of names. */
5475 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5476 if (!ea_list) {
5477 reply_nterror(
5478 req, NT_STATUS_INVALID_PARAMETER);
5479 return;
5481 break;
5484 case SMB_QUERY_POSIX_LOCK:
5486 if (fsp == NULL || fsp->fh->fd == -1) {
5487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5488 return;
5491 if (total_data != POSIX_LOCK_DATA_SIZE) {
5492 reply_nterror(
5493 req, NT_STATUS_INVALID_PARAMETER);
5494 return;
5497 /* Copy the lock range data. */
5498 lock_data = (char *)talloc_memdup(
5499 req, pdata, total_data);
5500 if (!lock_data) {
5501 reply_nterror(req, NT_STATUS_NO_MEMORY);
5502 return;
5504 lock_data_count = total_data;
5506 default:
5507 break;
5510 *pparams = (char *)SMB_REALLOC(*pparams,2);
5511 if (*pparams == NULL) {
5512 reply_nterror(req, NT_STATUS_NO_MEMORY);
5513 return;
5515 params = *pparams;
5516 SSVAL(params,0,0);
5519 * draft-leach-cifs-v1-spec-02.txt
5520 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5521 * says:
5523 * The requested information is placed in the Data portion of the
5524 * transaction response. For the information levels greater than 0x100,
5525 * the transaction response has 1 parameter word which should be
5526 * ignored by the client.
5528 * However Windows only follows this rule for the IS_NAME_VALID call.
5530 switch (info_level) {
5531 case SMB_INFO_IS_NAME_VALID:
5532 param_size = 0;
5533 break;
5536 if ((info_level & 0xFF00) == 0xFF00) {
5538 * We use levels that start with 0xFF00
5539 * internally to represent SMB2 specific levels
5541 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5542 return;
5545 status = smbd_do_qfilepathinfo(conn, req, info_level,
5546 fsp, smb_fname,
5547 delete_pending, write_time_ts,
5548 ea_list,
5549 lock_data_count, lock_data,
5550 req->flags2, max_data_bytes,
5551 ppdata, &data_size);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 reply_nterror(req, status);
5554 return;
5557 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5558 max_data_bytes);
5560 return;
5563 /****************************************************************************
5564 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5565 code.
5566 ****************************************************************************/
5568 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5569 connection_struct *conn,
5570 struct smb_request *req,
5571 bool overwrite_if_exists,
5572 const struct smb_filename *smb_fname_old,
5573 struct smb_filename *smb_fname_new)
5575 NTSTATUS status = NT_STATUS_OK;
5577 /* source must already exist. */
5578 if (!VALID_STAT(smb_fname_old->st)) {
5579 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5582 if (VALID_STAT(smb_fname_new->st)) {
5583 if (overwrite_if_exists) {
5584 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5585 return NT_STATUS_FILE_IS_A_DIRECTORY;
5587 status = unlink_internals(conn,
5588 req,
5589 FILE_ATTRIBUTE_NORMAL,
5590 smb_fname_new,
5591 false);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 return status;
5595 } else {
5596 /* Disallow if newname already exists. */
5597 return NT_STATUS_OBJECT_NAME_COLLISION;
5601 /* No links from a directory. */
5602 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5603 return NT_STATUS_FILE_IS_A_DIRECTORY;
5606 /* Setting a hardlink to/from a stream isn't currently supported. */
5607 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5608 is_ntfs_stream_smb_fname(smb_fname_new)) {
5609 return NT_STATUS_INVALID_PARAMETER;
5612 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5613 smb_fname_old->base_name, smb_fname_new->base_name));
5615 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5616 smb_fname_new->base_name) != 0) {
5617 status = map_nt_error_from_unix(errno);
5618 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5619 nt_errstr(status), smb_fname_old->base_name,
5620 smb_fname_new->base_name));
5622 return status;
5625 /****************************************************************************
5626 Deal with setting the time from any of the setfilepathinfo functions.
5627 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5628 calling this function.
5629 ****************************************************************************/
5631 NTSTATUS smb_set_file_time(connection_struct *conn,
5632 files_struct *fsp,
5633 const struct smb_filename *smb_fname,
5634 struct smb_file_time *ft,
5635 bool setting_write_time)
5637 struct smb_filename smb_fname_base;
5638 uint32 action =
5639 FILE_NOTIFY_CHANGE_LAST_ACCESS
5640 |FILE_NOTIFY_CHANGE_LAST_WRITE
5641 |FILE_NOTIFY_CHANGE_CREATION;
5643 if (!VALID_STAT(smb_fname->st)) {
5644 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5647 /* get some defaults (no modifications) if any info is zero or -1. */
5648 if (null_timespec(ft->create_time)) {
5649 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5652 if (null_timespec(ft->atime)) {
5653 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5656 if (null_timespec(ft->mtime)) {
5657 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5660 if (!setting_write_time) {
5661 /* ft->mtime comes from change time, not write time. */
5662 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5665 /* Ensure the resolution is the correct for
5666 * what we can store on this filesystem. */
5668 round_timespec(conn->ts_res, &ft->create_time);
5669 round_timespec(conn->ts_res, &ft->ctime);
5670 round_timespec(conn->ts_res, &ft->atime);
5671 round_timespec(conn->ts_res, &ft->mtime);
5673 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5674 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5675 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5676 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5677 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5678 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5679 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5680 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5682 if (setting_write_time) {
5684 * This was a Windows setfileinfo on an open file.
5685 * NT does this a lot. We also need to
5686 * set the time here, as it can be read by
5687 * FindFirst/FindNext and with the patch for bug #2045
5688 * in smbd/fileio.c it ensures that this timestamp is
5689 * kept sticky even after a write. We save the request
5690 * away and will set it on file close and after a write. JRA.
5693 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5694 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5696 if (fsp != NULL) {
5697 if (fsp->base_fsp) {
5698 set_sticky_write_time_fsp(fsp->base_fsp,
5699 ft->mtime);
5700 } else {
5701 set_sticky_write_time_fsp(fsp, ft->mtime);
5703 } else {
5704 set_sticky_write_time_path(
5705 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5706 ft->mtime);
5710 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5712 /* Always call ntimes on the base, even if a stream was passed in. */
5713 smb_fname_base = *smb_fname;
5714 smb_fname_base.stream_name = NULL;
5716 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5717 return map_nt_error_from_unix(errno);
5720 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5721 smb_fname->base_name);
5722 return NT_STATUS_OK;
5725 /****************************************************************************
5726 Deal with setting the dosmode from any of the setfilepathinfo functions.
5727 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5728 done before calling this function.
5729 ****************************************************************************/
5731 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5732 const struct smb_filename *smb_fname,
5733 uint32 dosmode)
5735 struct smb_filename *smb_fname_base = NULL;
5736 NTSTATUS status;
5738 if (!VALID_STAT(smb_fname->st)) {
5739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5742 /* Always operate on the base_name, even if a stream was passed in. */
5743 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5744 NULL, &smb_fname->st,
5745 &smb_fname_base);
5746 if (!NT_STATUS_IS_OK(status)) {
5747 return status;
5750 if (dosmode) {
5751 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5752 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5753 } else {
5754 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5758 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5760 /* check the mode isn't different, before changing it */
5761 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5762 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5763 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5764 (unsigned int)dosmode));
5766 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5767 false)) {
5768 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5769 "%s failed (%s)\n",
5770 smb_fname_str_dbg(smb_fname_base),
5771 strerror(errno)));
5772 status = map_nt_error_from_unix(errno);
5773 goto out;
5776 status = NT_STATUS_OK;
5777 out:
5778 TALLOC_FREE(smb_fname_base);
5779 return status;
5782 /****************************************************************************
5783 Deal with setting the size from any of the setfilepathinfo functions.
5784 ****************************************************************************/
5786 static NTSTATUS smb_set_file_size(connection_struct *conn,
5787 struct smb_request *req,
5788 files_struct *fsp,
5789 const struct smb_filename *smb_fname,
5790 const SMB_STRUCT_STAT *psbuf,
5791 off_t size,
5792 bool fail_after_createfile)
5794 NTSTATUS status = NT_STATUS_OK;
5795 struct smb_filename *smb_fname_tmp = NULL;
5796 files_struct *new_fsp = NULL;
5798 if (!VALID_STAT(*psbuf)) {
5799 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5802 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5804 if (size == get_file_size_stat(psbuf)) {
5805 return NT_STATUS_OK;
5808 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5809 smb_fname_str_dbg(smb_fname), (double)size));
5811 if (fsp && fsp->fh->fd != -1) {
5812 /* Handle based call. */
5813 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5814 return NT_STATUS_ACCESS_DENIED;
5817 if (vfs_set_filelen(fsp, size) == -1) {
5818 return map_nt_error_from_unix(errno);
5820 trigger_write_time_update_immediate(fsp);
5821 return NT_STATUS_OK;
5824 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5825 if (!NT_STATUS_IS_OK(status)) {
5826 return status;
5829 smb_fname_tmp->st = *psbuf;
5831 status = SMB_VFS_CREATE_FILE(
5832 conn, /* conn */
5833 req, /* req */
5834 0, /* root_dir_fid */
5835 smb_fname_tmp, /* fname */
5836 FILE_WRITE_DATA, /* access_mask */
5837 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5838 FILE_SHARE_DELETE),
5839 FILE_OPEN, /* create_disposition*/
5840 0, /* create_options */
5841 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5842 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5843 0, /* allocation_size */
5844 0, /* private_flags */
5845 NULL, /* sd */
5846 NULL, /* ea_list */
5847 &new_fsp, /* result */
5848 NULL); /* pinfo */
5850 TALLOC_FREE(smb_fname_tmp);
5852 if (!NT_STATUS_IS_OK(status)) {
5853 /* NB. We check for open_was_deferred in the caller. */
5854 return status;
5857 /* See RAW-SFILEINFO-END-OF-FILE */
5858 if (fail_after_createfile) {
5859 close_file(req, new_fsp,NORMAL_CLOSE);
5860 return NT_STATUS_INVALID_LEVEL;
5863 if (vfs_set_filelen(new_fsp, size) == -1) {
5864 status = map_nt_error_from_unix(errno);
5865 close_file(req, new_fsp,NORMAL_CLOSE);
5866 return status;
5869 trigger_write_time_update_immediate(new_fsp);
5870 close_file(req, new_fsp,NORMAL_CLOSE);
5871 return NT_STATUS_OK;
5874 /****************************************************************************
5875 Deal with SMB_INFO_SET_EA.
5876 ****************************************************************************/
5878 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5879 const char *pdata,
5880 int total_data,
5881 files_struct *fsp,
5882 const struct smb_filename *smb_fname)
5884 struct ea_list *ea_list = NULL;
5885 TALLOC_CTX *ctx = NULL;
5886 NTSTATUS status = NT_STATUS_OK;
5888 if (total_data < 10) {
5890 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5891 length. They seem to have no effect. Bug #3212. JRA */
5893 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5894 /* We're done. We only get EA info in this call. */
5895 return NT_STATUS_OK;
5898 return NT_STATUS_INVALID_PARAMETER;
5901 if (IVAL(pdata,0) > total_data) {
5902 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5903 IVAL(pdata,0), (unsigned int)total_data));
5904 return NT_STATUS_INVALID_PARAMETER;
5907 ctx = talloc_tos();
5908 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5909 if (!ea_list) {
5910 return NT_STATUS_INVALID_PARAMETER;
5913 status = set_ea(conn, fsp, smb_fname, ea_list);
5915 return status;
5918 /****************************************************************************
5919 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5920 ****************************************************************************/
5922 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5923 const char *pdata,
5924 int total_data,
5925 files_struct *fsp)
5927 struct ea_list *ea_list = NULL;
5928 NTSTATUS status;
5930 if (!fsp) {
5931 return NT_STATUS_INVALID_HANDLE;
5934 if (!lp_ea_support(SNUM(conn))) {
5935 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5936 "EA's not supported.\n",
5937 (unsigned int)total_data));
5938 return NT_STATUS_EAS_NOT_SUPPORTED;
5941 if (total_data < 10) {
5942 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5943 "too small.\n",
5944 (unsigned int)total_data));
5945 return NT_STATUS_INVALID_PARAMETER;
5948 ea_list = read_nttrans_ea_list(talloc_tos(),
5949 pdata,
5950 total_data);
5952 if (!ea_list) {
5953 return NT_STATUS_INVALID_PARAMETER;
5956 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5958 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5959 smb_fname_str_dbg(fsp->fsp_name),
5960 nt_errstr(status) ));
5962 return status;
5966 /****************************************************************************
5967 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5968 ****************************************************************************/
5970 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5971 const char *pdata,
5972 int total_data,
5973 files_struct *fsp,
5974 struct smb_filename *smb_fname)
5976 NTSTATUS status = NT_STATUS_OK;
5977 bool delete_on_close;
5978 uint32 dosmode = 0;
5980 if (total_data < 1) {
5981 return NT_STATUS_INVALID_PARAMETER;
5984 if (fsp == NULL) {
5985 return NT_STATUS_INVALID_HANDLE;
5988 delete_on_close = (CVAL(pdata,0) ? True : False);
5989 dosmode = dos_mode(conn, smb_fname);
5991 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5992 "delete_on_close = %u\n",
5993 smb_fname_str_dbg(smb_fname),
5994 (unsigned int)dosmode,
5995 (unsigned int)delete_on_close ));
5997 if (delete_on_close) {
5998 status = can_set_delete_on_close(fsp, dosmode);
5999 if (!NT_STATUS_IS_OK(status)) {
6000 return status;
6004 /* The set is across all open files on this dev/inode pair. */
6005 if (!set_delete_on_close(fsp, delete_on_close,
6006 conn->session_info->security_token,
6007 conn->session_info->unix_token)) {
6008 return NT_STATUS_ACCESS_DENIED;
6010 return NT_STATUS_OK;
6013 /****************************************************************************
6014 Deal with SMB_FILE_POSITION_INFORMATION.
6015 ****************************************************************************/
6017 static NTSTATUS smb_file_position_information(connection_struct *conn,
6018 const char *pdata,
6019 int total_data,
6020 files_struct *fsp)
6022 uint64_t position_information;
6024 if (total_data < 8) {
6025 return NT_STATUS_INVALID_PARAMETER;
6028 if (fsp == NULL) {
6029 /* Ignore on pathname based set. */
6030 return NT_STATUS_OK;
6033 position_information = (uint64_t)IVAL(pdata,0);
6034 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6036 DEBUG(10,("smb_file_position_information: Set file position "
6037 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6038 (double)position_information));
6039 fsp->fh->position_information = position_information;
6040 return NT_STATUS_OK;
6043 /****************************************************************************
6044 Deal with SMB_FILE_MODE_INFORMATION.
6045 ****************************************************************************/
6047 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6048 const char *pdata,
6049 int total_data)
6051 uint32 mode;
6053 if (total_data < 4) {
6054 return NT_STATUS_INVALID_PARAMETER;
6056 mode = IVAL(pdata,0);
6057 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6058 return NT_STATUS_INVALID_PARAMETER;
6060 return NT_STATUS_OK;
6063 /****************************************************************************
6064 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6065 ****************************************************************************/
6067 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6068 struct smb_request *req,
6069 const char *pdata,
6070 int total_data,
6071 const struct smb_filename *smb_fname)
6073 char *link_target = NULL;
6074 const char *newname = smb_fname->base_name;
6075 TALLOC_CTX *ctx = talloc_tos();
6077 /* Set a symbolic link. */
6078 /* Don't allow this if follow links is false. */
6080 if (total_data == 0) {
6081 return NT_STATUS_INVALID_PARAMETER;
6084 if (!lp_symlinks(SNUM(conn))) {
6085 return NT_STATUS_ACCESS_DENIED;
6088 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6089 total_data, STR_TERMINATE);
6091 if (!link_target) {
6092 return NT_STATUS_INVALID_PARAMETER;
6095 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6096 newname, link_target ));
6098 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6099 return map_nt_error_from_unix(errno);
6102 return NT_STATUS_OK;
6105 /****************************************************************************
6106 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6107 ****************************************************************************/
6109 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6110 struct smb_request *req,
6111 const char *pdata, int total_data,
6112 struct smb_filename *smb_fname_new)
6114 char *oldname = NULL;
6115 struct smb_filename *smb_fname_old = NULL;
6116 TALLOC_CTX *ctx = talloc_tos();
6117 NTSTATUS status = NT_STATUS_OK;
6119 /* Set a hard link. */
6120 if (total_data == 0) {
6121 return NT_STATUS_INVALID_PARAMETER;
6124 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6125 total_data, STR_TERMINATE, &status);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return status;
6130 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6131 smb_fname_str_dbg(smb_fname_new), oldname));
6133 status = filename_convert(ctx,
6134 conn,
6135 req->flags2 & FLAGS2_DFS_PATHNAMES,
6136 oldname,
6138 NULL,
6139 &smb_fname_old);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 return status;
6144 return hardlink_internals(ctx, conn, req, false,
6145 smb_fname_old, smb_fname_new);
6148 /****************************************************************************
6149 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6150 ****************************************************************************/
6152 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6153 struct smb_request *req,
6154 const char *pdata,
6155 int total_data,
6156 files_struct *fsp,
6157 struct smb_filename *smb_fname_src)
6159 bool overwrite;
6160 uint32_t len;
6161 char *newname = NULL;
6162 struct smb_filename *smb_fname_dst = NULL;
6163 NTSTATUS status = NT_STATUS_OK;
6164 TALLOC_CTX *ctx = talloc_tos();
6166 if (!fsp) {
6167 return NT_STATUS_INVALID_HANDLE;
6170 if (total_data < 20) {
6171 return NT_STATUS_INVALID_PARAMETER;
6174 overwrite = (CVAL(pdata,0) ? True : False);
6175 len = IVAL(pdata,16);
6177 if (len > (total_data - 20) || (len == 0)) {
6178 return NT_STATUS_INVALID_PARAMETER;
6181 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6182 &pdata[20], len, STR_TERMINATE,
6183 &status);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 return status;
6188 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6189 newname));
6191 status = filename_convert(ctx,
6192 conn,
6193 req->flags2 & FLAGS2_DFS_PATHNAMES,
6194 newname,
6195 UCF_SAVE_LCOMP,
6196 NULL,
6197 &smb_fname_dst);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 return status;
6202 if (fsp->base_fsp) {
6203 /* newname must be a stream name. */
6204 if (newname[0] != ':') {
6205 return NT_STATUS_NOT_SUPPORTED;
6208 /* Create an smb_fname to call rename_internals_fsp() with. */
6209 status = create_synthetic_smb_fname(talloc_tos(),
6210 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6211 &smb_fname_dst);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 goto out;
6217 * Set the original last component, since
6218 * rename_internals_fsp() requires it.
6220 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6221 newname);
6222 if (smb_fname_dst->original_lcomp == NULL) {
6223 status = NT_STATUS_NO_MEMORY;
6224 goto out;
6229 DEBUG(10,("smb2_file_rename_information: "
6230 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6231 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6232 smb_fname_str_dbg(smb_fname_dst)));
6233 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6234 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6235 overwrite);
6237 out:
6238 TALLOC_FREE(smb_fname_dst);
6239 return status;
6242 static NTSTATUS smb_file_link_information(connection_struct *conn,
6243 struct smb_request *req,
6244 const char *pdata,
6245 int total_data,
6246 files_struct *fsp,
6247 struct smb_filename *smb_fname_src)
6249 bool overwrite;
6250 uint32_t len;
6251 char *newname = NULL;
6252 struct smb_filename *smb_fname_dst = NULL;
6253 NTSTATUS status = NT_STATUS_OK;
6254 TALLOC_CTX *ctx = talloc_tos();
6256 if (!fsp) {
6257 return NT_STATUS_INVALID_HANDLE;
6260 if (total_data < 20) {
6261 return NT_STATUS_INVALID_PARAMETER;
6264 overwrite = (CVAL(pdata,0) ? true : false);
6265 len = IVAL(pdata,16);
6267 if (len > (total_data - 20) || (len == 0)) {
6268 return NT_STATUS_INVALID_PARAMETER;
6271 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6272 &pdata[20], len, STR_TERMINATE,
6273 &status);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 return status;
6278 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6279 newname));
6281 status = filename_convert(ctx,
6282 conn,
6283 req->flags2 & FLAGS2_DFS_PATHNAMES,
6284 newname,
6285 UCF_SAVE_LCOMP,
6286 NULL,
6287 &smb_fname_dst);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 return status;
6292 if (fsp->base_fsp) {
6293 /* No stream names. */
6294 return NT_STATUS_NOT_SUPPORTED;
6297 DEBUG(10,("smb_file_link_information: "
6298 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6299 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6300 smb_fname_str_dbg(smb_fname_dst)));
6301 status = hardlink_internals(ctx,
6302 conn,
6303 req,
6304 overwrite,
6305 fsp->fsp_name,
6306 smb_fname_dst);
6308 TALLOC_FREE(smb_fname_dst);
6309 return status;
6312 /****************************************************************************
6313 Deal with SMB_FILE_RENAME_INFORMATION.
6314 ****************************************************************************/
6316 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6317 struct smb_request *req,
6318 const char *pdata,
6319 int total_data,
6320 files_struct *fsp,
6321 struct smb_filename *smb_fname_src)
6323 bool overwrite;
6324 uint32 root_fid;
6325 uint32 len;
6326 char *newname = NULL;
6327 struct smb_filename *smb_fname_dst = NULL;
6328 bool dest_has_wcard = False;
6329 NTSTATUS status = NT_STATUS_OK;
6330 char *p;
6331 TALLOC_CTX *ctx = talloc_tos();
6333 if (total_data < 13) {
6334 return NT_STATUS_INVALID_PARAMETER;
6337 overwrite = (CVAL(pdata,0) ? True : False);
6338 root_fid = IVAL(pdata,4);
6339 len = IVAL(pdata,8);
6341 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6342 return NT_STATUS_INVALID_PARAMETER;
6345 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6346 len, 0, &status,
6347 &dest_has_wcard);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 return status;
6352 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6353 newname));
6355 status = resolve_dfspath_wcard(ctx, conn,
6356 req->flags2 & FLAGS2_DFS_PATHNAMES,
6357 newname,
6358 true,
6359 !conn->sconn->using_smb2,
6360 &newname,
6361 &dest_has_wcard);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 return status;
6366 /* Check the new name has no '/' characters. */
6367 if (strchr_m(newname, '/')) {
6368 return NT_STATUS_NOT_SUPPORTED;
6371 if (fsp && fsp->base_fsp) {
6372 /* newname must be a stream name. */
6373 if (newname[0] != ':') {
6374 return NT_STATUS_NOT_SUPPORTED;
6377 /* Create an smb_fname to call rename_internals_fsp() with. */
6378 status = create_synthetic_smb_fname(talloc_tos(),
6379 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6380 &smb_fname_dst);
6381 if (!NT_STATUS_IS_OK(status)) {
6382 goto out;
6386 * Set the original last component, since
6387 * rename_internals_fsp() requires it.
6389 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6390 newname);
6391 if (smb_fname_dst->original_lcomp == NULL) {
6392 status = NT_STATUS_NO_MEMORY;
6393 goto out;
6396 } else {
6398 * Build up an smb_fname_dst based on the filename passed in.
6399 * We basically just strip off the last component, and put on
6400 * the newname instead.
6402 char *base_name = NULL;
6404 /* newname must *not* be a stream name. */
6405 if (newname[0] == ':') {
6406 return NT_STATUS_NOT_SUPPORTED;
6410 * Strip off the last component (filename) of the path passed
6411 * in.
6413 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6414 if (!base_name) {
6415 return NT_STATUS_NO_MEMORY;
6417 p = strrchr_m(base_name, '/');
6418 if (p) {
6419 p[1] = '\0';
6420 } else {
6421 base_name = talloc_strdup(ctx, "");
6422 if (!base_name) {
6423 return NT_STATUS_NO_MEMORY;
6426 /* Append the new name. */
6427 base_name = talloc_asprintf_append(base_name,
6428 "%s",
6429 newname);
6430 if (!base_name) {
6431 return NT_STATUS_NO_MEMORY;
6434 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6435 (UCF_SAVE_LCOMP |
6436 (dest_has_wcard ?
6437 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6438 0)));
6440 /* If an error we expect this to be
6441 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6443 if (!NT_STATUS_IS_OK(status)) {
6444 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6445 status)) {
6446 goto out;
6448 /* Create an smb_fname to call rename_internals_fsp() */
6449 status = create_synthetic_smb_fname(ctx,
6450 base_name, NULL,
6451 NULL,
6452 &smb_fname_dst);
6453 if (!NT_STATUS_IS_OK(status)) {
6454 goto out;
6459 if (fsp) {
6460 DEBUG(10,("smb_file_rename_information: "
6461 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6462 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6463 smb_fname_str_dbg(smb_fname_dst)));
6464 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6465 overwrite);
6466 } else {
6467 DEBUG(10,("smb_file_rename_information: "
6468 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6469 smb_fname_str_dbg(smb_fname_src),
6470 smb_fname_str_dbg(smb_fname_dst)));
6471 status = rename_internals(ctx, conn, req, smb_fname_src,
6472 smb_fname_dst, 0, overwrite, false,
6473 dest_has_wcard,
6474 FILE_WRITE_ATTRIBUTES);
6476 out:
6477 TALLOC_FREE(smb_fname_dst);
6478 return status;
6481 /****************************************************************************
6482 Deal with SMB_SET_POSIX_ACL.
6483 ****************************************************************************/
6485 #if defined(HAVE_POSIX_ACLS)
6486 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6487 const char *pdata,
6488 int total_data,
6489 files_struct *fsp,
6490 const struct smb_filename *smb_fname)
6492 uint16 posix_acl_version;
6493 uint16 num_file_acls;
6494 uint16 num_def_acls;
6495 bool valid_file_acls = True;
6496 bool valid_def_acls = True;
6498 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6499 return NT_STATUS_INVALID_PARAMETER;
6501 posix_acl_version = SVAL(pdata,0);
6502 num_file_acls = SVAL(pdata,2);
6503 num_def_acls = SVAL(pdata,4);
6505 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6506 valid_file_acls = False;
6507 num_file_acls = 0;
6510 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6511 valid_def_acls = False;
6512 num_def_acls = 0;
6515 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6516 return NT_STATUS_INVALID_PARAMETER;
6519 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6520 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6521 return NT_STATUS_INVALID_PARAMETER;
6524 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6525 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6526 (unsigned int)num_file_acls,
6527 (unsigned int)num_def_acls));
6529 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6530 smb_fname->base_name, num_file_acls,
6531 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6532 return map_nt_error_from_unix(errno);
6535 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6536 smb_fname->base_name, &smb_fname->st, num_def_acls,
6537 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6538 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6539 return map_nt_error_from_unix(errno);
6541 return NT_STATUS_OK;
6543 #endif
6545 /****************************************************************************
6546 Deal with SMB_SET_POSIX_LOCK.
6547 ****************************************************************************/
6549 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6550 struct smb_request *req,
6551 const char *pdata,
6552 int total_data,
6553 files_struct *fsp)
6555 uint64_t count;
6556 uint64_t offset;
6557 uint64_t smblctx;
6558 bool blocking_lock = False;
6559 enum brl_type lock_type;
6561 NTSTATUS status = NT_STATUS_OK;
6563 if (fsp == NULL || fsp->fh->fd == -1) {
6564 return NT_STATUS_INVALID_HANDLE;
6567 if (total_data != POSIX_LOCK_DATA_SIZE) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6572 case POSIX_LOCK_TYPE_READ:
6573 lock_type = READ_LOCK;
6574 break;
6575 case POSIX_LOCK_TYPE_WRITE:
6576 /* Return the right POSIX-mappable error code for files opened read-only. */
6577 if (!fsp->can_write) {
6578 return NT_STATUS_INVALID_HANDLE;
6580 lock_type = WRITE_LOCK;
6581 break;
6582 case POSIX_LOCK_TYPE_UNLOCK:
6583 lock_type = UNLOCK_LOCK;
6584 break;
6585 default:
6586 return NT_STATUS_INVALID_PARAMETER;
6589 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6590 blocking_lock = False;
6591 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6592 blocking_lock = True;
6593 } else {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 if (!lp_blocking_locks(SNUM(conn))) {
6598 blocking_lock = False;
6601 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6602 #if defined(HAVE_LONGLONG)
6603 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6604 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6605 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6606 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6607 #else /* HAVE_LONGLONG */
6608 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6609 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6610 #endif /* HAVE_LONGLONG */
6612 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6613 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6614 fsp_str_dbg(fsp),
6615 (unsigned int)lock_type,
6616 (unsigned long long)smblctx,
6617 (double)count,
6618 (double)offset ));
6620 if (lock_type == UNLOCK_LOCK) {
6621 status = do_unlock(req->sconn->msg_ctx,
6622 fsp,
6623 smblctx,
6624 count,
6625 offset,
6626 POSIX_LOCK);
6627 } else {
6628 uint64_t block_smblctx;
6630 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6631 fsp,
6632 smblctx,
6633 count,
6634 offset,
6635 lock_type,
6636 POSIX_LOCK,
6637 blocking_lock,
6638 &status,
6639 &block_smblctx,
6640 NULL);
6642 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6644 * A blocking lock was requested. Package up
6645 * this smb into a queued request and push it
6646 * onto the blocking lock queue.
6648 if(push_blocking_lock_request(br_lck,
6649 req,
6650 fsp,
6651 -1, /* infinite timeout. */
6653 smblctx,
6654 lock_type,
6655 POSIX_LOCK,
6656 offset,
6657 count,
6658 block_smblctx)) {
6659 TALLOC_FREE(br_lck);
6660 return status;
6663 TALLOC_FREE(br_lck);
6666 return status;
6669 /****************************************************************************
6670 Deal with SMB_SET_FILE_BASIC_INFO.
6671 ****************************************************************************/
6673 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6674 const char *pdata,
6675 int total_data,
6676 files_struct *fsp,
6677 const struct smb_filename *smb_fname)
6679 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6680 struct smb_file_time ft;
6681 uint32 dosmode = 0;
6682 NTSTATUS status = NT_STATUS_OK;
6684 ZERO_STRUCT(ft);
6686 if (total_data < 36) {
6687 return NT_STATUS_INVALID_PARAMETER;
6690 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 return status;
6695 /* Set the attributes */
6696 dosmode = IVAL(pdata,32);
6697 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6698 if (!NT_STATUS_IS_OK(status)) {
6699 return status;
6702 /* create time */
6703 ft.create_time = interpret_long_date(pdata);
6705 /* access time */
6706 ft.atime = interpret_long_date(pdata+8);
6708 /* write time. */
6709 ft.mtime = interpret_long_date(pdata+16);
6711 /* change time. */
6712 ft.ctime = interpret_long_date(pdata+24);
6714 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6715 smb_fname_str_dbg(smb_fname)));
6717 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6718 true);
6721 /****************************************************************************
6722 Deal with SMB_INFO_STANDARD.
6723 ****************************************************************************/
6725 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6726 const char *pdata,
6727 int total_data,
6728 files_struct *fsp,
6729 const struct smb_filename *smb_fname)
6731 NTSTATUS status;
6732 struct smb_file_time ft;
6734 ZERO_STRUCT(ft);
6736 if (total_data < 12) {
6737 return NT_STATUS_INVALID_PARAMETER;
6740 /* create time */
6741 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6742 /* access time */
6743 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6744 /* write time */
6745 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6747 DEBUG(10,("smb_set_info_standard: file %s\n",
6748 smb_fname_str_dbg(smb_fname)));
6750 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6751 if (!NT_STATUS_IS_OK(status)) {
6752 return status;
6755 return smb_set_file_time(conn,
6756 fsp,
6757 smb_fname,
6758 &ft,
6759 true);
6762 /****************************************************************************
6763 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6764 ****************************************************************************/
6766 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6767 struct smb_request *req,
6768 const char *pdata,
6769 int total_data,
6770 files_struct *fsp,
6771 struct smb_filename *smb_fname)
6773 uint64_t allocation_size = 0;
6774 NTSTATUS status = NT_STATUS_OK;
6775 files_struct *new_fsp = NULL;
6777 if (!VALID_STAT(smb_fname->st)) {
6778 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6781 if (total_data < 8) {
6782 return NT_STATUS_INVALID_PARAMETER;
6785 allocation_size = (uint64_t)IVAL(pdata,0);
6786 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6787 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6788 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6789 (double)allocation_size));
6791 if (allocation_size) {
6792 allocation_size = smb_roundup(conn, allocation_size);
6795 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6796 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6797 (double)allocation_size));
6799 if (fsp && fsp->fh->fd != -1) {
6800 /* Open file handle. */
6801 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6802 return NT_STATUS_ACCESS_DENIED;
6805 /* Only change if needed. */
6806 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6807 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6808 return map_nt_error_from_unix(errno);
6811 /* But always update the time. */
6813 * This is equivalent to a write. Ensure it's seen immediately
6814 * if there are no pending writes.
6816 trigger_write_time_update_immediate(fsp);
6817 return NT_STATUS_OK;
6820 /* Pathname or stat or directory file. */
6821 status = SMB_VFS_CREATE_FILE(
6822 conn, /* conn */
6823 req, /* req */
6824 0, /* root_dir_fid */
6825 smb_fname, /* fname */
6826 FILE_WRITE_DATA, /* access_mask */
6827 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6828 FILE_SHARE_DELETE),
6829 FILE_OPEN, /* create_disposition*/
6830 0, /* create_options */
6831 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6832 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6833 0, /* allocation_size */
6834 0, /* private_flags */
6835 NULL, /* sd */
6836 NULL, /* ea_list */
6837 &new_fsp, /* result */
6838 NULL); /* pinfo */
6840 if (!NT_STATUS_IS_OK(status)) {
6841 /* NB. We check for open_was_deferred in the caller. */
6842 return status;
6845 /* Only change if needed. */
6846 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6847 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6848 status = map_nt_error_from_unix(errno);
6849 close_file(req, new_fsp, NORMAL_CLOSE);
6850 return status;
6854 /* Changing the allocation size should set the last mod time. */
6856 * This is equivalent to a write. Ensure it's seen immediately
6857 * if there are no pending writes.
6859 trigger_write_time_update_immediate(new_fsp);
6861 close_file(req, new_fsp, NORMAL_CLOSE);
6862 return NT_STATUS_OK;
6865 /****************************************************************************
6866 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6867 ****************************************************************************/
6869 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6870 struct smb_request *req,
6871 const char *pdata,
6872 int total_data,
6873 files_struct *fsp,
6874 const struct smb_filename *smb_fname,
6875 bool fail_after_createfile)
6877 off_t size;
6879 if (total_data < 8) {
6880 return NT_STATUS_INVALID_PARAMETER;
6883 size = IVAL(pdata,0);
6884 size |= (((off_t)IVAL(pdata,4)) << 32);
6885 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6886 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6887 (double)size));
6889 return smb_set_file_size(conn, req,
6890 fsp,
6891 smb_fname,
6892 &smb_fname->st,
6893 size,
6894 fail_after_createfile);
6897 /****************************************************************************
6898 Allow a UNIX info mknod.
6899 ****************************************************************************/
6901 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6902 const char *pdata,
6903 int total_data,
6904 const struct smb_filename *smb_fname)
6906 uint32 file_type = IVAL(pdata,56);
6907 #if defined(HAVE_MAKEDEV)
6908 uint32 dev_major = IVAL(pdata,60);
6909 uint32 dev_minor = IVAL(pdata,68);
6910 #endif
6911 SMB_DEV_T dev = (SMB_DEV_T)0;
6912 uint32 raw_unixmode = IVAL(pdata,84);
6913 NTSTATUS status;
6914 mode_t unixmode;
6916 if (total_data < 100) {
6917 return NT_STATUS_INVALID_PARAMETER;
6920 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6921 PERM_NEW_FILE, &unixmode);
6922 if (!NT_STATUS_IS_OK(status)) {
6923 return status;
6926 #if defined(HAVE_MAKEDEV)
6927 dev = makedev(dev_major, dev_minor);
6928 #endif
6930 switch (file_type) {
6931 #if defined(S_IFIFO)
6932 case UNIX_TYPE_FIFO:
6933 unixmode |= S_IFIFO;
6934 break;
6935 #endif
6936 #if defined(S_IFSOCK)
6937 case UNIX_TYPE_SOCKET:
6938 unixmode |= S_IFSOCK;
6939 break;
6940 #endif
6941 #if defined(S_IFCHR)
6942 case UNIX_TYPE_CHARDEV:
6943 unixmode |= S_IFCHR;
6944 break;
6945 #endif
6946 #if defined(S_IFBLK)
6947 case UNIX_TYPE_BLKDEV:
6948 unixmode |= S_IFBLK;
6949 break;
6950 #endif
6951 default:
6952 return NT_STATUS_INVALID_PARAMETER;
6955 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6956 "%.0f mode 0%o for file %s\n", (double)dev,
6957 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6959 /* Ok - do the mknod. */
6960 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6961 return map_nt_error_from_unix(errno);
6964 /* If any of the other "set" calls fail we
6965 * don't want to end up with a half-constructed mknod.
6968 if (lp_inherit_perms(SNUM(conn))) {
6969 char *parent;
6970 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6971 &parent, NULL)) {
6972 return NT_STATUS_NO_MEMORY;
6974 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6975 unixmode);
6976 TALLOC_FREE(parent);
6979 return NT_STATUS_OK;
6982 /****************************************************************************
6983 Deal with SMB_SET_FILE_UNIX_BASIC.
6984 ****************************************************************************/
6986 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6987 struct smb_request *req,
6988 const char *pdata,
6989 int total_data,
6990 files_struct *fsp,
6991 const struct smb_filename *smb_fname)
6993 struct smb_file_time ft;
6994 uint32 raw_unixmode;
6995 mode_t unixmode;
6996 off_t size = 0;
6997 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6998 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6999 NTSTATUS status = NT_STATUS_OK;
7000 bool delete_on_fail = False;
7001 enum perm_type ptype;
7002 files_struct *all_fsps = NULL;
7003 bool modify_mtime = true;
7004 struct file_id id;
7005 struct smb_filename *smb_fname_tmp = NULL;
7006 SMB_STRUCT_STAT sbuf;
7008 ZERO_STRUCT(ft);
7010 if (total_data < 100) {
7011 return NT_STATUS_INVALID_PARAMETER;
7014 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7015 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7016 size=IVAL(pdata,0); /* first 8 Bytes are size */
7017 size |= (((off_t)IVAL(pdata,4)) << 32);
7020 ft.atime = interpret_long_date(pdata+24); /* access_time */
7021 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7022 set_owner = (uid_t)IVAL(pdata,40);
7023 set_grp = (gid_t)IVAL(pdata,48);
7024 raw_unixmode = IVAL(pdata,84);
7026 if (VALID_STAT(smb_fname->st)) {
7027 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7028 ptype = PERM_EXISTING_DIR;
7029 } else {
7030 ptype = PERM_EXISTING_FILE;
7032 } else {
7033 ptype = PERM_NEW_FILE;
7036 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7037 ptype, &unixmode);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 return status;
7042 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7043 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7044 smb_fname_str_dbg(smb_fname), (double)size,
7045 (unsigned int)set_owner, (unsigned int)set_grp,
7046 (int)raw_unixmode));
7048 sbuf = smb_fname->st;
7050 if (!VALID_STAT(sbuf)) {
7052 * The only valid use of this is to create character and block
7053 * devices, and named pipes. This is deprecated (IMHO) and
7054 * a new info level should be used for mknod. JRA.
7057 status = smb_unix_mknod(conn,
7058 pdata,
7059 total_data,
7060 smb_fname);
7061 if (!NT_STATUS_IS_OK(status)) {
7062 return status;
7065 status = copy_smb_filename(talloc_tos(), smb_fname,
7066 &smb_fname_tmp);
7067 if (!NT_STATUS_IS_OK(status)) {
7068 return status;
7071 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7072 status = map_nt_error_from_unix(errno);
7073 TALLOC_FREE(smb_fname_tmp);
7074 SMB_VFS_UNLINK(conn, smb_fname);
7075 return status;
7078 sbuf = smb_fname_tmp->st;
7079 smb_fname = smb_fname_tmp;
7081 /* Ensure we don't try and change anything else. */
7082 raw_unixmode = SMB_MODE_NO_CHANGE;
7083 size = get_file_size_stat(&sbuf);
7084 ft.atime = sbuf.st_ex_atime;
7085 ft.mtime = sbuf.st_ex_mtime;
7087 * We continue here as we might want to change the
7088 * owner uid/gid.
7090 delete_on_fail = True;
7093 #if 1
7094 /* Horrible backwards compatibility hack as an old server bug
7095 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7096 * */
7098 if (!size) {
7099 size = get_file_size_stat(&sbuf);
7101 #endif
7104 * Deal with the UNIX specific mode set.
7107 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7108 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7109 "setting mode 0%o for file %s\n",
7110 (unsigned int)unixmode,
7111 smb_fname_str_dbg(smb_fname)));
7112 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7113 return map_nt_error_from_unix(errno);
7118 * Deal with the UNIX specific uid set.
7121 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7122 (sbuf.st_ex_uid != set_owner)) {
7123 int ret;
7125 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7126 "changing owner %u for path %s\n",
7127 (unsigned int)set_owner,
7128 smb_fname_str_dbg(smb_fname)));
7130 if (S_ISLNK(sbuf.st_ex_mode)) {
7131 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7132 set_owner, (gid_t)-1);
7133 } else {
7134 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7135 set_owner, (gid_t)-1);
7138 if (ret != 0) {
7139 status = map_nt_error_from_unix(errno);
7140 if (delete_on_fail) {
7141 SMB_VFS_UNLINK(conn, smb_fname);
7143 return status;
7148 * Deal with the UNIX specific gid set.
7151 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7152 (sbuf.st_ex_gid != set_grp)) {
7153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7154 "changing group %u for file %s\n",
7155 (unsigned int)set_owner,
7156 smb_fname_str_dbg(smb_fname)));
7157 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7158 set_grp) != 0) {
7159 status = map_nt_error_from_unix(errno);
7160 if (delete_on_fail) {
7161 SMB_VFS_UNLINK(conn, smb_fname);
7163 return status;
7167 /* Deal with any size changes. */
7169 status = smb_set_file_size(conn, req,
7170 fsp,
7171 smb_fname,
7172 &sbuf,
7173 size,
7174 false);
7175 if (!NT_STATUS_IS_OK(status)) {
7176 return status;
7179 /* Deal with any time changes. */
7180 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7181 /* No change, don't cancel anything. */
7182 return status;
7185 id = vfs_file_id_from_sbuf(conn, &sbuf);
7186 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7187 all_fsps = file_find_di_next(all_fsps)) {
7189 * We're setting the time explicitly for UNIX.
7190 * Cancel any pending changes over all handles.
7192 all_fsps->update_write_time_on_close = false;
7193 TALLOC_FREE(all_fsps->update_write_time_event);
7197 * Override the "setting_write_time"
7198 * parameter here as it almost does what
7199 * we need. Just remember if we modified
7200 * mtime and send the notify ourselves.
7202 if (null_timespec(ft.mtime)) {
7203 modify_mtime = false;
7206 status = smb_set_file_time(conn,
7207 fsp,
7208 smb_fname,
7209 &ft,
7210 false);
7211 if (modify_mtime) {
7212 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7213 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7215 return status;
7218 /****************************************************************************
7219 Deal with SMB_SET_FILE_UNIX_INFO2.
7220 ****************************************************************************/
7222 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7223 struct smb_request *req,
7224 const char *pdata,
7225 int total_data,
7226 files_struct *fsp,
7227 const struct smb_filename *smb_fname)
7229 NTSTATUS status;
7230 uint32 smb_fflags;
7231 uint32 smb_fmask;
7233 if (total_data < 116) {
7234 return NT_STATUS_INVALID_PARAMETER;
7237 /* Start by setting all the fields that are common between UNIX_BASIC
7238 * and UNIX_INFO2.
7240 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7241 fsp, smb_fname);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 return status;
7246 smb_fflags = IVAL(pdata, 108);
7247 smb_fmask = IVAL(pdata, 112);
7249 /* NB: We should only attempt to alter the file flags if the client
7250 * sends a non-zero mask.
7252 if (smb_fmask != 0) {
7253 int stat_fflags = 0;
7255 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7256 smb_fmask, &stat_fflags)) {
7257 /* Client asked to alter a flag we don't understand. */
7258 return NT_STATUS_INVALID_PARAMETER;
7261 if (fsp && fsp->fh->fd != -1) {
7262 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7263 return NT_STATUS_NOT_SUPPORTED;
7264 } else {
7265 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7266 stat_fflags) != 0) {
7267 return map_nt_error_from_unix(errno);
7272 /* XXX: need to add support for changing the create_time here. You
7273 * can do this for paths on Darwin with setattrlist(2). The right way
7274 * to hook this up is probably by extending the VFS utimes interface.
7277 return NT_STATUS_OK;
7280 /****************************************************************************
7281 Create a directory with POSIX semantics.
7282 ****************************************************************************/
7284 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7285 struct smb_request *req,
7286 char **ppdata,
7287 int total_data,
7288 struct smb_filename *smb_fname,
7289 int *pdata_return_size)
7291 NTSTATUS status = NT_STATUS_OK;
7292 uint32 raw_unixmode = 0;
7293 uint32 mod_unixmode = 0;
7294 mode_t unixmode = (mode_t)0;
7295 files_struct *fsp = NULL;
7296 uint16 info_level_return = 0;
7297 int info;
7298 char *pdata = *ppdata;
7300 if (total_data < 18) {
7301 return NT_STATUS_INVALID_PARAMETER;
7304 raw_unixmode = IVAL(pdata,8);
7305 /* Next 4 bytes are not yet defined. */
7307 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7308 PERM_NEW_DIR, &unixmode);
7309 if (!NT_STATUS_IS_OK(status)) {
7310 return status;
7313 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7315 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7316 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7318 status = SMB_VFS_CREATE_FILE(
7319 conn, /* conn */
7320 req, /* req */
7321 0, /* root_dir_fid */
7322 smb_fname, /* fname */
7323 FILE_READ_ATTRIBUTES, /* access_mask */
7324 FILE_SHARE_NONE, /* share_access */
7325 FILE_CREATE, /* create_disposition*/
7326 FILE_DIRECTORY_FILE, /* create_options */
7327 mod_unixmode, /* file_attributes */
7328 0, /* oplock_request */
7329 0, /* allocation_size */
7330 0, /* private_flags */
7331 NULL, /* sd */
7332 NULL, /* ea_list */
7333 &fsp, /* result */
7334 &info); /* pinfo */
7336 if (NT_STATUS_IS_OK(status)) {
7337 close_file(req, fsp, NORMAL_CLOSE);
7340 info_level_return = SVAL(pdata,16);
7342 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7343 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7344 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7345 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7346 } else {
7347 *pdata_return_size = 12;
7350 /* Realloc the data size */
7351 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7352 if (*ppdata == NULL) {
7353 *pdata_return_size = 0;
7354 return NT_STATUS_NO_MEMORY;
7356 pdata = *ppdata;
7358 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7359 SSVAL(pdata,2,0); /* No fnum. */
7360 SIVAL(pdata,4,info); /* Was directory created. */
7362 switch (info_level_return) {
7363 case SMB_QUERY_FILE_UNIX_BASIC:
7364 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7365 SSVAL(pdata,10,0); /* Padding. */
7366 store_file_unix_basic(conn, pdata + 12, fsp,
7367 &smb_fname->st);
7368 break;
7369 case SMB_QUERY_FILE_UNIX_INFO2:
7370 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7371 SSVAL(pdata,10,0); /* Padding. */
7372 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7373 &smb_fname->st);
7374 break;
7375 default:
7376 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7377 SSVAL(pdata,10,0); /* Padding. */
7378 break;
7381 return status;
7384 /****************************************************************************
7385 Open/Create a file with POSIX semantics.
7386 ****************************************************************************/
7388 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7389 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7391 static NTSTATUS smb_posix_open(connection_struct *conn,
7392 struct smb_request *req,
7393 char **ppdata,
7394 int total_data,
7395 struct smb_filename *smb_fname,
7396 int *pdata_return_size)
7398 bool extended_oplock_granted = False;
7399 char *pdata = *ppdata;
7400 uint32 flags = 0;
7401 uint32 wire_open_mode = 0;
7402 uint32 raw_unixmode = 0;
7403 uint32 mod_unixmode = 0;
7404 uint32 create_disp = 0;
7405 uint32 access_mask = 0;
7406 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7407 NTSTATUS status = NT_STATUS_OK;
7408 mode_t unixmode = (mode_t)0;
7409 files_struct *fsp = NULL;
7410 int oplock_request = 0;
7411 int info = 0;
7412 uint16 info_level_return = 0;
7414 if (total_data < 18) {
7415 return NT_STATUS_INVALID_PARAMETER;
7418 flags = IVAL(pdata,0);
7419 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7420 if (oplock_request) {
7421 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7424 wire_open_mode = IVAL(pdata,4);
7426 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7427 return smb_posix_mkdir(conn, req,
7428 ppdata,
7429 total_data,
7430 smb_fname,
7431 pdata_return_size);
7434 switch (wire_open_mode & SMB_ACCMODE) {
7435 case SMB_O_RDONLY:
7436 access_mask = SMB_O_RDONLY_MAPPING;
7437 break;
7438 case SMB_O_WRONLY:
7439 access_mask = SMB_O_WRONLY_MAPPING;
7440 break;
7441 case SMB_O_RDWR:
7442 access_mask = (SMB_O_RDONLY_MAPPING|
7443 SMB_O_WRONLY_MAPPING);
7444 break;
7445 default:
7446 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7447 (unsigned int)wire_open_mode ));
7448 return NT_STATUS_INVALID_PARAMETER;
7451 wire_open_mode &= ~SMB_ACCMODE;
7453 /* First take care of O_CREAT|O_EXCL interactions. */
7454 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7455 case (SMB_O_CREAT | SMB_O_EXCL):
7456 /* File exists fail. File not exist create. */
7457 create_disp = FILE_CREATE;
7458 break;
7459 case SMB_O_CREAT:
7460 /* File exists open. File not exist create. */
7461 create_disp = FILE_OPEN_IF;
7462 break;
7463 case SMB_O_EXCL:
7464 /* O_EXCL on its own without O_CREAT is undefined.
7465 We deliberately ignore it as some versions of
7466 Linux CIFSFS can send a bare O_EXCL on the
7467 wire which other filesystems in the kernel
7468 ignore. See bug 9519 for details. */
7470 /* Fallthrough. */
7472 case 0:
7473 /* File exists open. File not exist fail. */
7474 create_disp = FILE_OPEN;
7475 break;
7476 default:
7477 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7478 (unsigned int)wire_open_mode ));
7479 return NT_STATUS_INVALID_PARAMETER;
7482 /* Next factor in the effects of O_TRUNC. */
7483 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7485 if (wire_open_mode & SMB_O_TRUNC) {
7486 switch (create_disp) {
7487 case FILE_CREATE:
7488 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7489 /* Leave create_disp alone as
7490 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7492 /* File exists fail. File not exist create. */
7493 break;
7494 case FILE_OPEN_IF:
7495 /* SMB_O_CREAT | SMB_O_TRUNC */
7496 /* File exists overwrite. File not exist create. */
7497 create_disp = FILE_OVERWRITE_IF;
7498 break;
7499 case FILE_OPEN:
7500 /* SMB_O_TRUNC */
7501 /* File exists overwrite. File not exist fail. */
7502 create_disp = FILE_OVERWRITE;
7503 break;
7504 default:
7505 /* Cannot get here. */
7506 smb_panic("smb_posix_open: logic error");
7507 return NT_STATUS_INVALID_PARAMETER;
7511 raw_unixmode = IVAL(pdata,8);
7512 /* Next 4 bytes are not yet defined. */
7514 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7515 (VALID_STAT(smb_fname->st) ?
7516 PERM_EXISTING_FILE : PERM_NEW_FILE),
7517 &unixmode);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 return status;
7523 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7525 if (wire_open_mode & SMB_O_SYNC) {
7526 create_options |= FILE_WRITE_THROUGH;
7528 if (wire_open_mode & SMB_O_APPEND) {
7529 access_mask |= FILE_APPEND_DATA;
7531 if (wire_open_mode & SMB_O_DIRECT) {
7532 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7535 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7536 VALID_STAT_OF_DIR(smb_fname->st)) {
7537 if (access_mask != SMB_O_RDONLY_MAPPING) {
7538 return NT_STATUS_FILE_IS_A_DIRECTORY;
7540 create_options &= ~FILE_NON_DIRECTORY_FILE;
7541 create_options |= FILE_DIRECTORY_FILE;
7544 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7545 smb_fname_str_dbg(smb_fname),
7546 (unsigned int)wire_open_mode,
7547 (unsigned int)unixmode ));
7549 status = SMB_VFS_CREATE_FILE(
7550 conn, /* conn */
7551 req, /* req */
7552 0, /* root_dir_fid */
7553 smb_fname, /* fname */
7554 access_mask, /* access_mask */
7555 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7556 FILE_SHARE_DELETE),
7557 create_disp, /* create_disposition*/
7558 create_options, /* create_options */
7559 mod_unixmode, /* file_attributes */
7560 oplock_request, /* oplock_request */
7561 0, /* allocation_size */
7562 0, /* private_flags */
7563 NULL, /* sd */
7564 NULL, /* ea_list */
7565 &fsp, /* result */
7566 &info); /* pinfo */
7568 if (!NT_STATUS_IS_OK(status)) {
7569 return status;
7572 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7573 extended_oplock_granted = True;
7576 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7577 extended_oplock_granted = True;
7580 info_level_return = SVAL(pdata,16);
7582 /* Allocate the correct return size. */
7584 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7585 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7586 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7587 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7588 } else {
7589 *pdata_return_size = 12;
7592 /* Realloc the data size */
7593 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7594 if (*ppdata == NULL) {
7595 close_file(req, fsp, ERROR_CLOSE);
7596 *pdata_return_size = 0;
7597 return NT_STATUS_NO_MEMORY;
7599 pdata = *ppdata;
7601 if (extended_oplock_granted) {
7602 if (flags & REQUEST_BATCH_OPLOCK) {
7603 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7604 } else {
7605 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7607 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7608 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7609 } else {
7610 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7613 SSVAL(pdata,2,fsp->fnum);
7614 SIVAL(pdata,4,info); /* Was file created etc. */
7616 switch (info_level_return) {
7617 case SMB_QUERY_FILE_UNIX_BASIC:
7618 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7619 SSVAL(pdata,10,0); /* padding. */
7620 store_file_unix_basic(conn, pdata + 12, fsp,
7621 &smb_fname->st);
7622 break;
7623 case SMB_QUERY_FILE_UNIX_INFO2:
7624 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7625 SSVAL(pdata,10,0); /* padding. */
7626 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7627 &smb_fname->st);
7628 break;
7629 default:
7630 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7631 SSVAL(pdata,10,0); /* padding. */
7632 break;
7634 return NT_STATUS_OK;
7637 /****************************************************************************
7638 Delete a file with POSIX semantics.
7639 ****************************************************************************/
7641 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7642 struct smb_request *req,
7643 const char *pdata,
7644 int total_data,
7645 struct smb_filename *smb_fname)
7647 NTSTATUS status = NT_STATUS_OK;
7648 files_struct *fsp = NULL;
7649 uint16 flags = 0;
7650 char del = 1;
7651 int info = 0;
7652 int create_options = 0;
7653 int i;
7654 struct share_mode_lock *lck = NULL;
7656 if (total_data < 2) {
7657 return NT_STATUS_INVALID_PARAMETER;
7660 flags = SVAL(pdata,0);
7662 if (!VALID_STAT(smb_fname->st)) {
7663 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7666 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7667 !VALID_STAT_OF_DIR(smb_fname->st)) {
7668 return NT_STATUS_NOT_A_DIRECTORY;
7671 DEBUG(10,("smb_posix_unlink: %s %s\n",
7672 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7673 smb_fname_str_dbg(smb_fname)));
7675 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7676 create_options |= FILE_DIRECTORY_FILE;
7679 status = SMB_VFS_CREATE_FILE(
7680 conn, /* conn */
7681 req, /* req */
7682 0, /* root_dir_fid */
7683 smb_fname, /* fname */
7684 DELETE_ACCESS, /* access_mask */
7685 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7686 FILE_SHARE_DELETE),
7687 FILE_OPEN, /* create_disposition*/
7688 create_options, /* create_options */
7689 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7690 0, /* oplock_request */
7691 0, /* allocation_size */
7692 0, /* private_flags */
7693 NULL, /* sd */
7694 NULL, /* ea_list */
7695 &fsp, /* result */
7696 &info); /* pinfo */
7698 if (!NT_STATUS_IS_OK(status)) {
7699 return status;
7703 * Don't lie to client. If we can't really delete due to
7704 * non-POSIX opens return SHARING_VIOLATION.
7707 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7708 if (lck == NULL) {
7709 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7710 "lock for file %s\n", fsp_str_dbg(fsp)));
7711 close_file(req, fsp, NORMAL_CLOSE);
7712 return NT_STATUS_INVALID_PARAMETER;
7716 * See if others still have the file open. If this is the case, then
7717 * don't delete. If all opens are POSIX delete we can set the delete
7718 * on close disposition.
7720 for (i=0; i<lck->data->num_share_modes; i++) {
7721 struct share_mode_entry *e = &lck->data->share_modes[i];
7722 if (is_valid_share_mode_entry(e)) {
7723 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7724 continue;
7726 if (share_mode_stale_pid(lck->data, i)) {
7727 continue;
7729 /* Fail with sharing violation. */
7730 TALLOC_FREE(lck);
7731 close_file(req, fsp, NORMAL_CLOSE);
7732 return NT_STATUS_SHARING_VIOLATION;
7737 * Set the delete on close.
7739 status = smb_set_file_disposition_info(conn,
7740 &del,
7742 fsp,
7743 smb_fname);
7745 TALLOC_FREE(lck);
7747 if (!NT_STATUS_IS_OK(status)) {
7748 close_file(req, fsp, NORMAL_CLOSE);
7749 return status;
7751 return close_file(req, fsp, NORMAL_CLOSE);
7754 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7755 struct smb_request *req,
7756 TALLOC_CTX *mem_ctx,
7757 uint16_t info_level,
7758 files_struct *fsp,
7759 struct smb_filename *smb_fname,
7760 char **ppdata, int total_data,
7761 int *ret_data_size)
7763 char *pdata = *ppdata;
7764 NTSTATUS status = NT_STATUS_OK;
7765 int data_return_size = 0;
7767 *ret_data_size = 0;
7769 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7770 return NT_STATUS_INVALID_LEVEL;
7773 if (!CAN_WRITE(conn)) {
7774 /* Allow POSIX opens. The open path will deny
7775 * any non-readonly opens. */
7776 if (info_level != SMB_POSIX_PATH_OPEN) {
7777 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7781 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7782 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7783 fsp_fnum_dbg(fsp),
7784 info_level, total_data));
7786 switch (info_level) {
7788 case SMB_INFO_STANDARD:
7790 status = smb_set_info_standard(conn,
7791 pdata,
7792 total_data,
7793 fsp,
7794 smb_fname);
7795 break;
7798 case SMB_INFO_SET_EA:
7800 status = smb_info_set_ea(conn,
7801 pdata,
7802 total_data,
7803 fsp,
7804 smb_fname);
7805 break;
7808 case SMB_SET_FILE_BASIC_INFO:
7809 case SMB_FILE_BASIC_INFORMATION:
7811 status = smb_set_file_basic_info(conn,
7812 pdata,
7813 total_data,
7814 fsp,
7815 smb_fname);
7816 break;
7819 case SMB_FILE_ALLOCATION_INFORMATION:
7820 case SMB_SET_FILE_ALLOCATION_INFO:
7822 status = smb_set_file_allocation_info(conn, req,
7823 pdata,
7824 total_data,
7825 fsp,
7826 smb_fname);
7827 break;
7830 case SMB_FILE_END_OF_FILE_INFORMATION:
7831 case SMB_SET_FILE_END_OF_FILE_INFO:
7834 * XP/Win7 both fail after the createfile with
7835 * SMB_SET_FILE_END_OF_FILE_INFO but not
7836 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7837 * The level is known here, so pass it down
7838 * appropriately.
7840 bool should_fail =
7841 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7843 status = smb_set_file_end_of_file_info(conn, req,
7844 pdata,
7845 total_data,
7846 fsp,
7847 smb_fname,
7848 should_fail);
7849 break;
7852 case SMB_FILE_DISPOSITION_INFORMATION:
7853 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7855 #if 0
7856 /* JRA - We used to just ignore this on a path ?
7857 * Shouldn't this be invalid level on a pathname
7858 * based call ?
7860 if (tran_call != TRANSACT2_SETFILEINFO) {
7861 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7863 #endif
7864 status = smb_set_file_disposition_info(conn,
7865 pdata,
7866 total_data,
7867 fsp,
7868 smb_fname);
7869 break;
7872 case SMB_FILE_POSITION_INFORMATION:
7874 status = smb_file_position_information(conn,
7875 pdata,
7876 total_data,
7877 fsp);
7878 break;
7881 case SMB_FILE_FULL_EA_INFORMATION:
7883 status = smb_set_file_full_ea_info(conn,
7884 pdata,
7885 total_data,
7886 fsp);
7887 break;
7890 /* From tridge Samba4 :
7891 * MODE_INFORMATION in setfileinfo (I have no
7892 * idea what "mode information" on a file is - it takes a value of 0,
7893 * 2, 4 or 6. What could it be?).
7896 case SMB_FILE_MODE_INFORMATION:
7898 status = smb_file_mode_information(conn,
7899 pdata,
7900 total_data);
7901 break;
7905 * CIFS UNIX extensions.
7908 case SMB_SET_FILE_UNIX_BASIC:
7910 status = smb_set_file_unix_basic(conn, req,
7911 pdata,
7912 total_data,
7913 fsp,
7914 smb_fname);
7915 break;
7918 case SMB_SET_FILE_UNIX_INFO2:
7920 status = smb_set_file_unix_info2(conn, req,
7921 pdata,
7922 total_data,
7923 fsp,
7924 smb_fname);
7925 break;
7928 case SMB_SET_FILE_UNIX_LINK:
7930 if (fsp) {
7931 /* We must have a pathname for this. */
7932 return NT_STATUS_INVALID_LEVEL;
7934 status = smb_set_file_unix_link(conn, req, pdata,
7935 total_data, smb_fname);
7936 break;
7939 case SMB_SET_FILE_UNIX_HLINK:
7941 if (fsp) {
7942 /* We must have a pathname for this. */
7943 return NT_STATUS_INVALID_LEVEL;
7945 status = smb_set_file_unix_hlink(conn, req,
7946 pdata, total_data,
7947 smb_fname);
7948 break;
7951 case SMB_FILE_RENAME_INFORMATION:
7953 status = smb_file_rename_information(conn, req,
7954 pdata, total_data,
7955 fsp, smb_fname);
7956 break;
7959 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7961 /* SMB2 rename information. */
7962 status = smb2_file_rename_information(conn, req,
7963 pdata, total_data,
7964 fsp, smb_fname);
7965 break;
7968 case SMB_FILE_LINK_INFORMATION:
7970 status = smb_file_link_information(conn, req,
7971 pdata, total_data,
7972 fsp, smb_fname);
7973 break;
7976 #if defined(HAVE_POSIX_ACLS)
7977 case SMB_SET_POSIX_ACL:
7979 status = smb_set_posix_acl(conn,
7980 pdata,
7981 total_data,
7982 fsp,
7983 smb_fname);
7984 break;
7986 #endif
7988 case SMB_SET_POSIX_LOCK:
7990 if (!fsp) {
7991 return NT_STATUS_INVALID_LEVEL;
7993 status = smb_set_posix_lock(conn, req,
7994 pdata, total_data, fsp);
7995 break;
7998 case SMB_POSIX_PATH_OPEN:
8000 if (fsp) {
8001 /* We must have a pathname for this. */
8002 return NT_STATUS_INVALID_LEVEL;
8005 status = smb_posix_open(conn, req,
8006 ppdata,
8007 total_data,
8008 smb_fname,
8009 &data_return_size);
8010 break;
8013 case SMB_POSIX_PATH_UNLINK:
8015 if (fsp) {
8016 /* We must have a pathname for this. */
8017 return NT_STATUS_INVALID_LEVEL;
8020 status = smb_posix_unlink(conn, req,
8021 pdata,
8022 total_data,
8023 smb_fname);
8024 break;
8027 default:
8028 return NT_STATUS_INVALID_LEVEL;
8031 if (!NT_STATUS_IS_OK(status)) {
8032 return status;
8035 *ret_data_size = data_return_size;
8036 return NT_STATUS_OK;
8039 /****************************************************************************
8040 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8041 ****************************************************************************/
8043 static void call_trans2setfilepathinfo(connection_struct *conn,
8044 struct smb_request *req,
8045 unsigned int tran_call,
8046 char **pparams, int total_params,
8047 char **ppdata, int total_data,
8048 unsigned int max_data_bytes)
8050 char *params = *pparams;
8051 char *pdata = *ppdata;
8052 uint16 info_level;
8053 struct smb_filename *smb_fname = NULL;
8054 files_struct *fsp = NULL;
8055 NTSTATUS status = NT_STATUS_OK;
8056 int data_return_size = 0;
8058 if (!params) {
8059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8060 return;
8063 if (tran_call == TRANSACT2_SETFILEINFO) {
8064 if (total_params < 4) {
8065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8066 return;
8069 fsp = file_fsp(req, SVAL(params,0));
8070 /* Basic check for non-null fsp. */
8071 if (!check_fsp_open(conn, req, fsp)) {
8072 return;
8074 info_level = SVAL(params,2);
8076 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8077 &smb_fname);
8078 if (!NT_STATUS_IS_OK(status)) {
8079 reply_nterror(req, status);
8080 return;
8083 if(fsp->fh->fd == -1) {
8085 * This is actually a SETFILEINFO on a directory
8086 * handle (returned from an NT SMB). NT5.0 seems
8087 * to do this call. JRA.
8089 if (INFO_LEVEL_IS_UNIX(info_level)) {
8090 /* Always do lstat for UNIX calls. */
8091 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8092 DEBUG(3,("call_trans2setfilepathinfo: "
8093 "SMB_VFS_LSTAT of %s failed "
8094 "(%s)\n",
8095 smb_fname_str_dbg(smb_fname),
8096 strerror(errno)));
8097 reply_nterror(req, map_nt_error_from_unix(errno));
8098 return;
8100 } else {
8101 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8102 DEBUG(3,("call_trans2setfilepathinfo: "
8103 "fileinfo of %s failed (%s)\n",
8104 smb_fname_str_dbg(smb_fname),
8105 strerror(errno)));
8106 reply_nterror(req, map_nt_error_from_unix(errno));
8107 return;
8110 } else if (fsp->print_file) {
8112 * Doing a DELETE_ON_CLOSE should cancel a print job.
8114 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8115 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8117 DEBUG(3,("call_trans2setfilepathinfo: "
8118 "Cancelling print job (%s)\n",
8119 fsp_str_dbg(fsp)));
8121 SSVAL(params,0,0);
8122 send_trans2_replies(conn, req, params, 2,
8123 *ppdata, 0,
8124 max_data_bytes);
8125 return;
8126 } else {
8127 reply_nterror(req,
8128 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8129 return;
8131 } else {
8133 * Original code - this is an open file.
8135 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8136 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8137 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8138 strerror(errno)));
8139 reply_nterror(req, map_nt_error_from_unix(errno));
8140 return;
8143 } else {
8144 char *fname = NULL;
8145 uint32_t ucf_flags = 0;
8147 /* set path info */
8148 if (total_params < 7) {
8149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8150 return;
8153 info_level = SVAL(params,0);
8154 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8155 total_params - 6, STR_TERMINATE,
8156 &status);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 reply_nterror(req, status);
8159 return;
8162 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8163 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8164 info_level == SMB_FILE_RENAME_INFORMATION ||
8165 info_level == SMB_POSIX_PATH_UNLINK) {
8166 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8169 status = filename_convert(req, conn,
8170 req->flags2 & FLAGS2_DFS_PATHNAMES,
8171 fname,
8172 ucf_flags,
8173 NULL,
8174 &smb_fname);
8175 if (!NT_STATUS_IS_OK(status)) {
8176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8177 reply_botherror(req,
8178 NT_STATUS_PATH_NOT_COVERED,
8179 ERRSRV, ERRbadpath);
8180 return;
8182 reply_nterror(req, status);
8183 return;
8186 if (INFO_LEVEL_IS_UNIX(info_level)) {
8188 * For CIFS UNIX extensions the target name may not exist.
8191 /* Always do lstat for UNIX calls. */
8192 SMB_VFS_LSTAT(conn, smb_fname);
8194 } else if (!VALID_STAT(smb_fname->st) &&
8195 SMB_VFS_STAT(conn, smb_fname)) {
8196 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8197 "%s failed (%s)\n",
8198 smb_fname_str_dbg(smb_fname),
8199 strerror(errno)));
8200 reply_nterror(req, map_nt_error_from_unix(errno));
8201 return;
8205 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8206 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8207 fsp_fnum_dbg(fsp),
8208 info_level,total_data));
8210 /* Realloc the parameter size */
8211 *pparams = (char *)SMB_REALLOC(*pparams,2);
8212 if (*pparams == NULL) {
8213 reply_nterror(req, NT_STATUS_NO_MEMORY);
8214 return;
8216 params = *pparams;
8218 SSVAL(params,0,0);
8220 status = smbd_do_setfilepathinfo(conn, req, req,
8221 info_level,
8222 fsp,
8223 smb_fname,
8224 ppdata, total_data,
8225 &data_return_size);
8226 if (!NT_STATUS_IS_OK(status)) {
8227 if (open_was_deferred(req->sconn, req->mid)) {
8228 /* We have re-scheduled this call. */
8229 return;
8231 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8232 /* We have re-scheduled this call. */
8233 return;
8235 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8236 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8237 ERRSRV, ERRbadpath);
8238 return;
8240 if (info_level == SMB_POSIX_PATH_OPEN) {
8241 reply_openerror(req, status);
8242 return;
8245 reply_nterror(req, status);
8246 return;
8249 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8250 max_data_bytes);
8252 return;
8255 /****************************************************************************
8256 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8257 ****************************************************************************/
8259 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8260 char **pparams, int total_params,
8261 char **ppdata, int total_data,
8262 unsigned int max_data_bytes)
8264 struct smb_filename *smb_dname = NULL;
8265 char *params = *pparams;
8266 char *pdata = *ppdata;
8267 char *directory = NULL;
8268 NTSTATUS status = NT_STATUS_OK;
8269 struct ea_list *ea_list = NULL;
8270 TALLOC_CTX *ctx = talloc_tos();
8272 if (!CAN_WRITE(conn)) {
8273 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8274 return;
8277 if (total_params < 5) {
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8279 return;
8282 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8283 total_params - 4, STR_TERMINATE,
8284 &status);
8285 if (!NT_STATUS_IS_OK(status)) {
8286 reply_nterror(req, status);
8287 return;
8290 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8292 status = filename_convert(ctx,
8293 conn,
8294 req->flags2 & FLAGS2_DFS_PATHNAMES,
8295 directory,
8297 NULL,
8298 &smb_dname);
8300 if (!NT_STATUS_IS_OK(status)) {
8301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8302 reply_botherror(req,
8303 NT_STATUS_PATH_NOT_COVERED,
8304 ERRSRV, ERRbadpath);
8305 return;
8307 reply_nterror(req, status);
8308 return;
8312 * OS/2 workplace shell seems to send SET_EA requests of "null"
8313 * length (4 bytes containing IVAL 4).
8314 * They seem to have no effect. Bug #3212. JRA.
8317 if (total_data && (total_data != 4)) {
8318 /* Any data in this call is an EA list. */
8319 if (total_data < 10) {
8320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8321 goto out;
8324 if (IVAL(pdata,0) > total_data) {
8325 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8326 IVAL(pdata,0), (unsigned int)total_data));
8327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8328 goto out;
8331 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8332 total_data - 4);
8333 if (!ea_list) {
8334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8335 goto out;
8338 if (!lp_ea_support(SNUM(conn))) {
8339 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8340 goto out;
8343 /* If total_data == 4 Windows doesn't care what values
8344 * are placed in that field, it just ignores them.
8345 * The System i QNTC IBM SMB client puts bad values here,
8346 * so ignore them. */
8348 status = create_directory(conn, req, smb_dname);
8350 if (!NT_STATUS_IS_OK(status)) {
8351 reply_nterror(req, status);
8352 goto out;
8355 /* Try and set any given EA. */
8356 if (ea_list) {
8357 status = set_ea(conn, NULL, smb_dname, ea_list);
8358 if (!NT_STATUS_IS_OK(status)) {
8359 reply_nterror(req, status);
8360 goto out;
8364 /* Realloc the parameter and data sizes */
8365 *pparams = (char *)SMB_REALLOC(*pparams,2);
8366 if(*pparams == NULL) {
8367 reply_nterror(req, NT_STATUS_NO_MEMORY);
8368 goto out;
8370 params = *pparams;
8372 SSVAL(params,0,0);
8374 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8376 out:
8377 TALLOC_FREE(smb_dname);
8378 return;
8381 /****************************************************************************
8382 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8383 We don't actually do this - we just send a null response.
8384 ****************************************************************************/
8386 static void call_trans2findnotifyfirst(connection_struct *conn,
8387 struct smb_request *req,
8388 char **pparams, int total_params,
8389 char **ppdata, int total_data,
8390 unsigned int max_data_bytes)
8392 char *params = *pparams;
8393 uint16 info_level;
8395 if (total_params < 6) {
8396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8397 return;
8400 info_level = SVAL(params,4);
8401 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8403 switch (info_level) {
8404 case 1:
8405 case 2:
8406 break;
8407 default:
8408 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8409 return;
8412 /* Realloc the parameter and data sizes */
8413 *pparams = (char *)SMB_REALLOC(*pparams,6);
8414 if (*pparams == NULL) {
8415 reply_nterror(req, NT_STATUS_NO_MEMORY);
8416 return;
8418 params = *pparams;
8420 SSVAL(params,0,fnf_handle);
8421 SSVAL(params,2,0); /* No changes */
8422 SSVAL(params,4,0); /* No EA errors */
8424 fnf_handle++;
8426 if(fnf_handle == 0)
8427 fnf_handle = 257;
8429 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8431 return;
8434 /****************************************************************************
8435 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8436 changes). Currently this does nothing.
8437 ****************************************************************************/
8439 static void call_trans2findnotifynext(connection_struct *conn,
8440 struct smb_request *req,
8441 char **pparams, int total_params,
8442 char **ppdata, int total_data,
8443 unsigned int max_data_bytes)
8445 char *params = *pparams;
8447 DEBUG(3,("call_trans2findnotifynext\n"));
8449 /* Realloc the parameter and data sizes */
8450 *pparams = (char *)SMB_REALLOC(*pparams,4);
8451 if (*pparams == NULL) {
8452 reply_nterror(req, NT_STATUS_NO_MEMORY);
8453 return;
8455 params = *pparams;
8457 SSVAL(params,0,0); /* No changes */
8458 SSVAL(params,2,0); /* No EA errors */
8460 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8462 return;
8465 /****************************************************************************
8466 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8467 ****************************************************************************/
8469 static void call_trans2getdfsreferral(connection_struct *conn,
8470 struct smb_request *req,
8471 char **pparams, int total_params,
8472 char **ppdata, int total_data,
8473 unsigned int max_data_bytes)
8475 char *params = *pparams;
8476 char *pathname = NULL;
8477 int reply_size = 0;
8478 int max_referral_level;
8479 NTSTATUS status = NT_STATUS_OK;
8480 TALLOC_CTX *ctx = talloc_tos();
8482 DEBUG(10,("call_trans2getdfsreferral\n"));
8484 if (total_params < 3) {
8485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8486 return;
8489 max_referral_level = SVAL(params,0);
8491 if(!lp_host_msdfs()) {
8492 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8493 return;
8496 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8497 total_params - 2, STR_TERMINATE);
8498 if (!pathname) {
8499 reply_nterror(req, NT_STATUS_NOT_FOUND);
8500 return;
8502 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8503 ppdata,&status)) < 0) {
8504 reply_nterror(req, status);
8505 return;
8508 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8509 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8510 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8512 return;
8515 #define LMCAT_SPL 0x53
8516 #define LMFUNC_GETJOBID 0x60
8518 /****************************************************************************
8519 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8520 ****************************************************************************/
8522 static void call_trans2ioctl(connection_struct *conn,
8523 struct smb_request *req,
8524 char **pparams, int total_params,
8525 char **ppdata, int total_data,
8526 unsigned int max_data_bytes)
8528 char *pdata = *ppdata;
8529 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8531 /* check for an invalid fid before proceeding */
8533 if (!fsp) {
8534 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8535 return;
8538 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8539 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8540 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8541 if (*ppdata == NULL) {
8542 reply_nterror(req, NT_STATUS_NO_MEMORY);
8543 return;
8545 pdata = *ppdata;
8547 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8548 CAN ACCEPT THIS IN UNICODE. JRA. */
8550 /* Job number */
8551 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8553 srvstr_push(pdata, req->flags2, pdata + 2,
8554 lp_netbios_name(), 15,
8555 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8556 srvstr_push(pdata, req->flags2, pdata+18,
8557 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8558 STR_ASCII|STR_TERMINATE); /* Service name */
8559 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8560 max_data_bytes);
8561 return;
8564 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8565 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8568 /****************************************************************************
8569 Reply to a SMBfindclose (stop trans2 directory search).
8570 ****************************************************************************/
8572 void reply_findclose(struct smb_request *req)
8574 int dptr_num;
8575 struct smbd_server_connection *sconn = req->sconn;
8577 START_PROFILE(SMBfindclose);
8579 if (req->wct < 1) {
8580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8581 END_PROFILE(SMBfindclose);
8582 return;
8585 dptr_num = SVALS(req->vwv+0, 0);
8587 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8589 dptr_close(sconn, &dptr_num);
8591 reply_outbuf(req, 0, 0);
8593 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8595 END_PROFILE(SMBfindclose);
8596 return;
8599 /****************************************************************************
8600 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8601 ****************************************************************************/
8603 void reply_findnclose(struct smb_request *req)
8605 int dptr_num;
8607 START_PROFILE(SMBfindnclose);
8609 if (req->wct < 1) {
8610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8611 END_PROFILE(SMBfindnclose);
8612 return;
8615 dptr_num = SVAL(req->vwv+0, 0);
8617 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8619 /* We never give out valid handles for a
8620 findnotifyfirst - so any dptr_num is ok here.
8621 Just ignore it. */
8623 reply_outbuf(req, 0, 0);
8625 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8627 END_PROFILE(SMBfindnclose);
8628 return;
8631 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8632 struct trans_state *state)
8634 if (get_Protocol() >= PROTOCOL_NT1) {
8635 req->flags2 |= 0x40; /* IS_LONG_NAME */
8636 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8639 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8640 if (state->call != TRANSACT2_QFSINFO &&
8641 state->call != TRANSACT2_SETFSINFO) {
8642 DEBUG(0,("handle_trans2: encryption required "
8643 "with call 0x%x\n",
8644 (unsigned int)state->call));
8645 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8646 return;
8650 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8652 /* Now we must call the relevant TRANS2 function */
8653 switch(state->call) {
8654 case TRANSACT2_OPEN:
8656 START_PROFILE(Trans2_open);
8657 call_trans2open(conn, req,
8658 &state->param, state->total_param,
8659 &state->data, state->total_data,
8660 state->max_data_return);
8661 END_PROFILE(Trans2_open);
8662 break;
8665 case TRANSACT2_FINDFIRST:
8667 START_PROFILE(Trans2_findfirst);
8668 call_trans2findfirst(conn, req,
8669 &state->param, state->total_param,
8670 &state->data, state->total_data,
8671 state->max_data_return);
8672 END_PROFILE(Trans2_findfirst);
8673 break;
8676 case TRANSACT2_FINDNEXT:
8678 START_PROFILE(Trans2_findnext);
8679 call_trans2findnext(conn, req,
8680 &state->param, state->total_param,
8681 &state->data, state->total_data,
8682 state->max_data_return);
8683 END_PROFILE(Trans2_findnext);
8684 break;
8687 case TRANSACT2_QFSINFO:
8689 START_PROFILE(Trans2_qfsinfo);
8690 call_trans2qfsinfo(conn, req,
8691 &state->param, state->total_param,
8692 &state->data, state->total_data,
8693 state->max_data_return);
8694 END_PROFILE(Trans2_qfsinfo);
8695 break;
8698 case TRANSACT2_SETFSINFO:
8700 START_PROFILE(Trans2_setfsinfo);
8701 call_trans2setfsinfo(conn, req,
8702 &state->param, state->total_param,
8703 &state->data, state->total_data,
8704 state->max_data_return);
8705 END_PROFILE(Trans2_setfsinfo);
8706 break;
8709 case TRANSACT2_QPATHINFO:
8710 case TRANSACT2_QFILEINFO:
8712 START_PROFILE(Trans2_qpathinfo);
8713 call_trans2qfilepathinfo(conn, req, state->call,
8714 &state->param, state->total_param,
8715 &state->data, state->total_data,
8716 state->max_data_return);
8717 END_PROFILE(Trans2_qpathinfo);
8718 break;
8721 case TRANSACT2_SETPATHINFO:
8722 case TRANSACT2_SETFILEINFO:
8724 START_PROFILE(Trans2_setpathinfo);
8725 call_trans2setfilepathinfo(conn, req, state->call,
8726 &state->param, state->total_param,
8727 &state->data, state->total_data,
8728 state->max_data_return);
8729 END_PROFILE(Trans2_setpathinfo);
8730 break;
8733 case TRANSACT2_FINDNOTIFYFIRST:
8735 START_PROFILE(Trans2_findnotifyfirst);
8736 call_trans2findnotifyfirst(conn, req,
8737 &state->param, state->total_param,
8738 &state->data, state->total_data,
8739 state->max_data_return);
8740 END_PROFILE(Trans2_findnotifyfirst);
8741 break;
8744 case TRANSACT2_FINDNOTIFYNEXT:
8746 START_PROFILE(Trans2_findnotifynext);
8747 call_trans2findnotifynext(conn, req,
8748 &state->param, state->total_param,
8749 &state->data, state->total_data,
8750 state->max_data_return);
8751 END_PROFILE(Trans2_findnotifynext);
8752 break;
8755 case TRANSACT2_MKDIR:
8757 START_PROFILE(Trans2_mkdir);
8758 call_trans2mkdir(conn, req,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_mkdir);
8763 break;
8766 case TRANSACT2_GET_DFS_REFERRAL:
8768 START_PROFILE(Trans2_get_dfs_referral);
8769 call_trans2getdfsreferral(conn, req,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_get_dfs_referral);
8774 break;
8777 case TRANSACT2_IOCTL:
8779 START_PROFILE(Trans2_ioctl);
8780 call_trans2ioctl(conn, req,
8781 &state->param, state->total_param,
8782 &state->data, state->total_data,
8783 state->max_data_return);
8784 END_PROFILE(Trans2_ioctl);
8785 break;
8788 default:
8789 /* Error in request */
8790 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8791 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8795 /****************************************************************************
8796 Reply to a SMBtrans2.
8797 ****************************************************************************/
8799 void reply_trans2(struct smb_request *req)
8801 connection_struct *conn = req->conn;
8802 unsigned int dsoff;
8803 unsigned int dscnt;
8804 unsigned int psoff;
8805 unsigned int pscnt;
8806 unsigned int tran_call;
8807 struct trans_state *state;
8808 NTSTATUS result;
8810 START_PROFILE(SMBtrans2);
8812 if (req->wct < 14) {
8813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8814 END_PROFILE(SMBtrans2);
8815 return;
8818 dsoff = SVAL(req->vwv+12, 0);
8819 dscnt = SVAL(req->vwv+11, 0);
8820 psoff = SVAL(req->vwv+10, 0);
8821 pscnt = SVAL(req->vwv+9, 0);
8822 tran_call = SVAL(req->vwv+14, 0);
8824 result = allow_new_trans(conn->pending_trans, req->mid);
8825 if (!NT_STATUS_IS_OK(result)) {
8826 DEBUG(2, ("Got invalid trans2 request: %s\n",
8827 nt_errstr(result)));
8828 reply_nterror(req, result);
8829 END_PROFILE(SMBtrans2);
8830 return;
8833 if (IS_IPC(conn)) {
8834 switch (tran_call) {
8835 /* List the allowed trans2 calls on IPC$ */
8836 case TRANSACT2_OPEN:
8837 case TRANSACT2_GET_DFS_REFERRAL:
8838 case TRANSACT2_QFILEINFO:
8839 case TRANSACT2_QFSINFO:
8840 case TRANSACT2_SETFSINFO:
8841 break;
8842 default:
8843 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8844 END_PROFILE(SMBtrans2);
8845 return;
8849 if ((state = talloc(conn, struct trans_state)) == NULL) {
8850 DEBUG(0, ("talloc failed\n"));
8851 reply_nterror(req, NT_STATUS_NO_MEMORY);
8852 END_PROFILE(SMBtrans2);
8853 return;
8856 state->cmd = SMBtrans2;
8858 state->mid = req->mid;
8859 state->vuid = req->vuid;
8860 state->setup_count = SVAL(req->vwv+13, 0);
8861 state->setup = NULL;
8862 state->total_param = SVAL(req->vwv+0, 0);
8863 state->param = NULL;
8864 state->total_data = SVAL(req->vwv+1, 0);
8865 state->data = NULL;
8866 state->max_param_return = SVAL(req->vwv+2, 0);
8867 state->max_data_return = SVAL(req->vwv+3, 0);
8868 state->max_setup_return = SVAL(req->vwv+4, 0);
8869 state->close_on_completion = BITSETW(req->vwv+5, 0);
8870 state->one_way = BITSETW(req->vwv+5, 1);
8872 state->call = tran_call;
8874 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8875 is so as a sanity check */
8876 if (state->setup_count != 1) {
8878 * Need to have rc=0 for ioctl to get job id for OS/2.
8879 * Network printing will fail if function is not successful.
8880 * Similar function in reply.c will be used if protocol
8881 * is LANMAN1.0 instead of LM1.2X002.
8882 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8883 * outbuf doesn't have to be set(only job id is used).
8885 if ( (state->setup_count == 4)
8886 && (tran_call == TRANSACT2_IOCTL)
8887 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8888 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8889 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8890 } else {
8891 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8892 DEBUG(2,("Transaction is %d\n",tran_call));
8893 TALLOC_FREE(state);
8894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8895 END_PROFILE(SMBtrans2);
8896 return;
8900 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8901 goto bad_param;
8903 if (state->total_data) {
8905 if (trans_oob(state->total_data, 0, dscnt)
8906 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8907 goto bad_param;
8910 /* Can't use talloc here, the core routines do realloc on the
8911 * params and data. */
8912 state->data = (char *)SMB_MALLOC(state->total_data);
8913 if (state->data == NULL) {
8914 DEBUG(0,("reply_trans2: data malloc fail for %u "
8915 "bytes !\n", (unsigned int)state->total_data));
8916 TALLOC_FREE(state);
8917 reply_nterror(req, NT_STATUS_NO_MEMORY);
8918 END_PROFILE(SMBtrans2);
8919 return;
8922 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8925 if (state->total_param) {
8927 if (trans_oob(state->total_param, 0, pscnt)
8928 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8929 goto bad_param;
8932 /* Can't use talloc here, the core routines do realloc on the
8933 * params and data. */
8934 state->param = (char *)SMB_MALLOC(state->total_param);
8935 if (state->param == NULL) {
8936 DEBUG(0,("reply_trans: param malloc fail for %u "
8937 "bytes !\n", (unsigned int)state->total_param));
8938 SAFE_FREE(state->data);
8939 TALLOC_FREE(state);
8940 reply_nterror(req, NT_STATUS_NO_MEMORY);
8941 END_PROFILE(SMBtrans2);
8942 return;
8945 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8948 state->received_data = dscnt;
8949 state->received_param = pscnt;
8951 if ((state->received_param == state->total_param) &&
8952 (state->received_data == state->total_data)) {
8954 handle_trans2(conn, req, state);
8956 SAFE_FREE(state->data);
8957 SAFE_FREE(state->param);
8958 TALLOC_FREE(state);
8959 END_PROFILE(SMBtrans2);
8960 return;
8963 DLIST_ADD(conn->pending_trans, state);
8965 /* We need to send an interim response then receive the rest
8966 of the parameter/data bytes */
8967 reply_outbuf(req, 0, 0);
8968 show_msg((char *)req->outbuf);
8969 END_PROFILE(SMBtrans2);
8970 return;
8972 bad_param:
8974 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8975 SAFE_FREE(state->data);
8976 SAFE_FREE(state->param);
8977 TALLOC_FREE(state);
8978 END_PROFILE(SMBtrans2);
8979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8983 /****************************************************************************
8984 Reply to a SMBtranss2
8985 ****************************************************************************/
8987 void reply_transs2(struct smb_request *req)
8989 connection_struct *conn = req->conn;
8990 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8991 struct trans_state *state;
8993 START_PROFILE(SMBtranss2);
8995 show_msg((const char *)req->inbuf);
8997 /* Windows clients expect all replies to
8998 a transact secondary (SMBtranss2 0x33)
8999 to have a command code of transact
9000 (SMBtrans2 0x32). See bug #8989
9001 and also [MS-CIFS] section 2.2.4.47.2
9002 for details.
9004 req->cmd = SMBtrans2;
9006 if (req->wct < 8) {
9007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9008 END_PROFILE(SMBtranss2);
9009 return;
9012 for (state = conn->pending_trans; state != NULL;
9013 state = state->next) {
9014 if (state->mid == req->mid) {
9015 break;
9019 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9021 END_PROFILE(SMBtranss2);
9022 return;
9025 /* Revise state->total_param and state->total_data in case they have
9026 changed downwards */
9028 if (SVAL(req->vwv+0, 0) < state->total_param)
9029 state->total_param = SVAL(req->vwv+0, 0);
9030 if (SVAL(req->vwv+1, 0) < state->total_data)
9031 state->total_data = SVAL(req->vwv+1, 0);
9033 pcnt = SVAL(req->vwv+2, 0);
9034 poff = SVAL(req->vwv+3, 0);
9035 pdisp = SVAL(req->vwv+4, 0);
9037 dcnt = SVAL(req->vwv+5, 0);
9038 doff = SVAL(req->vwv+6, 0);
9039 ddisp = SVAL(req->vwv+7, 0);
9041 state->received_param += pcnt;
9042 state->received_data += dcnt;
9044 if ((state->received_data > state->total_data) ||
9045 (state->received_param > state->total_param))
9046 goto bad_param;
9048 if (pcnt) {
9049 if (trans_oob(state->total_param, pdisp, pcnt)
9050 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9051 goto bad_param;
9053 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9056 if (dcnt) {
9057 if (trans_oob(state->total_data, ddisp, dcnt)
9058 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9059 goto bad_param;
9061 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9064 if ((state->received_param < state->total_param) ||
9065 (state->received_data < state->total_data)) {
9066 END_PROFILE(SMBtranss2);
9067 return;
9070 handle_trans2(conn, req, state);
9072 DLIST_REMOVE(conn->pending_trans, state);
9073 SAFE_FREE(state->data);
9074 SAFE_FREE(state->param);
9075 TALLOC_FREE(state);
9077 END_PROFILE(SMBtranss2);
9078 return;
9080 bad_param:
9082 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9083 DLIST_REMOVE(conn->pending_trans, state);
9084 SAFE_FREE(state->data);
9085 SAFE_FREE(state->param);
9086 TALLOC_FREE(state);
9087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9088 END_PROFILE(SMBtranss2);
9089 return;