negoex.idl: use DATA_BLOB for negoex_BYTE_VECTOR
[Samba.git] / source3 / smbd / trans2.c
blob11c97e89269d11c847240daeeec831acb773a24b
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
53 char *pdata,
54 files_struct *fsp,
55 const SMB_STRUCT_STAT *psbuf);
57 NTSTATUS check_access_fsp(const struct files_struct *fsp,
58 uint32_t access_mask)
60 if (!(fsp->access_mask & access_mask)) {
61 return NT_STATUS_ACCESS_DENIED;
63 return NT_STATUS_OK;
66 /********************************************************************
67 The canonical "check access" based on object handle or path function.
68 ********************************************************************/
70 NTSTATUS check_access(connection_struct *conn,
71 files_struct *fsp,
72 const struct smb_filename *smb_fname,
73 uint32_t access_mask)
75 NTSTATUS status;
77 if (fsp) {
78 status = check_access_fsp(fsp, access_mask);
79 } else {
80 status = smbd_check_access_rights(conn, smb_fname,
81 false, access_mask);
84 return status;
87 /********************************************************************
88 Roundup a value to the nearest allocation roundup size boundary.
89 Only do this for Windows clients.
90 ********************************************************************/
92 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
94 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
96 /* Only roundup for Windows clients. */
97 enum remote_arch_types ra_type = get_remote_arch();
98 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
99 val = SMB_ROUNDUP(val,rval);
101 return val;
104 /********************************************************************
105 Create a 64 bit FileIndex. If the file is on the same device as
106 the root of the share, just return the 64-bit inode. If it isn't,
107 mangle as we used to do.
108 ********************************************************************/
110 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
112 uint64_t file_index;
113 if (conn->base_share_dev == psbuf->st_ex_dev) {
114 return (uint64_t)psbuf->st_ex_ino;
116 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
117 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
118 return file_index;
121 /****************************************************************************
122 Utility functions for dealing with extended attributes.
123 ****************************************************************************/
125 /****************************************************************************
126 Refuse to allow clients to overwrite our private xattrs.
127 ****************************************************************************/
129 bool samba_private_attr_name(const char *unix_ea_name)
131 static const char * const prohibited_ea_names[] = {
132 SAMBA_POSIX_INHERITANCE_EA_NAME,
133 SAMBA_XATTR_DOS_ATTRIB,
134 SAMBA_XATTR_MARKER,
135 XATTR_NTACL_NAME,
136 NULL
139 int i;
141 for (i = 0; prohibited_ea_names[i]; i++) {
142 if (strequal( prohibited_ea_names[i], unix_ea_name))
143 return true;
145 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
146 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
147 return true;
149 return false;
152 /****************************************************************************
153 Get one EA value. Fill in a struct ea_struct.
154 ****************************************************************************/
156 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
157 files_struct *fsp, const char *fname,
158 const char *ea_name, struct ea_struct *pea)
160 /* Get the value of this xattr. Max size is 64k. */
161 size_t attr_size = 256;
162 char *val = NULL;
163 ssize_t sizeret;
165 again:
167 val = talloc_realloc(mem_ctx, val, char, attr_size);
168 if (!val) {
169 return NT_STATUS_NO_MEMORY;
172 if (fsp && fsp->fh->fd != -1) {
173 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
174 } else {
175 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
178 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
179 attr_size = 65536;
180 goto again;
183 if (sizeret == -1) {
184 return map_nt_error_from_unix(errno);
187 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
188 dump_data(10, (uint8_t *)val, sizeret);
190 pea->flags = 0;
191 if (strnequal(ea_name, "user.", 5)) {
192 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
193 } else {
194 pea->name = talloc_strdup(mem_ctx, ea_name);
196 if (pea->name == NULL) {
197 TALLOC_FREE(val);
198 return NT_STATUS_NO_MEMORY;
200 pea->value.data = (unsigned char *)val;
201 pea->value.length = (size_t)sizeret;
202 return NT_STATUS_OK;
205 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
206 files_struct *fsp, const char *fname,
207 char ***pnames, size_t *pnum_names)
209 /* Get a list of all xattrs. Max namesize is 64k. */
210 size_t ea_namelist_size = 1024;
211 char *ea_namelist = NULL;
213 char *p;
214 char **names, **tmp;
215 size_t num_names;
216 ssize_t sizeret = -1;
218 if (!lp_ea_support(SNUM(conn))) {
219 if (pnames) {
220 *pnames = NULL;
222 *pnum_names = 0;
223 return NT_STATUS_OK;
227 * TALLOC the result early to get the talloc hierarchy right.
230 names = talloc_array(mem_ctx, char *, 1);
231 if (names == NULL) {
232 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY;
236 while (ea_namelist_size <= 65536) {
238 ea_namelist = talloc_realloc(
239 names, ea_namelist, char, ea_namelist_size);
240 if (ea_namelist == NULL) {
241 DEBUG(0, ("talloc failed\n"));
242 TALLOC_FREE(names);
243 return NT_STATUS_NO_MEMORY;
246 if (fsp && fsp->fh->fd != -1) {
247 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
248 ea_namelist_size);
249 } else {
250 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
251 ea_namelist_size);
254 if ((sizeret == -1) && (errno == ERANGE)) {
255 ea_namelist_size *= 2;
257 else {
258 break;
262 if (sizeret == -1) {
263 TALLOC_FREE(names);
264 return map_nt_error_from_unix(errno);
267 DEBUG(10, ("%s: ea_namelist size = %u\n",
268 __func__, (unsigned int)sizeret));
270 if (sizeret == 0) {
271 TALLOC_FREE(names);
272 if (pnames) {
273 *pnames = NULL;
275 *pnum_names = 0;
276 return NT_STATUS_OK;
280 * Ensure the result is 0-terminated
283 if (ea_namelist[sizeret-1] != '\0') {
284 TALLOC_FREE(names);
285 return NT_STATUS_INTERNAL_ERROR;
289 * count the names
291 num_names = 0;
293 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
294 num_names += 1;
297 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
298 if (tmp == NULL) {
299 DEBUG(0, ("talloc failed\n"));
300 TALLOC_FREE(names);
301 return NT_STATUS_NO_MEMORY;
304 names = tmp;
305 num_names = 0;
307 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
308 names[num_names++] = p;
311 if (pnames) {
312 *pnames = names;
313 } else {
314 TALLOC_FREE(names);
316 *pnum_names = num_names;
317 return NT_STATUS_OK;
320 /****************************************************************************
321 Return a linked list of the total EA's. Plus the total size
322 ****************************************************************************/
324 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
325 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
327 /* Get a list of all xattrs. Max namesize is 64k. */
328 size_t i, num_names;
329 char **names;
330 struct ea_list *ea_list_head = NULL;
331 NTSTATUS status;
333 *pea_total_len = 0;
334 *ea_list = NULL;
336 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
337 &names, &num_names);
339 if (!NT_STATUS_IS_OK(status)) {
340 return status;
343 if (num_names == 0) {
344 *ea_list = NULL;
345 return NT_STATUS_OK;
348 for (i=0; i<num_names; i++) {
349 struct ea_list *listp;
350 fstring dos_ea_name;
352 if (strnequal(names[i], "system.", 7)
353 || samba_private_attr_name(names[i]))
354 continue;
357 * Filter out any underlying POSIX EA names
358 * that a Windows client can't handle.
360 if (!lp_posix_pathnames() &&
361 is_invalid_windows_ea_name(names[i])) {
362 continue;
365 listp = talloc(mem_ctx, struct ea_list);
366 if (listp == NULL) {
367 return NT_STATUS_NO_MEMORY;
370 status = get_ea_value(listp, conn, fsp,
371 fname, names[i],
372 &listp->ea);
374 if (!NT_STATUS_IS_OK(status)) {
375 TALLOC_FREE(listp);
376 return status;
379 if (listp->ea.value.length == 0) {
381 * We can never return a zero length EA.
382 * Windows reports the EA's as corrupted.
384 TALLOC_FREE(listp);
385 continue;
388 push_ascii_fstring(dos_ea_name, listp->ea.name);
390 *pea_total_len +=
391 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
393 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
394 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
395 (unsigned int)listp->ea.value.length));
397 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
401 /* Add on 4 for total length. */
402 if (*pea_total_len) {
403 *pea_total_len += 4;
406 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
407 (unsigned int)*pea_total_len));
409 *ea_list = ea_list_head;
410 return NT_STATUS_OK;
413 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
414 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
416 *pea_total_len = 0;
417 *ea_list = NULL;
419 if (!lp_ea_support(SNUM(conn))) {
420 return NT_STATUS_OK;
423 if (is_ntfs_stream_smb_fname(smb_fname)) {
424 return NT_STATUS_INVALID_PARAMETER;
427 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
430 /****************************************************************************
431 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
432 that was filled.
433 ****************************************************************************/
435 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
436 connection_struct *conn, struct ea_list *ea_list)
438 unsigned int ret_data_size = 4;
439 char *p = pdata;
441 SMB_ASSERT(total_data_size >= 4);
443 if (!lp_ea_support(SNUM(conn))) {
444 SIVAL(pdata,4,0);
445 return 4;
448 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
449 size_t dos_namelen;
450 fstring dos_ea_name;
451 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
452 dos_namelen = strlen(dos_ea_name);
453 if (dos_namelen > 255 || dos_namelen == 0) {
454 break;
456 if (ea_list->ea.value.length > 65535) {
457 break;
459 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
460 break;
463 /* We know we have room. */
464 SCVAL(p,0,ea_list->ea.flags);
465 SCVAL(p,1,dos_namelen);
466 SSVAL(p,2,ea_list->ea.value.length);
467 strlcpy(p+4, dos_ea_name, dos_namelen+1);
468 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
470 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
471 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
474 ret_data_size = PTR_DIFF(p, pdata);
475 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
476 SIVAL(pdata,0,ret_data_size);
477 return ret_data_size;
480 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
481 char *pdata,
482 unsigned int total_data_size,
483 unsigned int *ret_data_size,
484 connection_struct *conn,
485 struct ea_list *ea_list)
487 uint8_t *p = (uint8_t *)pdata;
488 uint8_t *last_start = NULL;
489 bool do_store_data = (pdata != NULL);
491 *ret_data_size = 0;
493 if (!lp_ea_support(SNUM(conn))) {
494 return NT_STATUS_NO_EAS_ON_FILE;
497 for (; ea_list; ea_list = ea_list->next) {
498 size_t dos_namelen;
499 fstring dos_ea_name;
500 size_t this_size;
501 size_t pad = 0;
503 if (last_start != NULL && do_store_data) {
504 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
506 last_start = p;
508 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
509 dos_namelen = strlen(dos_ea_name);
510 if (dos_namelen > 255 || dos_namelen == 0) {
511 return NT_STATUS_INTERNAL_ERROR;
513 if (ea_list->ea.value.length > 65535) {
514 return NT_STATUS_INTERNAL_ERROR;
517 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
519 if (ea_list->next) {
520 pad = (4 - (this_size % 4)) % 4;
521 this_size += pad;
524 if (do_store_data) {
525 if (this_size > total_data_size) {
526 return NT_STATUS_INFO_LENGTH_MISMATCH;
529 /* We know we have room. */
530 SIVAL(p, 0x00, 0); /* next offset */
531 SCVAL(p, 0x04, ea_list->ea.flags);
532 SCVAL(p, 0x05, dos_namelen);
533 SSVAL(p, 0x06, ea_list->ea.value.length);
534 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
535 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
536 if (pad) {
537 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
538 '\0',
539 pad);
541 total_data_size -= this_size;
544 p += this_size;
547 *ret_data_size = PTR_DIFF(p, pdata);
548 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
549 return NT_STATUS_OK;
552 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
554 size_t total_ea_len = 0;
555 TALLOC_CTX *mem_ctx;
556 struct ea_list *ea_list = NULL;
558 if (!lp_ea_support(SNUM(conn))) {
559 return 0;
561 mem_ctx = talloc_stackframe();
563 /* If this is a stream fsp, then we need to instead find the
564 * estimated ea len from the main file, not the stream
565 * (streams cannot have EAs), but the estimate isn't just 0 in
566 * this case! */
567 if (is_ntfs_stream_smb_fname(smb_fname)) {
568 fsp = NULL;
570 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
571 if(conn->sconn->using_smb2) {
572 NTSTATUS status;
573 unsigned int ret_data_size;
575 * We're going to be using fill_ea_chained_buffer() to
576 * marshall EA's - this size is significantly larger
577 * than the SMB1 buffer. Re-calculate the size without
578 * marshalling.
580 status = fill_ea_chained_buffer(mem_ctx,
581 NULL,
583 &ret_data_size,
584 conn,
585 ea_list);
586 if (!NT_STATUS_IS_OK(status)) {
587 ret_data_size = 0;
589 total_ea_len = ret_data_size;
591 TALLOC_FREE(mem_ctx);
592 return total_ea_len;
595 /****************************************************************************
596 Ensure the EA name is case insensitive by matching any existing EA name.
597 ****************************************************************************/
599 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
601 size_t total_ea_len;
602 TALLOC_CTX *mem_ctx = talloc_tos();
603 struct ea_list *ea_list;
604 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
605 if (!NT_STATUS_IS_OK(status)) {
606 return;
609 for (; ea_list; ea_list = ea_list->next) {
610 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
611 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
612 &unix_ea_name[5], ea_list->ea.name));
613 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
614 break;
619 /****************************************************************************
620 Set or delete an extended attribute.
621 ****************************************************************************/
623 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
624 const struct smb_filename *smb_fname, struct ea_list *ea_list)
626 NTSTATUS status;
627 char *fname = NULL;
629 if (!lp_ea_support(SNUM(conn))) {
630 return NT_STATUS_EAS_NOT_SUPPORTED;
633 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
634 if (!NT_STATUS_IS_OK(status)) {
635 return status;
638 /* Setting EAs on streams isn't supported. */
639 if (is_ntfs_stream_smb_fname(smb_fname)) {
640 return NT_STATUS_INVALID_PARAMETER;
644 * Filter out invalid Windows EA names - before
645 * we set *any* of them.
648 if (ea_list_has_invalid_name(ea_list)) {
649 return STATUS_INVALID_EA_NAME;
652 fname = smb_fname->base_name;
654 for (;ea_list; ea_list = ea_list->next) {
655 int ret;
656 fstring unix_ea_name;
658 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
659 fstrcat(unix_ea_name, ea_list->ea.name);
661 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
663 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
665 if (samba_private_attr_name(unix_ea_name)) {
666 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
667 return NT_STATUS_ACCESS_DENIED;
670 if (ea_list->ea.value.length == 0) {
671 /* Remove the attribute. */
672 if (fsp && (fsp->fh->fd != -1)) {
673 DEBUG(10,("set_ea: deleting ea name %s on "
674 "file %s by file descriptor.\n",
675 unix_ea_name, fsp_str_dbg(fsp)));
676 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
677 } else {
678 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
679 unix_ea_name, fname));
680 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
682 #ifdef ENOATTR
683 /* Removing a non existent attribute always succeeds. */
684 if (ret == -1 && errno == ENOATTR) {
685 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
686 unix_ea_name));
687 ret = 0;
689 #endif
690 } else {
691 if (fsp && (fsp->fh->fd != -1)) {
692 DEBUG(10,("set_ea: setting ea name %s on file "
693 "%s by file descriptor.\n",
694 unix_ea_name, fsp_str_dbg(fsp)));
695 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
697 } else {
698 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
699 unix_ea_name, fname));
700 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
701 ea_list->ea.value.data, ea_list->ea.value.length, 0);
705 if (ret == -1) {
706 #ifdef ENOTSUP
707 if (errno == ENOTSUP) {
708 return NT_STATUS_EAS_NOT_SUPPORTED;
710 #endif
711 return map_nt_error_from_unix(errno);
715 return NT_STATUS_OK;
717 /****************************************************************************
718 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
719 ****************************************************************************/
721 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
723 struct ea_list *ea_list_head = NULL;
724 size_t converted_size, offset = 0;
726 while (offset + 2 < data_size) {
727 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
728 unsigned int namelen = CVAL(pdata,offset);
730 offset++; /* Go past the namelen byte. */
732 /* integer wrap paranioa. */
733 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
734 (offset > data_size) || (namelen > data_size) ||
735 (offset + namelen >= data_size)) {
736 break;
738 /* Ensure the name is null terminated. */
739 if (pdata[offset + namelen] != '\0') {
740 return NULL;
742 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
743 &converted_size)) {
744 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
745 "failed: %s", strerror(errno)));
747 if (!eal->ea.name) {
748 return NULL;
751 offset += (namelen + 1); /* Go past the name + terminating zero. */
752 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
753 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
756 return ea_list_head;
759 /****************************************************************************
760 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
761 ****************************************************************************/
763 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
765 struct ea_list *ea_list_head = NULL;
766 size_t offset = 0;
767 size_t bytes_used = 0;
769 while (offset < data_size) {
770 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
772 if (!eal) {
773 return NULL;
776 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
777 offset += bytes_used;
780 return ea_list_head;
783 /****************************************************************************
784 Count the total EA size needed.
785 ****************************************************************************/
787 static size_t ea_list_size(struct ea_list *ealist)
789 fstring dos_ea_name;
790 struct ea_list *listp;
791 size_t ret = 0;
793 for (listp = ealist; listp; listp = listp->next) {
794 push_ascii_fstring(dos_ea_name, listp->ea.name);
795 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
797 /* Add on 4 for total length. */
798 if (ret) {
799 ret += 4;
802 return ret;
805 /****************************************************************************
806 Return a union of EA's from a file list and a list of names.
807 The TALLOC context for the two lists *MUST* be identical as we steal
808 memory from one list to add to another. JRA.
809 ****************************************************************************/
811 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
813 struct ea_list *nlistp, *flistp;
815 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
816 for (flistp = file_list; flistp; flistp = flistp->next) {
817 if (strequal(nlistp->ea.name, flistp->ea.name)) {
818 break;
822 if (flistp) {
823 /* Copy the data from this entry. */
824 nlistp->ea.flags = flistp->ea.flags;
825 nlistp->ea.value = flistp->ea.value;
826 } else {
827 /* Null entry. */
828 nlistp->ea.flags = 0;
829 ZERO_STRUCT(nlistp->ea.value);
833 *total_ea_len = ea_list_size(name_list);
834 return name_list;
837 /****************************************************************************
838 Send the required number of replies back.
839 We assume all fields other than the data fields are
840 set correctly for the type of call.
841 HACK ! Always assumes smb_setup field is zero.
842 ****************************************************************************/
844 void send_trans2_replies(connection_struct *conn,
845 struct smb_request *req,
846 NTSTATUS status,
847 const char *params,
848 int paramsize,
849 const char *pdata,
850 int datasize,
851 int max_data_bytes)
853 /* As we are using a protocol > LANMAN1 then the max_send
854 variable must have been set in the sessetupX call.
855 This takes precedence over the max_xmit field in the
856 global struct. These different max_xmit variables should
857 be merged as this is now too confusing */
859 int data_to_send = datasize;
860 int params_to_send = paramsize;
861 int useable_space;
862 const char *pp = params;
863 const char *pd = pdata;
864 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
865 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
866 int data_alignment_offset = 0;
867 bool overflow = False;
868 struct smbXsrv_connection *xconn = req->xconn;
869 int max_send = xconn->smb1.sessions.max_send;
871 /* Modify the data_to_send and datasize and set the error if
872 we're trying to send more than max_data_bytes. We still send
873 the part of the packet(s) that fit. Strange, but needed
874 for OS/2. */
876 if (max_data_bytes > 0 && datasize > max_data_bytes) {
877 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
878 max_data_bytes, datasize ));
879 datasize = data_to_send = max_data_bytes;
880 overflow = True;
883 /* If there genuinely are no parameters or data to send just send the empty packet */
885 if(params_to_send == 0 && data_to_send == 0) {
886 reply_outbuf(req, 10, 0);
887 if (NT_STATUS_V(status)) {
888 uint8_t eclass;
889 uint32_t ecode;
890 ntstatus_to_dos(status, &eclass, &ecode);
891 error_packet_set((char *)req->outbuf,
892 eclass, ecode, status,
893 __LINE__,__FILE__);
895 show_msg((char *)req->outbuf);
896 if (!srv_send_smb(xconn,
897 (char *)req->outbuf,
898 true, req->seqnum+1,
899 IS_CONN_ENCRYPTED(conn),
900 &req->pcd)) {
901 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
903 TALLOC_FREE(req->outbuf);
904 return;
907 /* When sending params and data ensure that both are nicely aligned */
908 /* Only do this alignment when there is also data to send - else
909 can cause NT redirector problems. */
911 if (((params_to_send % 4) != 0) && (data_to_send != 0))
912 data_alignment_offset = 4 - (params_to_send % 4);
914 /* Space is bufsize minus Netbios over TCP header minus SMB header */
915 /* The alignment_offset is to align the param bytes on an even byte
916 boundary. NT 4.0 Beta needs this to work correctly. */
918 useable_space = max_send - (smb_size
919 + 2 * 10 /* wct */
920 + alignment_offset
921 + data_alignment_offset);
923 if (useable_space < 0) {
924 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
925 "= %d!!!", useable_space));
926 exit_server_cleanly("send_trans2_replies: Not enough space");
929 while (params_to_send || data_to_send) {
930 /* Calculate whether we will totally or partially fill this packet */
932 total_sent_thistime = params_to_send + data_to_send;
934 /* We can never send more than useable_space */
936 * Note that 'useable_space' does not include the alignment offsets,
937 * but we must include the alignment offsets in the calculation of
938 * the length of the data we send over the wire, as the alignment offsets
939 * are sent here. Fix from Marc_Jacobsen@hp.com.
942 total_sent_thistime = MIN(total_sent_thistime, useable_space);
944 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
945 + data_alignment_offset);
947 /* Set total params and data to be sent */
948 SSVAL(req->outbuf,smb_tprcnt,paramsize);
949 SSVAL(req->outbuf,smb_tdrcnt,datasize);
951 /* Calculate how many parameters and data we can fit into
952 * this packet. Parameters get precedence
955 params_sent_thistime = MIN(params_to_send,useable_space);
956 data_sent_thistime = useable_space - params_sent_thistime;
957 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
959 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
961 /* smb_proff is the offset from the start of the SMB header to the
962 parameter bytes, however the first 4 bytes of outbuf are
963 the Netbios over TCP header. Thus use smb_base() to subtract
964 them from the calculation */
966 SSVAL(req->outbuf,smb_proff,
967 ((smb_buf(req->outbuf)+alignment_offset)
968 - smb_base(req->outbuf)));
970 if(params_sent_thistime == 0)
971 SSVAL(req->outbuf,smb_prdisp,0);
972 else
973 /* Absolute displacement of param bytes sent in this packet */
974 SSVAL(req->outbuf,smb_prdisp,pp - params);
976 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
977 if(data_sent_thistime == 0) {
978 SSVAL(req->outbuf,smb_droff,0);
979 SSVAL(req->outbuf,smb_drdisp, 0);
980 } else {
981 /* The offset of the data bytes is the offset of the
982 parameter bytes plus the number of parameters being sent this time */
983 SSVAL(req->outbuf, smb_droff,
984 ((smb_buf(req->outbuf)+alignment_offset)
985 - smb_base(req->outbuf))
986 + params_sent_thistime + data_alignment_offset);
987 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
990 /* Initialize the padding for alignment */
992 if (alignment_offset != 0) {
993 memset(smb_buf(req->outbuf), 0, alignment_offset);
996 /* Copy the param bytes into the packet */
998 if(params_sent_thistime) {
999 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1000 params_sent_thistime);
1003 /* Copy in the data bytes */
1004 if(data_sent_thistime) {
1005 if (data_alignment_offset != 0) {
1006 memset((smb_buf(req->outbuf)+alignment_offset+
1007 params_sent_thistime), 0,
1008 data_alignment_offset);
1010 memcpy(smb_buf(req->outbuf)+alignment_offset
1011 +params_sent_thistime+data_alignment_offset,
1012 pd,data_sent_thistime);
1015 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1016 params_sent_thistime, data_sent_thistime, useable_space));
1017 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1018 params_to_send, data_to_send, paramsize, datasize));
1020 if (overflow) {
1021 error_packet_set((char *)req->outbuf,
1022 ERRDOS,ERRbufferoverflow,
1023 STATUS_BUFFER_OVERFLOW,
1024 __LINE__,__FILE__);
1025 } else if (NT_STATUS_V(status)) {
1026 uint8_t eclass;
1027 uint32_t ecode;
1028 ntstatus_to_dos(status, &eclass, &ecode);
1029 error_packet_set((char *)req->outbuf,
1030 eclass, ecode, status,
1031 __LINE__,__FILE__);
1034 /* Send the packet */
1035 show_msg((char *)req->outbuf);
1036 if (!srv_send_smb(xconn,
1037 (char *)req->outbuf,
1038 true, req->seqnum+1,
1039 IS_CONN_ENCRYPTED(conn),
1040 &req->pcd))
1041 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1043 TALLOC_FREE(req->outbuf);
1045 pp += params_sent_thistime;
1046 pd += data_sent_thistime;
1048 params_to_send -= params_sent_thistime;
1049 data_to_send -= data_sent_thistime;
1051 /* Sanity check */
1052 if(params_to_send < 0 || data_to_send < 0) {
1053 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1054 params_to_send, data_to_send));
1055 return;
1059 return;
1062 /****************************************************************************
1063 Reply to a TRANSACT2_OPEN.
1064 ****************************************************************************/
1066 static void call_trans2open(connection_struct *conn,
1067 struct smb_request *req,
1068 char **pparams, int total_params,
1069 char **ppdata, int total_data,
1070 unsigned int max_data_bytes)
1072 struct smb_filename *smb_fname = NULL;
1073 char *params = *pparams;
1074 char *pdata = *ppdata;
1075 int deny_mode;
1076 int32_t open_attr;
1077 bool oplock_request;
1078 #if 0
1079 bool return_additional_info;
1080 int16 open_sattr;
1081 time_t open_time;
1082 #endif
1083 int open_ofun;
1084 uint32_t open_size;
1085 char *pname;
1086 char *fname = NULL;
1087 off_t size=0;
1088 int fattr=0,mtime=0;
1089 SMB_INO_T inode = 0;
1090 int smb_action = 0;
1091 files_struct *fsp;
1092 struct ea_list *ea_list = NULL;
1093 uint16_t flags = 0;
1094 NTSTATUS status;
1095 uint32_t access_mask;
1096 uint32_t share_mode;
1097 uint32_t create_disposition;
1098 uint32_t create_options = 0;
1099 uint32_t private_flags = 0;
1100 TALLOC_CTX *ctx = talloc_tos();
1103 * Ensure we have enough parameters to perform the operation.
1106 if (total_params < 29) {
1107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1108 goto out;
1111 flags = SVAL(params, 0);
1112 deny_mode = SVAL(params, 2);
1113 open_attr = SVAL(params,6);
1114 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1115 if (oplock_request) {
1116 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1119 #if 0
1120 return_additional_info = BITSETW(params,0);
1121 open_sattr = SVAL(params, 4);
1122 open_time = make_unix_date3(params+8);
1123 #endif
1124 open_ofun = SVAL(params,12);
1125 open_size = IVAL(params,14);
1126 pname = &params[28];
1128 if (IS_IPC(conn)) {
1129 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1130 goto out;
1133 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1134 total_params - 28, STR_TERMINATE,
1135 &status);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 reply_nterror(req, status);
1138 goto out;
1141 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1142 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1143 (unsigned int)open_ofun, open_size));
1145 status = filename_convert(ctx,
1146 conn,
1147 req->flags2 & FLAGS2_DFS_PATHNAMES,
1148 fname,
1150 NULL,
1151 &smb_fname);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1154 reply_botherror(req,
1155 NT_STATUS_PATH_NOT_COVERED,
1156 ERRSRV, ERRbadpath);
1157 goto out;
1159 reply_nterror(req, status);
1160 goto out;
1163 if (open_ofun == 0) {
1164 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1165 goto out;
1168 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1169 open_ofun,
1170 &access_mask, &share_mode,
1171 &create_disposition,
1172 &create_options,
1173 &private_flags)) {
1174 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1175 goto out;
1178 /* Any data in this call is an EA list. */
1179 if (total_data && (total_data != 4)) {
1180 if (total_data < 10) {
1181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1182 goto out;
1185 if (IVAL(pdata,0) > total_data) {
1186 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1187 IVAL(pdata,0), (unsigned int)total_data));
1188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1189 goto out;
1192 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1193 total_data - 4);
1194 if (!ea_list) {
1195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1196 goto out;
1199 if (!lp_ea_support(SNUM(conn))) {
1200 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1201 goto out;
1204 if (ea_list_has_invalid_name(ea_list)) {
1205 int param_len = 30;
1206 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1207 if(*pparams == NULL ) {
1208 reply_nterror(req, NT_STATUS_NO_MEMORY);
1209 goto out;
1211 params = *pparams;
1212 memset(params, '\0', param_len);
1213 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1214 params, param_len, NULL, 0, max_data_bytes);
1215 goto out;
1219 status = SMB_VFS_CREATE_FILE(
1220 conn, /* conn */
1221 req, /* req */
1222 0, /* root_dir_fid */
1223 smb_fname, /* fname */
1224 access_mask, /* access_mask */
1225 share_mode, /* share_access */
1226 create_disposition, /* create_disposition*/
1227 create_options, /* create_options */
1228 open_attr, /* file_attributes */
1229 oplock_request, /* oplock_request */
1230 NULL, /* lease */
1231 open_size, /* allocation_size */
1232 private_flags,
1233 NULL, /* sd */
1234 ea_list, /* ea_list */
1235 &fsp, /* result */
1236 &smb_action, /* psbuf */
1237 NULL, NULL); /* create context */
1239 if (!NT_STATUS_IS_OK(status)) {
1240 if (open_was_deferred(req->xconn, req->mid)) {
1241 /* We have re-scheduled this call. */
1242 goto out;
1244 reply_openerror(req, status);
1245 goto out;
1248 size = get_file_size_stat(&smb_fname->st);
1249 fattr = dos_mode(conn, smb_fname);
1250 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1251 inode = smb_fname->st.st_ex_ino;
1252 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1253 close_file(req, fsp, ERROR_CLOSE);
1254 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1255 goto out;
1258 /* Realloc the size of parameters and data we will return */
1259 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1260 if(*pparams == NULL ) {
1261 reply_nterror(req, NT_STATUS_NO_MEMORY);
1262 goto out;
1264 params = *pparams;
1266 SSVAL(params,0,fsp->fnum);
1267 SSVAL(params,2,fattr);
1268 srv_put_dos_date2(params,4, mtime);
1269 SIVAL(params,8, (uint32_t)size);
1270 SSVAL(params,12,deny_mode);
1271 SSVAL(params,14,0); /* open_type - file or directory. */
1272 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1274 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1275 smb_action |= EXTENDED_OPLOCK_GRANTED;
1278 SSVAL(params,18,smb_action);
1281 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1283 SIVAL(params,20,inode);
1284 SSVAL(params,24,0); /* Padding. */
1285 if (flags & 8) {
1286 uint32_t ea_size = estimate_ea_size(conn, fsp,
1287 smb_fname);
1288 SIVAL(params, 26, ea_size);
1289 } else {
1290 SIVAL(params, 26, 0);
1293 /* Send the required number of replies */
1294 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1295 out:
1296 TALLOC_FREE(smb_fname);
1299 /*********************************************************
1300 Routine to check if a given string matches exactly.
1301 as a special case a mask of "." does NOT match. That
1302 is required for correct wildcard semantics
1303 Case can be significant or not.
1304 **********************************************************/
1306 static bool exact_match(bool has_wild,
1307 bool case_sensitive,
1308 const char *str,
1309 const char *mask)
1311 if (mask[0] == '.' && mask[1] == 0) {
1312 return false;
1315 if (has_wild) {
1316 return false;
1319 if (case_sensitive) {
1320 return strcmp(str,mask)==0;
1321 } else {
1322 return strcasecmp_m(str,mask) == 0;
1326 /****************************************************************************
1327 Return the filetype for UNIX extensions.
1328 ****************************************************************************/
1330 static uint32_t unix_filetype(mode_t mode)
1332 if(S_ISREG(mode))
1333 return UNIX_TYPE_FILE;
1334 else if(S_ISDIR(mode))
1335 return UNIX_TYPE_DIR;
1336 #ifdef S_ISLNK
1337 else if(S_ISLNK(mode))
1338 return UNIX_TYPE_SYMLINK;
1339 #endif
1340 #ifdef S_ISCHR
1341 else if(S_ISCHR(mode))
1342 return UNIX_TYPE_CHARDEV;
1343 #endif
1344 #ifdef S_ISBLK
1345 else if(S_ISBLK(mode))
1346 return UNIX_TYPE_BLKDEV;
1347 #endif
1348 #ifdef S_ISFIFO
1349 else if(S_ISFIFO(mode))
1350 return UNIX_TYPE_FIFO;
1351 #endif
1352 #ifdef S_ISSOCK
1353 else if(S_ISSOCK(mode))
1354 return UNIX_TYPE_SOCKET;
1355 #endif
1357 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1358 return UNIX_TYPE_UNKNOWN;
1361 /****************************************************************************
1362 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1363 ****************************************************************************/
1365 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1367 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1368 const SMB_STRUCT_STAT *psbuf,
1369 uint32_t perms,
1370 enum perm_type ptype,
1371 mode_t *ret_perms)
1373 mode_t ret = 0;
1375 if (perms == SMB_MODE_NO_CHANGE) {
1376 if (!VALID_STAT(*psbuf)) {
1377 return NT_STATUS_INVALID_PARAMETER;
1378 } else {
1379 *ret_perms = psbuf->st_ex_mode;
1380 return NT_STATUS_OK;
1384 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1385 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1386 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1387 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1388 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1389 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1390 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1391 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1392 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1393 #ifdef S_ISVTX
1394 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1395 #endif
1396 #ifdef S_ISGID
1397 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1398 #endif
1399 #ifdef S_ISUID
1400 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1401 #endif
1403 if (ptype == PERM_NEW_FILE) {
1405 * "create mask"/"force create mode" are
1406 * only applied to new files, not existing ones.
1408 ret &= lp_create_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_create_mode(SNUM(conn));
1411 } else if (ptype == PERM_NEW_DIR) {
1413 * "directory mask"/"force directory mode" are
1414 * only applied to new directories, not existing ones.
1416 ret &= lp_directory_mask(SNUM(conn));
1417 /* Add in force bits */
1418 ret |= lp_force_directory_mode(SNUM(conn));
1421 *ret_perms = ret;
1422 return NT_STATUS_OK;
1425 /****************************************************************************
1426 Needed to show the msdfs symlinks as directories. Modifies psbuf
1427 to be a directory if it's a msdfs link.
1428 ****************************************************************************/
1430 static bool check_msdfs_link(connection_struct *conn,
1431 const char *pathname,
1432 SMB_STRUCT_STAT *psbuf)
1434 int saved_errno = errno;
1435 if(lp_host_msdfs() &&
1436 lp_msdfs_root(SNUM(conn)) &&
1437 is_msdfs_link(conn, pathname, psbuf)) {
1439 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1440 "as a directory\n",
1441 pathname));
1442 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1443 errno = saved_errno;
1444 return true;
1446 errno = saved_errno;
1447 return false;
1451 /****************************************************************************
1452 Get a level dependent lanman2 dir entry.
1453 ****************************************************************************/
1455 struct smbd_dirptr_lanman2_state {
1456 connection_struct *conn;
1457 uint32_t info_level;
1458 bool check_mangled_names;
1459 bool has_wild;
1460 bool got_exact_match;
1463 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1464 void *private_data,
1465 const char *dname,
1466 const char *mask,
1467 char **_fname)
1469 struct smbd_dirptr_lanman2_state *state =
1470 (struct smbd_dirptr_lanman2_state *)private_data;
1471 bool ok;
1472 char mangled_name[13]; /* mangled 8.3 name. */
1473 bool got_match;
1474 const char *fname;
1476 /* Mangle fname if it's an illegal name. */
1477 if (mangle_must_mangle(dname, state->conn->params)) {
1479 * Slow path - ensure we can push the original name as UCS2. If
1480 * not, then just don't return this name.
1482 NTSTATUS status;
1483 size_t ret_len = 0;
1484 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1485 uint8_t *tmp = talloc_array(talloc_tos(),
1486 uint8_t,
1487 len);
1489 status = srvstr_push(NULL,
1490 FLAGS2_UNICODE_STRINGS,
1491 tmp,
1492 dname,
1493 len,
1494 STR_TERMINATE,
1495 &ret_len);
1497 TALLOC_FREE(tmp);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 return false;
1503 ok = name_to_8_3(dname, mangled_name,
1504 true, state->conn->params);
1505 if (!ok) {
1506 return false;
1508 fname = mangled_name;
1509 } else {
1510 fname = dname;
1513 got_match = exact_match(state->has_wild,
1514 state->conn->case_sensitive,
1515 fname, mask);
1516 state->got_exact_match = got_match;
1517 if (!got_match) {
1518 got_match = mask_match(fname, mask,
1519 state->conn->case_sensitive);
1522 if(!got_match && state->check_mangled_names &&
1523 !mangle_is_8_3(fname, false, state->conn->params)) {
1525 * It turns out that NT matches wildcards against
1526 * both long *and* short names. This may explain some
1527 * of the wildcard wierdness from old DOS clients
1528 * that some people have been seeing.... JRA.
1530 /* Force the mangling into 8.3. */
1531 ok = name_to_8_3(fname, mangled_name,
1532 false, state->conn->params);
1533 if (!ok) {
1534 return false;
1537 got_match = exact_match(state->has_wild,
1538 state->conn->case_sensitive,
1539 mangled_name, mask);
1540 state->got_exact_match = got_match;
1541 if (!got_match) {
1542 got_match = mask_match(mangled_name, mask,
1543 state->conn->case_sensitive);
1547 if (!got_match) {
1548 return false;
1551 *_fname = talloc_strdup(ctx, fname);
1552 if (*_fname == NULL) {
1553 return false;
1556 return true;
1559 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1560 void *private_data,
1561 struct smb_filename *smb_fname,
1562 uint32_t *_mode)
1564 struct smbd_dirptr_lanman2_state *state =
1565 (struct smbd_dirptr_lanman2_state *)private_data;
1566 bool ms_dfs_link = false;
1567 uint32_t mode = 0;
1569 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1570 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1571 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1572 "Couldn't lstat [%s] (%s)\n",
1573 smb_fname_str_dbg(smb_fname),
1574 strerror(errno)));
1575 return false;
1577 } else if (!VALID_STAT(smb_fname->st) &&
1578 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1579 /* Needed to show the msdfs symlinks as
1580 * directories */
1582 ms_dfs_link = check_msdfs_link(state->conn,
1583 smb_fname->base_name,
1584 &smb_fname->st);
1585 if (!ms_dfs_link) {
1586 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1587 "Couldn't stat [%s] (%s)\n",
1588 smb_fname_str_dbg(smb_fname),
1589 strerror(errno)));
1590 return false;
1594 if (ms_dfs_link) {
1595 mode = dos_mode_msdfs(state->conn, smb_fname);
1596 } else {
1597 mode = dos_mode(state->conn, smb_fname);
1600 *_mode = mode;
1601 return true;
1604 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1605 connection_struct *conn,
1606 uint16_t flags2,
1607 uint32_t info_level,
1608 struct ea_list *name_list,
1609 bool check_mangled_names,
1610 bool requires_resume_key,
1611 uint32_t mode,
1612 const char *fname,
1613 const struct smb_filename *smb_fname,
1614 int space_remaining,
1615 uint8_t align,
1616 bool do_pad,
1617 char *base_data,
1618 char **ppdata,
1619 char *end_data,
1620 uint64_t *last_entry_off)
1622 char *p, *q, *pdata = *ppdata;
1623 uint32_t reskey=0;
1624 uint64_t file_size = 0;
1625 uint64_t allocation_size = 0;
1626 uint64_t file_index = 0;
1627 size_t len = 0;
1628 struct timespec mdate_ts = {0};
1629 struct timespec adate_ts = {0};
1630 struct timespec cdate_ts = {0};
1631 struct timespec create_date_ts = {0};
1632 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1633 char *nameptr;
1634 char *last_entry_ptr;
1635 bool was_8_3;
1636 int off;
1637 int pad = 0;
1638 NTSTATUS status;
1639 struct readdir_attr_data *readdir_attr_data = NULL;
1641 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1642 file_size = get_file_size_stat(&smb_fname->st);
1644 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1646 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1649 return status;
1653 file_index = get_FileIndex(conn, &smb_fname->st);
1655 mdate_ts = smb_fname->st.st_ex_mtime;
1656 adate_ts = smb_fname->st.st_ex_atime;
1657 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1658 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1660 if (lp_dos_filetime_resolution(SNUM(conn))) {
1661 dos_filetime_timespec(&create_date_ts);
1662 dos_filetime_timespec(&mdate_ts);
1663 dos_filetime_timespec(&adate_ts);
1664 dos_filetime_timespec(&cdate_ts);
1667 create_date = convert_timespec_to_time_t(create_date_ts);
1668 mdate = convert_timespec_to_time_t(mdate_ts);
1669 adate = convert_timespec_to_time_t(adate_ts);
1671 /* align the record */
1672 SMB_ASSERT(align >= 1);
1674 off = (int)PTR_DIFF(pdata, base_data);
1675 pad = (off + (align-1)) & ~(align-1);
1676 pad -= off;
1678 if (pad && pad > space_remaining) {
1679 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1680 "for padding (wanted %u, had %d)\n",
1681 (unsigned int)pad,
1682 space_remaining ));
1683 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1686 off += pad;
1687 /* initialize padding to 0 */
1688 if (pad) {
1689 memset(pdata, 0, pad);
1691 space_remaining -= pad;
1693 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1694 space_remaining ));
1696 pdata += pad;
1697 p = pdata;
1698 last_entry_ptr = p;
1700 pad = 0;
1701 off = 0;
1703 switch (info_level) {
1704 case SMB_FIND_INFO_STANDARD:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1706 if(requires_resume_key) {
1707 SIVAL(p,0,reskey);
1708 p += 4;
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32_t)file_size);
1714 SIVAL(p,16,(uint32_t)allocation_size);
1715 SSVAL(p,20,mode);
1716 p += 23;
1717 nameptr = p;
1718 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 p += ucs2_align(base_data, p, 0);
1721 status = srvstr_push(base_data, flags2, p,
1722 fname, PTR_DIFF(end_data, p),
1723 STR_TERMINATE, &len);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 return status;
1727 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1728 if (len > 2) {
1729 SCVAL(nameptr, -1, len - 2);
1730 } else {
1731 SCVAL(nameptr, -1, 0);
1733 } else {
1734 if (len > 1) {
1735 SCVAL(nameptr, -1, len - 1);
1736 } else {
1737 SCVAL(nameptr, -1, 0);
1740 p += len;
1741 break;
1743 case SMB_FIND_EA_SIZE:
1744 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1745 if (requires_resume_key) {
1746 SIVAL(p,0,reskey);
1747 p += 4;
1749 srv_put_dos_date2(p,0,create_date);
1750 srv_put_dos_date2(p,4,adate);
1751 srv_put_dos_date2(p,8,mdate);
1752 SIVAL(p,12,(uint32_t)file_size);
1753 SIVAL(p,16,(uint32_t)allocation_size);
1754 SSVAL(p,20,mode);
1756 unsigned int ea_size = estimate_ea_size(conn, NULL,
1757 smb_fname);
1758 SIVAL(p,22,ea_size); /* Extended attributes */
1760 p += 27;
1761 nameptr = p - 1;
1762 status = srvstr_push(base_data, flags2,
1763 p, fname, PTR_DIFF(end_data, p),
1764 STR_TERMINATE | STR_NOALIGN, &len);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 return status;
1768 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1769 if (len > 2) {
1770 len -= 2;
1771 } else {
1772 len = 0;
1774 } else {
1775 if (len > 1) {
1776 len -= 1;
1777 } else {
1778 len = 0;
1781 SCVAL(nameptr,0,len);
1782 p += len;
1783 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1784 break;
1786 case SMB_FIND_EA_LIST:
1788 struct ea_list *file_list = NULL;
1789 size_t ea_len = 0;
1791 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1792 if (!name_list) {
1793 return NT_STATUS_INVALID_PARAMETER;
1795 if (requires_resume_key) {
1796 SIVAL(p,0,reskey);
1797 p += 4;
1799 srv_put_dos_date2(p,0,create_date);
1800 srv_put_dos_date2(p,4,adate);
1801 srv_put_dos_date2(p,8,mdate);
1802 SIVAL(p,12,(uint32_t)file_size);
1803 SIVAL(p,16,(uint32_t)allocation_size);
1804 SSVAL(p,20,mode);
1805 p += 22; /* p now points to the EA area. */
1807 status = get_ea_list_from_file(ctx, conn, NULL,
1808 smb_fname,
1809 &ea_len, &file_list);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 file_list = NULL;
1813 name_list = ea_list_union(name_list, file_list, &ea_len);
1815 /* We need to determine if this entry will fit in the space available. */
1816 /* Max string size is 255 bytes. */
1817 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1818 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1819 "(wanted %u, had %d)\n",
1820 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1821 space_remaining ));
1822 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1825 /* Push the ea_data followed by the name. */
1826 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1827 nameptr = p;
1828 status = srvstr_push(base_data, flags2,
1829 p + 1, fname, PTR_DIFF(end_data, p+1),
1830 STR_TERMINATE | STR_NOALIGN, &len);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 return status;
1834 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1835 if (len > 2) {
1836 len -= 2;
1837 } else {
1838 len = 0;
1840 } else {
1841 if (len > 1) {
1842 len -= 1;
1843 } else {
1844 len = 0;
1847 SCVAL(nameptr,0,len);
1848 p += len + 1;
1849 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1850 break;
1853 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1855 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1856 p += 4;
1857 SIVAL(p,0,reskey); p += 4;
1858 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1862 SOFF_T(p,0,file_size); p += 8;
1863 SOFF_T(p,0,allocation_size); p += 8;
1864 SIVAL(p,0,mode); p += 4;
1865 q = p; p += 4; /* q is placeholder for name length. */
1866 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1867 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1868 } else {
1869 unsigned int ea_size = estimate_ea_size(conn, NULL,
1870 smb_fname);
1871 SIVAL(p,0,ea_size); /* Extended attributes */
1873 p += 4;
1874 /* Clear the short name buffer. This is
1875 * IMPORTANT as not doing so will trigger
1876 * a Win2k client bug. JRA.
1878 if (!was_8_3 && check_mangled_names) {
1879 char mangled_name[13]; /* mangled 8.3 name. */
1880 if (!name_to_8_3(fname,mangled_name,True,
1881 conn->params)) {
1882 /* Error - mangle failed ! */
1883 memset(mangled_name,'\0',12);
1885 mangled_name[12] = 0;
1886 status = srvstr_push(base_data, flags2,
1887 p+2, mangled_name, 24,
1888 STR_UPPER|STR_UNICODE, &len);
1889 if (!NT_STATUS_IS_OK(status)) {
1890 return status;
1892 if (len < 24) {
1893 memset(p + 2 + len,'\0',24 - len);
1895 SSVAL(p, 0, len);
1896 } else {
1897 memset(p,'\0',26);
1899 p += 2 + 24;
1900 status = srvstr_push(base_data, flags2, p,
1901 fname, PTR_DIFF(end_data, p),
1902 STR_TERMINATE_ASCII, &len);
1903 if (!NT_STATUS_IS_OK(status)) {
1904 return status;
1906 SIVAL(q,0,len);
1907 p += len;
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1916 SIVAL(pdata,0,pad);
1918 * set padding to zero
1920 if (do_pad) {
1921 memset(p, 0, pad - len);
1922 p = pdata + pad;
1923 } else {
1924 p = pdata + len;
1926 break;
1928 case SMB_FIND_FILE_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1930 p += 4;
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 status = srvstr_push(base_data, flags2,
1940 p + 4, fname, PTR_DIFF(end_data, p+4),
1941 STR_TERMINATE_ASCII, &len);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 return status;
1945 SIVAL(p,0,len);
1946 p += 4 + len;
1948 len = PTR_DIFF(p, pdata);
1949 pad = (len + (align-1)) & ~(align-1);
1951 * offset to the next entry, the caller
1952 * will overwrite it for the last entry
1953 * that's why we always include the padding
1955 SIVAL(pdata,0,pad);
1957 * set padding to zero
1959 if (do_pad) {
1960 memset(p, 0, pad - len);
1961 p = pdata + pad;
1962 } else {
1963 p = pdata + len;
1965 break;
1967 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1968 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1969 p += 4;
1970 SIVAL(p,0,reskey); p += 4;
1971 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1972 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1973 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1974 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1975 SOFF_T(p,0,file_size); p += 8;
1976 SOFF_T(p,0,allocation_size); p += 8;
1977 SIVAL(p,0,mode); p += 4;
1978 q = p; p += 4; /* q is placeholder for name length. */
1980 unsigned int ea_size = estimate_ea_size(conn, NULL,
1981 smb_fname);
1982 SIVAL(p,0,ea_size); /* Extended attributes */
1983 p +=4;
1985 status = srvstr_push(base_data, flags2, p,
1986 fname, PTR_DIFF(end_data, p),
1987 STR_TERMINATE_ASCII, &len);
1988 if (!NT_STATUS_IS_OK(status)) {
1989 return status;
1991 SIVAL(q, 0, len);
1992 p += len;
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2001 SIVAL(pdata,0,pad);
2003 * set padding to zero
2005 if (do_pad) {
2006 memset(p, 0, pad - len);
2007 p = pdata + pad;
2008 } else {
2009 p = pdata + len;
2011 break;
2013 case SMB_FIND_FILE_NAMES_INFO:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2015 p += 4;
2016 SIVAL(p,0,reskey); p += 4;
2017 p += 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 status = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2022 STR_TERMINATE_ASCII, &len);
2023 if (!NT_STATUS_IS_OK(status)) {
2024 return status;
2026 SIVAL(p, -4, len);
2027 p += len;
2029 len = PTR_DIFF(p, pdata);
2030 pad = (len + (align-1)) & ~(align-1);
2032 * offset to the next entry, the caller
2033 * will overwrite it for the last entry
2034 * that's why we always include the padding
2036 SIVAL(pdata,0,pad);
2038 * set padding to zero
2040 if (do_pad) {
2041 memset(p, 0, pad - len);
2042 p = pdata + pad;
2043 } else {
2044 p = pdata + len;
2046 break;
2048 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2049 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2050 p += 4;
2051 SIVAL(p,0,reskey); p += 4;
2052 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2053 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2054 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2055 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2056 SOFF_T(p,0,file_size); p += 8;
2057 SOFF_T(p,0,allocation_size); p += 8;
2058 SIVAL(p,0,mode); p += 4;
2059 q = p; p += 4; /* q is placeholder for name length. */
2060 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2061 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2062 } else {
2063 unsigned int ea_size = estimate_ea_size(conn, NULL,
2064 smb_fname);
2065 SIVAL(p,0,ea_size); /* Extended attributes */
2067 p += 4;
2068 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2069 SBVAL(p,0,file_index); p += 8;
2070 status = srvstr_push(base_data, flags2, p,
2071 fname, PTR_DIFF(end_data, p),
2072 STR_TERMINATE_ASCII, &len);
2073 if (!NT_STATUS_IS_OK(status)) {
2074 return status;
2076 SIVAL(q, 0, len);
2077 p += len;
2079 len = PTR_DIFF(p, pdata);
2080 pad = (len + (align-1)) & ~(align-1);
2082 * offset to the next entry, the caller
2083 * will overwrite it for the last entry
2084 * that's why we always include the padding
2086 SIVAL(pdata,0,pad);
2088 * set padding to zero
2090 if (do_pad) {
2091 memset(p, 0, pad - len);
2092 p = pdata + pad;
2093 } else {
2094 p = pdata + len;
2096 break;
2098 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2099 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2100 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2101 p += 4;
2102 SIVAL(p,0,reskey); p += 4;
2103 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2106 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2107 SOFF_T(p,0,file_size); p += 8;
2108 SOFF_T(p,0,allocation_size); p += 8;
2109 SIVAL(p,0,mode); p += 4;
2110 q = p; p += 4; /* q is placeholder for name length */
2111 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2112 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2113 } else if (readdir_attr_data &&
2114 readdir_attr_data->type == RDATTR_AAPL) {
2116 * OS X specific SMB2 extension negotiated via
2117 * AAPL create context: return max_access in
2118 * ea_size field.
2120 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2121 } else {
2122 unsigned int ea_size = estimate_ea_size(conn, NULL,
2123 smb_fname);
2124 SIVAL(p,0,ea_size); /* Extended attributes */
2126 p += 4;
2128 if (readdir_attr_data &&
2129 readdir_attr_data->type == RDATTR_AAPL) {
2131 * OS X specific SMB2 extension negotiated via
2132 * AAPL create context: return resource fork
2133 * length and compressed FinderInfo in
2134 * shortname field.
2136 * According to documentation short_name_len
2137 * should be 0, but on the wire behaviour
2138 * shows its set to 24 by clients.
2140 SSVAL(p, 0, 24);
2142 /* Resourefork length */
2143 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2145 /* Compressed FinderInfo */
2146 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2147 } else if (!was_8_3 && check_mangled_names) {
2148 char mangled_name[13]; /* mangled 8.3 name. */
2149 if (!name_to_8_3(fname,mangled_name,True,
2150 conn->params)) {
2151 /* Error - mangle failed ! */
2152 memset(mangled_name,'\0',12);
2154 mangled_name[12] = 0;
2155 status = srvstr_push(base_data, flags2,
2156 p+2, mangled_name, 24,
2157 STR_UPPER|STR_UNICODE, &len);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 return status;
2161 SSVAL(p, 0, len);
2162 if (len < 24) {
2163 memset(p + 2 + len,'\0',24 - len);
2165 SSVAL(p, 0, len);
2166 } else {
2167 /* Clear the short name buffer. This is
2168 * IMPORTANT as not doing so will trigger
2169 * a Win2k client bug. JRA.
2171 memset(p,'\0',26);
2173 p += 26;
2175 /* Reserved ? */
2176 if (readdir_attr_data &&
2177 readdir_attr_data->type == RDATTR_AAPL) {
2179 * OS X specific SMB2 extension negotiated via
2180 * AAPL create context: return UNIX mode in
2181 * reserved field.
2183 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2184 SSVAL(p, 0, aapl_mode);
2185 } else {
2186 SSVAL(p, 0, 0);
2188 p += 2;
2190 SBVAL(p,0,file_index); p += 8;
2191 status = srvstr_push(base_data, flags2, p,
2192 fname, PTR_DIFF(end_data, p),
2193 STR_TERMINATE_ASCII, &len);
2194 if (!NT_STATUS_IS_OK(status)) {
2195 return status;
2197 SIVAL(q,0,len);
2198 p += len;
2200 len = PTR_DIFF(p, pdata);
2201 pad = (len + (align-1)) & ~(align-1);
2203 * offset to the next entry, the caller
2204 * will overwrite it for the last entry
2205 * that's why we always include the padding
2207 SIVAL(pdata,0,pad);
2209 * set padding to zero
2211 if (do_pad) {
2212 memset(p, 0, pad - len);
2213 p = pdata + pad;
2214 } else {
2215 p = pdata + len;
2217 break;
2219 /* CIFS UNIX Extension. */
2221 case SMB_FIND_FILE_UNIX:
2222 case SMB_FIND_FILE_UNIX_INFO2:
2223 p+= 4;
2224 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2226 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2228 if (info_level == SMB_FIND_FILE_UNIX) {
2229 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2230 p = store_file_unix_basic(conn, p,
2231 NULL, &smb_fname->st);
2232 status = srvstr_push(base_data, flags2, p,
2233 fname, PTR_DIFF(end_data, p),
2234 STR_TERMINATE, &len);
2235 if (!NT_STATUS_IS_OK(status)) {
2236 return status;
2238 } else {
2239 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2240 p = store_file_unix_basic_info2(conn, p,
2241 NULL, &smb_fname->st);
2242 nameptr = p;
2243 p += 4;
2244 status = srvstr_push(base_data, flags2, p, fname,
2245 PTR_DIFF(end_data, p), 0, &len);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 return status;
2249 SIVAL(nameptr, 0, len);
2252 p += len;
2254 len = PTR_DIFF(p, pdata);
2255 pad = (len + (align-1)) & ~(align-1);
2257 * offset to the next entry, the caller
2258 * will overwrite it for the last entry
2259 * that's why we always include the padding
2261 SIVAL(pdata,0,pad);
2263 * set padding to zero
2265 if (do_pad) {
2266 memset(p, 0, pad - len);
2267 p = pdata + pad;
2268 } else {
2269 p = pdata + len;
2271 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2273 break;
2275 default:
2276 return NT_STATUS_INVALID_LEVEL;
2279 if (PTR_DIFF(p,pdata) > space_remaining) {
2280 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2281 "(wanted %u, had %d)\n",
2282 (unsigned int)PTR_DIFF(p,pdata),
2283 space_remaining ));
2284 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2287 /* Setup the last entry pointer, as an offset from base_data */
2288 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2289 /* Advance the data pointer to the next slot */
2290 *ppdata = p;
2292 return NT_STATUS_OK;
2295 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2296 connection_struct *conn,
2297 struct dptr_struct *dirptr,
2298 uint16_t flags2,
2299 const char *path_mask,
2300 uint32_t dirtype,
2301 int info_level,
2302 int requires_resume_key,
2303 bool dont_descend,
2304 bool ask_sharemode,
2305 uint8_t align,
2306 bool do_pad,
2307 char **ppdata,
2308 char *base_data,
2309 char *end_data,
2310 int space_remaining,
2311 bool *got_exact_match,
2312 int *_last_entry_off,
2313 struct ea_list *name_list)
2315 const char *p;
2316 const char *mask = NULL;
2317 long prev_dirpos = 0;
2318 uint32_t mode = 0;
2319 char *fname = NULL;
2320 struct smb_filename *smb_fname = NULL;
2321 struct smbd_dirptr_lanman2_state state;
2322 bool ok;
2323 uint64_t last_entry_off = 0;
2324 NTSTATUS status;
2326 ZERO_STRUCT(state);
2327 state.conn = conn;
2328 state.info_level = info_level;
2329 state.check_mangled_names = lp_mangled_names(conn->params);
2330 state.has_wild = dptr_has_wild(dirptr);
2331 state.got_exact_match = false;
2333 *got_exact_match = false;
2335 p = strrchr_m(path_mask,'/');
2336 if(p != NULL) {
2337 if(p[1] == '\0') {
2338 mask = "*.*";
2339 } else {
2340 mask = p+1;
2342 } else {
2343 mask = path_mask;
2346 ok = smbd_dirptr_get_entry(ctx,
2347 dirptr,
2348 mask,
2349 dirtype,
2350 dont_descend,
2351 ask_sharemode,
2352 smbd_dirptr_lanman2_match_fn,
2353 smbd_dirptr_lanman2_mode_fn,
2354 &state,
2355 &fname,
2356 &smb_fname,
2357 &mode,
2358 &prev_dirpos);
2359 if (!ok) {
2360 return NT_STATUS_END_OF_FILE;
2363 *got_exact_match = state.got_exact_match;
2365 status = smbd_marshall_dir_entry(ctx,
2366 conn,
2367 flags2,
2368 info_level,
2369 name_list,
2370 state.check_mangled_names,
2371 requires_resume_key,
2372 mode,
2373 fname,
2374 smb_fname,
2375 space_remaining,
2376 align,
2377 do_pad,
2378 base_data,
2379 ppdata,
2380 end_data,
2381 &last_entry_off);
2382 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2383 DEBUG(1,("Conversion error: illegal character: %s\n",
2384 smb_fname_str_dbg(smb_fname)));
2386 TALLOC_FREE(fname);
2387 TALLOC_FREE(smb_fname);
2388 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2389 dptr_SeekDir(dirptr, prev_dirpos);
2390 return status;
2392 if (!NT_STATUS_IS_OK(status)) {
2393 return status;
2396 *_last_entry_off = last_entry_off;
2397 return NT_STATUS_OK;
2400 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2401 connection_struct *conn,
2402 struct dptr_struct *dirptr,
2403 uint16_t flags2,
2404 const char *path_mask,
2405 uint32_t dirtype,
2406 int info_level,
2407 bool requires_resume_key,
2408 bool dont_descend,
2409 bool ask_sharemode,
2410 char **ppdata,
2411 char *base_data,
2412 char *end_data,
2413 int space_remaining,
2414 bool *got_exact_match,
2415 int *last_entry_off,
2416 struct ea_list *name_list)
2418 uint8_t align = 4;
2419 const bool do_pad = true;
2421 if (info_level >= 1 && info_level <= 3) {
2422 /* No alignment on earlier info levels. */
2423 align = 1;
2426 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2427 path_mask, dirtype, info_level,
2428 requires_resume_key, dont_descend, ask_sharemode,
2429 align, do_pad,
2430 ppdata, base_data, end_data,
2431 space_remaining,
2432 got_exact_match,
2433 last_entry_off, name_list);
2436 /****************************************************************************
2437 Reply to a TRANS2_FINDFIRST.
2438 ****************************************************************************/
2440 static void call_trans2findfirst(connection_struct *conn,
2441 struct smb_request *req,
2442 char **pparams, int total_params,
2443 char **ppdata, int total_data,
2444 unsigned int max_data_bytes)
2446 /* We must be careful here that we don't return more than the
2447 allowed number of data bytes. If this means returning fewer than
2448 maxentries then so be it. We assume that the redirector has
2449 enough room for the fixed number of parameter bytes it has
2450 requested. */
2451 struct smb_filename *smb_dname = NULL;
2452 char *params = *pparams;
2453 char *pdata = *ppdata;
2454 char *data_end;
2455 uint32_t dirtype;
2456 int maxentries;
2457 uint16_t findfirst_flags;
2458 bool close_after_first;
2459 bool close_if_end;
2460 bool requires_resume_key;
2461 int info_level;
2462 char *directory = NULL;
2463 char *mask = NULL;
2464 char *p;
2465 int last_entry_off=0;
2466 int dptr_num = -1;
2467 int numentries = 0;
2468 int i;
2469 bool finished = False;
2470 bool dont_descend = False;
2471 bool out_of_space = False;
2472 int space_remaining;
2473 bool mask_contains_wcard = False;
2474 struct ea_list *ea_list = NULL;
2475 NTSTATUS ntstatus = NT_STATUS_OK;
2476 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2477 TALLOC_CTX *ctx = talloc_tos();
2478 struct dptr_struct *dirptr = NULL;
2479 struct smbd_server_connection *sconn = req->sconn;
2480 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2481 bool backup_priv = false;
2482 bool as_root = false;
2484 if (total_params < 13) {
2485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2486 goto out;
2489 dirtype = SVAL(params,0);
2490 maxentries = SVAL(params,2);
2491 findfirst_flags = SVAL(params,4);
2492 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2493 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2494 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2495 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2496 security_token_has_privilege(get_current_nttok(conn),
2497 SEC_PRIV_BACKUP));
2499 info_level = SVAL(params,6);
2501 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2502 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2503 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2504 (int)backup_priv,
2505 info_level, max_data_bytes));
2507 if (!maxentries) {
2508 /* W2K3 seems to treat zero as 1. */
2509 maxentries = 1;
2512 switch (info_level) {
2513 case SMB_FIND_INFO_STANDARD:
2514 case SMB_FIND_EA_SIZE:
2515 case SMB_FIND_EA_LIST:
2516 case SMB_FIND_FILE_DIRECTORY_INFO:
2517 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2518 case SMB_FIND_FILE_NAMES_INFO:
2519 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2520 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2521 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2522 break;
2523 case SMB_FIND_FILE_UNIX:
2524 case SMB_FIND_FILE_UNIX_INFO2:
2525 /* Always use filesystem for UNIX mtime query. */
2526 ask_sharemode = false;
2527 if (!lp_unix_extensions()) {
2528 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2529 goto out;
2531 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2532 break;
2533 default:
2534 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2535 goto out;
2538 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2539 params+12, total_params - 12,
2540 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2541 if (!NT_STATUS_IS_OK(ntstatus)) {
2542 reply_nterror(req, ntstatus);
2543 goto out;
2546 if (backup_priv) {
2547 become_root();
2548 as_root = true;
2549 ntstatus = filename_convert_with_privilege(ctx,
2550 conn,
2551 req,
2552 directory,
2553 ucf_flags,
2554 &mask_contains_wcard,
2555 &smb_dname);
2556 } else {
2557 ntstatus = filename_convert(ctx, conn,
2558 req->flags2 & FLAGS2_DFS_PATHNAMES,
2559 directory,
2560 ucf_flags,
2561 &mask_contains_wcard,
2562 &smb_dname);
2565 if (!NT_STATUS_IS_OK(ntstatus)) {
2566 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2567 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2568 ERRSRV, ERRbadpath);
2569 goto out;
2571 reply_nterror(req, ntstatus);
2572 goto out;
2575 mask = smb_dname->original_lcomp;
2577 directory = smb_dname->base_name;
2579 p = strrchr_m(directory,'/');
2580 if(p == NULL) {
2581 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2582 if((directory[0] == '.') && (directory[1] == '\0')) {
2583 mask = talloc_strdup(ctx,"*");
2584 if (!mask) {
2585 reply_nterror(req, NT_STATUS_NO_MEMORY);
2586 goto out;
2588 mask_contains_wcard = True;
2590 } else {
2591 *p = 0;
2594 if (p == NULL || p == directory) {
2595 /* Ensure we don't have a directory name of "". */
2596 directory = talloc_strdup(talloc_tos(), ".");
2597 if (!directory) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2599 goto out;
2603 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2605 if (info_level == SMB_FIND_EA_LIST) {
2606 uint32_t ea_size;
2608 if (total_data < 4) {
2609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2610 goto out;
2613 ea_size = IVAL(pdata,0);
2614 if (ea_size != total_data) {
2615 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2616 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2618 goto out;
2621 if (!lp_ea_support(SNUM(conn))) {
2622 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2623 goto out;
2626 /* Pull out the list of names. */
2627 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2628 if (!ea_list) {
2629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2630 goto out;
2634 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2636 goto out;
2639 *ppdata = (char *)SMB_REALLOC(
2640 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2641 if(*ppdata == NULL ) {
2642 reply_nterror(req, NT_STATUS_NO_MEMORY);
2643 goto out;
2645 pdata = *ppdata;
2646 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2648 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2649 * error.
2651 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2652 /* Realloc the params space */
2653 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2654 if (*pparams == NULL) {
2655 reply_nterror(req, NT_STATUS_NO_MEMORY);
2656 goto out;
2658 params = *pparams;
2660 /* Save the wildcard match and attribs we are using on this directory -
2661 needed as lanman2 assumes these are being saved between calls */
2663 ntstatus = dptr_create(conn,
2664 req,
2665 NULL, /* fsp */
2666 directory,
2667 False,
2668 True,
2669 req->smbpid,
2670 mask,
2671 mask_contains_wcard,
2672 dirtype,
2673 &dirptr);
2675 if (!NT_STATUS_IS_OK(ntstatus)) {
2676 reply_nterror(req, ntstatus);
2677 goto out;
2680 if (backup_priv) {
2681 /* Remember this in case we have
2682 to do a findnext. */
2683 dptr_set_priv(dirptr);
2686 dptr_num = dptr_dnum(dirptr);
2687 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2689 /* Initialize per TRANS2_FIND_FIRST operation data */
2690 dptr_init_search_op(dirptr);
2692 /* We don't need to check for VOL here as this is returned by
2693 a different TRANS2 call. */
2695 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2696 directory,lp_dont_descend(ctx, SNUM(conn))));
2697 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2698 dont_descend = True;
2700 p = pdata;
2701 space_remaining = max_data_bytes;
2702 out_of_space = False;
2704 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2705 bool got_exact_match = False;
2707 /* this is a heuristic to avoid seeking the dirptr except when
2708 absolutely necessary. It allows for a filename of about 40 chars */
2709 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2710 out_of_space = True;
2711 finished = False;
2712 } else {
2713 ntstatus = get_lanman2_dir_entry(ctx,
2714 conn,
2715 dirptr,
2716 req->flags2,
2717 mask,dirtype,info_level,
2718 requires_resume_key,dont_descend,
2719 ask_sharemode,
2720 &p,pdata,data_end,
2721 space_remaining,
2722 &got_exact_match,
2723 &last_entry_off, ea_list);
2724 if (NT_STATUS_EQUAL(ntstatus,
2725 NT_STATUS_ILLEGAL_CHARACTER)) {
2727 * Bad character conversion on name. Ignore this
2728 * entry.
2730 continue;
2732 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2733 out_of_space = true;
2734 } else {
2735 finished = !NT_STATUS_IS_OK(ntstatus);
2739 if (!finished && !out_of_space)
2740 numentries++;
2743 * As an optimisation if we know we aren't looking
2744 * for a wildcard name (ie. the name matches the wildcard exactly)
2745 * then we can finish on any (first) match.
2746 * This speeds up large directory searches. JRA.
2749 if(got_exact_match)
2750 finished = True;
2752 /* Ensure space_remaining never goes -ve. */
2753 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2754 space_remaining = 0;
2755 out_of_space = true;
2756 } else {
2757 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2761 /* Check if we can close the dirptr */
2762 if(close_after_first || (finished && close_if_end)) {
2763 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2764 dptr_close(sconn, &dptr_num);
2768 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2769 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2770 * the protocol level is less than NT1. Tested with smbclient. JRA.
2771 * This should fix the OS/2 client bug #2335.
2774 if(numentries == 0) {
2775 dptr_close(sconn, &dptr_num);
2776 if (get_Protocol() < PROTOCOL_NT1) {
2777 reply_force_doserror(req, ERRDOS, ERRnofiles);
2778 goto out;
2779 } else {
2780 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2781 ERRDOS, ERRbadfile);
2782 goto out;
2786 /* At this point pdata points to numentries directory entries. */
2788 /* Set up the return parameter block */
2789 SSVAL(params,0,dptr_num);
2790 SSVAL(params,2,numentries);
2791 SSVAL(params,4,finished);
2792 SSVAL(params,6,0); /* Never an EA error */
2793 SSVAL(params,8,last_entry_off);
2795 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2796 max_data_bytes);
2798 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2799 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2800 if (!directory) {
2801 reply_nterror(req, NT_STATUS_NO_MEMORY);
2805 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2806 smb_fn_name(req->cmd),
2807 mask, directory, dirtype, numentries ) );
2810 * Force a name mangle here to ensure that the
2811 * mask as an 8.3 name is top of the mangled cache.
2812 * The reasons for this are subtle. Don't remove
2813 * this code unless you know what you are doing
2814 * (see PR#13758). JRA.
2817 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2818 char mangled_name[13];
2819 name_to_8_3(mask, mangled_name, True, conn->params);
2821 out:
2823 if (as_root) {
2824 unbecome_root();
2827 TALLOC_FREE(smb_dname);
2828 return;
2831 /****************************************************************************
2832 Reply to a TRANS2_FINDNEXT.
2833 ****************************************************************************/
2835 static void call_trans2findnext(connection_struct *conn,
2836 struct smb_request *req,
2837 char **pparams, int total_params,
2838 char **ppdata, int total_data,
2839 unsigned int max_data_bytes)
2841 /* We must be careful here that we don't return more than the
2842 allowed number of data bytes. If this means returning fewer than
2843 maxentries then so be it. We assume that the redirector has
2844 enough room for the fixed number of parameter bytes it has
2845 requested. */
2846 char *params = *pparams;
2847 char *pdata = *ppdata;
2848 char *data_end;
2849 int dptr_num;
2850 int maxentries;
2851 uint16_t info_level;
2852 uint32_t resume_key;
2853 uint16_t findnext_flags;
2854 bool close_after_request;
2855 bool close_if_end;
2856 bool requires_resume_key;
2857 bool continue_bit;
2858 bool mask_contains_wcard = False;
2859 char *resume_name = NULL;
2860 const char *mask = NULL;
2861 const char *directory = NULL;
2862 char *p = NULL;
2863 uint16_t dirtype;
2864 int numentries = 0;
2865 int i, last_entry_off=0;
2866 bool finished = False;
2867 bool dont_descend = False;
2868 bool out_of_space = False;
2869 int space_remaining;
2870 struct ea_list *ea_list = NULL;
2871 NTSTATUS ntstatus = NT_STATUS_OK;
2872 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2873 TALLOC_CTX *ctx = talloc_tos();
2874 struct dptr_struct *dirptr;
2875 struct smbd_server_connection *sconn = req->sconn;
2876 bool backup_priv = false;
2877 bool as_root = false;
2879 if (total_params < 13) {
2880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2881 return;
2884 dptr_num = SVAL(params,0);
2885 maxentries = SVAL(params,2);
2886 info_level = SVAL(params,4);
2887 resume_key = IVAL(params,6);
2888 findnext_flags = SVAL(params,10);
2889 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2890 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2891 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2892 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2894 if (!continue_bit) {
2895 /* We only need resume_name if continue_bit is zero. */
2896 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2897 params+12,
2898 total_params - 12, STR_TERMINATE, &ntstatus,
2899 &mask_contains_wcard);
2900 if (!NT_STATUS_IS_OK(ntstatus)) {
2901 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2902 complain (it thinks we're asking for the directory above the shared
2903 path or an invalid name). Catch this as the resume name is only compared, never used in
2904 a file access. JRA. */
2905 srvstr_pull_talloc(ctx, params, req->flags2,
2906 &resume_name, params+12,
2907 total_params - 12,
2908 STR_TERMINATE);
2910 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2911 reply_nterror(req, ntstatus);
2912 return;
2917 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2918 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2919 resume_key = %d resume name = %s continue=%d level = %d\n",
2920 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2921 requires_resume_key, resume_key,
2922 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2924 if (!maxentries) {
2925 /* W2K3 seems to treat zero as 1. */
2926 maxentries = 1;
2929 switch (info_level) {
2930 case SMB_FIND_INFO_STANDARD:
2931 case SMB_FIND_EA_SIZE:
2932 case SMB_FIND_EA_LIST:
2933 case SMB_FIND_FILE_DIRECTORY_INFO:
2934 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2935 case SMB_FIND_FILE_NAMES_INFO:
2936 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2937 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2938 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2939 break;
2940 case SMB_FIND_FILE_UNIX:
2941 case SMB_FIND_FILE_UNIX_INFO2:
2942 /* Always use filesystem for UNIX mtime query. */
2943 ask_sharemode = false;
2944 if (!lp_unix_extensions()) {
2945 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2946 return;
2948 break;
2949 default:
2950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2951 return;
2954 if (info_level == SMB_FIND_EA_LIST) {
2955 uint32_t ea_size;
2957 if (total_data < 4) {
2958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2959 return;
2962 ea_size = IVAL(pdata,0);
2963 if (ea_size != total_data) {
2964 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2965 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2967 return;
2970 if (!lp_ea_support(SNUM(conn))) {
2971 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2972 return;
2975 /* Pull out the list of names. */
2976 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2977 if (!ea_list) {
2978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2979 return;
2983 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2985 return;
2988 *ppdata = (char *)SMB_REALLOC(
2989 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2990 if(*ppdata == NULL) {
2991 reply_nterror(req, NT_STATUS_NO_MEMORY);
2992 return;
2995 pdata = *ppdata;
2996 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2999 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3000 * error.
3002 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3003 /* Realloc the params space */
3004 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3005 if(*pparams == NULL ) {
3006 reply_nterror(req, NT_STATUS_NO_MEMORY);
3007 return;
3010 params = *pparams;
3012 /* Check that the dptr is valid */
3013 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3014 reply_nterror(req, STATUS_NO_MORE_FILES);
3015 return;
3018 directory = dptr_path(sconn, dptr_num);
3020 /* Get the wildcard mask from the dptr */
3021 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3022 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3023 reply_nterror(req, STATUS_NO_MORE_FILES);
3024 return;
3027 /* Get the attr mask from the dptr */
3028 dirtype = dptr_attr(sconn, dptr_num);
3030 backup_priv = dptr_get_priv(dirptr);
3032 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3033 "backup_priv = %d\n",
3034 dptr_num, mask, dirtype,
3035 (long)dirptr,
3036 dptr_TellDir(dirptr),
3037 (int)backup_priv));
3039 /* Initialize per TRANS2_FIND_NEXT operation data */
3040 dptr_init_search_op(dirptr);
3042 /* We don't need to check for VOL here as this is returned by
3043 a different TRANS2 call. */
3045 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3046 directory,lp_dont_descend(ctx, SNUM(conn))));
3047 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3048 dont_descend = True;
3050 p = pdata;
3051 space_remaining = max_data_bytes;
3052 out_of_space = False;
3054 if (backup_priv) {
3055 become_root();
3056 as_root = true;
3060 * Seek to the correct position. We no longer use the resume key but
3061 * depend on the last file name instead.
3064 if(!continue_bit && resume_name && *resume_name) {
3065 SMB_STRUCT_STAT st;
3067 long current_pos = 0;
3069 * Remember, name_to_8_3 is called by
3070 * get_lanman2_dir_entry(), so the resume name
3071 * could be mangled. Ensure we check the unmangled name.
3074 if (mangle_is_mangled(resume_name, conn->params)) {
3075 char *new_resume_name = NULL;
3076 mangle_lookup_name_from_8_3(ctx,
3077 resume_name,
3078 &new_resume_name,
3079 conn->params);
3080 if (new_resume_name) {
3081 resume_name = new_resume_name;
3086 * Fix for NT redirector problem triggered by resume key indexes
3087 * changing between directory scans. We now return a resume key of 0
3088 * and instead look for the filename to continue from (also given
3089 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3090 * findfirst/findnext (as is usual) then the directory pointer
3091 * should already be at the correct place.
3094 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3095 } /* end if resume_name && !continue_bit */
3097 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3098 bool got_exact_match = False;
3100 /* this is a heuristic to avoid seeking the dirptr except when
3101 absolutely necessary. It allows for a filename of about 40 chars */
3102 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3103 out_of_space = True;
3104 finished = False;
3105 } else {
3106 ntstatus = get_lanman2_dir_entry(ctx,
3107 conn,
3108 dirptr,
3109 req->flags2,
3110 mask,dirtype,info_level,
3111 requires_resume_key,dont_descend,
3112 ask_sharemode,
3113 &p,pdata,data_end,
3114 space_remaining,
3115 &got_exact_match,
3116 &last_entry_off, ea_list);
3117 if (NT_STATUS_EQUAL(ntstatus,
3118 NT_STATUS_ILLEGAL_CHARACTER)) {
3120 * Bad character conversion on name. Ignore this
3121 * entry.
3123 continue;
3125 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3126 out_of_space = true;
3127 } else {
3128 finished = !NT_STATUS_IS_OK(ntstatus);
3132 if (!finished && !out_of_space)
3133 numentries++;
3136 * As an optimisation if we know we aren't looking
3137 * for a wildcard name (ie. the name matches the wildcard exactly)
3138 * then we can finish on any (first) match.
3139 * This speeds up large directory searches. JRA.
3142 if(got_exact_match)
3143 finished = True;
3145 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3148 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3149 smb_fn_name(req->cmd),
3150 mask, directory, dirtype, numentries ) );
3152 /* Check if we can close the dirptr */
3153 if(close_after_request || (finished && close_if_end)) {
3154 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3155 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3158 if (as_root) {
3159 unbecome_root();
3162 /* Set up the return parameter block */
3163 SSVAL(params,0,numentries);
3164 SSVAL(params,2,finished);
3165 SSVAL(params,4,0); /* Never an EA error */
3166 SSVAL(params,6,last_entry_off);
3168 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3169 max_data_bytes);
3171 return;
3174 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3176 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3177 return objid;
3180 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3182 SMB_ASSERT(extended_info != NULL);
3184 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3185 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3186 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3187 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3188 #ifdef SAMBA_VERSION_REVISION
3189 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3190 #endif
3191 extended_info->samba_subversion = 0;
3192 #ifdef SAMBA_VERSION_RC_RELEASE
3193 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3194 #else
3195 #ifdef SAMBA_VERSION_PRE_RELEASE
3196 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3197 #endif
3198 #endif
3199 #ifdef SAMBA_VERSION_VENDOR_PATCH
3200 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3201 #endif
3202 extended_info->samba_gitcommitdate = 0;
3203 #ifdef SAMBA_VERSION_COMMIT_TIME
3204 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3205 #endif
3207 memset(extended_info->samba_version_string, 0,
3208 sizeof(extended_info->samba_version_string));
3210 snprintf (extended_info->samba_version_string,
3211 sizeof(extended_info->samba_version_string),
3212 "%s", samba_version_string());
3215 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3216 connection_struct *conn,
3217 TALLOC_CTX *mem_ctx,
3218 uint16_t info_level,
3219 uint16_t flags2,
3220 unsigned int max_data_bytes,
3221 size_t *fixed_portion,
3222 struct smb_filename *fname,
3223 char **ppdata,
3224 int *ret_data_len)
3226 char *pdata, *end_data;
3227 int data_len = 0;
3228 size_t len = 0;
3229 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3230 int snum = SNUM(conn);
3231 const char *fstype = lp_fstype(SNUM(conn));
3232 const char *filename = NULL;
3233 const uint64_t bytes_per_sector = 512;
3234 uint32_t additional_flags = 0;
3235 struct smb_filename smb_fname;
3236 SMB_STRUCT_STAT st;
3237 NTSTATUS status = NT_STATUS_OK;
3238 uint64_t df_ret;
3240 if (fname == NULL || fname->base_name == NULL) {
3241 filename = ".";
3242 } else {
3243 filename = fname->base_name;
3246 if (IS_IPC(conn)) {
3247 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3248 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3249 "info level (0x%x) on IPC$.\n",
3250 (unsigned int)info_level));
3251 return NT_STATUS_ACCESS_DENIED;
3255 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3257 ZERO_STRUCT(smb_fname);
3258 smb_fname.base_name = discard_const_p(char, filename);
3260 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3261 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3262 return map_nt_error_from_unix(errno);
3265 st = smb_fname.st;
3267 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3268 return NT_STATUS_INVALID_PARAMETER;
3271 *ppdata = (char *)SMB_REALLOC(
3272 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3273 if (*ppdata == NULL) {
3274 return NT_STATUS_NO_MEMORY;
3277 pdata = *ppdata;
3278 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3279 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3281 *fixed_portion = 0;
3283 switch (info_level) {
3284 case SMB_INFO_ALLOCATION:
3286 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3287 data_len = 18;
3288 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3289 &dsize);
3290 if (df_ret == (uint64_t)-1) {
3291 return map_nt_error_from_unix(errno);
3294 block_size = lp_block_size(snum);
3295 if (bsize < block_size) {
3296 uint64_t factor = block_size/bsize;
3297 bsize = block_size;
3298 dsize /= factor;
3299 dfree /= factor;
3301 if (bsize > block_size) {
3302 uint64_t factor = bsize/block_size;
3303 bsize = block_size;
3304 dsize *= factor;
3305 dfree *= factor;
3307 sectors_per_unit = bsize/bytes_per_sector;
3309 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3311 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3313 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3314 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3315 SIVAL(pdata,l1_cUnit,dsize);
3316 SIVAL(pdata,l1_cUnitAvail,dfree);
3317 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3318 break;
3321 case SMB_INFO_VOLUME:
3322 /* Return volume name */
3324 * Add volume serial number - hash of a combination of
3325 * the called hostname and the service name.
3327 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3329 * Win2k3 and previous mess this up by sending a name length
3330 * one byte short. I believe only older clients (OS/2 Win9x) use
3331 * this call so try fixing this by adding a terminating null to
3332 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3334 status = srvstr_push(
3335 pdata, flags2,
3336 pdata+l2_vol_szVolLabel, vname,
3337 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3338 STR_NOALIGN|STR_TERMINATE, &len);
3339 if (!NT_STATUS_IS_OK(status)) {
3340 return status;
3342 SCVAL(pdata,l2_vol_cch,len);
3343 data_len = l2_vol_szVolLabel + len;
3344 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3345 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3346 (unsigned)len, vname));
3347 break;
3349 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3350 case SMB_FS_ATTRIBUTE_INFORMATION:
3352 additional_flags = 0;
3353 #if defined(HAVE_SYS_QUOTAS)
3354 additional_flags |= FILE_VOLUME_QUOTAS;
3355 #endif
3357 if(lp_nt_acl_support(SNUM(conn))) {
3358 additional_flags |= FILE_PERSISTENT_ACLS;
3361 /* Capabilities are filled in at connection time through STATVFS call */
3362 additional_flags |= conn->fs_capabilities;
3363 additional_flags |= lp_parm_int(conn->params->service,
3364 "share", "fake_fscaps",
3367 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3368 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3369 additional_flags); /* FS ATTRIBUTES */
3371 SIVAL(pdata,4,255); /* Max filename component length */
3372 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3373 and will think we can't do long filenames */
3374 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3375 PTR_DIFF(end_data, pdata+12),
3376 STR_UNICODE, &len);
3377 if (!NT_STATUS_IS_OK(status)) {
3378 return status;
3380 SIVAL(pdata,8,len);
3381 data_len = 12 + len;
3382 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3383 /* the client only requested a portion of the
3384 file system name */
3385 data_len = max_data_bytes;
3386 status = STATUS_BUFFER_OVERFLOW;
3388 *fixed_portion = 16;
3389 break;
3391 case SMB_QUERY_FS_LABEL_INFO:
3392 case SMB_FS_LABEL_INFORMATION:
3393 status = srvstr_push(pdata, flags2, pdata+4, vname,
3394 PTR_DIFF(end_data, pdata+4), 0, &len);
3395 if (!NT_STATUS_IS_OK(status)) {
3396 return status;
3398 data_len = 4 + len;
3399 SIVAL(pdata,0,len);
3400 break;
3402 case SMB_QUERY_FS_VOLUME_INFO:
3403 case SMB_FS_VOLUME_INFORMATION:
3406 * Add volume serial number - hash of a combination of
3407 * the called hostname and the service name.
3409 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3410 (str_checksum(get_local_machine_name())<<16));
3412 /* Max label len is 32 characters. */
3413 status = srvstr_push(pdata, flags2, pdata+18, vname,
3414 PTR_DIFF(end_data, pdata+18),
3415 STR_UNICODE, &len);
3416 if (!NT_STATUS_IS_OK(status)) {
3417 return status;
3419 SIVAL(pdata,12,len);
3420 data_len = 18+len;
3422 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3423 (int)strlen(vname),vname,
3424 lp_servicename(talloc_tos(), snum)));
3425 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3426 /* the client only requested a portion of the
3427 volume label */
3428 data_len = max_data_bytes;
3429 status = STATUS_BUFFER_OVERFLOW;
3431 *fixed_portion = 24;
3432 break;
3434 case SMB_QUERY_FS_SIZE_INFO:
3435 case SMB_FS_SIZE_INFORMATION:
3437 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3438 data_len = 24;
3439 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3440 &dsize);
3441 if (df_ret == (uint64_t)-1) {
3442 return map_nt_error_from_unix(errno);
3444 block_size = lp_block_size(snum);
3445 if (bsize < block_size) {
3446 uint64_t factor = block_size/bsize;
3447 bsize = block_size;
3448 dsize /= factor;
3449 dfree /= factor;
3451 if (bsize > block_size) {
3452 uint64_t factor = bsize/block_size;
3453 bsize = block_size;
3454 dsize *= factor;
3455 dfree *= factor;
3457 sectors_per_unit = bsize/bytes_per_sector;
3458 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3459 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3460 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3461 SBIG_UINT(pdata,0,dsize);
3462 SBIG_UINT(pdata,8,dfree);
3463 SIVAL(pdata,16,sectors_per_unit);
3464 SIVAL(pdata,20,bytes_per_sector);
3465 *fixed_portion = 24;
3466 break;
3469 case SMB_FS_FULL_SIZE_INFORMATION:
3471 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3472 data_len = 32;
3473 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3474 &dsize);
3475 if (df_ret == (uint64_t)-1) {
3476 return map_nt_error_from_unix(errno);
3478 block_size = lp_block_size(snum);
3479 if (bsize < block_size) {
3480 uint64_t factor = block_size/bsize;
3481 bsize = block_size;
3482 dsize /= factor;
3483 dfree /= factor;
3485 if (bsize > block_size) {
3486 uint64_t factor = bsize/block_size;
3487 bsize = block_size;
3488 dsize *= factor;
3489 dfree *= factor;
3491 sectors_per_unit = bsize/bytes_per_sector;
3492 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3493 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3494 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3495 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3496 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3497 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3498 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3499 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3500 *fixed_portion = 32;
3501 break;
3504 case SMB_QUERY_FS_DEVICE_INFO:
3505 case SMB_FS_DEVICE_INFORMATION:
3507 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3509 if (!CAN_WRITE(conn)) {
3510 characteristics |= FILE_READ_ONLY_DEVICE;
3512 data_len = 8;
3513 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3514 SIVAL(pdata,4,characteristics);
3515 *fixed_portion = 8;
3516 break;
3519 #ifdef HAVE_SYS_QUOTAS
3520 case SMB_FS_QUOTA_INFORMATION:
3522 * what we have to send --metze:
3524 * Unknown1: 24 NULL bytes
3525 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3526 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3527 * Quota Flags: 2 byte :
3528 * Unknown3: 6 NULL bytes
3530 * 48 bytes total
3532 * details for Quota Flags:
3534 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3535 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3536 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3537 * 0x0001 Enable Quotas: enable quota for this fs
3541 /* we need to fake up a fsp here,
3542 * because its not send in this call
3544 files_struct fsp;
3545 SMB_NTQUOTA_STRUCT quotas;
3547 ZERO_STRUCT(fsp);
3548 ZERO_STRUCT(quotas);
3550 fsp.conn = conn;
3551 fsp.fnum = FNUM_FIELD_INVALID;
3553 /* access check */
3554 if (get_current_uid(conn) != 0) {
3555 DEBUG(0,("get_user_quota: access_denied "
3556 "service [%s] user [%s]\n",
3557 lp_servicename(talloc_tos(), SNUM(conn)),
3558 conn->session_info->unix_info->unix_name));
3559 return NT_STATUS_ACCESS_DENIED;
3562 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3563 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3564 return map_nt_error_from_unix(errno);
3567 data_len = 48;
3569 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3570 lp_servicename(talloc_tos(), SNUM(conn))));
3572 /* Unknown1 24 NULL bytes*/
3573 SBIG_UINT(pdata,0,(uint64_t)0);
3574 SBIG_UINT(pdata,8,(uint64_t)0);
3575 SBIG_UINT(pdata,16,(uint64_t)0);
3577 /* Default Soft Quota 8 bytes */
3578 SBIG_UINT(pdata,24,quotas.softlim);
3580 /* Default Hard Quota 8 bytes */
3581 SBIG_UINT(pdata,32,quotas.hardlim);
3583 /* Quota flag 2 bytes */
3584 SSVAL(pdata,40,quotas.qflags);
3586 /* Unknown3 6 NULL bytes */
3587 SSVAL(pdata,42,0);
3588 SIVAL(pdata,44,0);
3590 break;
3592 #endif /* HAVE_SYS_QUOTAS */
3593 case SMB_FS_OBJECTID_INFORMATION:
3595 unsigned char objid[16];
3596 struct smb_extended_info extended_info;
3597 memcpy(pdata,create_volume_objectid(conn, objid),16);
3598 samba_extended_info_version (&extended_info);
3599 SIVAL(pdata,16,extended_info.samba_magic);
3600 SIVAL(pdata,20,extended_info.samba_version);
3601 SIVAL(pdata,24,extended_info.samba_subversion);
3602 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3603 memcpy(pdata+36,extended_info.samba_version_string,28);
3604 data_len = 64;
3605 break;
3608 case SMB_FS_SECTOR_SIZE_INFORMATION:
3610 data_len = 28;
3612 * These values match a physical Windows Server 2012
3613 * share backed by NTFS atop spinning rust.
3615 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3616 /* logical_bytes_per_sector */
3617 SIVAL(pdata, 0, bytes_per_sector);
3618 /* phys_bytes_per_sector_atomic */
3619 SIVAL(pdata, 4, bytes_per_sector);
3620 /* phys_bytes_per_sector_perf */
3621 SIVAL(pdata, 8, bytes_per_sector);
3622 /* fs_effective_phys_bytes_per_sector_atomic */
3623 SIVAL(pdata, 12, bytes_per_sector);
3624 /* flags */
3625 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3626 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3627 /* byte_off_sector_align */
3628 SIVAL(pdata, 20, 0);
3629 /* byte_off_partition_align */
3630 SIVAL(pdata, 24, 0);
3631 *fixed_portion = 28;
3632 break;
3637 * Query the version and capabilities of the CIFS UNIX extensions
3638 * in use.
3641 case SMB_QUERY_CIFS_UNIX_INFO:
3643 bool large_write = lp_min_receive_file_size() &&
3644 !srv_is_signing_active(xconn);
3645 bool large_read = !srv_is_signing_active(xconn);
3646 int encrypt_caps = 0;
3648 if (!lp_unix_extensions()) {
3649 return NT_STATUS_INVALID_LEVEL;
3652 switch (conn->encrypt_level) {
3653 case SMB_SIGNING_OFF:
3654 encrypt_caps = 0;
3655 break;
3656 case SMB_SIGNING_DESIRED:
3657 case SMB_SIGNING_IF_REQUIRED:
3658 case SMB_SIGNING_DEFAULT:
3659 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3660 break;
3661 case SMB_SIGNING_REQUIRED:
3662 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3663 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3664 large_write = false;
3665 large_read = false;
3666 break;
3669 data_len = 12;
3670 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3671 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3673 /* We have POSIX ACLs, pathname, encryption,
3674 * large read/write, and locking capability. */
3676 SBIG_UINT(pdata,4,((uint64_t)(
3677 CIFS_UNIX_POSIX_ACLS_CAP|
3678 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3679 CIFS_UNIX_FCNTL_LOCKS_CAP|
3680 CIFS_UNIX_EXTATTR_CAP|
3681 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3682 encrypt_caps|
3683 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3684 (large_write ?
3685 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3686 break;
3689 case SMB_QUERY_POSIX_FS_INFO:
3691 int rc;
3692 vfs_statvfs_struct svfs;
3694 if (!lp_unix_extensions()) {
3695 return NT_STATUS_INVALID_LEVEL;
3698 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3700 if (!rc) {
3701 data_len = 56;
3702 SIVAL(pdata,0,svfs.OptimalTransferSize);
3703 SIVAL(pdata,4,svfs.BlockSize);
3704 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3705 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3706 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3707 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3708 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3709 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3710 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3711 #ifdef EOPNOTSUPP
3712 } else if (rc == EOPNOTSUPP) {
3713 return NT_STATUS_INVALID_LEVEL;
3714 #endif /* EOPNOTSUPP */
3715 } else {
3716 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3717 return NT_STATUS_DOS(ERRSRV, ERRerror);
3719 break;
3722 case SMB_QUERY_POSIX_WHOAMI:
3724 uint32_t flags = 0;
3725 uint32_t sid_bytes;
3726 int i;
3728 if (!lp_unix_extensions()) {
3729 return NT_STATUS_INVALID_LEVEL;
3732 if (max_data_bytes < 40) {
3733 return NT_STATUS_BUFFER_TOO_SMALL;
3736 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3737 flags |= SMB_WHOAMI_GUEST;
3740 /* NOTE: 8 bytes for UID/GID, irrespective of native
3741 * platform size. This matches
3742 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3744 data_len = 4 /* flags */
3745 + 4 /* flag mask */
3746 + 8 /* uid */
3747 + 8 /* gid */
3748 + 4 /* ngroups */
3749 + 4 /* num_sids */
3750 + 4 /* SID bytes */
3751 + 4 /* pad/reserved */
3752 + (conn->session_info->unix_token->ngroups * 8)
3753 /* groups list */
3754 + (conn->session_info->security_token->num_sids *
3755 SID_MAX_SIZE)
3756 /* SID list */;
3758 SIVAL(pdata, 0, flags);
3759 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3760 SBIG_UINT(pdata, 8,
3761 (uint64_t)conn->session_info->unix_token->uid);
3762 SBIG_UINT(pdata, 16,
3763 (uint64_t)conn->session_info->unix_token->gid);
3766 if (data_len >= max_data_bytes) {
3767 /* Potential overflow, skip the GIDs and SIDs. */
3769 SIVAL(pdata, 24, 0); /* num_groups */
3770 SIVAL(pdata, 28, 0); /* num_sids */
3771 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3772 SIVAL(pdata, 36, 0); /* reserved */
3774 data_len = 40;
3775 break;
3778 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3779 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3781 /* We walk the SID list twice, but this call is fairly
3782 * infrequent, and I don't expect that it's performance
3783 * sensitive -- jpeach
3785 for (i = 0, sid_bytes = 0;
3786 i < conn->session_info->security_token->num_sids; ++i) {
3787 sid_bytes += ndr_size_dom_sid(
3788 &conn->session_info->security_token->sids[i],
3792 /* SID list byte count */
3793 SIVAL(pdata, 32, sid_bytes);
3795 /* 4 bytes pad/reserved - must be zero */
3796 SIVAL(pdata, 36, 0);
3797 data_len = 40;
3799 /* GID list */
3800 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3801 SBIG_UINT(pdata, data_len,
3802 (uint64_t)conn->session_info->unix_token->groups[i]);
3803 data_len += 8;
3806 /* SID list */
3807 for (i = 0;
3808 i < conn->session_info->security_token->num_sids; ++i) {
3809 int sid_len = ndr_size_dom_sid(
3810 &conn->session_info->security_token->sids[i],
3813 sid_linearize((uint8_t *)(pdata + data_len),
3814 sid_len,
3815 &conn->session_info->security_token->sids[i]);
3816 data_len += sid_len;
3819 break;
3822 case SMB_MAC_QUERY_FS_INFO:
3824 * Thursby MAC extension... ONLY on NTFS filesystems
3825 * once we do streams then we don't need this
3827 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3828 data_len = 88;
3829 SIVAL(pdata,84,0x100); /* Don't support mac... */
3830 break;
3832 /* drop through */
3833 default:
3834 return NT_STATUS_INVALID_LEVEL;
3837 *ret_data_len = data_len;
3838 return status;
3841 /****************************************************************************
3842 Reply to a TRANS2_QFSINFO (query filesystem info).
3843 ****************************************************************************/
3845 static void call_trans2qfsinfo(connection_struct *conn,
3846 struct smb_request *req,
3847 char **pparams, int total_params,
3848 char **ppdata, int total_data,
3849 unsigned int max_data_bytes)
3851 char *params = *pparams;
3852 uint16_t info_level;
3853 int data_len = 0;
3854 size_t fixed_portion;
3855 NTSTATUS status;
3857 if (total_params < 2) {
3858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3859 return;
3862 info_level = SVAL(params,0);
3864 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3865 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3866 DEBUG(0,("call_trans2qfsinfo: encryption required "
3867 "and info level 0x%x sent.\n",
3868 (unsigned int)info_level));
3869 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3870 return;
3874 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3876 status = smbd_do_qfsinfo(req->xconn, conn, req,
3877 info_level,
3878 req->flags2,
3879 max_data_bytes,
3880 &fixed_portion,
3881 NULL,
3882 ppdata, &data_len);
3883 if (!NT_STATUS_IS_OK(status)) {
3884 reply_nterror(req, status);
3885 return;
3888 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3889 max_data_bytes);
3891 DEBUG( 4, ( "%s info_level = %d\n",
3892 smb_fn_name(req->cmd), info_level) );
3894 return;
3897 /****************************************************************************
3898 Reply to a TRANS2_SETFSINFO (set filesystem info).
3899 ****************************************************************************/
3901 static void call_trans2setfsinfo(connection_struct *conn,
3902 struct smb_request *req,
3903 char **pparams, int total_params,
3904 char **ppdata, int total_data,
3905 unsigned int max_data_bytes)
3907 struct smbXsrv_connection *xconn = req->xconn;
3908 char *pdata = *ppdata;
3909 char *params = *pparams;
3910 uint16_t info_level;
3912 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3913 lp_servicename(talloc_tos(), SNUM(conn))));
3915 /* */
3916 if (total_params < 4) {
3917 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3918 total_params));
3919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3920 return;
3923 info_level = SVAL(params,2);
3925 if (IS_IPC(conn)) {
3926 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3927 info_level != SMB_SET_CIFS_UNIX_INFO) {
3928 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3929 "info level (0x%x) on IPC$.\n",
3930 (unsigned int)info_level));
3931 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3932 return;
3936 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3937 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3938 DEBUG(0,("call_trans2setfsinfo: encryption required "
3939 "and info level 0x%x sent.\n",
3940 (unsigned int)info_level));
3941 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3942 return;
3946 switch(info_level) {
3947 case SMB_SET_CIFS_UNIX_INFO:
3948 if (!lp_unix_extensions()) {
3949 DEBUG(2,("call_trans2setfsinfo: "
3950 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3951 "unix extensions off\n"));
3952 reply_nterror(req,
3953 NT_STATUS_INVALID_LEVEL);
3954 return;
3957 /* There should be 12 bytes of capabilities set. */
3958 if (total_data < 12) {
3959 reply_nterror(
3960 req,
3961 NT_STATUS_INVALID_PARAMETER);
3962 return;
3964 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3965 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3966 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3967 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3968 /* Just print these values for now. */
3969 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3970 "major = %u, minor = %u cap_low = 0x%x, "
3971 "cap_high = 0x%xn",
3972 (unsigned int)xconn->
3973 smb1.unix_info.client_major,
3974 (unsigned int)xconn->
3975 smb1.unix_info.client_minor,
3976 (unsigned int)xconn->
3977 smb1.unix_info.client_cap_low,
3978 (unsigned int)xconn->
3979 smb1.unix_info.client_cap_high));
3981 /* Here is where we must switch to posix pathname processing... */
3982 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3983 lp_set_posix_pathnames();
3984 mangle_change_to_posix();
3987 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3988 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3989 /* Client that knows how to do posix locks,
3990 * but not posix open/mkdir operations. Set a
3991 * default type for read/write checks. */
3993 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3996 break;
3998 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4000 NTSTATUS status;
4001 size_t param_len = 0;
4002 size_t data_len = total_data;
4004 if (!lp_unix_extensions()) {
4005 reply_nterror(
4006 req,
4007 NT_STATUS_INVALID_LEVEL);
4008 return;
4011 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4012 reply_nterror(
4013 req,
4014 NT_STATUS_NOT_SUPPORTED);
4015 return;
4018 if (xconn->smb1.echo_handler.trusted_fde) {
4019 DEBUG( 2,("call_trans2setfsinfo: "
4020 "request transport encryption disabled"
4021 "with 'fork echo handler = yes'\n"));
4022 reply_nterror(
4023 req,
4024 NT_STATUS_NOT_SUPPORTED);
4025 return;
4028 DEBUG( 4,("call_trans2setfsinfo: "
4029 "request transport encryption.\n"));
4031 status = srv_request_encryption_setup(conn,
4032 (unsigned char **)ppdata,
4033 &data_len,
4034 (unsigned char **)pparams,
4035 &param_len);
4037 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4038 !NT_STATUS_IS_OK(status)) {
4039 reply_nterror(req, status);
4040 return;
4043 send_trans2_replies(conn, req,
4044 NT_STATUS_OK,
4045 *pparams,
4046 param_len,
4047 *ppdata,
4048 data_len,
4049 max_data_bytes);
4051 if (NT_STATUS_IS_OK(status)) {
4052 /* Server-side transport
4053 * encryption is now *on*. */
4054 status = srv_encryption_start(conn);
4055 if (!NT_STATUS_IS_OK(status)) {
4056 char *reason = talloc_asprintf(talloc_tos(),
4057 "Failure in setting "
4058 "up encrypted transport: %s",
4059 nt_errstr(status));
4060 exit_server_cleanly(reason);
4063 return;
4066 case SMB_FS_QUOTA_INFORMATION:
4068 files_struct *fsp = NULL;
4069 SMB_NTQUOTA_STRUCT quotas;
4071 ZERO_STRUCT(quotas);
4073 /* access check */
4074 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4075 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4076 lp_servicename(talloc_tos(), SNUM(conn)),
4077 conn->session_info->unix_info->unix_name));
4078 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4079 return;
4082 /* note: normally there're 48 bytes,
4083 * but we didn't use the last 6 bytes for now
4084 * --metze
4086 fsp = file_fsp(req, SVAL(params,0));
4088 if (!check_fsp_ntquota_handle(conn, req,
4089 fsp)) {
4090 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4091 reply_nterror(
4092 req, NT_STATUS_INVALID_HANDLE);
4093 return;
4096 if (total_data < 42) {
4097 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4098 total_data));
4099 reply_nterror(
4100 req,
4101 NT_STATUS_INVALID_PARAMETER);
4102 return;
4105 /* unknown_1 24 NULL bytes in pdata*/
4107 /* the soft quotas 8 bytes (uint64_t)*/
4108 quotas.softlim = BVAL(pdata,24);
4110 /* the hard quotas 8 bytes (uint64_t)*/
4111 quotas.hardlim = BVAL(pdata,32);
4113 /* quota_flags 2 bytes **/
4114 quotas.qflags = SVAL(pdata,40);
4116 /* unknown_2 6 NULL bytes follow*/
4118 /* now set the quotas */
4119 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4120 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4121 reply_nterror(req, map_nt_error_from_unix(errno));
4122 return;
4125 break;
4127 default:
4128 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4129 info_level));
4130 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4131 return;
4132 break;
4136 * sending this reply works fine,
4137 * but I'm not sure it's the same
4138 * like windows do...
4139 * --metze
4141 reply_outbuf(req, 10, 0);
4144 #if defined(HAVE_POSIX_ACLS)
4145 /****************************************************************************
4146 Utility function to count the number of entries in a POSIX acl.
4147 ****************************************************************************/
4149 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4151 unsigned int ace_count = 0;
4152 int entry_id = SMB_ACL_FIRST_ENTRY;
4153 SMB_ACL_ENTRY_T entry;
4155 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4156 /* get_next... */
4157 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4158 entry_id = SMB_ACL_NEXT_ENTRY;
4160 ace_count++;
4162 return ace_count;
4165 /****************************************************************************
4166 Utility function to marshall a POSIX acl into wire format.
4167 ****************************************************************************/
4169 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4171 int entry_id = SMB_ACL_FIRST_ENTRY;
4172 SMB_ACL_ENTRY_T entry;
4174 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4175 SMB_ACL_TAG_T tagtype;
4176 SMB_ACL_PERMSET_T permset;
4177 unsigned char perms = 0;
4178 unsigned int own_grp;
4180 /* get_next... */
4181 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4182 entry_id = SMB_ACL_NEXT_ENTRY;
4185 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4186 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4187 return False;
4190 if (sys_acl_get_permset(entry, &permset) == -1) {
4191 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4192 return False;
4195 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4196 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4197 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4199 SCVAL(pdata,1,perms);
4201 switch (tagtype) {
4202 case SMB_ACL_USER_OBJ:
4203 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4204 own_grp = (unsigned int)pst->st_ex_uid;
4205 SIVAL(pdata,2,own_grp);
4206 SIVAL(pdata,6,0);
4207 break;
4208 case SMB_ACL_USER:
4210 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4211 if (!puid) {
4212 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4213 return False;
4215 own_grp = (unsigned int)*puid;
4216 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4217 SIVAL(pdata,2,own_grp);
4218 SIVAL(pdata,6,0);
4219 break;
4221 case SMB_ACL_GROUP_OBJ:
4222 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4223 own_grp = (unsigned int)pst->st_ex_gid;
4224 SIVAL(pdata,2,own_grp);
4225 SIVAL(pdata,6,0);
4226 break;
4227 case SMB_ACL_GROUP:
4229 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4230 if (!pgid) {
4231 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4232 return False;
4234 own_grp = (unsigned int)*pgid;
4235 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4236 SIVAL(pdata,2,own_grp);
4237 SIVAL(pdata,6,0);
4238 break;
4240 case SMB_ACL_MASK:
4241 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4242 SIVAL(pdata,2,0xFFFFFFFF);
4243 SIVAL(pdata,6,0xFFFFFFFF);
4244 break;
4245 case SMB_ACL_OTHER:
4246 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4247 SIVAL(pdata,2,0xFFFFFFFF);
4248 SIVAL(pdata,6,0xFFFFFFFF);
4249 break;
4250 default:
4251 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4252 return False;
4254 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4257 return True;
4259 #endif
4261 /****************************************************************************
4262 Store the FILE_UNIX_BASIC info.
4263 ****************************************************************************/
4265 static char *store_file_unix_basic(connection_struct *conn,
4266 char *pdata,
4267 files_struct *fsp,
4268 const SMB_STRUCT_STAT *psbuf)
4270 uint64_t file_index = get_FileIndex(conn, psbuf);
4271 dev_t devno;
4273 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4274 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4276 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4277 pdata += 8;
4279 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4280 pdata += 8;
4282 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4283 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4284 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4285 pdata += 24;
4287 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4288 SIVAL(pdata,4,0);
4289 pdata += 8;
4291 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4292 SIVAL(pdata,4,0);
4293 pdata += 8;
4295 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4296 pdata += 4;
4298 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4299 devno = psbuf->st_ex_rdev;
4300 } else {
4301 devno = psbuf->st_ex_dev;
4304 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4305 SIVAL(pdata,4,0);
4306 pdata += 8;
4308 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4309 SIVAL(pdata,4,0);
4310 pdata += 8;
4312 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4313 pdata += 8;
4315 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4316 SIVAL(pdata,4,0);
4317 pdata += 8;
4319 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4320 SIVAL(pdata,4,0);
4321 pdata += 8;
4323 return pdata;
4326 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4327 * the chflags(2) (or equivalent) flags.
4329 * XXX: this really should be behind the VFS interface. To do this, we would
4330 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4331 * Each VFS module could then implement its own mapping as appropriate for the
4332 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4334 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4335 info2_flags_map[] =
4337 #ifdef UF_NODUMP
4338 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4339 #endif
4341 #ifdef UF_IMMUTABLE
4342 { UF_IMMUTABLE, EXT_IMMUTABLE },
4343 #endif
4345 #ifdef UF_APPEND
4346 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4347 #endif
4349 #ifdef UF_HIDDEN
4350 { UF_HIDDEN, EXT_HIDDEN },
4351 #endif
4353 /* Do not remove. We need to guarantee that this array has at least one
4354 * entry to build on HP-UX.
4356 { 0, 0 }
4360 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4361 uint32_t *smb_fflags, uint32_t *smb_fmask)
4363 int i;
4365 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4366 *smb_fmask |= info2_flags_map[i].smb_fflag;
4367 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4368 *smb_fflags |= info2_flags_map[i].smb_fflag;
4373 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4374 const uint32_t smb_fflags,
4375 const uint32_t smb_fmask,
4376 int *stat_fflags)
4378 uint32_t max_fmask = 0;
4379 int i;
4381 *stat_fflags = psbuf->st_ex_flags;
4383 /* For each flags requested in smb_fmask, check the state of the
4384 * corresponding flag in smb_fflags and set or clear the matching
4385 * stat flag.
4388 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4389 max_fmask |= info2_flags_map[i].smb_fflag;
4390 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4391 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4392 *stat_fflags |= info2_flags_map[i].stat_fflag;
4393 } else {
4394 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4399 /* If smb_fmask is asking to set any bits that are not supported by
4400 * our flag mappings, we should fail.
4402 if ((smb_fmask & max_fmask) != smb_fmask) {
4403 return False;
4406 return True;
4410 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4411 * of file flags and birth (create) time.
4413 static char *store_file_unix_basic_info2(connection_struct *conn,
4414 char *pdata,
4415 files_struct *fsp,
4416 const SMB_STRUCT_STAT *psbuf)
4418 uint32_t file_flags = 0;
4419 uint32_t flags_mask = 0;
4421 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4423 /* Create (birth) time 64 bit */
4424 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4425 pdata += 8;
4427 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4428 SIVAL(pdata, 0, file_flags); /* flags */
4429 SIVAL(pdata, 4, flags_mask); /* mask */
4430 pdata += 8;
4432 return pdata;
4435 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4436 const struct stream_struct *streams,
4437 char *data,
4438 unsigned int max_data_bytes,
4439 unsigned int *data_size)
4441 unsigned int i;
4442 unsigned int ofs = 0;
4444 if (max_data_bytes < 32) {
4445 return NT_STATUS_INFO_LENGTH_MISMATCH;
4448 for (i = 0; i < num_streams; i++) {
4449 unsigned int next_offset;
4450 size_t namelen;
4451 smb_ucs2_t *namebuf;
4453 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4454 streams[i].name, &namelen) ||
4455 namelen <= 2)
4457 return NT_STATUS_INVALID_PARAMETER;
4461 * name_buf is now null-terminated, we need to marshall as not
4462 * terminated
4465 namelen -= 2;
4468 * We cannot overflow ...
4470 if ((ofs + 24 + namelen) > max_data_bytes) {
4471 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4472 i));
4473 TALLOC_FREE(namebuf);
4474 return STATUS_BUFFER_OVERFLOW;
4477 SIVAL(data, ofs+4, namelen);
4478 SOFF_T(data, ofs+8, streams[i].size);
4479 SOFF_T(data, ofs+16, streams[i].alloc_size);
4480 memcpy(data+ofs+24, namebuf, namelen);
4481 TALLOC_FREE(namebuf);
4483 next_offset = ofs + 24 + namelen;
4485 if (i == num_streams-1) {
4486 SIVAL(data, ofs, 0);
4488 else {
4489 unsigned int align = ndr_align_size(next_offset, 8);
4491 if ((next_offset + align) > max_data_bytes) {
4492 DEBUG(10, ("refusing to overflow align "
4493 "reply at stream %u\n",
4494 i));
4495 TALLOC_FREE(namebuf);
4496 return STATUS_BUFFER_OVERFLOW;
4499 memset(data+next_offset, 0, align);
4500 next_offset += align;
4502 SIVAL(data, ofs, next_offset - ofs);
4503 ofs = next_offset;
4506 ofs = next_offset;
4509 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4511 *data_size = ofs;
4513 return NT_STATUS_OK;
4516 /****************************************************************************
4517 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4518 ****************************************************************************/
4520 static void call_trans2qpipeinfo(connection_struct *conn,
4521 struct smb_request *req,
4522 unsigned int tran_call,
4523 char **pparams, int total_params,
4524 char **ppdata, int total_data,
4525 unsigned int max_data_bytes)
4527 char *params = *pparams;
4528 char *pdata = *ppdata;
4529 unsigned int data_size = 0;
4530 unsigned int param_size = 2;
4531 uint16_t info_level;
4532 files_struct *fsp;
4534 if (!params) {
4535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4536 return;
4539 if (total_params < 4) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541 return;
4544 fsp = file_fsp(req, SVAL(params,0));
4545 if (!fsp_is_np(fsp)) {
4546 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4547 return;
4550 info_level = SVAL(params,2);
4552 *pparams = (char *)SMB_REALLOC(*pparams,2);
4553 if (*pparams == NULL) {
4554 reply_nterror(req, NT_STATUS_NO_MEMORY);
4555 return;
4557 params = *pparams;
4558 SSVAL(params,0,0);
4559 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4561 return;
4563 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4564 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4565 if (*ppdata == NULL ) {
4566 reply_nterror(req, NT_STATUS_NO_MEMORY);
4567 return;
4569 pdata = *ppdata;
4571 switch (info_level) {
4572 case SMB_FILE_STANDARD_INFORMATION:
4573 memset(pdata,0,24);
4574 SOFF_T(pdata,0,4096LL);
4575 SIVAL(pdata,16,1);
4576 SIVAL(pdata,20,1);
4577 data_size = 24;
4578 break;
4580 default:
4581 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4582 return;
4585 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4586 max_data_bytes);
4588 return;
4591 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4592 TALLOC_CTX *mem_ctx,
4593 uint16_t info_level,
4594 files_struct *fsp,
4595 struct smb_filename *smb_fname,
4596 bool delete_pending,
4597 struct timespec write_time_ts,
4598 struct ea_list *ea_list,
4599 int lock_data_count,
4600 char *lock_data,
4601 uint16_t flags2,
4602 unsigned int max_data_bytes,
4603 size_t *fixed_portion,
4604 char **ppdata,
4605 unsigned int *pdata_size)
4607 char *pdata = *ppdata;
4608 char *dstart, *dend;
4609 unsigned int data_size;
4610 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4611 time_t create_time, mtime, atime, c_time;
4612 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4613 char *p;
4614 char *base_name;
4615 char *dos_fname;
4616 int mode;
4617 int nlink;
4618 NTSTATUS status;
4619 uint64_t file_size = 0;
4620 uint64_t pos = 0;
4621 uint64_t allocation_size = 0;
4622 uint64_t file_index = 0;
4623 uint32_t access_mask = 0;
4624 size_t len = 0;
4626 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4627 return NT_STATUS_INVALID_LEVEL;
4630 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4631 smb_fname_str_dbg(smb_fname),
4632 fsp_fnum_dbg(fsp),
4633 info_level, max_data_bytes));
4635 mode = dos_mode(conn, smb_fname);
4636 nlink = psbuf->st_ex_nlink;
4638 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4639 nlink = 1;
4642 if ((nlink > 0) && delete_pending) {
4643 nlink -= 1;
4646 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4647 return NT_STATUS_INVALID_PARAMETER;
4650 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4651 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4652 if (*ppdata == NULL) {
4653 return NT_STATUS_NO_MEMORY;
4655 pdata = *ppdata;
4656 dstart = pdata;
4657 dend = dstart + data_size - 1;
4659 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4660 update_stat_ex_mtime(psbuf, write_time_ts);
4663 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4664 mtime_ts = psbuf->st_ex_mtime;
4665 atime_ts = psbuf->st_ex_atime;
4666 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4668 if (lp_dos_filetime_resolution(SNUM(conn))) {
4669 dos_filetime_timespec(&create_time_ts);
4670 dos_filetime_timespec(&mtime_ts);
4671 dos_filetime_timespec(&atime_ts);
4672 dos_filetime_timespec(&ctime_ts);
4675 create_time = convert_timespec_to_time_t(create_time_ts);
4676 mtime = convert_timespec_to_time_t(mtime_ts);
4677 atime = convert_timespec_to_time_t(atime_ts);
4678 c_time = convert_timespec_to_time_t(ctime_ts);
4680 p = strrchr_m(smb_fname->base_name,'/');
4681 if (!p)
4682 base_name = smb_fname->base_name;
4683 else
4684 base_name = p+1;
4686 /* NT expects the name to be in an exact form of the *full*
4687 filename. See the trans2 torture test */
4688 if (ISDOT(base_name)) {
4689 dos_fname = talloc_strdup(mem_ctx, "\\");
4690 if (!dos_fname) {
4691 return NT_STATUS_NO_MEMORY;
4693 } else {
4694 dos_fname = talloc_asprintf(mem_ctx,
4695 "\\%s",
4696 smb_fname->base_name);
4697 if (!dos_fname) {
4698 return NT_STATUS_NO_MEMORY;
4700 if (is_ntfs_stream_smb_fname(smb_fname)) {
4701 dos_fname = talloc_asprintf(dos_fname, "%s",
4702 smb_fname->stream_name);
4703 if (!dos_fname) {
4704 return NT_STATUS_NO_MEMORY;
4708 string_replace(dos_fname, '/', '\\');
4711 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4713 if (!fsp) {
4714 /* Do we have this path open ? */
4715 files_struct *fsp1;
4716 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4717 fsp1 = file_find_di_first(conn->sconn, fileid);
4718 if (fsp1 && fsp1->initial_allocation_size) {
4719 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4723 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4724 file_size = get_file_size_stat(psbuf);
4727 if (fsp) {
4728 pos = fsp->fh->position_information;
4731 if (fsp) {
4732 access_mask = fsp->access_mask;
4733 } else {
4734 /* GENERIC_EXECUTE mapping from Windows */
4735 access_mask = 0x12019F;
4738 /* This should be an index number - looks like
4739 dev/ino to me :-)
4741 I think this causes us to fail the IFSKIT
4742 BasicFileInformationTest. -tpot */
4743 file_index = get_FileIndex(conn, psbuf);
4745 *fixed_portion = 0;
4747 switch (info_level) {
4748 case SMB_INFO_STANDARD:
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4750 data_size = 22;
4751 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4752 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4753 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4754 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4755 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4756 SSVAL(pdata,l1_attrFile,mode);
4757 break;
4759 case SMB_INFO_QUERY_EA_SIZE:
4761 unsigned int ea_size =
4762 estimate_ea_size(conn, fsp,
4763 smb_fname);
4764 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4765 data_size = 26;
4766 srv_put_dos_date2(pdata,0,create_time);
4767 srv_put_dos_date2(pdata,4,atime);
4768 srv_put_dos_date2(pdata,8,mtime); /* write time */
4769 SIVAL(pdata,12,(uint32_t)file_size);
4770 SIVAL(pdata,16,(uint32_t)allocation_size);
4771 SSVAL(pdata,20,mode);
4772 SIVAL(pdata,22,ea_size);
4773 break;
4776 case SMB_INFO_IS_NAME_VALID:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4778 if (fsp) {
4779 /* os/2 needs this ? really ?*/
4780 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4782 /* This is only reached for qpathinfo */
4783 data_size = 0;
4784 break;
4786 case SMB_INFO_QUERY_EAS_FROM_LIST:
4788 size_t total_ea_len = 0;
4789 struct ea_list *ea_file_list = NULL;
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4792 status =
4793 get_ea_list_from_file(mem_ctx, conn, fsp,
4794 smb_fname,
4795 &total_ea_len, &ea_file_list);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 return status;
4800 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4802 if (!ea_list || (total_ea_len > data_size)) {
4803 data_size = 4;
4804 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4805 break;
4808 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4809 break;
4812 case SMB_INFO_QUERY_ALL_EAS:
4814 /* We have data_size bytes to put EA's into. */
4815 size_t total_ea_len = 0;
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4818 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4819 smb_fname,
4820 &total_ea_len, &ea_list);
4821 if (!NT_STATUS_IS_OK(status)) {
4822 return status;
4825 if (!ea_list || (total_ea_len > data_size)) {
4826 data_size = 4;
4827 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4828 break;
4831 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4832 break;
4835 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4837 /* This is FileFullEaInformation - 0xF which maps to
4838 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4840 /* We have data_size bytes to put EA's into. */
4841 size_t total_ea_len = 0;
4842 struct ea_list *ea_file_list = NULL;
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4846 /*TODO: add filtering and index handling */
4848 status =
4849 get_ea_list_from_file(mem_ctx, conn, fsp,
4850 smb_fname,
4851 &total_ea_len, &ea_file_list);
4852 if (!NT_STATUS_IS_OK(status)) {
4853 return status;
4855 if (!ea_file_list) {
4856 return NT_STATUS_NO_EAS_ON_FILE;
4859 status = fill_ea_chained_buffer(mem_ctx,
4860 pdata,
4861 data_size,
4862 &data_size,
4863 conn, ea_file_list);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 return status;
4867 break;
4870 case SMB_FILE_BASIC_INFORMATION:
4871 case SMB_QUERY_FILE_BASIC_INFO:
4873 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4874 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4875 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4876 } else {
4877 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4878 data_size = 40;
4879 SIVAL(pdata,36,0);
4881 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4882 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4883 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4884 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4885 SIVAL(pdata,32,mode);
4887 DEBUG(5,("SMB_QFBI - "));
4888 DEBUG(5,("create: %s ", ctime(&create_time)));
4889 DEBUG(5,("access: %s ", ctime(&atime)));
4890 DEBUG(5,("write: %s ", ctime(&mtime)));
4891 DEBUG(5,("change: %s ", ctime(&c_time)));
4892 DEBUG(5,("mode: %x\n", mode));
4893 *fixed_portion = data_size;
4894 break;
4896 case SMB_FILE_STANDARD_INFORMATION:
4897 case SMB_QUERY_FILE_STANDARD_INFO:
4899 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4900 data_size = 24;
4901 SOFF_T(pdata,0,allocation_size);
4902 SOFF_T(pdata,8,file_size);
4903 SIVAL(pdata,16,nlink);
4904 SCVAL(pdata,20,delete_pending?1:0);
4905 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4906 SSVAL(pdata,22,0); /* Padding. */
4907 *fixed_portion = 24;
4908 break;
4910 case SMB_FILE_EA_INFORMATION:
4911 case SMB_QUERY_FILE_EA_INFO:
4913 unsigned int ea_size =
4914 estimate_ea_size(conn, fsp, smb_fname);
4915 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4916 data_size = 4;
4917 *fixed_portion = 4;
4918 SIVAL(pdata,0,ea_size);
4919 break;
4922 /* Get the 8.3 name - used if NT SMB was negotiated. */
4923 case SMB_QUERY_FILE_ALT_NAME_INFO:
4924 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4926 char mangled_name[13];
4927 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4928 if (!name_to_8_3(base_name,mangled_name,
4929 True,conn->params)) {
4930 return NT_STATUS_NO_MEMORY;
4932 status = srvstr_push(dstart, flags2,
4933 pdata+4, mangled_name,
4934 PTR_DIFF(dend, pdata+4),
4935 STR_UNICODE, &len);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 return status;
4939 data_size = 4 + len;
4940 SIVAL(pdata,0,len);
4941 *fixed_portion = 8;
4942 break;
4945 case SMB_QUERY_FILE_NAME_INFO:
4948 this must be *exactly* right for ACLs on mapped drives to work
4950 status = srvstr_push(dstart, flags2,
4951 pdata+4, dos_fname,
4952 PTR_DIFF(dend, pdata+4),
4953 STR_UNICODE, &len);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 return status;
4957 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4958 data_size = 4 + len;
4959 SIVAL(pdata,0,len);
4960 break;
4963 case SMB_FILE_ALLOCATION_INFORMATION:
4964 case SMB_QUERY_FILE_ALLOCATION_INFO:
4965 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4966 data_size = 8;
4967 SOFF_T(pdata,0,allocation_size);
4968 break;
4970 case SMB_FILE_END_OF_FILE_INFORMATION:
4971 case SMB_QUERY_FILE_END_OF_FILEINFO:
4972 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4973 data_size = 8;
4974 SOFF_T(pdata,0,file_size);
4975 break;
4977 case SMB_QUERY_FILE_ALL_INFO:
4978 case SMB_FILE_ALL_INFORMATION:
4980 unsigned int ea_size =
4981 estimate_ea_size(conn, fsp, smb_fname);
4982 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4983 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4984 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4985 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4986 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4987 SIVAL(pdata,32,mode);
4988 SIVAL(pdata,36,0); /* padding. */
4989 pdata += 40;
4990 SOFF_T(pdata,0,allocation_size);
4991 SOFF_T(pdata,8,file_size);
4992 SIVAL(pdata,16,nlink);
4993 SCVAL(pdata,20,delete_pending);
4994 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4995 SSVAL(pdata,22,0);
4996 pdata += 24;
4997 SIVAL(pdata,0,ea_size);
4998 pdata += 4; /* EA info */
4999 status = srvstr_push(dstart, flags2,
5000 pdata+4, dos_fname,
5001 PTR_DIFF(dend, pdata+4),
5002 STR_UNICODE, &len);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 return status;
5006 SIVAL(pdata,0,len);
5007 pdata += 4 + len;
5008 data_size = PTR_DIFF(pdata,(*ppdata));
5009 *fixed_portion = 10;
5010 break;
5013 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5015 unsigned int ea_size =
5016 estimate_ea_size(conn, fsp, smb_fname);
5017 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5018 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5019 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5020 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5021 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5022 SIVAL(pdata, 0x20, mode);
5023 SIVAL(pdata, 0x24, 0); /* padding. */
5024 SBVAL(pdata, 0x28, allocation_size);
5025 SBVAL(pdata, 0x30, file_size);
5026 SIVAL(pdata, 0x38, nlink);
5027 SCVAL(pdata, 0x3C, delete_pending);
5028 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5029 SSVAL(pdata, 0x3E, 0); /* padding */
5030 SBVAL(pdata, 0x40, file_index);
5031 SIVAL(pdata, 0x48, ea_size);
5032 SIVAL(pdata, 0x4C, access_mask);
5033 SBVAL(pdata, 0x50, pos);
5034 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5035 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5037 pdata += 0x60;
5039 status = srvstr_push(dstart, flags2,
5040 pdata+4, dos_fname,
5041 PTR_DIFF(dend, pdata+4),
5042 STR_UNICODE, &len);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 return status;
5046 SIVAL(pdata,0,len);
5047 pdata += 4 + len;
5048 data_size = PTR_DIFF(pdata,(*ppdata));
5049 *fixed_portion = 104;
5050 break;
5052 case SMB_FILE_INTERNAL_INFORMATION:
5054 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5055 SBVAL(pdata, 0, file_index);
5056 data_size = 8;
5057 *fixed_portion = 8;
5058 break;
5060 case SMB_FILE_ACCESS_INFORMATION:
5061 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5062 SIVAL(pdata, 0, access_mask);
5063 data_size = 4;
5064 *fixed_portion = 4;
5065 break;
5067 case SMB_FILE_NAME_INFORMATION:
5068 /* Pathname with leading '\'. */
5070 size_t byte_len;
5071 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5072 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5073 SIVAL(pdata,0,byte_len);
5074 data_size = 4 + byte_len;
5075 break;
5078 case SMB_FILE_DISPOSITION_INFORMATION:
5079 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5080 data_size = 1;
5081 SCVAL(pdata,0,delete_pending);
5082 *fixed_portion = 1;
5083 break;
5085 case SMB_FILE_POSITION_INFORMATION:
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5087 data_size = 8;
5088 SOFF_T(pdata,0,pos);
5089 *fixed_portion = 8;
5090 break;
5092 case SMB_FILE_MODE_INFORMATION:
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5094 SIVAL(pdata,0,mode);
5095 data_size = 4;
5096 *fixed_portion = 4;
5097 break;
5099 case SMB_FILE_ALIGNMENT_INFORMATION:
5100 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5101 SIVAL(pdata,0,0); /* No alignment needed. */
5102 data_size = 4;
5103 *fixed_portion = 4;
5104 break;
5107 * NT4 server just returns "invalid query" to this - if we try
5108 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5109 * want this. JRA.
5111 /* The first statement above is false - verified using Thursby
5112 * client against NT4 -- gcolley.
5114 case SMB_QUERY_FILE_STREAM_INFO:
5115 case SMB_FILE_STREAM_INFORMATION: {
5116 unsigned int num_streams = 0;
5117 struct stream_struct *streams = NULL;
5119 DEBUG(10,("smbd_do_qfilepathinfo: "
5120 "SMB_FILE_STREAM_INFORMATION\n"));
5122 if (is_ntfs_stream_smb_fname(smb_fname)) {
5123 return NT_STATUS_INVALID_PARAMETER;
5126 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5127 talloc_tos(), &num_streams, &streams);
5129 if (!NT_STATUS_IS_OK(status)) {
5130 DEBUG(10, ("could not get stream info: %s\n",
5131 nt_errstr(status)));
5132 return status;
5135 status = marshall_stream_info(num_streams, streams,
5136 pdata, max_data_bytes,
5137 &data_size);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 DEBUG(10, ("marshall_stream_info failed: %s\n",
5141 nt_errstr(status)));
5142 TALLOC_FREE(streams);
5143 return status;
5146 TALLOC_FREE(streams);
5148 *fixed_portion = 32;
5150 break;
5152 case SMB_QUERY_COMPRESSION_INFO:
5153 case SMB_FILE_COMPRESSION_INFORMATION:
5154 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5155 SOFF_T(pdata,0,file_size);
5156 SIVAL(pdata,8,0); /* ??? */
5157 SIVAL(pdata,12,0); /* ??? */
5158 data_size = 16;
5159 *fixed_portion = 16;
5160 break;
5162 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5164 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5165 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5166 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5167 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5168 SOFF_T(pdata,32,allocation_size);
5169 SOFF_T(pdata,40,file_size);
5170 SIVAL(pdata,48,mode);
5171 SIVAL(pdata,52,0); /* ??? */
5172 data_size = 56;
5173 *fixed_portion = 56;
5174 break;
5176 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5177 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5178 SIVAL(pdata,0,mode);
5179 SIVAL(pdata,4,0);
5180 data_size = 8;
5181 *fixed_portion = 8;
5182 break;
5185 * CIFS UNIX Extensions.
5188 case SMB_QUERY_FILE_UNIX_BASIC:
5190 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5191 data_size = PTR_DIFF(pdata,(*ppdata));
5193 DEBUG(4,("smbd_do_qfilepathinfo: "
5194 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5195 dump_data(4, (uint8_t *)(*ppdata), data_size);
5197 break;
5199 case SMB_QUERY_FILE_UNIX_INFO2:
5201 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5202 data_size = PTR_DIFF(pdata,(*ppdata));
5205 int i;
5206 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5208 for (i=0; i<100; i++)
5209 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5210 DEBUG(4,("\n"));
5213 break;
5215 case SMB_QUERY_FILE_UNIX_LINK:
5217 int link_len = 0;
5218 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5220 if (!buffer) {
5221 return NT_STATUS_NO_MEMORY;
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5225 #ifdef S_ISLNK
5226 if(!S_ISLNK(psbuf->st_ex_mode)) {
5227 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5229 #else
5230 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5231 #endif
5232 link_len = SMB_VFS_READLINK(conn,
5233 smb_fname->base_name,
5234 buffer, PATH_MAX);
5235 if (link_len == -1) {
5236 return map_nt_error_from_unix(errno);
5238 buffer[link_len] = 0;
5239 status = srvstr_push(dstart, flags2,
5240 pdata, buffer,
5241 PTR_DIFF(dend, pdata),
5242 STR_TERMINATE, &len);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 return status;
5246 pdata += len;
5247 data_size = PTR_DIFF(pdata,(*ppdata));
5249 break;
5252 #if defined(HAVE_POSIX_ACLS)
5253 case SMB_QUERY_POSIX_ACL:
5255 SMB_ACL_T file_acl = NULL;
5256 SMB_ACL_T def_acl = NULL;
5257 uint16_t num_file_acls = 0;
5258 uint16_t num_def_acls = 0;
5260 if (fsp && fsp->fh->fd != -1) {
5261 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5262 talloc_tos());
5263 } else {
5264 file_acl =
5265 SMB_VFS_SYS_ACL_GET_FILE(conn,
5266 smb_fname->base_name,
5267 SMB_ACL_TYPE_ACCESS,
5268 talloc_tos());
5271 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5272 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5273 "not implemented on "
5274 "filesystem containing %s\n",
5275 smb_fname->base_name));
5276 return NT_STATUS_NOT_IMPLEMENTED;
5279 if (S_ISDIR(psbuf->st_ex_mode)) {
5280 if (fsp && fsp->is_directory) {
5281 def_acl =
5282 SMB_VFS_SYS_ACL_GET_FILE(
5283 conn,
5284 fsp->fsp_name->base_name,
5285 SMB_ACL_TYPE_DEFAULT,
5286 talloc_tos());
5287 } else {
5288 def_acl =
5289 SMB_VFS_SYS_ACL_GET_FILE(
5290 conn,
5291 smb_fname->base_name,
5292 SMB_ACL_TYPE_DEFAULT,
5293 talloc_tos());
5295 def_acl = free_empty_sys_acl(conn, def_acl);
5298 num_file_acls = count_acl_entries(conn, file_acl);
5299 num_def_acls = count_acl_entries(conn, def_acl);
5301 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5302 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5303 data_size,
5304 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5305 SMB_POSIX_ACL_HEADER_SIZE) ));
5306 if (file_acl) {
5307 TALLOC_FREE(file_acl);
5309 if (def_acl) {
5310 TALLOC_FREE(def_acl);
5312 return NT_STATUS_BUFFER_TOO_SMALL;
5315 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5316 SSVAL(pdata,2,num_file_acls);
5317 SSVAL(pdata,4,num_def_acls);
5318 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5319 if (file_acl) {
5320 TALLOC_FREE(file_acl);
5322 if (def_acl) {
5323 TALLOC_FREE(def_acl);
5325 return NT_STATUS_INTERNAL_ERROR;
5327 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5328 if (file_acl) {
5329 TALLOC_FREE(file_acl);
5331 if (def_acl) {
5332 TALLOC_FREE(def_acl);
5334 return NT_STATUS_INTERNAL_ERROR;
5337 if (file_acl) {
5338 TALLOC_FREE(file_acl);
5340 if (def_acl) {
5341 TALLOC_FREE(def_acl);
5343 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5344 break;
5346 #endif
5349 case SMB_QUERY_POSIX_LOCK:
5351 uint64_t count;
5352 uint64_t offset;
5353 uint64_t smblctx;
5354 enum brl_type lock_type;
5356 /* We need an open file with a real fd for this. */
5357 if (!fsp || fsp->fh->fd == -1) {
5358 return NT_STATUS_INVALID_LEVEL;
5361 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5362 return NT_STATUS_INVALID_PARAMETER;
5365 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5366 case POSIX_LOCK_TYPE_READ:
5367 lock_type = READ_LOCK;
5368 break;
5369 case POSIX_LOCK_TYPE_WRITE:
5370 lock_type = WRITE_LOCK;
5371 break;
5372 case POSIX_LOCK_TYPE_UNLOCK:
5373 default:
5374 /* There's no point in asking for an unlock... */
5375 return NT_STATUS_INVALID_PARAMETER;
5378 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5379 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5380 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5382 status = query_lock(fsp,
5383 &smblctx,
5384 &count,
5385 &offset,
5386 &lock_type,
5387 POSIX_LOCK);
5389 if (ERROR_WAS_LOCK_DENIED(status)) {
5390 /* Here we need to report who has it locked... */
5391 data_size = POSIX_LOCK_DATA_SIZE;
5393 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5394 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5395 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5396 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5397 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5399 } else if (NT_STATUS_IS_OK(status)) {
5400 /* For success we just return a copy of what we sent
5401 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5402 data_size = POSIX_LOCK_DATA_SIZE;
5403 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5404 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5405 } else {
5406 return status;
5408 break;
5411 default:
5412 return NT_STATUS_INVALID_LEVEL;
5415 *pdata_size = data_size;
5416 return NT_STATUS_OK;
5419 /****************************************************************************
5420 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5421 file name or file id).
5422 ****************************************************************************/
5424 static void call_trans2qfilepathinfo(connection_struct *conn,
5425 struct smb_request *req,
5426 unsigned int tran_call,
5427 char **pparams, int total_params,
5428 char **ppdata, int total_data,
5429 unsigned int max_data_bytes)
5431 char *params = *pparams;
5432 char *pdata = *ppdata;
5433 uint16_t info_level;
5434 unsigned int data_size = 0;
5435 unsigned int param_size = 2;
5436 struct smb_filename *smb_fname = NULL;
5437 bool delete_pending = False;
5438 struct timespec write_time_ts;
5439 files_struct *fsp = NULL;
5440 struct file_id fileid;
5441 struct ea_list *ea_list = NULL;
5442 int lock_data_count = 0;
5443 char *lock_data = NULL;
5444 size_t fixed_portion;
5445 NTSTATUS status = NT_STATUS_OK;
5447 if (!params) {
5448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5449 return;
5452 ZERO_STRUCT(write_time_ts);
5454 if (tran_call == TRANSACT2_QFILEINFO) {
5455 if (total_params < 4) {
5456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5457 return;
5460 if (IS_IPC(conn)) {
5461 call_trans2qpipeinfo(conn, req, tran_call,
5462 pparams, total_params,
5463 ppdata, total_data,
5464 max_data_bytes);
5465 return;
5468 fsp = file_fsp(req, SVAL(params,0));
5469 info_level = SVAL(params,2);
5471 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5473 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5475 return;
5478 /* Initial check for valid fsp ptr. */
5479 if (!check_fsp_open(conn, req, fsp)) {
5480 return;
5483 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5484 if (smb_fname == NULL) {
5485 reply_nterror(req, NT_STATUS_NO_MEMORY);
5486 return;
5489 if(fsp->fake_file_handle) {
5491 * This is actually for the QUOTA_FAKE_FILE --metze
5494 /* We know this name is ok, it's already passed the checks. */
5496 } else if(fsp->fh->fd == -1) {
5498 * This is actually a QFILEINFO on a directory
5499 * handle (returned from an NT SMB). NT5.0 seems
5500 * to do this call. JRA.
5503 if (INFO_LEVEL_IS_UNIX(info_level)) {
5504 /* Always do lstat for UNIX calls. */
5505 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5506 DEBUG(3,("call_trans2qfilepathinfo: "
5507 "SMB_VFS_LSTAT of %s failed "
5508 "(%s)\n",
5509 smb_fname_str_dbg(smb_fname),
5510 strerror(errno)));
5511 reply_nterror(req,
5512 map_nt_error_from_unix(errno));
5513 return;
5515 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5516 DEBUG(3,("call_trans2qfilepathinfo: "
5517 "SMB_VFS_STAT of %s failed (%s)\n",
5518 smb_fname_str_dbg(smb_fname),
5519 strerror(errno)));
5520 reply_nterror(req,
5521 map_nt_error_from_unix(errno));
5522 return;
5525 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5526 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5527 } else {
5529 * Original code - this is an open file.
5531 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5532 DEBUG(3, ("fstat of %s failed (%s)\n",
5533 fsp_fnum_dbg(fsp), strerror(errno)));
5534 reply_nterror(req,
5535 map_nt_error_from_unix(errno));
5536 return;
5538 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5539 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5542 } else {
5543 uint32_t name_hash;
5544 char *fname = NULL;
5545 uint32_t ucf_flags = 0;
5547 /* qpathinfo */
5548 if (total_params < 7) {
5549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5550 return;
5553 info_level = SVAL(params,0);
5555 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5557 if (INFO_LEVEL_IS_UNIX(info_level)) {
5558 if (!lp_unix_extensions()) {
5559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5560 return;
5562 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5563 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5564 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5565 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5569 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5570 total_params - 6,
5571 STR_TERMINATE, &status);
5572 if (!NT_STATUS_IS_OK(status)) {
5573 reply_nterror(req, status);
5574 return;
5577 status = filename_convert(req,
5578 conn,
5579 req->flags2 & FLAGS2_DFS_PATHNAMES,
5580 fname,
5581 ucf_flags,
5582 NULL,
5583 &smb_fname);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5586 reply_botherror(req,
5587 NT_STATUS_PATH_NOT_COVERED,
5588 ERRSRV, ERRbadpath);
5589 return;
5591 reply_nterror(req, status);
5592 return;
5595 /* If this is a stream, check if there is a delete_pending. */
5596 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5597 && is_ntfs_stream_smb_fname(smb_fname)) {
5598 struct smb_filename *smb_fname_base;
5600 /* Create an smb_filename with stream_name == NULL. */
5601 smb_fname_base = synthetic_smb_fname(
5602 talloc_tos(), smb_fname->base_name,
5603 NULL, NULL);
5604 if (smb_fname_base == NULL) {
5605 reply_nterror(req, NT_STATUS_NO_MEMORY);
5606 return;
5609 if (INFO_LEVEL_IS_UNIX(info_level)) {
5610 /* Always do lstat for UNIX calls. */
5611 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5612 DEBUG(3,("call_trans2qfilepathinfo: "
5613 "SMB_VFS_LSTAT of %s failed "
5614 "(%s)\n",
5615 smb_fname_str_dbg(smb_fname_base),
5616 strerror(errno)));
5617 TALLOC_FREE(smb_fname_base);
5618 reply_nterror(req,
5619 map_nt_error_from_unix(errno));
5620 return;
5622 } else {
5623 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5624 DEBUG(3,("call_trans2qfilepathinfo: "
5625 "fileinfo of %s failed "
5626 "(%s)\n",
5627 smb_fname_str_dbg(smb_fname_base),
5628 strerror(errno)));
5629 TALLOC_FREE(smb_fname_base);
5630 reply_nterror(req,
5631 map_nt_error_from_unix(errno));
5632 return;
5636 status = file_name_hash(conn,
5637 smb_fname_str_dbg(smb_fname_base),
5638 &name_hash);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 TALLOC_FREE(smb_fname_base);
5641 reply_nterror(req, status);
5642 return;
5645 fileid = vfs_file_id_from_sbuf(conn,
5646 &smb_fname_base->st);
5647 TALLOC_FREE(smb_fname_base);
5648 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5649 if (delete_pending) {
5650 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5651 return;
5655 if (INFO_LEVEL_IS_UNIX(info_level)) {
5656 /* Always do lstat for UNIX calls. */
5657 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5658 DEBUG(3,("call_trans2qfilepathinfo: "
5659 "SMB_VFS_LSTAT of %s failed (%s)\n",
5660 smb_fname_str_dbg(smb_fname),
5661 strerror(errno)));
5662 reply_nterror(req,
5663 map_nt_error_from_unix(errno));
5664 return;
5667 } else {
5668 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5669 DEBUG(3,("call_trans2qfilepathinfo: "
5670 "SMB_VFS_STAT of %s failed (%s)\n",
5671 smb_fname_str_dbg(smb_fname),
5672 strerror(errno)));
5673 reply_nterror(req,
5674 map_nt_error_from_unix(errno));
5675 return;
5679 status = file_name_hash(conn,
5680 smb_fname_str_dbg(smb_fname),
5681 &name_hash);
5682 if (!NT_STATUS_IS_OK(status)) {
5683 reply_nterror(req, status);
5684 return;
5687 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5688 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5689 if (delete_pending) {
5690 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5691 return;
5695 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5696 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5697 fsp_fnum_dbg(fsp),
5698 info_level,tran_call,total_data));
5700 /* Pull out any data sent here before we realloc. */
5701 switch (info_level) {
5702 case SMB_INFO_QUERY_EAS_FROM_LIST:
5704 /* Pull any EA list from the data portion. */
5705 uint32_t ea_size;
5707 if (total_data < 4) {
5708 reply_nterror(
5709 req, NT_STATUS_INVALID_PARAMETER);
5710 return;
5712 ea_size = IVAL(pdata,0);
5714 if (total_data > 0 && ea_size != total_data) {
5715 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5716 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5717 reply_nterror(
5718 req, NT_STATUS_INVALID_PARAMETER);
5719 return;
5722 if (!lp_ea_support(SNUM(conn))) {
5723 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5724 return;
5727 /* Pull out the list of names. */
5728 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5729 if (!ea_list) {
5730 reply_nterror(
5731 req, NT_STATUS_INVALID_PARAMETER);
5732 return;
5734 break;
5737 case SMB_QUERY_POSIX_LOCK:
5739 if (fsp == NULL || fsp->fh->fd == -1) {
5740 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5741 return;
5744 if (total_data != POSIX_LOCK_DATA_SIZE) {
5745 reply_nterror(
5746 req, NT_STATUS_INVALID_PARAMETER);
5747 return;
5750 /* Copy the lock range data. */
5751 lock_data = (char *)talloc_memdup(
5752 req, pdata, total_data);
5753 if (!lock_data) {
5754 reply_nterror(req, NT_STATUS_NO_MEMORY);
5755 return;
5757 lock_data_count = total_data;
5759 default:
5760 break;
5763 *pparams = (char *)SMB_REALLOC(*pparams,2);
5764 if (*pparams == NULL) {
5765 reply_nterror(req, NT_STATUS_NO_MEMORY);
5766 return;
5768 params = *pparams;
5769 SSVAL(params,0,0);
5772 * draft-leach-cifs-v1-spec-02.txt
5773 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5774 * says:
5776 * The requested information is placed in the Data portion of the
5777 * transaction response. For the information levels greater than 0x100,
5778 * the transaction response has 1 parameter word which should be
5779 * ignored by the client.
5781 * However Windows only follows this rule for the IS_NAME_VALID call.
5783 switch (info_level) {
5784 case SMB_INFO_IS_NAME_VALID:
5785 param_size = 0;
5786 break;
5789 if ((info_level & 0xFF00) == 0xFF00) {
5791 * We use levels that start with 0xFF00
5792 * internally to represent SMB2 specific levels
5794 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5795 return;
5798 status = smbd_do_qfilepathinfo(conn, req, info_level,
5799 fsp, smb_fname,
5800 delete_pending, write_time_ts,
5801 ea_list,
5802 lock_data_count, lock_data,
5803 req->flags2, max_data_bytes,
5804 &fixed_portion,
5805 ppdata, &data_size);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 reply_nterror(req, status);
5808 return;
5810 if (fixed_portion > max_data_bytes) {
5811 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5812 return;
5815 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5816 max_data_bytes);
5818 return;
5821 /****************************************************************************
5822 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5823 code.
5824 ****************************************************************************/
5826 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5827 connection_struct *conn,
5828 struct smb_request *req,
5829 bool overwrite_if_exists,
5830 const struct smb_filename *smb_fname_old,
5831 struct smb_filename *smb_fname_new)
5833 NTSTATUS status = NT_STATUS_OK;
5835 /* source must already exist. */
5836 if (!VALID_STAT(smb_fname_old->st)) {
5837 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5840 if (VALID_STAT(smb_fname_new->st)) {
5841 if (overwrite_if_exists) {
5842 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5843 return NT_STATUS_FILE_IS_A_DIRECTORY;
5845 status = unlink_internals(conn,
5846 req,
5847 FILE_ATTRIBUTE_NORMAL,
5848 smb_fname_new,
5849 false);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 return status;
5853 } else {
5854 /* Disallow if newname already exists. */
5855 return NT_STATUS_OBJECT_NAME_COLLISION;
5859 /* No links from a directory. */
5860 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5861 return NT_STATUS_FILE_IS_A_DIRECTORY;
5864 /* Setting a hardlink to/from a stream isn't currently supported. */
5865 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5866 is_ntfs_stream_smb_fname(smb_fname_new)) {
5867 return NT_STATUS_INVALID_PARAMETER;
5870 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5871 smb_fname_old->base_name, smb_fname_new->base_name));
5873 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5874 smb_fname_new->base_name) != 0) {
5875 status = map_nt_error_from_unix(errno);
5876 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5877 nt_errstr(status), smb_fname_old->base_name,
5878 smb_fname_new->base_name));
5880 return status;
5883 /****************************************************************************
5884 Deal with setting the time from any of the setfilepathinfo functions.
5885 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5886 calling this function.
5887 ****************************************************************************/
5889 NTSTATUS smb_set_file_time(connection_struct *conn,
5890 files_struct *fsp,
5891 const struct smb_filename *smb_fname,
5892 struct smb_file_time *ft,
5893 bool setting_write_time)
5895 struct smb_filename smb_fname_base;
5896 uint32_t action =
5897 FILE_NOTIFY_CHANGE_LAST_ACCESS
5898 |FILE_NOTIFY_CHANGE_LAST_WRITE
5899 |FILE_NOTIFY_CHANGE_CREATION;
5901 if (!VALID_STAT(smb_fname->st)) {
5902 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5905 /* get some defaults (no modifications) if any info is zero or -1. */
5906 if (null_timespec(ft->create_time)) {
5907 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5910 if (null_timespec(ft->atime)) {
5911 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5914 if (null_timespec(ft->mtime)) {
5915 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5918 if (!setting_write_time) {
5919 /* ft->mtime comes from change time, not write time. */
5920 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5923 /* Ensure the resolution is the correct for
5924 * what we can store on this filesystem. */
5926 round_timespec(conn->ts_res, &ft->create_time);
5927 round_timespec(conn->ts_res, &ft->ctime);
5928 round_timespec(conn->ts_res, &ft->atime);
5929 round_timespec(conn->ts_res, &ft->mtime);
5931 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5932 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5933 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5934 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5935 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5936 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5937 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5938 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5940 if (setting_write_time) {
5942 * This was a Windows setfileinfo on an open file.
5943 * NT does this a lot. We also need to
5944 * set the time here, as it can be read by
5945 * FindFirst/FindNext and with the patch for bug #2045
5946 * in smbd/fileio.c it ensures that this timestamp is
5947 * kept sticky even after a write. We save the request
5948 * away and will set it on file close and after a write. JRA.
5951 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5952 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5954 if (fsp != NULL) {
5955 if (fsp->base_fsp) {
5956 set_sticky_write_time_fsp(fsp->base_fsp,
5957 ft->mtime);
5958 } else {
5959 set_sticky_write_time_fsp(fsp, ft->mtime);
5961 } else {
5962 set_sticky_write_time_path(
5963 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5964 ft->mtime);
5968 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5970 /* Always call ntimes on the base, even if a stream was passed in. */
5971 smb_fname_base = *smb_fname;
5972 smb_fname_base.stream_name = NULL;
5974 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5975 return map_nt_error_from_unix(errno);
5978 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5979 smb_fname->base_name);
5980 return NT_STATUS_OK;
5983 /****************************************************************************
5984 Deal with setting the dosmode from any of the setfilepathinfo functions.
5985 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5986 done before calling this function.
5987 ****************************************************************************/
5989 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5990 const struct smb_filename *smb_fname,
5991 uint32_t dosmode)
5993 struct smb_filename *smb_fname_base;
5994 NTSTATUS status;
5996 if (!VALID_STAT(smb_fname->st)) {
5997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6000 /* Always operate on the base_name, even if a stream was passed in. */
6001 smb_fname_base = synthetic_smb_fname(
6002 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
6003 if (smb_fname_base == NULL) {
6004 return NT_STATUS_NO_MEMORY;
6007 if (dosmode) {
6008 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6009 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6010 } else {
6011 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6015 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6017 /* check the mode isn't different, before changing it */
6018 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6019 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6020 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6021 (unsigned int)dosmode));
6023 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6024 false)) {
6025 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6026 "%s failed (%s)\n",
6027 smb_fname_str_dbg(smb_fname_base),
6028 strerror(errno)));
6029 status = map_nt_error_from_unix(errno);
6030 goto out;
6033 status = NT_STATUS_OK;
6034 out:
6035 TALLOC_FREE(smb_fname_base);
6036 return status;
6039 /****************************************************************************
6040 Deal with setting the size from any of the setfilepathinfo functions.
6041 ****************************************************************************/
6043 static NTSTATUS smb_set_file_size(connection_struct *conn,
6044 struct smb_request *req,
6045 files_struct *fsp,
6046 const struct smb_filename *smb_fname,
6047 const SMB_STRUCT_STAT *psbuf,
6048 off_t size,
6049 bool fail_after_createfile)
6051 NTSTATUS status = NT_STATUS_OK;
6052 struct smb_filename *smb_fname_tmp = NULL;
6053 files_struct *new_fsp = NULL;
6055 if (!VALID_STAT(*psbuf)) {
6056 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6059 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6061 if (size == get_file_size_stat(psbuf)) {
6062 return NT_STATUS_OK;
6065 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6066 smb_fname_str_dbg(smb_fname), (double)size));
6068 if (fsp && fsp->fh->fd != -1) {
6069 /* Handle based call. */
6070 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6071 return NT_STATUS_ACCESS_DENIED;
6074 if (vfs_set_filelen(fsp, size) == -1) {
6075 return map_nt_error_from_unix(errno);
6077 trigger_write_time_update_immediate(fsp);
6078 return NT_STATUS_OK;
6081 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6082 if (smb_fname_tmp == NULL) {
6083 return NT_STATUS_NO_MEMORY;
6086 smb_fname_tmp->st = *psbuf;
6088 status = SMB_VFS_CREATE_FILE(
6089 conn, /* conn */
6090 req, /* req */
6091 0, /* root_dir_fid */
6092 smb_fname_tmp, /* fname */
6093 FILE_WRITE_DATA, /* access_mask */
6094 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6095 FILE_SHARE_DELETE),
6096 FILE_OPEN, /* create_disposition*/
6097 0, /* create_options */
6098 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6099 0, /* oplock_request */
6100 NULL, /* lease */
6101 0, /* allocation_size */
6102 0, /* private_flags */
6103 NULL, /* sd */
6104 NULL, /* ea_list */
6105 &new_fsp, /* result */
6106 NULL, /* pinfo */
6107 NULL, NULL); /* create context */
6109 TALLOC_FREE(smb_fname_tmp);
6111 if (!NT_STATUS_IS_OK(status)) {
6112 /* NB. We check for open_was_deferred in the caller. */
6113 return status;
6116 /* See RAW-SFILEINFO-END-OF-FILE */
6117 if (fail_after_createfile) {
6118 close_file(req, new_fsp,NORMAL_CLOSE);
6119 return NT_STATUS_INVALID_LEVEL;
6122 if (vfs_set_filelen(new_fsp, size) == -1) {
6123 status = map_nt_error_from_unix(errno);
6124 close_file(req, new_fsp,NORMAL_CLOSE);
6125 return status;
6128 trigger_write_time_update_immediate(new_fsp);
6129 close_file(req, new_fsp,NORMAL_CLOSE);
6130 return NT_STATUS_OK;
6133 /****************************************************************************
6134 Deal with SMB_INFO_SET_EA.
6135 ****************************************************************************/
6137 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6138 const char *pdata,
6139 int total_data,
6140 files_struct *fsp,
6141 const struct smb_filename *smb_fname)
6143 struct ea_list *ea_list = NULL;
6144 TALLOC_CTX *ctx = NULL;
6145 NTSTATUS status = NT_STATUS_OK;
6147 if (total_data < 10) {
6149 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6150 length. They seem to have no effect. Bug #3212. JRA */
6152 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6153 /* We're done. We only get EA info in this call. */
6154 return NT_STATUS_OK;
6157 return NT_STATUS_INVALID_PARAMETER;
6160 if (IVAL(pdata,0) > total_data) {
6161 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6162 IVAL(pdata,0), (unsigned int)total_data));
6163 return NT_STATUS_INVALID_PARAMETER;
6166 ctx = talloc_tos();
6167 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6168 if (!ea_list) {
6169 return NT_STATUS_INVALID_PARAMETER;
6172 status = set_ea(conn, fsp, smb_fname, ea_list);
6174 return status;
6177 /****************************************************************************
6178 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6179 ****************************************************************************/
6181 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6182 const char *pdata,
6183 int total_data,
6184 files_struct *fsp)
6186 struct ea_list *ea_list = NULL;
6187 NTSTATUS status;
6189 if (!fsp) {
6190 return NT_STATUS_INVALID_HANDLE;
6193 if (!lp_ea_support(SNUM(conn))) {
6194 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6195 "EA's not supported.\n",
6196 (unsigned int)total_data));
6197 return NT_STATUS_EAS_NOT_SUPPORTED;
6200 if (total_data < 10) {
6201 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6202 "too small.\n",
6203 (unsigned int)total_data));
6204 return NT_STATUS_INVALID_PARAMETER;
6207 ea_list = read_nttrans_ea_list(talloc_tos(),
6208 pdata,
6209 total_data);
6211 if (!ea_list) {
6212 return NT_STATUS_INVALID_PARAMETER;
6215 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6217 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6218 smb_fname_str_dbg(fsp->fsp_name),
6219 nt_errstr(status) ));
6221 return status;
6225 /****************************************************************************
6226 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6227 ****************************************************************************/
6229 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6230 const char *pdata,
6231 int total_data,
6232 files_struct *fsp,
6233 struct smb_filename *smb_fname)
6235 NTSTATUS status = NT_STATUS_OK;
6236 bool delete_on_close;
6237 uint32_t dosmode = 0;
6239 if (total_data < 1) {
6240 return NT_STATUS_INVALID_PARAMETER;
6243 if (fsp == NULL) {
6244 return NT_STATUS_INVALID_HANDLE;
6247 delete_on_close = (CVAL(pdata,0) ? True : False);
6248 dosmode = dos_mode(conn, smb_fname);
6250 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6251 "delete_on_close = %u\n",
6252 smb_fname_str_dbg(smb_fname),
6253 (unsigned int)dosmode,
6254 (unsigned int)delete_on_close ));
6256 if (delete_on_close) {
6257 status = can_set_delete_on_close(fsp, dosmode);
6258 if (!NT_STATUS_IS_OK(status)) {
6259 return status;
6263 /* The set is across all open files on this dev/inode pair. */
6264 if (!set_delete_on_close(fsp, delete_on_close,
6265 conn->session_info->security_token,
6266 conn->session_info->unix_token)) {
6267 return NT_STATUS_ACCESS_DENIED;
6269 return NT_STATUS_OK;
6272 /****************************************************************************
6273 Deal with SMB_FILE_POSITION_INFORMATION.
6274 ****************************************************************************/
6276 static NTSTATUS smb_file_position_information(connection_struct *conn,
6277 const char *pdata,
6278 int total_data,
6279 files_struct *fsp)
6281 uint64_t position_information;
6283 if (total_data < 8) {
6284 return NT_STATUS_INVALID_PARAMETER;
6287 if (fsp == NULL) {
6288 /* Ignore on pathname based set. */
6289 return NT_STATUS_OK;
6292 position_information = (uint64_t)IVAL(pdata,0);
6293 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6295 DEBUG(10,("smb_file_position_information: Set file position "
6296 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6297 (double)position_information));
6298 fsp->fh->position_information = position_information;
6299 return NT_STATUS_OK;
6302 /****************************************************************************
6303 Deal with SMB_FILE_MODE_INFORMATION.
6304 ****************************************************************************/
6306 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6307 const char *pdata,
6308 int total_data)
6310 uint32_t mode;
6312 if (total_data < 4) {
6313 return NT_STATUS_INVALID_PARAMETER;
6315 mode = IVAL(pdata,0);
6316 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6317 return NT_STATUS_INVALID_PARAMETER;
6319 return NT_STATUS_OK;
6322 /****************************************************************************
6323 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6324 ****************************************************************************/
6326 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6327 struct smb_request *req,
6328 const char *pdata,
6329 int total_data,
6330 const struct smb_filename *smb_fname)
6332 char *link_target = NULL;
6333 const char *newname = smb_fname->base_name;
6334 TALLOC_CTX *ctx = talloc_tos();
6336 /* Set a symbolic link. */
6337 /* Don't allow this if follow links is false. */
6339 if (total_data == 0) {
6340 return NT_STATUS_INVALID_PARAMETER;
6343 if (!lp_follow_symlinks(SNUM(conn))) {
6344 return NT_STATUS_ACCESS_DENIED;
6347 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6348 total_data, STR_TERMINATE);
6350 if (!link_target) {
6351 return NT_STATUS_INVALID_PARAMETER;
6354 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6355 newname, link_target ));
6357 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6358 return map_nt_error_from_unix(errno);
6361 return NT_STATUS_OK;
6364 /****************************************************************************
6365 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6366 ****************************************************************************/
6368 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6369 struct smb_request *req,
6370 const char *pdata, int total_data,
6371 struct smb_filename *smb_fname_new)
6373 char *oldname = NULL;
6374 struct smb_filename *smb_fname_old = NULL;
6375 TALLOC_CTX *ctx = talloc_tos();
6376 NTSTATUS status = NT_STATUS_OK;
6378 /* Set a hard link. */
6379 if (total_data == 0) {
6380 return NT_STATUS_INVALID_PARAMETER;
6383 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6384 total_data, STR_TERMINATE, &status);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 return status;
6389 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6390 smb_fname_str_dbg(smb_fname_new), oldname));
6392 status = filename_convert(ctx,
6393 conn,
6394 req->flags2 & FLAGS2_DFS_PATHNAMES,
6395 oldname,
6397 NULL,
6398 &smb_fname_old);
6399 if (!NT_STATUS_IS_OK(status)) {
6400 return status;
6403 return hardlink_internals(ctx, conn, req, false,
6404 smb_fname_old, smb_fname_new);
6407 /****************************************************************************
6408 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6409 ****************************************************************************/
6411 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6412 struct smb_request *req,
6413 const char *pdata,
6414 int total_data,
6415 files_struct *fsp,
6416 struct smb_filename *smb_fname_src)
6418 bool overwrite;
6419 uint32_t len;
6420 char *newname = NULL;
6421 struct smb_filename *smb_fname_dst = NULL;
6422 NTSTATUS status = NT_STATUS_OK;
6423 TALLOC_CTX *ctx = talloc_tos();
6425 if (!fsp) {
6426 return NT_STATUS_INVALID_HANDLE;
6429 if (total_data < 20) {
6430 return NT_STATUS_INVALID_PARAMETER;
6433 overwrite = (CVAL(pdata,0) ? True : False);
6434 len = IVAL(pdata,16);
6436 if (len > (total_data - 20) || (len == 0)) {
6437 return NT_STATUS_INVALID_PARAMETER;
6440 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6441 &pdata[20], len, STR_TERMINATE,
6442 &status);
6443 if (!NT_STATUS_IS_OK(status)) {
6444 return status;
6447 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6448 newname));
6450 status = filename_convert(ctx,
6451 conn,
6452 req->flags2 & FLAGS2_DFS_PATHNAMES,
6453 newname,
6454 UCF_SAVE_LCOMP,
6455 NULL,
6456 &smb_fname_dst);
6457 if (!NT_STATUS_IS_OK(status)) {
6458 return status;
6461 if (fsp->base_fsp) {
6462 /* newname must be a stream name. */
6463 if (newname[0] != ':') {
6464 return NT_STATUS_NOT_SUPPORTED;
6467 /* Create an smb_fname to call rename_internals_fsp() with. */
6468 smb_fname_dst = synthetic_smb_fname(
6469 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6470 newname, NULL);
6471 if (smb_fname_dst == NULL) {
6472 status = NT_STATUS_NO_MEMORY;
6473 goto out;
6477 * Set the original last component, since
6478 * rename_internals_fsp() requires it.
6480 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6481 newname);
6482 if (smb_fname_dst->original_lcomp == NULL) {
6483 status = NT_STATUS_NO_MEMORY;
6484 goto out;
6489 DEBUG(10,("smb2_file_rename_information: "
6490 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6491 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6492 smb_fname_str_dbg(smb_fname_dst)));
6493 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6494 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6495 overwrite);
6497 out:
6498 TALLOC_FREE(smb_fname_dst);
6499 return status;
6502 static NTSTATUS smb_file_link_information(connection_struct *conn,
6503 struct smb_request *req,
6504 const char *pdata,
6505 int total_data,
6506 files_struct *fsp,
6507 struct smb_filename *smb_fname_src)
6509 bool overwrite;
6510 uint32_t len;
6511 char *newname = NULL;
6512 struct smb_filename *smb_fname_dst = NULL;
6513 NTSTATUS status = NT_STATUS_OK;
6514 TALLOC_CTX *ctx = talloc_tos();
6516 if (!fsp) {
6517 return NT_STATUS_INVALID_HANDLE;
6520 if (total_data < 20) {
6521 return NT_STATUS_INVALID_PARAMETER;
6524 overwrite = (CVAL(pdata,0) ? true : false);
6525 len = IVAL(pdata,16);
6527 if (len > (total_data - 20) || (len == 0)) {
6528 return NT_STATUS_INVALID_PARAMETER;
6531 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6532 &pdata[20], len, STR_TERMINATE,
6533 &status);
6534 if (!NT_STATUS_IS_OK(status)) {
6535 return status;
6538 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6539 newname));
6541 status = filename_convert(ctx,
6542 conn,
6543 req->flags2 & FLAGS2_DFS_PATHNAMES,
6544 newname,
6545 UCF_SAVE_LCOMP,
6546 NULL,
6547 &smb_fname_dst);
6548 if (!NT_STATUS_IS_OK(status)) {
6549 return status;
6552 if (fsp->base_fsp) {
6553 /* No stream names. */
6554 return NT_STATUS_NOT_SUPPORTED;
6557 DEBUG(10,("smb_file_link_information: "
6558 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6559 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6560 smb_fname_str_dbg(smb_fname_dst)));
6561 status = hardlink_internals(ctx,
6562 conn,
6563 req,
6564 overwrite,
6565 fsp->fsp_name,
6566 smb_fname_dst);
6568 TALLOC_FREE(smb_fname_dst);
6569 return status;
6572 /****************************************************************************
6573 Deal with SMB_FILE_RENAME_INFORMATION.
6574 ****************************************************************************/
6576 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6577 struct smb_request *req,
6578 const char *pdata,
6579 int total_data,
6580 files_struct *fsp,
6581 struct smb_filename *smb_fname_src)
6583 bool overwrite;
6584 uint32_t root_fid;
6585 uint32_t len;
6586 char *newname = NULL;
6587 struct smb_filename *smb_fname_dst = NULL;
6588 bool dest_has_wcard = False;
6589 NTSTATUS status = NT_STATUS_OK;
6590 char *p;
6591 TALLOC_CTX *ctx = talloc_tos();
6593 if (total_data < 13) {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 overwrite = (CVAL(pdata,0) ? True : False);
6598 root_fid = IVAL(pdata,4);
6599 len = IVAL(pdata,8);
6601 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6602 return NT_STATUS_INVALID_PARAMETER;
6605 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6606 len, 0, &status,
6607 &dest_has_wcard);
6608 if (!NT_STATUS_IS_OK(status)) {
6609 return status;
6612 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6613 newname));
6615 status = resolve_dfspath_wcard(ctx, conn,
6616 req->flags2 & FLAGS2_DFS_PATHNAMES,
6617 newname,
6618 true,
6619 !conn->sconn->using_smb2,
6620 &newname,
6621 &dest_has_wcard);
6622 if (!NT_STATUS_IS_OK(status)) {
6623 return status;
6626 /* Check the new name has no '/' characters. */
6627 if (strchr_m(newname, '/')) {
6628 return NT_STATUS_NOT_SUPPORTED;
6631 if (fsp && fsp->base_fsp) {
6632 /* newname must be a stream name. */
6633 if (newname[0] != ':') {
6634 return NT_STATUS_NOT_SUPPORTED;
6637 /* Create an smb_fname to call rename_internals_fsp() with. */
6638 smb_fname_dst = synthetic_smb_fname(
6639 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6640 newname, NULL);
6641 if (smb_fname_dst == NULL) {
6642 status = NT_STATUS_NO_MEMORY;
6643 goto out;
6647 * Set the original last component, since
6648 * rename_internals_fsp() requires it.
6650 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6651 newname);
6652 if (smb_fname_dst->original_lcomp == NULL) {
6653 status = NT_STATUS_NO_MEMORY;
6654 goto out;
6657 } else {
6659 * Build up an smb_fname_dst based on the filename passed in.
6660 * We basically just strip off the last component, and put on
6661 * the newname instead.
6663 char *base_name = NULL;
6665 /* newname must *not* be a stream name. */
6666 if (newname[0] == ':') {
6667 return NT_STATUS_NOT_SUPPORTED;
6671 * Strip off the last component (filename) of the path passed
6672 * in.
6674 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6675 if (!base_name) {
6676 return NT_STATUS_NO_MEMORY;
6678 p = strrchr_m(base_name, '/');
6679 if (p) {
6680 p[1] = '\0';
6681 } else {
6682 base_name = talloc_strdup(ctx, "");
6683 if (!base_name) {
6684 return NT_STATUS_NO_MEMORY;
6687 /* Append the new name. */
6688 base_name = talloc_asprintf_append(base_name,
6689 "%s",
6690 newname);
6691 if (!base_name) {
6692 return NT_STATUS_NO_MEMORY;
6695 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6696 (UCF_SAVE_LCOMP |
6697 (dest_has_wcard ?
6698 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6699 0)));
6701 /* If an error we expect this to be
6702 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6704 if (!NT_STATUS_IS_OK(status)) {
6705 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6706 status)) {
6707 goto out;
6709 /* Create an smb_fname to call rename_internals_fsp() */
6710 smb_fname_dst = synthetic_smb_fname(
6711 ctx, base_name, NULL, NULL);
6712 if (smb_fname_dst == NULL) {
6713 status = NT_STATUS_NO_MEMORY;
6714 goto out;
6719 if (fsp) {
6720 DEBUG(10,("smb_file_rename_information: "
6721 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6722 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6723 smb_fname_str_dbg(smb_fname_dst)));
6724 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6725 overwrite);
6726 } else {
6727 DEBUG(10,("smb_file_rename_information: "
6728 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6729 smb_fname_str_dbg(smb_fname_src),
6730 smb_fname_str_dbg(smb_fname_dst)));
6731 status = rename_internals(ctx, conn, req, smb_fname_src,
6732 smb_fname_dst, 0, overwrite, false,
6733 dest_has_wcard,
6734 FILE_WRITE_ATTRIBUTES);
6736 out:
6737 TALLOC_FREE(smb_fname_dst);
6738 return status;
6741 /****************************************************************************
6742 Deal with SMB_SET_POSIX_ACL.
6743 ****************************************************************************/
6745 #if defined(HAVE_POSIX_ACLS)
6746 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6747 const char *pdata,
6748 int total_data,
6749 files_struct *fsp,
6750 const struct smb_filename *smb_fname)
6752 uint16_t posix_acl_version;
6753 uint16_t num_file_acls;
6754 uint16_t num_def_acls;
6755 bool valid_file_acls = True;
6756 bool valid_def_acls = True;
6758 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6759 return NT_STATUS_INVALID_PARAMETER;
6761 posix_acl_version = SVAL(pdata,0);
6762 num_file_acls = SVAL(pdata,2);
6763 num_def_acls = SVAL(pdata,4);
6765 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6766 valid_file_acls = False;
6767 num_file_acls = 0;
6770 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6771 valid_def_acls = False;
6772 num_def_acls = 0;
6775 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6776 return NT_STATUS_INVALID_PARAMETER;
6779 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6780 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6781 return NT_STATUS_INVALID_PARAMETER;
6784 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6785 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6786 (unsigned int)num_file_acls,
6787 (unsigned int)num_def_acls));
6789 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6790 smb_fname->base_name, num_file_acls,
6791 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6792 return map_nt_error_from_unix(errno);
6795 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6796 smb_fname->base_name, &smb_fname->st, num_def_acls,
6797 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6798 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6799 return map_nt_error_from_unix(errno);
6801 return NT_STATUS_OK;
6803 #endif
6805 /****************************************************************************
6806 Deal with SMB_SET_POSIX_LOCK.
6807 ****************************************************************************/
6809 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6810 struct smb_request *req,
6811 const char *pdata,
6812 int total_data,
6813 files_struct *fsp)
6815 uint64_t count;
6816 uint64_t offset;
6817 uint64_t smblctx;
6818 bool blocking_lock = False;
6819 enum brl_type lock_type;
6821 NTSTATUS status = NT_STATUS_OK;
6823 if (fsp == NULL || fsp->fh->fd == -1) {
6824 return NT_STATUS_INVALID_HANDLE;
6827 if (total_data != POSIX_LOCK_DATA_SIZE) {
6828 return NT_STATUS_INVALID_PARAMETER;
6831 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6832 case POSIX_LOCK_TYPE_READ:
6833 lock_type = READ_LOCK;
6834 break;
6835 case POSIX_LOCK_TYPE_WRITE:
6836 /* Return the right POSIX-mappable error code for files opened read-only. */
6837 if (!fsp->can_write) {
6838 return NT_STATUS_INVALID_HANDLE;
6840 lock_type = WRITE_LOCK;
6841 break;
6842 case POSIX_LOCK_TYPE_UNLOCK:
6843 lock_type = UNLOCK_LOCK;
6844 break;
6845 default:
6846 return NT_STATUS_INVALID_PARAMETER;
6849 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6850 blocking_lock = False;
6851 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6852 blocking_lock = True;
6853 } else {
6854 return NT_STATUS_INVALID_PARAMETER;
6857 if (!lp_blocking_locks(SNUM(conn))) {
6858 blocking_lock = False;
6861 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6862 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6863 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6864 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6865 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6867 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6868 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6869 fsp_str_dbg(fsp),
6870 (unsigned int)lock_type,
6871 (unsigned long long)smblctx,
6872 (double)count,
6873 (double)offset ));
6875 if (lock_type == UNLOCK_LOCK) {
6876 status = do_unlock(req->sconn->msg_ctx,
6877 fsp,
6878 smblctx,
6879 count,
6880 offset,
6881 POSIX_LOCK);
6882 } else {
6883 uint64_t block_smblctx;
6885 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6886 fsp,
6887 smblctx,
6888 count,
6889 offset,
6890 lock_type,
6891 POSIX_LOCK,
6892 blocking_lock,
6893 &status,
6894 &block_smblctx);
6896 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6898 * A blocking lock was requested. Package up
6899 * this smb into a queued request and push it
6900 * onto the blocking lock queue.
6902 if(push_blocking_lock_request(br_lck,
6903 req,
6904 fsp,
6905 -1, /* infinite timeout. */
6907 smblctx,
6908 lock_type,
6909 POSIX_LOCK,
6910 offset,
6911 count,
6912 block_smblctx)) {
6913 TALLOC_FREE(br_lck);
6914 return status;
6917 TALLOC_FREE(br_lck);
6920 return status;
6923 /****************************************************************************
6924 Deal with SMB_SET_FILE_BASIC_INFO.
6925 ****************************************************************************/
6927 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6928 const char *pdata,
6929 int total_data,
6930 files_struct *fsp,
6931 const struct smb_filename *smb_fname)
6933 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6934 struct smb_file_time ft;
6935 uint32_t dosmode = 0;
6936 NTSTATUS status = NT_STATUS_OK;
6938 ZERO_STRUCT(ft);
6940 if (total_data < 36) {
6941 return NT_STATUS_INVALID_PARAMETER;
6944 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6945 if (!NT_STATUS_IS_OK(status)) {
6946 return status;
6949 /* Set the attributes */
6950 dosmode = IVAL(pdata,32);
6951 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 return status;
6956 /* create time */
6957 ft.create_time = interpret_long_date(pdata);
6959 /* access time */
6960 ft.atime = interpret_long_date(pdata+8);
6962 /* write time. */
6963 ft.mtime = interpret_long_date(pdata+16);
6965 /* change time. */
6966 ft.ctime = interpret_long_date(pdata+24);
6968 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6969 smb_fname_str_dbg(smb_fname)));
6971 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6972 true);
6975 /****************************************************************************
6976 Deal with SMB_INFO_STANDARD.
6977 ****************************************************************************/
6979 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6980 const char *pdata,
6981 int total_data,
6982 files_struct *fsp,
6983 const struct smb_filename *smb_fname)
6985 NTSTATUS status;
6986 struct smb_file_time ft;
6988 ZERO_STRUCT(ft);
6990 if (total_data < 12) {
6991 return NT_STATUS_INVALID_PARAMETER;
6994 /* create time */
6995 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6996 /* access time */
6997 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6998 /* write time */
6999 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7001 DEBUG(10,("smb_set_info_standard: file %s\n",
7002 smb_fname_str_dbg(smb_fname)));
7004 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7005 if (!NT_STATUS_IS_OK(status)) {
7006 return status;
7009 return smb_set_file_time(conn,
7010 fsp,
7011 smb_fname,
7012 &ft,
7013 true);
7016 /****************************************************************************
7017 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7018 ****************************************************************************/
7020 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7021 struct smb_request *req,
7022 const char *pdata,
7023 int total_data,
7024 files_struct *fsp,
7025 struct smb_filename *smb_fname)
7027 uint64_t allocation_size = 0;
7028 NTSTATUS status = NT_STATUS_OK;
7029 files_struct *new_fsp = NULL;
7031 if (!VALID_STAT(smb_fname->st)) {
7032 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7035 if (total_data < 8) {
7036 return NT_STATUS_INVALID_PARAMETER;
7039 allocation_size = (uint64_t)IVAL(pdata,0);
7040 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7041 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7042 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7043 (double)allocation_size));
7045 if (allocation_size) {
7046 allocation_size = smb_roundup(conn, allocation_size);
7049 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7050 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7051 (double)allocation_size));
7053 if (fsp && fsp->fh->fd != -1) {
7054 /* Open file handle. */
7055 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7056 return NT_STATUS_ACCESS_DENIED;
7059 /* Only change if needed. */
7060 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7061 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7062 return map_nt_error_from_unix(errno);
7065 /* But always update the time. */
7067 * This is equivalent to a write. Ensure it's seen immediately
7068 * if there are no pending writes.
7070 trigger_write_time_update_immediate(fsp);
7071 return NT_STATUS_OK;
7074 /* Pathname or stat or directory file. */
7075 status = SMB_VFS_CREATE_FILE(
7076 conn, /* conn */
7077 req, /* req */
7078 0, /* root_dir_fid */
7079 smb_fname, /* fname */
7080 FILE_WRITE_DATA, /* access_mask */
7081 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7082 FILE_SHARE_DELETE),
7083 FILE_OPEN, /* create_disposition*/
7084 0, /* create_options */
7085 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7086 0, /* oplock_request */
7087 NULL, /* lease */
7088 0, /* allocation_size */
7089 0, /* private_flags */
7090 NULL, /* sd */
7091 NULL, /* ea_list */
7092 &new_fsp, /* result */
7093 NULL, /* pinfo */
7094 NULL, NULL); /* create context */
7096 if (!NT_STATUS_IS_OK(status)) {
7097 /* NB. We check for open_was_deferred in the caller. */
7098 return status;
7101 /* Only change if needed. */
7102 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7103 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7104 status = map_nt_error_from_unix(errno);
7105 close_file(req, new_fsp, NORMAL_CLOSE);
7106 return status;
7110 /* Changing the allocation size should set the last mod time. */
7112 * This is equivalent to a write. Ensure it's seen immediately
7113 * if there are no pending writes.
7115 trigger_write_time_update_immediate(new_fsp);
7116 close_file(req, new_fsp, NORMAL_CLOSE);
7117 return NT_STATUS_OK;
7120 /****************************************************************************
7121 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7122 ****************************************************************************/
7124 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7125 struct smb_request *req,
7126 const char *pdata,
7127 int total_data,
7128 files_struct *fsp,
7129 const struct smb_filename *smb_fname,
7130 bool fail_after_createfile)
7132 off_t size;
7134 if (total_data < 8) {
7135 return NT_STATUS_INVALID_PARAMETER;
7138 size = IVAL(pdata,0);
7139 size |= (((off_t)IVAL(pdata,4)) << 32);
7140 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7141 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7142 (double)size));
7144 return smb_set_file_size(conn, req,
7145 fsp,
7146 smb_fname,
7147 &smb_fname->st,
7148 size,
7149 fail_after_createfile);
7152 /****************************************************************************
7153 Allow a UNIX info mknod.
7154 ****************************************************************************/
7156 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7157 const char *pdata,
7158 int total_data,
7159 const struct smb_filename *smb_fname)
7161 uint32_t file_type = IVAL(pdata,56);
7162 #if defined(HAVE_MAKEDEV)
7163 uint32_t dev_major = IVAL(pdata,60);
7164 uint32_t dev_minor = IVAL(pdata,68);
7165 #endif
7166 SMB_DEV_T dev = (SMB_DEV_T)0;
7167 uint32_t raw_unixmode = IVAL(pdata,84);
7168 NTSTATUS status;
7169 mode_t unixmode;
7171 if (total_data < 100) {
7172 return NT_STATUS_INVALID_PARAMETER;
7175 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7176 PERM_NEW_FILE, &unixmode);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 return status;
7181 #if defined(HAVE_MAKEDEV)
7182 dev = makedev(dev_major, dev_minor);
7183 #endif
7185 switch (file_type) {
7186 #if defined(S_IFIFO)
7187 case UNIX_TYPE_FIFO:
7188 unixmode |= S_IFIFO;
7189 break;
7190 #endif
7191 #if defined(S_IFSOCK)
7192 case UNIX_TYPE_SOCKET:
7193 unixmode |= S_IFSOCK;
7194 break;
7195 #endif
7196 #if defined(S_IFCHR)
7197 case UNIX_TYPE_CHARDEV:
7198 unixmode |= S_IFCHR;
7199 break;
7200 #endif
7201 #if defined(S_IFBLK)
7202 case UNIX_TYPE_BLKDEV:
7203 unixmode |= S_IFBLK;
7204 break;
7205 #endif
7206 default:
7207 return NT_STATUS_INVALID_PARAMETER;
7210 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7211 "%.0f mode 0%o for file %s\n", (double)dev,
7212 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7214 /* Ok - do the mknod. */
7215 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7216 return map_nt_error_from_unix(errno);
7219 /* If any of the other "set" calls fail we
7220 * don't want to end up with a half-constructed mknod.
7223 if (lp_inherit_permissions(SNUM(conn))) {
7224 char *parent;
7225 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7226 &parent, NULL)) {
7227 return NT_STATUS_NO_MEMORY;
7229 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7230 unixmode);
7231 TALLOC_FREE(parent);
7234 return NT_STATUS_OK;
7237 /****************************************************************************
7238 Deal with SMB_SET_FILE_UNIX_BASIC.
7239 ****************************************************************************/
7241 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7242 struct smb_request *req,
7243 const char *pdata,
7244 int total_data,
7245 files_struct *fsp,
7246 const struct smb_filename *smb_fname)
7248 struct smb_file_time ft;
7249 uint32_t raw_unixmode;
7250 mode_t unixmode;
7251 off_t size = 0;
7252 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7253 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7254 NTSTATUS status = NT_STATUS_OK;
7255 bool delete_on_fail = False;
7256 enum perm_type ptype;
7257 files_struct *all_fsps = NULL;
7258 bool modify_mtime = true;
7259 struct file_id id;
7260 struct smb_filename *smb_fname_tmp = NULL;
7261 SMB_STRUCT_STAT sbuf;
7263 ZERO_STRUCT(ft);
7265 if (total_data < 100) {
7266 return NT_STATUS_INVALID_PARAMETER;
7269 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7270 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7271 size=IVAL(pdata,0); /* first 8 Bytes are size */
7272 size |= (((off_t)IVAL(pdata,4)) << 32);
7275 ft.atime = interpret_long_date(pdata+24); /* access_time */
7276 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7277 set_owner = (uid_t)IVAL(pdata,40);
7278 set_grp = (gid_t)IVAL(pdata,48);
7279 raw_unixmode = IVAL(pdata,84);
7281 if (VALID_STAT(smb_fname->st)) {
7282 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7283 ptype = PERM_EXISTING_DIR;
7284 } else {
7285 ptype = PERM_EXISTING_FILE;
7287 } else {
7288 ptype = PERM_NEW_FILE;
7291 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7292 ptype, &unixmode);
7293 if (!NT_STATUS_IS_OK(status)) {
7294 return status;
7297 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7298 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7299 smb_fname_str_dbg(smb_fname), (double)size,
7300 (unsigned int)set_owner, (unsigned int)set_grp,
7301 (int)raw_unixmode));
7303 sbuf = smb_fname->st;
7305 if (!VALID_STAT(sbuf)) {
7307 * The only valid use of this is to create character and block
7308 * devices, and named pipes. This is deprecated (IMHO) and
7309 * a new info level should be used for mknod. JRA.
7312 status = smb_unix_mknod(conn,
7313 pdata,
7314 total_data,
7315 smb_fname);
7316 if (!NT_STATUS_IS_OK(status)) {
7317 return status;
7320 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7321 if (smb_fname_tmp == NULL) {
7322 return NT_STATUS_NO_MEMORY;
7325 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7326 status = map_nt_error_from_unix(errno);
7327 TALLOC_FREE(smb_fname_tmp);
7328 SMB_VFS_UNLINK(conn, smb_fname);
7329 return status;
7332 sbuf = smb_fname_tmp->st;
7333 smb_fname = smb_fname_tmp;
7335 /* Ensure we don't try and change anything else. */
7336 raw_unixmode = SMB_MODE_NO_CHANGE;
7337 size = get_file_size_stat(&sbuf);
7338 ft.atime = sbuf.st_ex_atime;
7339 ft.mtime = sbuf.st_ex_mtime;
7341 * We continue here as we might want to change the
7342 * owner uid/gid.
7344 delete_on_fail = True;
7347 #if 1
7348 /* Horrible backwards compatibility hack as an old server bug
7349 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7350 * */
7352 if (!size) {
7353 size = get_file_size_stat(&sbuf);
7355 #endif
7358 * Deal with the UNIX specific mode set.
7361 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7362 int ret;
7364 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7365 "setting mode 0%o for file %s\n",
7366 (unsigned int)unixmode,
7367 smb_fname_str_dbg(smb_fname)));
7368 if (fsp && fsp->fh->fd != -1) {
7369 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7370 } else {
7371 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7373 if (ret != 0) {
7374 return map_nt_error_from_unix(errno);
7379 * Deal with the UNIX specific uid set.
7382 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7383 (sbuf.st_ex_uid != set_owner)) {
7384 int ret;
7386 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7387 "changing owner %u for path %s\n",
7388 (unsigned int)set_owner,
7389 smb_fname_str_dbg(smb_fname)));
7391 if (fsp && fsp->fh->fd != -1) {
7392 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7393 } else {
7395 * UNIX extensions calls must always operate
7396 * on symlinks.
7398 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7399 set_owner, (gid_t)-1);
7402 if (ret != 0) {
7403 status = map_nt_error_from_unix(errno);
7404 if (delete_on_fail) {
7405 SMB_VFS_UNLINK(conn, smb_fname);
7407 return status;
7412 * Deal with the UNIX specific gid set.
7415 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7416 (sbuf.st_ex_gid != set_grp)) {
7417 int ret;
7419 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7420 "changing group %u for file %s\n",
7421 (unsigned int)set_owner,
7422 smb_fname_str_dbg(smb_fname)));
7423 if (fsp && fsp->fh->fd != -1) {
7424 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7425 } else {
7427 * UNIX extensions calls must always operate
7428 * on symlinks.
7430 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7431 set_grp);
7433 if (ret != 0) {
7434 status = map_nt_error_from_unix(errno);
7435 if (delete_on_fail) {
7436 SMB_VFS_UNLINK(conn, smb_fname);
7438 return status;
7442 /* Deal with any size changes. */
7444 status = smb_set_file_size(conn, req,
7445 fsp,
7446 smb_fname,
7447 &sbuf,
7448 size,
7449 false);
7450 if (!NT_STATUS_IS_OK(status)) {
7451 return status;
7454 /* Deal with any time changes. */
7455 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7456 /* No change, don't cancel anything. */
7457 return status;
7460 id = vfs_file_id_from_sbuf(conn, &sbuf);
7461 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7462 all_fsps = file_find_di_next(all_fsps)) {
7464 * We're setting the time explicitly for UNIX.
7465 * Cancel any pending changes over all handles.
7467 all_fsps->update_write_time_on_close = false;
7468 TALLOC_FREE(all_fsps->update_write_time_event);
7472 * Override the "setting_write_time"
7473 * parameter here as it almost does what
7474 * we need. Just remember if we modified
7475 * mtime and send the notify ourselves.
7477 if (null_timespec(ft.mtime)) {
7478 modify_mtime = false;
7481 status = smb_set_file_time(conn,
7482 fsp,
7483 smb_fname,
7484 &ft,
7485 false);
7486 if (modify_mtime) {
7487 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7488 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7490 return status;
7493 /****************************************************************************
7494 Deal with SMB_SET_FILE_UNIX_INFO2.
7495 ****************************************************************************/
7497 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7498 struct smb_request *req,
7499 const char *pdata,
7500 int total_data,
7501 files_struct *fsp,
7502 const struct smb_filename *smb_fname)
7504 NTSTATUS status;
7505 uint32_t smb_fflags;
7506 uint32_t smb_fmask;
7508 if (total_data < 116) {
7509 return NT_STATUS_INVALID_PARAMETER;
7512 /* Start by setting all the fields that are common between UNIX_BASIC
7513 * and UNIX_INFO2.
7515 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7516 fsp, smb_fname);
7517 if (!NT_STATUS_IS_OK(status)) {
7518 return status;
7521 smb_fflags = IVAL(pdata, 108);
7522 smb_fmask = IVAL(pdata, 112);
7524 /* NB: We should only attempt to alter the file flags if the client
7525 * sends a non-zero mask.
7527 if (smb_fmask != 0) {
7528 int stat_fflags = 0;
7530 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7531 smb_fmask, &stat_fflags)) {
7532 /* Client asked to alter a flag we don't understand. */
7533 return NT_STATUS_INVALID_PARAMETER;
7536 if (fsp && fsp->fh->fd != -1) {
7537 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7538 return NT_STATUS_NOT_SUPPORTED;
7539 } else {
7540 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7541 stat_fflags) != 0) {
7542 return map_nt_error_from_unix(errno);
7547 /* XXX: need to add support for changing the create_time here. You
7548 * can do this for paths on Darwin with setattrlist(2). The right way
7549 * to hook this up is probably by extending the VFS utimes interface.
7552 return NT_STATUS_OK;
7555 /****************************************************************************
7556 Create a directory with POSIX semantics.
7557 ****************************************************************************/
7559 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7560 struct smb_request *req,
7561 char **ppdata,
7562 int total_data,
7563 struct smb_filename *smb_fname,
7564 int *pdata_return_size)
7566 NTSTATUS status = NT_STATUS_OK;
7567 uint32_t raw_unixmode = 0;
7568 uint32_t mod_unixmode = 0;
7569 mode_t unixmode = (mode_t)0;
7570 files_struct *fsp = NULL;
7571 uint16_t info_level_return = 0;
7572 int info;
7573 char *pdata = *ppdata;
7575 if (total_data < 18) {
7576 return NT_STATUS_INVALID_PARAMETER;
7579 raw_unixmode = IVAL(pdata,8);
7580 /* Next 4 bytes are not yet defined. */
7582 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7583 PERM_NEW_DIR, &unixmode);
7584 if (!NT_STATUS_IS_OK(status)) {
7585 return status;
7588 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7590 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7591 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7593 status = SMB_VFS_CREATE_FILE(
7594 conn, /* conn */
7595 req, /* req */
7596 0, /* root_dir_fid */
7597 smb_fname, /* fname */
7598 FILE_READ_ATTRIBUTES, /* access_mask */
7599 FILE_SHARE_NONE, /* share_access */
7600 FILE_CREATE, /* create_disposition*/
7601 FILE_DIRECTORY_FILE, /* create_options */
7602 mod_unixmode, /* file_attributes */
7603 0, /* oplock_request */
7604 NULL, /* lease */
7605 0, /* allocation_size */
7606 0, /* private_flags */
7607 NULL, /* sd */
7608 NULL, /* ea_list */
7609 &fsp, /* result */
7610 &info, /* pinfo */
7611 NULL, NULL); /* create context */
7613 if (NT_STATUS_IS_OK(status)) {
7614 close_file(req, fsp, NORMAL_CLOSE);
7617 info_level_return = SVAL(pdata,16);
7619 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7620 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7621 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7622 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7623 } else {
7624 *pdata_return_size = 12;
7627 /* Realloc the data size */
7628 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7629 if (*ppdata == NULL) {
7630 *pdata_return_size = 0;
7631 return NT_STATUS_NO_MEMORY;
7633 pdata = *ppdata;
7635 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7636 SSVAL(pdata,2,0); /* No fnum. */
7637 SIVAL(pdata,4,info); /* Was directory created. */
7639 switch (info_level_return) {
7640 case SMB_QUERY_FILE_UNIX_BASIC:
7641 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7642 SSVAL(pdata,10,0); /* Padding. */
7643 store_file_unix_basic(conn, pdata + 12, fsp,
7644 &smb_fname->st);
7645 break;
7646 case SMB_QUERY_FILE_UNIX_INFO2:
7647 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7648 SSVAL(pdata,10,0); /* Padding. */
7649 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7650 &smb_fname->st);
7651 break;
7652 default:
7653 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7654 SSVAL(pdata,10,0); /* Padding. */
7655 break;
7658 return status;
7661 /****************************************************************************
7662 Open/Create a file with POSIX semantics.
7663 ****************************************************************************/
7665 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7666 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7668 static NTSTATUS smb_posix_open(connection_struct *conn,
7669 struct smb_request *req,
7670 char **ppdata,
7671 int total_data,
7672 struct smb_filename *smb_fname,
7673 int *pdata_return_size)
7675 bool extended_oplock_granted = False;
7676 char *pdata = *ppdata;
7677 uint32_t flags = 0;
7678 uint32_t wire_open_mode = 0;
7679 uint32_t raw_unixmode = 0;
7680 uint32_t mod_unixmode = 0;
7681 uint32_t create_disp = 0;
7682 uint32_t access_mask = 0;
7683 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7684 NTSTATUS status = NT_STATUS_OK;
7685 mode_t unixmode = (mode_t)0;
7686 files_struct *fsp = NULL;
7687 int oplock_request = 0;
7688 int info = 0;
7689 uint16_t info_level_return = 0;
7691 if (total_data < 18) {
7692 return NT_STATUS_INVALID_PARAMETER;
7695 flags = IVAL(pdata,0);
7696 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7697 if (oplock_request) {
7698 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7701 wire_open_mode = IVAL(pdata,4);
7703 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7704 return smb_posix_mkdir(conn, req,
7705 ppdata,
7706 total_data,
7707 smb_fname,
7708 pdata_return_size);
7711 switch (wire_open_mode & SMB_ACCMODE) {
7712 case SMB_O_RDONLY:
7713 access_mask = SMB_O_RDONLY_MAPPING;
7714 break;
7715 case SMB_O_WRONLY:
7716 access_mask = SMB_O_WRONLY_MAPPING;
7717 break;
7718 case SMB_O_RDWR:
7719 access_mask = (SMB_O_RDONLY_MAPPING|
7720 SMB_O_WRONLY_MAPPING);
7721 break;
7722 default:
7723 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7724 (unsigned int)wire_open_mode ));
7725 return NT_STATUS_INVALID_PARAMETER;
7728 wire_open_mode &= ~SMB_ACCMODE;
7730 /* First take care of O_CREAT|O_EXCL interactions. */
7731 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7732 case (SMB_O_CREAT | SMB_O_EXCL):
7733 /* File exists fail. File not exist create. */
7734 create_disp = FILE_CREATE;
7735 break;
7736 case SMB_O_CREAT:
7737 /* File exists open. File not exist create. */
7738 create_disp = FILE_OPEN_IF;
7739 break;
7740 case SMB_O_EXCL:
7741 /* O_EXCL on its own without O_CREAT is undefined.
7742 We deliberately ignore it as some versions of
7743 Linux CIFSFS can send a bare O_EXCL on the
7744 wire which other filesystems in the kernel
7745 ignore. See bug 9519 for details. */
7747 /* Fallthrough. */
7749 case 0:
7750 /* File exists open. File not exist fail. */
7751 create_disp = FILE_OPEN;
7752 break;
7753 default:
7754 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7755 (unsigned int)wire_open_mode ));
7756 return NT_STATUS_INVALID_PARAMETER;
7759 /* Next factor in the effects of O_TRUNC. */
7760 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7762 if (wire_open_mode & SMB_O_TRUNC) {
7763 switch (create_disp) {
7764 case FILE_CREATE:
7765 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7766 /* Leave create_disp alone as
7767 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7769 /* File exists fail. File not exist create. */
7770 break;
7771 case FILE_OPEN_IF:
7772 /* SMB_O_CREAT | SMB_O_TRUNC */
7773 /* File exists overwrite. File not exist create. */
7774 create_disp = FILE_OVERWRITE_IF;
7775 break;
7776 case FILE_OPEN:
7777 /* SMB_O_TRUNC */
7778 /* File exists overwrite. File not exist fail. */
7779 create_disp = FILE_OVERWRITE;
7780 break;
7781 default:
7782 /* Cannot get here. */
7783 smb_panic("smb_posix_open: logic error");
7784 return NT_STATUS_INVALID_PARAMETER;
7788 raw_unixmode = IVAL(pdata,8);
7789 /* Next 4 bytes are not yet defined. */
7791 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7792 (VALID_STAT(smb_fname->st) ?
7793 PERM_EXISTING_FILE : PERM_NEW_FILE),
7794 &unixmode);
7796 if (!NT_STATUS_IS_OK(status)) {
7797 return status;
7800 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7802 if (wire_open_mode & SMB_O_SYNC) {
7803 create_options |= FILE_WRITE_THROUGH;
7805 if (wire_open_mode & SMB_O_APPEND) {
7806 access_mask |= FILE_APPEND_DATA;
7808 if (wire_open_mode & SMB_O_DIRECT) {
7809 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7812 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7813 VALID_STAT_OF_DIR(smb_fname->st)) {
7814 if (access_mask != SMB_O_RDONLY_MAPPING) {
7815 return NT_STATUS_FILE_IS_A_DIRECTORY;
7817 create_options &= ~FILE_NON_DIRECTORY_FILE;
7818 create_options |= FILE_DIRECTORY_FILE;
7821 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7822 smb_fname_str_dbg(smb_fname),
7823 (unsigned int)wire_open_mode,
7824 (unsigned int)unixmode ));
7826 status = SMB_VFS_CREATE_FILE(
7827 conn, /* conn */
7828 req, /* req */
7829 0, /* root_dir_fid */
7830 smb_fname, /* fname */
7831 access_mask, /* access_mask */
7832 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7833 FILE_SHARE_DELETE),
7834 create_disp, /* create_disposition*/
7835 create_options, /* create_options */
7836 mod_unixmode, /* file_attributes */
7837 oplock_request, /* oplock_request */
7838 NULL, /* lease */
7839 0, /* allocation_size */
7840 0, /* private_flags */
7841 NULL, /* sd */
7842 NULL, /* ea_list */
7843 &fsp, /* result */
7844 &info, /* pinfo */
7845 NULL, NULL); /* create context */
7847 if (!NT_STATUS_IS_OK(status)) {
7848 return status;
7851 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7852 extended_oplock_granted = True;
7855 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7856 extended_oplock_granted = True;
7859 info_level_return = SVAL(pdata,16);
7861 /* Allocate the correct return size. */
7863 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7864 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7865 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7866 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7867 } else {
7868 *pdata_return_size = 12;
7871 /* Realloc the data size */
7872 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7873 if (*ppdata == NULL) {
7874 close_file(req, fsp, ERROR_CLOSE);
7875 *pdata_return_size = 0;
7876 return NT_STATUS_NO_MEMORY;
7878 pdata = *ppdata;
7880 if (extended_oplock_granted) {
7881 if (flags & REQUEST_BATCH_OPLOCK) {
7882 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7883 } else {
7884 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7886 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7887 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7888 } else {
7889 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7892 SSVAL(pdata,2,fsp->fnum);
7893 SIVAL(pdata,4,info); /* Was file created etc. */
7895 switch (info_level_return) {
7896 case SMB_QUERY_FILE_UNIX_BASIC:
7897 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7898 SSVAL(pdata,10,0); /* padding. */
7899 store_file_unix_basic(conn, pdata + 12, fsp,
7900 &smb_fname->st);
7901 break;
7902 case SMB_QUERY_FILE_UNIX_INFO2:
7903 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7904 SSVAL(pdata,10,0); /* padding. */
7905 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7906 &smb_fname->st);
7907 break;
7908 default:
7909 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7910 SSVAL(pdata,10,0); /* padding. */
7911 break;
7913 return NT_STATUS_OK;
7916 /****************************************************************************
7917 Delete a file with POSIX semantics.
7918 ****************************************************************************/
7920 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7921 struct smb_request *req,
7922 const char *pdata,
7923 int total_data,
7924 struct smb_filename *smb_fname)
7926 NTSTATUS status = NT_STATUS_OK;
7927 files_struct *fsp = NULL;
7928 uint16_t flags = 0;
7929 char del = 1;
7930 int info = 0;
7931 int create_options = 0;
7932 int i;
7933 struct share_mode_lock *lck = NULL;
7935 if (total_data < 2) {
7936 return NT_STATUS_INVALID_PARAMETER;
7939 flags = SVAL(pdata,0);
7941 if (!VALID_STAT(smb_fname->st)) {
7942 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7945 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7946 !VALID_STAT_OF_DIR(smb_fname->st)) {
7947 return NT_STATUS_NOT_A_DIRECTORY;
7950 DEBUG(10,("smb_posix_unlink: %s %s\n",
7951 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7952 smb_fname_str_dbg(smb_fname)));
7954 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7955 create_options |= FILE_DIRECTORY_FILE;
7958 status = SMB_VFS_CREATE_FILE(
7959 conn, /* conn */
7960 req, /* req */
7961 0, /* root_dir_fid */
7962 smb_fname, /* fname */
7963 DELETE_ACCESS, /* access_mask */
7964 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7965 FILE_SHARE_DELETE),
7966 FILE_OPEN, /* create_disposition*/
7967 create_options, /* create_options */
7968 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7969 0, /* oplock_request */
7970 NULL, /* lease */
7971 0, /* allocation_size */
7972 0, /* private_flags */
7973 NULL, /* sd */
7974 NULL, /* ea_list */
7975 &fsp, /* result */
7976 &info, /* pinfo */
7977 NULL, NULL); /* create context */
7979 if (!NT_STATUS_IS_OK(status)) {
7980 return status;
7984 * Don't lie to client. If we can't really delete due to
7985 * non-POSIX opens return SHARING_VIOLATION.
7988 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7989 if (lck == NULL) {
7990 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7991 "lock for file %s\n", fsp_str_dbg(fsp)));
7992 close_file(req, fsp, NORMAL_CLOSE);
7993 return NT_STATUS_INVALID_PARAMETER;
7997 * See if others still have the file open. If this is the case, then
7998 * don't delete. If all opens are POSIX delete we can set the delete
7999 * on close disposition.
8001 for (i=0; i<lck->data->num_share_modes; i++) {
8002 struct share_mode_entry *e = &lck->data->share_modes[i];
8003 if (is_valid_share_mode_entry(e)) {
8004 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8005 continue;
8007 if (share_mode_stale_pid(lck->data, i)) {
8008 continue;
8010 /* Fail with sharing violation. */
8011 TALLOC_FREE(lck);
8012 close_file(req, fsp, NORMAL_CLOSE);
8013 return NT_STATUS_SHARING_VIOLATION;
8018 * Set the delete on close.
8020 status = smb_set_file_disposition_info(conn,
8021 &del,
8023 fsp,
8024 smb_fname);
8026 TALLOC_FREE(lck);
8028 if (!NT_STATUS_IS_OK(status)) {
8029 close_file(req, fsp, NORMAL_CLOSE);
8030 return status;
8032 return close_file(req, fsp, NORMAL_CLOSE);
8035 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8036 struct smb_request *req,
8037 TALLOC_CTX *mem_ctx,
8038 uint16_t info_level,
8039 files_struct *fsp,
8040 struct smb_filename *smb_fname,
8041 char **ppdata, int total_data,
8042 int *ret_data_size)
8044 char *pdata = *ppdata;
8045 NTSTATUS status = NT_STATUS_OK;
8046 int data_return_size = 0;
8048 *ret_data_size = 0;
8050 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8051 return NT_STATUS_INVALID_LEVEL;
8054 if (!CAN_WRITE(conn)) {
8055 /* Allow POSIX opens. The open path will deny
8056 * any non-readonly opens. */
8057 if (info_level != SMB_POSIX_PATH_OPEN) {
8058 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8062 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8063 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8064 fsp_fnum_dbg(fsp),
8065 info_level, total_data));
8067 switch (info_level) {
8069 case SMB_INFO_STANDARD:
8071 status = smb_set_info_standard(conn,
8072 pdata,
8073 total_data,
8074 fsp,
8075 smb_fname);
8076 break;
8079 case SMB_INFO_SET_EA:
8081 status = smb_info_set_ea(conn,
8082 pdata,
8083 total_data,
8084 fsp,
8085 smb_fname);
8086 break;
8089 case SMB_SET_FILE_BASIC_INFO:
8090 case SMB_FILE_BASIC_INFORMATION:
8092 status = smb_set_file_basic_info(conn,
8093 pdata,
8094 total_data,
8095 fsp,
8096 smb_fname);
8097 break;
8100 case SMB_FILE_ALLOCATION_INFORMATION:
8101 case SMB_SET_FILE_ALLOCATION_INFO:
8103 status = smb_set_file_allocation_info(conn, req,
8104 pdata,
8105 total_data,
8106 fsp,
8107 smb_fname);
8108 break;
8111 case SMB_FILE_END_OF_FILE_INFORMATION:
8112 case SMB_SET_FILE_END_OF_FILE_INFO:
8115 * XP/Win7 both fail after the createfile with
8116 * SMB_SET_FILE_END_OF_FILE_INFO but not
8117 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8118 * The level is known here, so pass it down
8119 * appropriately.
8121 bool should_fail =
8122 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8124 status = smb_set_file_end_of_file_info(conn, req,
8125 pdata,
8126 total_data,
8127 fsp,
8128 smb_fname,
8129 should_fail);
8130 break;
8133 case SMB_FILE_DISPOSITION_INFORMATION:
8134 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8136 #if 0
8137 /* JRA - We used to just ignore this on a path ?
8138 * Shouldn't this be invalid level on a pathname
8139 * based call ?
8141 if (tran_call != TRANSACT2_SETFILEINFO) {
8142 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8144 #endif
8145 status = smb_set_file_disposition_info(conn,
8146 pdata,
8147 total_data,
8148 fsp,
8149 smb_fname);
8150 break;
8153 case SMB_FILE_POSITION_INFORMATION:
8155 status = smb_file_position_information(conn,
8156 pdata,
8157 total_data,
8158 fsp);
8159 break;
8162 case SMB_FILE_FULL_EA_INFORMATION:
8164 status = smb_set_file_full_ea_info(conn,
8165 pdata,
8166 total_data,
8167 fsp);
8168 break;
8171 /* From tridge Samba4 :
8172 * MODE_INFORMATION in setfileinfo (I have no
8173 * idea what "mode information" on a file is - it takes a value of 0,
8174 * 2, 4 or 6. What could it be?).
8177 case SMB_FILE_MODE_INFORMATION:
8179 status = smb_file_mode_information(conn,
8180 pdata,
8181 total_data);
8182 break;
8186 * CIFS UNIX extensions.
8189 case SMB_SET_FILE_UNIX_BASIC:
8191 status = smb_set_file_unix_basic(conn, req,
8192 pdata,
8193 total_data,
8194 fsp,
8195 smb_fname);
8196 break;
8199 case SMB_SET_FILE_UNIX_INFO2:
8201 status = smb_set_file_unix_info2(conn, req,
8202 pdata,
8203 total_data,
8204 fsp,
8205 smb_fname);
8206 break;
8209 case SMB_SET_FILE_UNIX_LINK:
8211 if (fsp) {
8212 /* We must have a pathname for this. */
8213 return NT_STATUS_INVALID_LEVEL;
8215 status = smb_set_file_unix_link(conn, req, pdata,
8216 total_data, smb_fname);
8217 break;
8220 case SMB_SET_FILE_UNIX_HLINK:
8222 if (fsp) {
8223 /* We must have a pathname for this. */
8224 return NT_STATUS_INVALID_LEVEL;
8226 status = smb_set_file_unix_hlink(conn, req,
8227 pdata, total_data,
8228 smb_fname);
8229 break;
8232 case SMB_FILE_RENAME_INFORMATION:
8234 status = smb_file_rename_information(conn, req,
8235 pdata, total_data,
8236 fsp, smb_fname);
8237 break;
8240 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8242 /* SMB2 rename information. */
8243 status = smb2_file_rename_information(conn, req,
8244 pdata, total_data,
8245 fsp, smb_fname);
8246 break;
8249 case SMB_FILE_LINK_INFORMATION:
8251 status = smb_file_link_information(conn, req,
8252 pdata, total_data,
8253 fsp, smb_fname);
8254 break;
8257 #if defined(HAVE_POSIX_ACLS)
8258 case SMB_SET_POSIX_ACL:
8260 status = smb_set_posix_acl(conn,
8261 pdata,
8262 total_data,
8263 fsp,
8264 smb_fname);
8265 break;
8267 #endif
8269 case SMB_SET_POSIX_LOCK:
8271 if (!fsp) {
8272 return NT_STATUS_INVALID_LEVEL;
8274 status = smb_set_posix_lock(conn, req,
8275 pdata, total_data, fsp);
8276 break;
8279 case SMB_POSIX_PATH_OPEN:
8281 if (fsp) {
8282 /* We must have a pathname for this. */
8283 return NT_STATUS_INVALID_LEVEL;
8286 status = smb_posix_open(conn, req,
8287 ppdata,
8288 total_data,
8289 smb_fname,
8290 &data_return_size);
8291 break;
8294 case SMB_POSIX_PATH_UNLINK:
8296 if (fsp) {
8297 /* We must have a pathname for this. */
8298 return NT_STATUS_INVALID_LEVEL;
8301 status = smb_posix_unlink(conn, req,
8302 pdata,
8303 total_data,
8304 smb_fname);
8305 break;
8308 default:
8309 return NT_STATUS_INVALID_LEVEL;
8312 if (!NT_STATUS_IS_OK(status)) {
8313 return status;
8316 *ret_data_size = data_return_size;
8317 return NT_STATUS_OK;
8320 /****************************************************************************
8321 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8322 ****************************************************************************/
8324 static void call_trans2setfilepathinfo(connection_struct *conn,
8325 struct smb_request *req,
8326 unsigned int tran_call,
8327 char **pparams, int total_params,
8328 char **ppdata, int total_data,
8329 unsigned int max_data_bytes)
8331 char *params = *pparams;
8332 char *pdata = *ppdata;
8333 uint16_t info_level;
8334 struct smb_filename *smb_fname = NULL;
8335 files_struct *fsp = NULL;
8336 NTSTATUS status = NT_STATUS_OK;
8337 int data_return_size = 0;
8339 if (!params) {
8340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8341 return;
8344 if (tran_call == TRANSACT2_SETFILEINFO) {
8345 if (total_params < 4) {
8346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8347 return;
8350 fsp = file_fsp(req, SVAL(params,0));
8351 /* Basic check for non-null fsp. */
8352 if (!check_fsp_open(conn, req, fsp)) {
8353 return;
8355 info_level = SVAL(params,2);
8357 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8358 if (smb_fname == NULL) {
8359 reply_nterror(req, NT_STATUS_NO_MEMORY);
8360 return;
8363 if(fsp->fh->fd == -1) {
8365 * This is actually a SETFILEINFO on a directory
8366 * handle (returned from an NT SMB). NT5.0 seems
8367 * to do this call. JRA.
8369 if (INFO_LEVEL_IS_UNIX(info_level)) {
8370 /* Always do lstat for UNIX calls. */
8371 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8372 DEBUG(3,("call_trans2setfilepathinfo: "
8373 "SMB_VFS_LSTAT of %s failed "
8374 "(%s)\n",
8375 smb_fname_str_dbg(smb_fname),
8376 strerror(errno)));
8377 reply_nterror(req, map_nt_error_from_unix(errno));
8378 return;
8380 } else {
8381 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8382 DEBUG(3,("call_trans2setfilepathinfo: "
8383 "fileinfo of %s failed (%s)\n",
8384 smb_fname_str_dbg(smb_fname),
8385 strerror(errno)));
8386 reply_nterror(req, map_nt_error_from_unix(errno));
8387 return;
8390 } else if (fsp->print_file) {
8392 * Doing a DELETE_ON_CLOSE should cancel a print job.
8394 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8395 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8397 DEBUG(3,("call_trans2setfilepathinfo: "
8398 "Cancelling print job (%s)\n",
8399 fsp_str_dbg(fsp)));
8401 SSVAL(params,0,0);
8402 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8403 *ppdata, 0,
8404 max_data_bytes);
8405 return;
8406 } else {
8407 reply_nterror(req,
8408 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8409 return;
8411 } else {
8413 * Original code - this is an open file.
8415 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8416 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8417 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8418 strerror(errno)));
8419 reply_nterror(req, map_nt_error_from_unix(errno));
8420 return;
8423 } else {
8424 char *fname = NULL;
8425 uint32_t ucf_flags = 0;
8427 /* set path info */
8428 if (total_params < 7) {
8429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8430 return;
8433 info_level = SVAL(params,0);
8434 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8435 total_params - 6, STR_TERMINATE,
8436 &status);
8437 if (!NT_STATUS_IS_OK(status)) {
8438 reply_nterror(req, status);
8439 return;
8442 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8443 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8444 info_level == SMB_FILE_RENAME_INFORMATION ||
8445 info_level == SMB_POSIX_PATH_UNLINK) {
8446 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8449 status = filename_convert(req, conn,
8450 req->flags2 & FLAGS2_DFS_PATHNAMES,
8451 fname,
8452 ucf_flags,
8453 NULL,
8454 &smb_fname);
8455 if (!NT_STATUS_IS_OK(status)) {
8456 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8457 reply_botherror(req,
8458 NT_STATUS_PATH_NOT_COVERED,
8459 ERRSRV, ERRbadpath);
8460 return;
8462 reply_nterror(req, status);
8463 return;
8466 if (INFO_LEVEL_IS_UNIX(info_level)) {
8468 * For CIFS UNIX extensions the target name may not exist.
8471 /* Always do lstat for UNIX calls. */
8472 SMB_VFS_LSTAT(conn, smb_fname);
8474 } else if (!VALID_STAT(smb_fname->st) &&
8475 SMB_VFS_STAT(conn, smb_fname)) {
8476 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8477 "%s failed (%s)\n",
8478 smb_fname_str_dbg(smb_fname),
8479 strerror(errno)));
8480 reply_nterror(req, map_nt_error_from_unix(errno));
8481 return;
8485 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8486 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8487 fsp_fnum_dbg(fsp),
8488 info_level,total_data));
8490 /* Realloc the parameter size */
8491 *pparams = (char *)SMB_REALLOC(*pparams,2);
8492 if (*pparams == NULL) {
8493 reply_nterror(req, NT_STATUS_NO_MEMORY);
8494 return;
8496 params = *pparams;
8498 SSVAL(params,0,0);
8500 status = smbd_do_setfilepathinfo(conn, req, req,
8501 info_level,
8502 fsp,
8503 smb_fname,
8504 ppdata, total_data,
8505 &data_return_size);
8506 if (!NT_STATUS_IS_OK(status)) {
8507 if (open_was_deferred(req->xconn, req->mid)) {
8508 /* We have re-scheduled this call. */
8509 return;
8511 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8512 /* We have re-scheduled this call. */
8513 return;
8515 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8516 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8517 ERRSRV, ERRbadpath);
8518 return;
8520 if (info_level == SMB_POSIX_PATH_OPEN) {
8521 reply_openerror(req, status);
8522 return;
8526 * Invalid EA name needs to return 2 param bytes,
8527 * not a zero-length error packet.
8529 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8530 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8531 max_data_bytes);
8532 } else {
8533 reply_nterror(req, status);
8535 return;
8538 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8539 max_data_bytes);
8541 return;
8544 /****************************************************************************
8545 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8546 ****************************************************************************/
8548 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8549 char **pparams, int total_params,
8550 char **ppdata, int total_data,
8551 unsigned int max_data_bytes)
8553 struct smb_filename *smb_dname = NULL;
8554 char *params = *pparams;
8555 char *pdata = *ppdata;
8556 char *directory = NULL;
8557 NTSTATUS status = NT_STATUS_OK;
8558 struct ea_list *ea_list = NULL;
8559 TALLOC_CTX *ctx = talloc_tos();
8561 if (!CAN_WRITE(conn)) {
8562 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8563 return;
8566 if (total_params < 5) {
8567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8568 return;
8571 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8572 total_params - 4, STR_TERMINATE,
8573 &status);
8574 if (!NT_STATUS_IS_OK(status)) {
8575 reply_nterror(req, status);
8576 return;
8579 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8581 status = filename_convert(ctx,
8582 conn,
8583 req->flags2 & FLAGS2_DFS_PATHNAMES,
8584 directory,
8586 NULL,
8587 &smb_dname);
8589 if (!NT_STATUS_IS_OK(status)) {
8590 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8591 reply_botherror(req,
8592 NT_STATUS_PATH_NOT_COVERED,
8593 ERRSRV, ERRbadpath);
8594 return;
8596 reply_nterror(req, status);
8597 return;
8601 * OS/2 workplace shell seems to send SET_EA requests of "null"
8602 * length (4 bytes containing IVAL 4).
8603 * They seem to have no effect. Bug #3212. JRA.
8606 if (total_data && (total_data != 4)) {
8607 /* Any data in this call is an EA list. */
8608 if (total_data < 10) {
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610 goto out;
8613 if (IVAL(pdata,0) > total_data) {
8614 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8615 IVAL(pdata,0), (unsigned int)total_data));
8616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8617 goto out;
8620 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8621 total_data - 4);
8622 if (!ea_list) {
8623 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8624 goto out;
8627 if (!lp_ea_support(SNUM(conn))) {
8628 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8629 goto out;
8632 /* If total_data == 4 Windows doesn't care what values
8633 * are placed in that field, it just ignores them.
8634 * The System i QNTC IBM SMB client puts bad values here,
8635 * so ignore them. */
8637 status = create_directory(conn, req, smb_dname);
8639 if (!NT_STATUS_IS_OK(status)) {
8640 reply_nterror(req, status);
8641 goto out;
8644 /* Try and set any given EA. */
8645 if (ea_list) {
8646 status = set_ea(conn, NULL, smb_dname, ea_list);
8647 if (!NT_STATUS_IS_OK(status)) {
8648 reply_nterror(req, status);
8649 goto out;
8653 /* Realloc the parameter and data sizes */
8654 *pparams = (char *)SMB_REALLOC(*pparams,2);
8655 if(*pparams == NULL) {
8656 reply_nterror(req, NT_STATUS_NO_MEMORY);
8657 goto out;
8659 params = *pparams;
8661 SSVAL(params,0,0);
8663 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8665 out:
8666 TALLOC_FREE(smb_dname);
8667 return;
8670 /****************************************************************************
8671 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8672 We don't actually do this - we just send a null response.
8673 ****************************************************************************/
8675 static void call_trans2findnotifyfirst(connection_struct *conn,
8676 struct smb_request *req,
8677 char **pparams, int total_params,
8678 char **ppdata, int total_data,
8679 unsigned int max_data_bytes)
8681 char *params = *pparams;
8682 uint16_t info_level;
8684 if (total_params < 6) {
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686 return;
8689 info_level = SVAL(params,4);
8690 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8692 switch (info_level) {
8693 case 1:
8694 case 2:
8695 break;
8696 default:
8697 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8698 return;
8701 /* Realloc the parameter and data sizes */
8702 *pparams = (char *)SMB_REALLOC(*pparams,6);
8703 if (*pparams == NULL) {
8704 reply_nterror(req, NT_STATUS_NO_MEMORY);
8705 return;
8707 params = *pparams;
8709 SSVAL(params,0,fnf_handle);
8710 SSVAL(params,2,0); /* No changes */
8711 SSVAL(params,4,0); /* No EA errors */
8713 fnf_handle++;
8715 if(fnf_handle == 0)
8716 fnf_handle = 257;
8718 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8720 return;
8723 /****************************************************************************
8724 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8725 changes). Currently this does nothing.
8726 ****************************************************************************/
8728 static void call_trans2findnotifynext(connection_struct *conn,
8729 struct smb_request *req,
8730 char **pparams, int total_params,
8731 char **ppdata, int total_data,
8732 unsigned int max_data_bytes)
8734 char *params = *pparams;
8736 DEBUG(3,("call_trans2findnotifynext\n"));
8738 /* Realloc the parameter and data sizes */
8739 *pparams = (char *)SMB_REALLOC(*pparams,4);
8740 if (*pparams == NULL) {
8741 reply_nterror(req, NT_STATUS_NO_MEMORY);
8742 return;
8744 params = *pparams;
8746 SSVAL(params,0,0); /* No changes */
8747 SSVAL(params,2,0); /* No EA errors */
8749 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8751 return;
8754 /****************************************************************************
8755 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8756 ****************************************************************************/
8758 static void call_trans2getdfsreferral(connection_struct *conn,
8759 struct smb_request *req,
8760 char **pparams, int total_params,
8761 char **ppdata, int total_data,
8762 unsigned int max_data_bytes)
8764 char *params = *pparams;
8765 char *pathname = NULL;
8766 int reply_size = 0;
8767 int max_referral_level;
8768 NTSTATUS status = NT_STATUS_OK;
8769 TALLOC_CTX *ctx = talloc_tos();
8771 DEBUG(10,("call_trans2getdfsreferral\n"));
8773 if (total_params < 3) {
8774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8775 return;
8778 max_referral_level = SVAL(params,0);
8780 if(!lp_host_msdfs()) {
8781 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8782 return;
8785 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8786 total_params - 2, STR_TERMINATE);
8787 if (!pathname) {
8788 reply_nterror(req, NT_STATUS_NOT_FOUND);
8789 return;
8791 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8792 ppdata,&status)) < 0) {
8793 reply_nterror(req, status);
8794 return;
8797 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8798 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8799 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8801 return;
8804 #define LMCAT_SPL 0x53
8805 #define LMFUNC_GETJOBID 0x60
8807 /****************************************************************************
8808 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8809 ****************************************************************************/
8811 static void call_trans2ioctl(connection_struct *conn,
8812 struct smb_request *req,
8813 char **pparams, int total_params,
8814 char **ppdata, int total_data,
8815 unsigned int max_data_bytes)
8817 char *pdata = *ppdata;
8818 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8819 NTSTATUS status;
8820 size_t len = 0;
8822 /* check for an invalid fid before proceeding */
8824 if (!fsp) {
8825 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8826 return;
8829 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8830 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8831 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8832 if (*ppdata == NULL) {
8833 reply_nterror(req, NT_STATUS_NO_MEMORY);
8834 return;
8836 pdata = *ppdata;
8838 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8839 CAN ACCEPT THIS IN UNICODE. JRA. */
8841 /* Job number */
8842 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8844 status = srvstr_push(pdata, req->flags2, pdata + 2,
8845 lp_netbios_name(), 15,
8846 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8847 if (!NT_STATUS_IS_OK(status)) {
8848 reply_nterror(req, status);
8849 return;
8851 status = srvstr_push(pdata, req->flags2, pdata+18,
8852 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8853 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8854 if (!NT_STATUS_IS_OK(status)) {
8855 reply_nterror(req, status);
8856 return;
8858 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8859 max_data_bytes);
8860 return;
8863 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8864 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8867 /****************************************************************************
8868 Reply to a SMBfindclose (stop trans2 directory search).
8869 ****************************************************************************/
8871 void reply_findclose(struct smb_request *req)
8873 int dptr_num;
8874 struct smbd_server_connection *sconn = req->sconn;
8876 START_PROFILE(SMBfindclose);
8878 if (req->wct < 1) {
8879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8880 END_PROFILE(SMBfindclose);
8881 return;
8884 dptr_num = SVALS(req->vwv+0, 0);
8886 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8888 dptr_close(sconn, &dptr_num);
8890 reply_outbuf(req, 0, 0);
8892 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8894 END_PROFILE(SMBfindclose);
8895 return;
8898 /****************************************************************************
8899 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8900 ****************************************************************************/
8902 void reply_findnclose(struct smb_request *req)
8904 int dptr_num;
8906 START_PROFILE(SMBfindnclose);
8908 if (req->wct < 1) {
8909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8910 END_PROFILE(SMBfindnclose);
8911 return;
8914 dptr_num = SVAL(req->vwv+0, 0);
8916 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8918 /* We never give out valid handles for a
8919 findnotifyfirst - so any dptr_num is ok here.
8920 Just ignore it. */
8922 reply_outbuf(req, 0, 0);
8924 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8926 END_PROFILE(SMBfindnclose);
8927 return;
8930 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8931 struct trans_state *state)
8933 if (get_Protocol() >= PROTOCOL_NT1) {
8934 req->flags2 |= 0x40; /* IS_LONG_NAME */
8935 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8938 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8939 if (state->call != TRANSACT2_QFSINFO &&
8940 state->call != TRANSACT2_SETFSINFO) {
8941 DEBUG(0,("handle_trans2: encryption required "
8942 "with call 0x%x\n",
8943 (unsigned int)state->call));
8944 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8945 return;
8949 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8951 /* Now we must call the relevant TRANS2 function */
8952 switch(state->call) {
8953 case TRANSACT2_OPEN:
8955 START_PROFILE(Trans2_open);
8956 call_trans2open(conn, req,
8957 &state->param, state->total_param,
8958 &state->data, state->total_data,
8959 state->max_data_return);
8960 END_PROFILE(Trans2_open);
8961 break;
8964 case TRANSACT2_FINDFIRST:
8966 START_PROFILE(Trans2_findfirst);
8967 call_trans2findfirst(conn, req,
8968 &state->param, state->total_param,
8969 &state->data, state->total_data,
8970 state->max_data_return);
8971 END_PROFILE(Trans2_findfirst);
8972 break;
8975 case TRANSACT2_FINDNEXT:
8977 START_PROFILE(Trans2_findnext);
8978 call_trans2findnext(conn, req,
8979 &state->param, state->total_param,
8980 &state->data, state->total_data,
8981 state->max_data_return);
8982 END_PROFILE(Trans2_findnext);
8983 break;
8986 case TRANSACT2_QFSINFO:
8988 START_PROFILE(Trans2_qfsinfo);
8989 call_trans2qfsinfo(conn, req,
8990 &state->param, state->total_param,
8991 &state->data, state->total_data,
8992 state->max_data_return);
8993 END_PROFILE(Trans2_qfsinfo);
8994 break;
8997 case TRANSACT2_SETFSINFO:
8999 START_PROFILE(Trans2_setfsinfo);
9000 call_trans2setfsinfo(conn, req,
9001 &state->param, state->total_param,
9002 &state->data, state->total_data,
9003 state->max_data_return);
9004 END_PROFILE(Trans2_setfsinfo);
9005 break;
9008 case TRANSACT2_QPATHINFO:
9009 case TRANSACT2_QFILEINFO:
9011 START_PROFILE(Trans2_qpathinfo);
9012 call_trans2qfilepathinfo(conn, req, state->call,
9013 &state->param, state->total_param,
9014 &state->data, state->total_data,
9015 state->max_data_return);
9016 END_PROFILE(Trans2_qpathinfo);
9017 break;
9020 case TRANSACT2_SETPATHINFO:
9021 case TRANSACT2_SETFILEINFO:
9023 START_PROFILE(Trans2_setpathinfo);
9024 call_trans2setfilepathinfo(conn, req, state->call,
9025 &state->param, state->total_param,
9026 &state->data, state->total_data,
9027 state->max_data_return);
9028 END_PROFILE(Trans2_setpathinfo);
9029 break;
9032 case TRANSACT2_FINDNOTIFYFIRST:
9034 START_PROFILE(Trans2_findnotifyfirst);
9035 call_trans2findnotifyfirst(conn, req,
9036 &state->param, state->total_param,
9037 &state->data, state->total_data,
9038 state->max_data_return);
9039 END_PROFILE(Trans2_findnotifyfirst);
9040 break;
9043 case TRANSACT2_FINDNOTIFYNEXT:
9045 START_PROFILE(Trans2_findnotifynext);
9046 call_trans2findnotifynext(conn, req,
9047 &state->param, state->total_param,
9048 &state->data, state->total_data,
9049 state->max_data_return);
9050 END_PROFILE(Trans2_findnotifynext);
9051 break;
9054 case TRANSACT2_MKDIR:
9056 START_PROFILE(Trans2_mkdir);
9057 call_trans2mkdir(conn, req,
9058 &state->param, state->total_param,
9059 &state->data, state->total_data,
9060 state->max_data_return);
9061 END_PROFILE(Trans2_mkdir);
9062 break;
9065 case TRANSACT2_GET_DFS_REFERRAL:
9067 START_PROFILE(Trans2_get_dfs_referral);
9068 call_trans2getdfsreferral(conn, req,
9069 &state->param, state->total_param,
9070 &state->data, state->total_data,
9071 state->max_data_return);
9072 END_PROFILE(Trans2_get_dfs_referral);
9073 break;
9076 case TRANSACT2_IOCTL:
9078 START_PROFILE(Trans2_ioctl);
9079 call_trans2ioctl(conn, req,
9080 &state->param, state->total_param,
9081 &state->data, state->total_data,
9082 state->max_data_return);
9083 END_PROFILE(Trans2_ioctl);
9084 break;
9087 default:
9088 /* Error in request */
9089 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9090 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9094 /****************************************************************************
9095 Reply to a SMBtrans2.
9096 ****************************************************************************/
9098 void reply_trans2(struct smb_request *req)
9100 connection_struct *conn = req->conn;
9101 unsigned int dsoff;
9102 unsigned int dscnt;
9103 unsigned int psoff;
9104 unsigned int pscnt;
9105 unsigned int tran_call;
9106 struct trans_state *state;
9107 NTSTATUS result;
9109 START_PROFILE(SMBtrans2);
9111 if (req->wct < 14) {
9112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9113 END_PROFILE(SMBtrans2);
9114 return;
9117 dsoff = SVAL(req->vwv+12, 0);
9118 dscnt = SVAL(req->vwv+11, 0);
9119 psoff = SVAL(req->vwv+10, 0);
9120 pscnt = SVAL(req->vwv+9, 0);
9121 tran_call = SVAL(req->vwv+14, 0);
9123 result = allow_new_trans(conn->pending_trans, req->mid);
9124 if (!NT_STATUS_IS_OK(result)) {
9125 DEBUG(2, ("Got invalid trans2 request: %s\n",
9126 nt_errstr(result)));
9127 reply_nterror(req, result);
9128 END_PROFILE(SMBtrans2);
9129 return;
9132 if (IS_IPC(conn)) {
9133 switch (tran_call) {
9134 /* List the allowed trans2 calls on IPC$ */
9135 case TRANSACT2_OPEN:
9136 case TRANSACT2_GET_DFS_REFERRAL:
9137 case TRANSACT2_QFILEINFO:
9138 case TRANSACT2_QFSINFO:
9139 case TRANSACT2_SETFSINFO:
9140 break;
9141 default:
9142 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9143 END_PROFILE(SMBtrans2);
9144 return;
9148 if ((state = talloc(conn, struct trans_state)) == NULL) {
9149 DEBUG(0, ("talloc failed\n"));
9150 reply_nterror(req, NT_STATUS_NO_MEMORY);
9151 END_PROFILE(SMBtrans2);
9152 return;
9155 state->cmd = SMBtrans2;
9157 state->mid = req->mid;
9158 state->vuid = req->vuid;
9159 state->setup_count = SVAL(req->vwv+13, 0);
9160 state->setup = NULL;
9161 state->total_param = SVAL(req->vwv+0, 0);
9162 state->param = NULL;
9163 state->total_data = SVAL(req->vwv+1, 0);
9164 state->data = NULL;
9165 state->max_param_return = SVAL(req->vwv+2, 0);
9166 state->max_data_return = SVAL(req->vwv+3, 0);
9167 state->max_setup_return = SVAL(req->vwv+4, 0);
9168 state->close_on_completion = BITSETW(req->vwv+5, 0);
9169 state->one_way = BITSETW(req->vwv+5, 1);
9171 state->call = tran_call;
9173 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9174 is so as a sanity check */
9175 if (state->setup_count != 1) {
9177 * Need to have rc=0 for ioctl to get job id for OS/2.
9178 * Network printing will fail if function is not successful.
9179 * Similar function in reply.c will be used if protocol
9180 * is LANMAN1.0 instead of LM1.2X002.
9181 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9182 * outbuf doesn't have to be set(only job id is used).
9184 if ( (state->setup_count == 4)
9185 && (tran_call == TRANSACT2_IOCTL)
9186 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9187 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9188 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9189 } else {
9190 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9191 DEBUG(2,("Transaction is %d\n",tran_call));
9192 TALLOC_FREE(state);
9193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9194 END_PROFILE(SMBtrans2);
9195 return;
9199 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9200 goto bad_param;
9202 if (state->total_data) {
9204 if (trans_oob(state->total_data, 0, dscnt)
9205 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9206 goto bad_param;
9209 /* Can't use talloc here, the core routines do realloc on the
9210 * params and data. */
9211 state->data = (char *)SMB_MALLOC(state->total_data);
9212 if (state->data == NULL) {
9213 DEBUG(0,("reply_trans2: data malloc fail for %u "
9214 "bytes !\n", (unsigned int)state->total_data));
9215 TALLOC_FREE(state);
9216 reply_nterror(req, NT_STATUS_NO_MEMORY);
9217 END_PROFILE(SMBtrans2);
9218 return;
9221 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9224 if (state->total_param) {
9226 if (trans_oob(state->total_param, 0, pscnt)
9227 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9228 goto bad_param;
9231 /* Can't use talloc here, the core routines do realloc on the
9232 * params and data. */
9233 state->param = (char *)SMB_MALLOC(state->total_param);
9234 if (state->param == NULL) {
9235 DEBUG(0,("reply_trans: param malloc fail for %u "
9236 "bytes !\n", (unsigned int)state->total_param));
9237 SAFE_FREE(state->data);
9238 TALLOC_FREE(state);
9239 reply_nterror(req, NT_STATUS_NO_MEMORY);
9240 END_PROFILE(SMBtrans2);
9241 return;
9244 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9247 state->received_data = dscnt;
9248 state->received_param = pscnt;
9250 if ((state->received_param == state->total_param) &&
9251 (state->received_data == state->total_data)) {
9253 handle_trans2(conn, req, state);
9255 SAFE_FREE(state->data);
9256 SAFE_FREE(state->param);
9257 TALLOC_FREE(state);
9258 END_PROFILE(SMBtrans2);
9259 return;
9262 DLIST_ADD(conn->pending_trans, state);
9264 /* We need to send an interim response then receive the rest
9265 of the parameter/data bytes */
9266 reply_outbuf(req, 0, 0);
9267 show_msg((char *)req->outbuf);
9268 END_PROFILE(SMBtrans2);
9269 return;
9271 bad_param:
9273 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9274 SAFE_FREE(state->data);
9275 SAFE_FREE(state->param);
9276 TALLOC_FREE(state);
9277 END_PROFILE(SMBtrans2);
9278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9282 /****************************************************************************
9283 Reply to a SMBtranss2
9284 ****************************************************************************/
9286 void reply_transs2(struct smb_request *req)
9288 connection_struct *conn = req->conn;
9289 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9290 struct trans_state *state;
9292 START_PROFILE(SMBtranss2);
9294 show_msg((const char *)req->inbuf);
9296 /* Windows clients expect all replies to
9297 a transact secondary (SMBtranss2 0x33)
9298 to have a command code of transact
9299 (SMBtrans2 0x32). See bug #8989
9300 and also [MS-CIFS] section 2.2.4.47.2
9301 for details.
9303 req->cmd = SMBtrans2;
9305 if (req->wct < 8) {
9306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9307 END_PROFILE(SMBtranss2);
9308 return;
9311 for (state = conn->pending_trans; state != NULL;
9312 state = state->next) {
9313 if (state->mid == req->mid) {
9314 break;
9318 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9320 END_PROFILE(SMBtranss2);
9321 return;
9324 /* Revise state->total_param and state->total_data in case they have
9325 changed downwards */
9327 if (SVAL(req->vwv+0, 0) < state->total_param)
9328 state->total_param = SVAL(req->vwv+0, 0);
9329 if (SVAL(req->vwv+1, 0) < state->total_data)
9330 state->total_data = SVAL(req->vwv+1, 0);
9332 pcnt = SVAL(req->vwv+2, 0);
9333 poff = SVAL(req->vwv+3, 0);
9334 pdisp = SVAL(req->vwv+4, 0);
9336 dcnt = SVAL(req->vwv+5, 0);
9337 doff = SVAL(req->vwv+6, 0);
9338 ddisp = SVAL(req->vwv+7, 0);
9340 state->received_param += pcnt;
9341 state->received_data += dcnt;
9343 if ((state->received_data > state->total_data) ||
9344 (state->received_param > state->total_param))
9345 goto bad_param;
9347 if (pcnt) {
9348 if (trans_oob(state->total_param, pdisp, pcnt)
9349 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9350 goto bad_param;
9352 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9355 if (dcnt) {
9356 if (trans_oob(state->total_data, ddisp, dcnt)
9357 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9358 goto bad_param;
9360 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9363 if ((state->received_param < state->total_param) ||
9364 (state->received_data < state->total_data)) {
9365 END_PROFILE(SMBtranss2);
9366 return;
9369 handle_trans2(conn, req, state);
9371 DLIST_REMOVE(conn->pending_trans, state);
9372 SAFE_FREE(state->data);
9373 SAFE_FREE(state->param);
9374 TALLOC_FREE(state);
9376 END_PROFILE(SMBtranss2);
9377 return;
9379 bad_param:
9381 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9382 DLIST_REMOVE(conn->pending_trans, state);
9383 SAFE_FREE(state->data);
9384 SAFE_FREE(state->param);
9385 TALLOC_FREE(state);
9386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9387 END_PROFILE(SMBtranss2);
9388 return;