VERSION: Disable git snapshots for the 4.1.4 release.
[Samba.git] / source3 / smbd / trans2.c
blob2f2bbf6e0672f951e94acf734e4541b50630f9dd
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
47 char *pdata,
48 files_struct *fsp,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
61 files_struct *fsp,
62 const struct smb_filename *smb_fname,
63 uint32_t access_mask)
65 if (fsp) {
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
69 } else {
70 NTSTATUS status = smbd_check_access_rights(conn,
71 smb_fname,
72 false,
73 access_mask);
74 if (!NT_STATUS_IS_OK(status)) {
75 return status;
78 return NT_STATUS_OK;
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
95 return val;
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 uint64_t file_index;
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 return file_index;
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
128 SAMBA_XATTR_MARKER,
129 XATTR_NTACL_NAME,
130 NULL
133 int i;
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 return true;
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
141 return true;
143 return false;
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
156 char *val = NULL;
157 ssize_t sizeret;
159 again:
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 if (!val) {
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 } else {
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
173 attr_size = 65536;
174 goto again;
177 if (sizeret == -1) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
184 pea->flags = 0;
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 } else {
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
191 TALLOC_FREE(val);
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
196 return NT_STATUS_OK;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
207 char *p;
208 char **names, **tmp;
209 size_t num_names;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
225 if (names == NULL) {
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
236 TALLOC_FREE(names);
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 ea_namelist_size);
243 } else {
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 ea_namelist_size);
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
251 else {
252 break;
256 if (sizeret == -1) {
257 TALLOC_FREE(names);
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
264 if (sizeret == 0) {
265 TALLOC_FREE(names);
266 if (pnames) {
267 *pnames = NULL;
269 *pnum_names = 0;
270 return NT_STATUS_OK;
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
278 TALLOC_FREE(names);
279 return NT_STATUS_INTERNAL_ERROR;
283 * count the names
285 num_names = 0;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 num_names += 1;
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 if (tmp == NULL) {
293 DEBUG(0, ("talloc failed\n"));
294 TALLOC_FREE(names);
295 return NT_STATUS_NO_MEMORY;
298 names = tmp;
299 num_names = 0;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
305 if (pnames) {
306 *pnames = names;
307 } else {
308 TALLOC_FREE(names);
310 *pnum_names = num_names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
322 size_t i, num_names;
323 char **names;
324 struct ea_list *ea_list_head = NULL;
325 NTSTATUS status;
327 *pea_total_len = 0;
328 *ea_list = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 &names, &num_names);
333 if (!NT_STATUS_IS_OK(status)) {
334 return status;
337 if (num_names == 0) {
338 *ea_list = NULL;
339 return NT_STATUS_OK;
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
344 fstring dos_ea_name;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
348 continue;
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
356 continue;
359 listp = talloc(mem_ctx, struct ea_list);
360 if (listp == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
365 fname, names[i],
366 &listp->ea);
368 if (!NT_STATUS_IS_OK(status)) {
369 TALLOC_FREE(listp);
370 return status;
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
378 TALLOC_FREE(listp);
379 continue;
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 *pea_total_len +=
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
397 *pea_total_len += 4;
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
404 return NT_STATUS_OK;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
410 *pea_total_len = 0;
411 *ea_list = NULL;
413 if (!lp_ea_support(SNUM(conn))) {
414 return NT_STATUS_OK;
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 that was filled.
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
433 char *p = pdata;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
438 SIVAL(pdata,4,0);
439 return 4;
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 size_t dos_namelen;
444 fstring dos_ea_name;
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
448 break;
450 if (ea_list->ea.value.length > 65535) {
451 break;
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
454 break;
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 char *pdata,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
485 *ret_data_size = 0;
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
492 size_t dos_namelen;
493 fstring dos_ea_name;
494 size_t this_size;
495 size_t pad = 0;
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 last_start = p;
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 if (ea_list->next) {
514 pad = (4 - (this_size % 4)) % 4;
515 this_size += pad;
518 if (do_store_data) {
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 if (pad) {
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
532 '\0',
533 pad);
535 total_data_size -= this_size;
538 p += this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
543 return NT_STATUS_OK;
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
549 TALLOC_CTX *mem_ctx;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
553 return 0;
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
560 * this case! */
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 fsp = NULL;
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
566 NTSTATUS status;
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
572 * marshalling.
574 status = fill_ea_chained_buffer(mem_ctx,
575 NULL,
577 &ret_data_size,
578 conn,
579 ea_list);
580 if (!NT_STATUS_IS_OK(status)) {
581 ret_data_size = 0;
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
586 return total_ea_len;
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 size_t total_ea_len;
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
600 return;
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
608 break;
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
620 NTSTATUS status;
621 char *fname = NULL;
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
629 return status;
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
649 int ret;
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 } else {
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 #ifdef ENOATTR
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
680 unix_ea_name));
681 ret = 0;
683 #endif
684 } else {
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 } else {
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (ret == -1) {
700 #ifdef ENOTSUP
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
704 #endif
705 return map_nt_error_from_unix(errno);
709 return NT_STATUS_OK;
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
730 break;
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
734 return NULL;
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 &converted_size)) {
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
741 if (!eal->ea.name) {
742 return NULL;
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
750 return ea_list_head;
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
760 size_t offset = 0;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
766 if (!eal) {
767 return NULL;
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
774 return ea_list_head;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
783 fstring dos_ea_name;
784 struct ea_list *listp;
785 size_t ret = 0;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
792 if (ret) {
793 ret += 4;
796 return ret;
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
812 break;
816 if (flistp) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
820 } else {
821 /* Null entry. */
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
828 return name_list;
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
840 NTSTATUS status,
841 const char *params,
842 int paramsize,
843 const char *pdata,
844 int datasize,
845 int max_data_bytes)
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
855 int useable_space;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
868 for OS/2. */
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
874 overflow = True;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
882 uint8_t eclass;
883 uint32_t ecode;
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
887 __LINE__,__FILE__);
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
891 (char *)req->outbuf,
892 true, req->seqnum+1,
893 IS_CONN_ENCRYPTED(conn),
894 &req->pcd)) {
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
898 return;
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
913 + 2 * 10 /* wct */
914 + alignment_offset
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
966 else
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
974 } else {
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1014 if (overflow) {
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1018 __LINE__,__FILE__);
1019 } else if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1034 &req->pcd))
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1045 /* Sanity check */
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1049 return;
1053 return;
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1069 int deny_mode;
1070 int32 open_attr;
1071 bool oplock_request;
1072 #if 0
1073 bool return_additional_info;
1074 int16 open_sattr;
1075 time_t open_time;
1076 #endif
1077 int open_ofun;
1078 uint32 open_size;
1079 char *pname;
1080 char *fname = NULL;
1081 off_t size=0;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1084 int smb_action = 0;
1085 files_struct *fsp;
1086 struct ea_list *ea_list = NULL;
1087 uint16 flags = 0;
1088 NTSTATUS status;
1089 uint32 access_mask;
1090 uint32 share_mode;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 goto out;
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1113 #if 0
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1117 #endif
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = &params[28];
1122 if (IS_IPC(conn)) {
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1124 goto out;
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1129 &status);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1132 goto out;
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1140 conn,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1142 fname,
1144 NULL,
1145 &smb_fname);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1151 goto out;
1153 reply_nterror(req, status);
1154 goto out;
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1159 goto out;
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1163 open_ofun,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1166 &create_options,
1167 &private_flags)) {
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1169 goto out;
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1176 goto out;
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1183 goto out;
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1187 total_data - 4);
1188 if (!ea_list) {
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1190 goto out;
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1195 goto out;
1198 if (ea_list_has_invalid_name(ea_list)) {
1199 int param_len = 30;
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1203 goto out;
1205 params = *pparams;
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1209 goto out;
1213 status = SMB_VFS_CREATE_FILE(
1214 conn, /* conn */
1215 req, /* req */
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1225 private_flags,
1226 NULL, /* sd */
1227 ea_list, /* ea_list */
1228 &fsp, /* result */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1234 goto out;
1236 reply_openerror(req, status);
1237 goto out;
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1247 goto out;
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1254 goto out;
1256 params = *pparams;
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1277 if (flags & 8) {
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1279 smb_fname);
1280 SIVAL(params, 26, ea_size);
1281 } else {
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1287 out:
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1300 const char *str,
1301 const char *mask)
1303 if (mask[0] == '.' && mask[1] == 0) {
1304 return false;
1307 if (has_wild) {
1308 return false;
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1313 } else {
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1324 if(S_ISREG(mode))
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1328 #ifdef S_ISLNK
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1331 #endif
1332 #ifdef S_ISCHR
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1335 #endif
1336 #ifdef S_ISBLK
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1339 #endif
1340 #ifdef S_ISFIFO
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1343 #endif
1344 #ifdef S_ISSOCK
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1347 #endif
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1361 uint32 perms,
1362 enum perm_type ptype,
1363 mode_t *ret_perms)
1365 mode_t ret = 0;
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1370 } else {
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1385 #ifdef S_ISVTX
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1387 #endif
1388 #ifdef S_ISGID
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1390 #endif
1391 #ifdef S_ISUID
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1393 #endif
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1413 *ret_perms = ret;
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 "as a directory\n",
1433 pathname));
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1436 return true;
1438 errno = saved_errno;
1439 return false;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1451 bool has_wild;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1456 void *private_data,
1457 const char *dname,
1458 const char *mask,
1459 char **_fname)
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1463 bool ok;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1465 bool got_match;
1466 const char *fname;
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1472 if (!ok) {
1473 return false;
1475 fname = mangled_name;
1476 } else {
1477 fname = dname;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1482 fname, mask);
1483 state->got_exact_match = got_match;
1484 if (!got_match) {
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1500 if (!ok) {
1501 return false;
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1508 if (!got_match) {
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1514 if (!got_match) {
1515 return false;
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1520 return false;
1523 return true;
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1527 void *private_data,
1528 struct smb_filename *smb_fname,
1529 uint32_t *_mode)
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1534 uint32_t mode = 0;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1541 strerror(errno)));
1542 return false;
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1547 * directories */
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1551 &smb_fname->st);
1552 if (!ms_dfs_link) {
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1556 strerror(errno)));
1557 return false;
1561 if (ms_dfs_link) {
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1563 } else {
1564 mode = dos_mode(state->conn, smb_fname);
1567 *_mode = mode;
1568 return true;
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1573 uint16_t flags2,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1578 uint32_t mode,
1579 const char *fname,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1582 uint8_t align,
1583 bool do_pad,
1584 char *base_data,
1585 char **ppdata,
1586 char *end_data,
1587 bool *out_of_space,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1591 uint32_t reskey=0;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1595 uint32_t len;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1598 char *nameptr;
1599 char *last_entry_ptr;
1600 bool was_8_3;
1601 int off;
1602 int pad = 0;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1639 pad -= off;
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1645 (unsigned int)pad,
1646 space_remaining ));
1647 return false; /* Not finished - just out of space */
1650 off += pad;
1651 /* initialize padding to 0 */
1652 if (pad) {
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1658 space_remaining ));
1660 pdata += pad;
1661 p = pdata;
1662 last_entry_ptr = p;
1664 pad = 0;
1665 off = 0;
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1671 SIVAL(p,0,reskey);
1672 p += 4;
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1679 SSVAL(p,20,mode);
1680 p += 23;
1681 nameptr = p;
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE);
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1689 if (len > 2) {
1690 SCVAL(nameptr, -1, len - 2);
1691 } else {
1692 SCVAL(nameptr, -1, 0);
1694 } else {
1695 if (len > 1) {
1696 SCVAL(nameptr, -1, len - 1);
1697 } else {
1698 SCVAL(nameptr, -1, 0);
1701 p += len;
1702 break;
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\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)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1715 SSVAL(p,20,mode);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1718 smb_fname);
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1721 p += 27;
1722 nameptr = p - 1;
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1727 if (len > 2) {
1728 len -= 2;
1729 } else {
1730 len = 0;
1732 } else {
1733 if (len > 1) {
1734 len -= 1;
1735 } else {
1736 len = 0;
1739 SCVAL(nameptr,0,len);
1740 p += len;
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 break;
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1747 size_t ea_len = 0;
1748 NTSTATUS status;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1751 if (!name_list) {
1752 return false;
1754 if (requires_resume_key) {
1755 SIVAL(p,0,reskey);
1756 p += 4;
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1763 SSVAL(p,20,mode);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1767 smb_fname,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 file_list = NULL;
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1781 space_remaining ));
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1787 nameptr = p;
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1792 if (len > 2) {
1793 len -= 2;
1794 } else {
1795 len = 0;
1797 } else {
1798 if (len > 1) {
1799 len -= 1;
1800 } else {
1801 len = 0;
1804 SCVAL(nameptr,0,len);
1805 p += len + 1;
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1807 break;
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1813 p += 4;
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1825 } else {
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1827 smb_fname);
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1830 p += 4;
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1838 conn->params)) {
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1846 if (len < 24) {
1847 memset(p + 2 + len,'\0',24 - len);
1849 SSVAL(p, 0, len);
1850 } else {
1851 memset(p,'\0',26);
1853 p += 2 + 24;
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1857 SIVAL(q,0,len);
1858 p += len;
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1867 SIVAL(pdata,0,pad);
1869 * set padding to zero
1871 if (do_pad) {
1872 memset(p, 0, pad - len);
1873 p = pdata + pad;
1874 } else {
1875 p = pdata + len;
1877 break;
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1881 p += 4;
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1893 SIVAL(p,0,len);
1894 p += 4 + len;
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1903 SIVAL(pdata,0,pad);
1905 * set padding to zero
1907 if (do_pad) {
1908 memset(p, 0, pad - len);
1909 p = pdata + pad;
1910 } else {
1911 p = pdata + len;
1913 break;
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1936 SIVAL(q, 0, len);
1937 p += len;
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1946 SIVAL(pdata,0,pad);
1948 * set padding to zero
1950 if (do_pad) {
1951 memset(p, 0, pad - len);
1952 p = pdata + pad;
1953 } else {
1954 p = pdata + len;
1956 break;
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1960 p += 4;
1961 SIVAL(p,0,reskey); p += 4;
1962 p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1968 SIVAL(p, -4, len);
1969 p += len;
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1978 SIVAL(pdata,0,pad);
1980 * set padding to zero
1982 if (do_pad) {
1983 memset(p, 0, pad - len);
1984 p = pdata + pad;
1985 } else {
1986 p = pdata + len;
1988 break;
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1992 p += 4;
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2004 } else {
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2006 smb_fname);
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2009 p += 4;
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2015 SIVAL(q, 0, len);
2016 p += len;
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2025 SIVAL(pdata,0,pad);
2027 * set padding to zero
2029 if (do_pad) {
2030 memset(p, 0, pad - len);
2031 p = pdata + pad;
2032 } else {
2033 p = pdata + len;
2035 break;
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2040 p += 4;
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2052 } else {
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2054 smb_fname);
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2057 p += 4;
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2065 conn->params)) {
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2073 SSVAL(p, 0, len);
2074 if (len < 24) {
2075 memset(p + 2 + len,'\0',24 - len);
2077 SSVAL(p, 0, len);
2078 } else {
2079 memset(p,'\0',26);
2081 p += 26;
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
2087 SIVAL(q,0,len);
2088 p += len;
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2097 SIVAL(pdata,0,pad);
2099 * set padding to zero
2101 if (do_pad) {
2102 memset(p, 0, pad - len);
2103 p = pdata + pad;
2104 } else {
2105 p = pdata + len;
2107 break;
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2113 p+= 4;
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2124 STR_TERMINATE);
2125 } else {
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2129 nameptr = p;
2130 p += 4;
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2136 p += len;
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2145 SIVAL(pdata,0,pad);
2147 * set padding to zero
2149 if (do_pad) {
2150 memset(p, 0, pad - len);
2151 p = pdata + pad;
2152 } else {
2153 p = pdata + len;
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2157 break;
2159 default:
2160 return false;
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2168 space_remaining ));
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2175 *ppdata = p;
2177 return true;
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 int requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 uint8_t align,
2191 bool do_pad,
2192 char **ppdata,
2193 char *base_data,
2194 char *end_data,
2195 int space_remaining,
2196 bool *out_of_space,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2201 const char *p;
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2204 uint32_t mode = 0;
2205 char *fname = NULL;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2208 bool ok;
2209 uint64_t last_entry_off = 0;
2211 ZERO_STRUCT(state);
2212 state.conn = conn;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2222 if(p != NULL) {
2223 if(p[1] == '\0') {
2224 mask = "*.*";
2225 } else {
2226 mask = p+1;
2228 } else {
2229 mask = path_mask;
2232 ok = smbd_dirptr_get_entry(ctx,
2233 dirptr,
2234 mask,
2235 dirtype,
2236 dont_descend,
2237 ask_sharemode,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2240 &state,
2241 &fname,
2242 &smb_fname,
2243 &mode,
2244 &prev_dirpos);
2245 if (!ok) {
2246 return false;
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2252 conn,
2253 flags2,
2254 info_level,
2255 name_list,
2256 state.check_mangled_names,
2257 requires_resume_key,
2258 mode,
2259 fname,
2260 smb_fname,
2261 space_remaining,
2262 align,
2263 do_pad,
2264 base_data,
2265 ppdata,
2266 end_data,
2267 out_of_space,
2268 &last_entry_off);
2269 TALLOC_FREE(fname);
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2273 return false;
2275 if (!ok) {
2276 return false;
2279 *_last_entry_off = last_entry_off;
2280 return true;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2286 uint16 flags2,
2287 const char *path_mask,
2288 uint32 dirtype,
2289 int info_level,
2290 bool requires_resume_key,
2291 bool dont_descend,
2292 bool ask_sharemode,
2293 char **ppdata,
2294 char *base_data,
2295 char *end_data,
2296 int space_remaining,
2297 bool *out_of_space,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2302 uint8_t align = 4;
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2307 align = 1;
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2313 align, do_pad,
2314 ppdata, base_data, end_data,
2315 space_remaining,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2334 requested. */
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2338 char *data_end;
2339 uint32 dirtype;
2340 int maxentries;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2343 bool close_if_end;
2344 bool requires_resume_key;
2345 int info_level;
2346 char *directory = NULL;
2347 char *mask = NULL;
2348 char *p;
2349 int last_entry_off=0;
2350 int dptr_num = -1;
2351 int numentries = 0;
2352 int i;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2367 if (total_params < 13) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2372 dirtype = SVAL(params,0);
2373 maxentries = SVAL(params,2);
2374 findfirst_flags = SVAL(params,4);
2375 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2376 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2377 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2378 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2379 security_token_has_privilege(get_current_nttok(conn),
2380 SEC_PRIV_BACKUP));
2382 info_level = SVAL(params,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2387 (int)backup_priv,
2388 info_level, max_data_bytes));
2390 if (!maxentries) {
2391 /* W2K3 seems to treat zero as 1. */
2392 maxentries = 1;
2395 switch (info_level) {
2396 case SMB_FIND_INFO_STANDARD:
2397 case SMB_FIND_EA_SIZE:
2398 case SMB_FIND_EA_LIST:
2399 case SMB_FIND_FILE_DIRECTORY_INFO:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_NAMES_INFO:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2405 break;
2406 case SMB_FIND_FILE_UNIX:
2407 case SMB_FIND_FILE_UNIX_INFO2:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode = false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 goto out;
2414 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 break;
2416 default:
2417 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2418 goto out;
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2422 params+12, total_params - 12,
2423 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2424 if (!NT_STATUS_IS_OK(ntstatus)) {
2425 reply_nterror(req, ntstatus);
2426 goto out;
2429 if (backup_priv) {
2430 become_root();
2431 ntstatus = filename_convert_with_privilege(ctx,
2432 conn,
2433 req,
2434 directory,
2435 ucf_flags,
2436 &mask_contains_wcard,
2437 &smb_dname);
2438 } else {
2439 ntstatus = filename_convert(ctx, conn,
2440 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 directory,
2442 ucf_flags,
2443 &mask_contains_wcard,
2444 &smb_dname);
2447 if (!NT_STATUS_IS_OK(ntstatus)) {
2448 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2450 ERRSRV, ERRbadpath);
2451 goto out;
2453 reply_nterror(req, ntstatus);
2454 goto out;
2457 mask = smb_dname->original_lcomp;
2459 directory = smb_dname->base_name;
2461 p = strrchr_m(directory,'/');
2462 if(p == NULL) {
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory[0] == '.') && (directory[1] == '\0')) {
2465 mask = talloc_strdup(ctx,"*");
2466 if (!mask) {
2467 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 goto out;
2470 mask_contains_wcard = True;
2472 } else {
2473 *p = 0;
2476 if (p == NULL || p == directory) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory = talloc_strdup(talloc_tos(), ".");
2479 if (!directory) {
2480 reply_nterror(req, NT_STATUS_NO_MEMORY);
2481 goto out;
2485 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2487 if (info_level == SMB_FIND_EA_LIST) {
2488 uint32 ea_size;
2490 if (total_data < 4) {
2491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2492 goto out;
2495 ea_size = IVAL(pdata,0);
2496 if (ea_size != total_data) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 goto out;
2503 if (!lp_ea_support(SNUM(conn))) {
2504 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2505 goto out;
2508 /* Pull out the list of names. */
2509 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2510 if (!ea_list) {
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2512 goto out;
2516 *ppdata = (char *)SMB_REALLOC(
2517 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2518 if(*ppdata == NULL ) {
2519 reply_nterror(req, NT_STATUS_NO_MEMORY);
2520 goto out;
2522 pdata = *ppdata;
2523 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2525 /* Realloc the params space */
2526 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2527 if (*pparams == NULL) {
2528 reply_nterror(req, NT_STATUS_NO_MEMORY);
2529 goto out;
2531 params = *pparams;
2533 /* Save the wildcard match and attribs we are using on this directory -
2534 needed as lanman2 assumes these are being saved between calls */
2536 ntstatus = dptr_create(conn,
2537 req,
2538 NULL, /* fsp */
2539 directory,
2540 False,
2541 True,
2542 req->smbpid,
2543 mask,
2544 mask_contains_wcard,
2545 dirtype,
2546 &dirptr);
2548 if (!NT_STATUS_IS_OK(ntstatus)) {
2549 reply_nterror(req, ntstatus);
2550 goto out;
2553 if (backup_priv) {
2554 /* Remember this in case we have
2555 to do a findnext. */
2556 dptr_set_priv(dirptr);
2559 dptr_num = dptr_dnum(dirptr);
2560 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2562 /* Initialize per TRANS2_FIND_FIRST operation data */
2563 dptr_init_search_op(dirptr);
2565 /* We don't need to check for VOL here as this is returned by
2566 a different TRANS2 call. */
2568 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2569 directory,lp_dontdescend(ctx, SNUM(conn))));
2570 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2571 dont_descend = True;
2573 p = pdata;
2574 space_remaining = max_data_bytes;
2575 out_of_space = False;
2577 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2578 bool got_exact_match = False;
2580 /* this is a heuristic to avoid seeking the dirptr except when
2581 absolutely necessary. It allows for a filename of about 40 chars */
2582 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2583 out_of_space = True;
2584 finished = False;
2585 } else {
2586 finished = !get_lanman2_dir_entry(ctx,
2587 conn,
2588 dirptr,
2589 req->flags2,
2590 mask,dirtype,info_level,
2591 requires_resume_key,dont_descend,
2592 ask_sharemode,
2593 &p,pdata,data_end,
2594 space_remaining, &out_of_space,
2595 &got_exact_match,
2596 &last_entry_off, ea_list);
2599 if (finished && out_of_space)
2600 finished = False;
2602 if (!finished && !out_of_space)
2603 numentries++;
2606 * As an optimisation if we know we aren't looking
2607 * for a wildcard name (ie. the name matches the wildcard exactly)
2608 * then we can finish on any (first) match.
2609 * This speeds up large directory searches. JRA.
2612 if(got_exact_match)
2613 finished = True;
2615 /* Ensure space_remaining never goes -ve. */
2616 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2617 space_remaining = 0;
2618 out_of_space = true;
2619 } else {
2620 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2624 /* Check if we can close the dirptr */
2625 if(close_after_first || (finished && close_if_end)) {
2626 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2627 dptr_close(sconn, &dptr_num);
2631 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2632 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2633 * the protocol level is less than NT1. Tested with smbclient. JRA.
2634 * This should fix the OS/2 client bug #2335.
2637 if(numentries == 0) {
2638 dptr_close(sconn, &dptr_num);
2639 if (get_Protocol() < PROTOCOL_NT1) {
2640 reply_force_doserror(req, ERRDOS, ERRnofiles);
2641 goto out;
2642 } else {
2643 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2644 ERRDOS, ERRbadfile);
2645 goto out;
2649 /* At this point pdata points to numentries directory entries. */
2651 /* Set up the return parameter block */
2652 SSVAL(params,0,dptr_num);
2653 SSVAL(params,2,numentries);
2654 SSVAL(params,4,finished);
2655 SSVAL(params,6,0); /* Never an EA error */
2656 SSVAL(params,8,last_entry_off);
2658 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2659 max_data_bytes);
2661 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2662 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2663 if (!directory) {
2664 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2669 smb_fn_name(req->cmd),
2670 mask, directory, dirtype, numentries ) );
2673 * Force a name mangle here to ensure that the
2674 * mask as an 8.3 name is top of the mangled cache.
2675 * The reasons for this are subtle. Don't remove
2676 * this code unless you know what you are doing
2677 * (see PR#13758). JRA.
2680 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2681 char mangled_name[13];
2682 name_to_8_3(mask, mangled_name, True, conn->params);
2684 out:
2686 if (backup_priv) {
2687 unbecome_root();
2690 TALLOC_FREE(smb_dname);
2691 return;
2694 /****************************************************************************
2695 Reply to a TRANS2_FINDNEXT.
2696 ****************************************************************************/
2698 static void call_trans2findnext(connection_struct *conn,
2699 struct smb_request *req,
2700 char **pparams, int total_params,
2701 char **ppdata, int total_data,
2702 unsigned int max_data_bytes)
2704 /* We must be careful here that we don't return more than the
2705 allowed number of data bytes. If this means returning fewer than
2706 maxentries then so be it. We assume that the redirector has
2707 enough room for the fixed number of parameter bytes it has
2708 requested. */
2709 char *params = *pparams;
2710 char *pdata = *ppdata;
2711 char *data_end;
2712 int dptr_num;
2713 int maxentries;
2714 uint16 info_level;
2715 uint32 resume_key;
2716 uint16 findnext_flags;
2717 bool close_after_request;
2718 bool close_if_end;
2719 bool requires_resume_key;
2720 bool continue_bit;
2721 bool mask_contains_wcard = False;
2722 char *resume_name = NULL;
2723 const char *mask = NULL;
2724 const char *directory = NULL;
2725 char *p = NULL;
2726 uint16 dirtype;
2727 int numentries = 0;
2728 int i, last_entry_off=0;
2729 bool finished = False;
2730 bool dont_descend = False;
2731 bool out_of_space = False;
2732 int space_remaining;
2733 struct ea_list *ea_list = NULL;
2734 NTSTATUS ntstatus = NT_STATUS_OK;
2735 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2736 TALLOC_CTX *ctx = talloc_tos();
2737 struct dptr_struct *dirptr;
2738 struct smbd_server_connection *sconn = req->sconn;
2739 bool backup_priv = false;
2741 if (total_params < 13) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2743 return;
2746 dptr_num = SVAL(params,0);
2747 maxentries = SVAL(params,2);
2748 info_level = SVAL(params,4);
2749 resume_key = IVAL(params,6);
2750 findnext_flags = SVAL(params,10);
2751 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2752 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2753 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2754 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2756 if (!continue_bit) {
2757 /* We only need resume_name if continue_bit is zero. */
2758 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2759 params+12,
2760 total_params - 12, STR_TERMINATE, &ntstatus,
2761 &mask_contains_wcard);
2762 if (!NT_STATUS_IS_OK(ntstatus)) {
2763 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2764 complain (it thinks we're asking for the directory above the shared
2765 path or an invalid name). Catch this as the resume name is only compared, never used in
2766 a file access. JRA. */
2767 srvstr_pull_talloc(ctx, params, req->flags2,
2768 &resume_name, params+12,
2769 total_params - 12,
2770 STR_TERMINATE);
2772 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2773 reply_nterror(req, ntstatus);
2774 return;
2779 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2780 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2781 resume_key = %d resume name = %s continue=%d level = %d\n",
2782 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2783 requires_resume_key, resume_key,
2784 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2786 if (!maxentries) {
2787 /* W2K3 seems to treat zero as 1. */
2788 maxentries = 1;
2791 switch (info_level) {
2792 case SMB_FIND_INFO_STANDARD:
2793 case SMB_FIND_EA_SIZE:
2794 case SMB_FIND_EA_LIST:
2795 case SMB_FIND_FILE_DIRECTORY_INFO:
2796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2797 case SMB_FIND_FILE_NAMES_INFO:
2798 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2799 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2801 break;
2802 case SMB_FIND_FILE_UNIX:
2803 case SMB_FIND_FILE_UNIX_INFO2:
2804 /* Always use filesystem for UNIX mtime query. */
2805 ask_sharemode = false;
2806 if (!lp_unix_extensions()) {
2807 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2808 return;
2810 break;
2811 default:
2812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 return;
2816 if (info_level == SMB_FIND_EA_LIST) {
2817 uint32 ea_size;
2819 if (total_data < 4) {
2820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 return;
2824 ea_size = IVAL(pdata,0);
2825 if (ea_size != total_data) {
2826 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2827 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2829 return;
2832 if (!lp_ea_support(SNUM(conn))) {
2833 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2834 return;
2837 /* Pull out the list of names. */
2838 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2839 if (!ea_list) {
2840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2841 return;
2845 *ppdata = (char *)SMB_REALLOC(
2846 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2847 if(*ppdata == NULL) {
2848 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 return;
2852 pdata = *ppdata;
2853 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2855 /* Realloc the params space */
2856 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2857 if(*pparams == NULL ) {
2858 reply_nterror(req, NT_STATUS_NO_MEMORY);
2859 return;
2862 params = *pparams;
2864 /* Check that the dptr is valid */
2865 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2866 reply_nterror(req, STATUS_NO_MORE_FILES);
2867 return;
2870 directory = dptr_path(sconn, dptr_num);
2872 /* Get the wildcard mask from the dptr */
2873 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2874 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2875 reply_nterror(req, STATUS_NO_MORE_FILES);
2876 return;
2879 /* Get the attr mask from the dptr */
2880 dirtype = dptr_attr(sconn, dptr_num);
2882 backup_priv = dptr_get_priv(dirptr);
2884 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2885 "backup_priv = %d\n",
2886 dptr_num, mask, dirtype,
2887 (long)dirptr,
2888 dptr_TellDir(dirptr),
2889 (int)backup_priv));
2891 /* Initialize per TRANS2_FIND_NEXT operation data */
2892 dptr_init_search_op(dirptr);
2894 /* We don't need to check for VOL here as this is returned by
2895 a different TRANS2 call. */
2897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2898 directory,lp_dontdescend(ctx, SNUM(conn))));
2899 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2900 dont_descend = True;
2902 p = pdata;
2903 space_remaining = max_data_bytes;
2904 out_of_space = False;
2906 if (backup_priv) {
2907 become_root();
2911 * Seek to the correct position. We no longer use the resume key but
2912 * depend on the last file name instead.
2915 if(!continue_bit && resume_name && *resume_name) {
2916 SMB_STRUCT_STAT st;
2918 long current_pos = 0;
2920 * Remember, name_to_8_3 is called by
2921 * get_lanman2_dir_entry(), so the resume name
2922 * could be mangled. Ensure we check the unmangled name.
2925 if (mangle_is_mangled(resume_name, conn->params)) {
2926 char *new_resume_name = NULL;
2927 mangle_lookup_name_from_8_3(ctx,
2928 resume_name,
2929 &new_resume_name,
2930 conn->params);
2931 if (new_resume_name) {
2932 resume_name = new_resume_name;
2937 * Fix for NT redirector problem triggered by resume key indexes
2938 * changing between directory scans. We now return a resume key of 0
2939 * and instead look for the filename to continue from (also given
2940 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2941 * findfirst/findnext (as is usual) then the directory pointer
2942 * should already be at the correct place.
2945 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2946 } /* end if resume_name && !continue_bit */
2948 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2949 bool got_exact_match = False;
2951 /* this is a heuristic to avoid seeking the dirptr except when
2952 absolutely necessary. It allows for a filename of about 40 chars */
2953 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2954 out_of_space = True;
2955 finished = False;
2956 } else {
2957 finished = !get_lanman2_dir_entry(ctx,
2958 conn,
2959 dirptr,
2960 req->flags2,
2961 mask,dirtype,info_level,
2962 requires_resume_key,dont_descend,
2963 ask_sharemode,
2964 &p,pdata,data_end,
2965 space_remaining, &out_of_space,
2966 &got_exact_match,
2967 &last_entry_off, ea_list);
2970 if (finished && out_of_space)
2971 finished = False;
2973 if (!finished && !out_of_space)
2974 numentries++;
2977 * As an optimisation if we know we aren't looking
2978 * for a wildcard name (ie. the name matches the wildcard exactly)
2979 * then we can finish on any (first) match.
2980 * This speeds up large directory searches. JRA.
2983 if(got_exact_match)
2984 finished = True;
2986 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2989 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req->cmd),
2991 mask, directory, dirtype, numentries ) );
2993 /* Check if we can close the dirptr */
2994 if(close_after_request || (finished && close_if_end)) {
2995 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2996 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2999 if (backup_priv) {
3000 unbecome_root();
3003 /* Set up the return parameter block */
3004 SSVAL(params,0,numentries);
3005 SSVAL(params,2,finished);
3006 SSVAL(params,4,0); /* Never an EA error */
3007 SSVAL(params,6,last_entry_off);
3009 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3010 max_data_bytes);
3012 return;
3015 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3017 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3018 return objid;
3021 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3023 SMB_ASSERT(extended_info != NULL);
3025 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3026 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3027 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3028 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3029 #ifdef SAMBA_VERSION_REVISION
3030 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3031 #endif
3032 extended_info->samba_subversion = 0;
3033 #ifdef SAMBA_VERSION_RC_RELEASE
3034 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3035 #else
3036 #ifdef SAMBA_VERSION_PRE_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3038 #endif
3039 #endif
3040 #ifdef SAMBA_VERSION_VENDOR_PATCH
3041 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3042 #endif
3043 extended_info->samba_gitcommitdate = 0;
3044 #ifdef SAMBA_VERSION_COMMIT_TIME
3045 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3046 #endif
3048 memset(extended_info->samba_version_string, 0,
3049 sizeof(extended_info->samba_version_string));
3051 snprintf (extended_info->samba_version_string,
3052 sizeof(extended_info->samba_version_string),
3053 "%s", samba_version_string());
3056 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3057 TALLOC_CTX *mem_ctx,
3058 uint16_t info_level,
3059 uint16_t flags2,
3060 unsigned int max_data_bytes,
3061 size_t *fixed_portion,
3062 struct smb_filename *fname,
3063 char **ppdata,
3064 int *ret_data_len)
3066 char *pdata, *end_data;
3067 int data_len = 0, len;
3068 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3069 int snum = SNUM(conn);
3070 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3071 char *filename = NULL;
3072 uint32 additional_flags = 0;
3073 struct smb_filename smb_fname;
3074 SMB_STRUCT_STAT st;
3075 NTSTATUS status = NT_STATUS_OK;
3077 if (fname == NULL || fname->base_name == NULL) {
3078 filename = ".";
3079 } else {
3080 filename = fname->base_name;
3083 if (IS_IPC(conn)) {
3084 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3085 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3086 "info level (0x%x) on IPC$.\n",
3087 (unsigned int)info_level));
3088 return NT_STATUS_ACCESS_DENIED;
3092 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3094 ZERO_STRUCT(smb_fname);
3095 smb_fname.base_name = discard_const_p(char, filename);
3097 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3098 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3099 return map_nt_error_from_unix(errno);
3102 st = smb_fname.st;
3104 *ppdata = (char *)SMB_REALLOC(
3105 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3106 if (*ppdata == NULL) {
3107 return NT_STATUS_NO_MEMORY;
3110 pdata = *ppdata;
3111 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3112 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3114 *fixed_portion = 0;
3116 switch (info_level) {
3117 case SMB_INFO_ALLOCATION:
3119 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3120 data_len = 18;
3121 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3122 return map_nt_error_from_unix(errno);
3125 block_size = lp_block_size(snum);
3126 if (bsize < block_size) {
3127 uint64_t factor = block_size/bsize;
3128 bsize = block_size;
3129 dsize /= factor;
3130 dfree /= factor;
3132 if (bsize > block_size) {
3133 uint64_t factor = bsize/block_size;
3134 bsize = block_size;
3135 dsize *= factor;
3136 dfree *= factor;
3138 bytes_per_sector = 512;
3139 sectors_per_unit = bsize/bytes_per_sector;
3141 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3142 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3143 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3145 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3146 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3147 SIVAL(pdata,l1_cUnit,dsize);
3148 SIVAL(pdata,l1_cUnitAvail,dfree);
3149 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3150 break;
3153 case SMB_INFO_VOLUME:
3154 /* Return volume name */
3156 * Add volume serial number - hash of a combination of
3157 * the called hostname and the service name.
3159 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3161 * Win2k3 and previous mess this up by sending a name length
3162 * one byte short. I believe only older clients (OS/2 Win9x) use
3163 * this call so try fixing this by adding a terminating null to
3164 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3166 len = srvstr_push(
3167 pdata, flags2,
3168 pdata+l2_vol_szVolLabel, vname,
3169 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3170 STR_NOALIGN|STR_TERMINATE);
3171 SCVAL(pdata,l2_vol_cch,len);
3172 data_len = l2_vol_szVolLabel + len;
3173 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3174 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3175 len, vname));
3176 break;
3178 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3179 case SMB_FS_ATTRIBUTE_INFORMATION:
3181 additional_flags = 0;
3182 #if defined(HAVE_SYS_QUOTAS)
3183 additional_flags |= FILE_VOLUME_QUOTAS;
3184 #endif
3186 if(lp_nt_acl_support(SNUM(conn))) {
3187 additional_flags |= FILE_PERSISTENT_ACLS;
3190 /* Capabilities are filled in at connection time through STATVFS call */
3191 additional_flags |= conn->fs_capabilities;
3192 additional_flags |= lp_parm_int(conn->params->service,
3193 "share", "fake_fscaps",
3196 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3197 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3198 additional_flags); /* FS ATTRIBUTES */
3200 SIVAL(pdata,4,255); /* Max filename component length */
3201 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3202 and will think we can't do long filenames */
3203 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3204 PTR_DIFF(end_data, pdata+12),
3205 STR_UNICODE);
3206 SIVAL(pdata,8,len);
3207 data_len = 12 + len;
3208 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3209 /* the client only requested a portion of the
3210 file system name */
3211 data_len = max_data_bytes;
3212 status = STATUS_BUFFER_OVERFLOW;
3214 *fixed_portion = 16;
3215 break;
3217 case SMB_QUERY_FS_LABEL_INFO:
3218 case SMB_FS_LABEL_INFORMATION:
3219 len = srvstr_push(pdata, flags2, pdata+4, vname,
3220 PTR_DIFF(end_data, pdata+4), 0);
3221 data_len = 4 + len;
3222 SIVAL(pdata,0,len);
3223 break;
3225 case SMB_QUERY_FS_VOLUME_INFO:
3226 case SMB_FS_VOLUME_INFORMATION:
3229 * Add volume serial number - hash of a combination of
3230 * the called hostname and the service name.
3232 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3233 (str_checksum(get_local_machine_name())<<16));
3235 /* Max label len is 32 characters. */
3236 len = srvstr_push(pdata, flags2, pdata+18, vname,
3237 PTR_DIFF(end_data, pdata+18),
3238 STR_UNICODE);
3239 SIVAL(pdata,12,len);
3240 data_len = 18+len;
3242 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3243 (int)strlen(vname),vname,
3244 lp_servicename(talloc_tos(), snum)));
3245 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3246 /* the client only requested a portion of the
3247 volume label */
3248 data_len = max_data_bytes;
3249 status = STATUS_BUFFER_OVERFLOW;
3251 *fixed_portion = 24;
3252 break;
3254 case SMB_QUERY_FS_SIZE_INFO:
3255 case SMB_FS_SIZE_INFORMATION:
3257 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3258 data_len = 24;
3259 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3260 return map_nt_error_from_unix(errno);
3262 block_size = lp_block_size(snum);
3263 if (bsize < block_size) {
3264 uint64_t factor = block_size/bsize;
3265 bsize = block_size;
3266 dsize /= factor;
3267 dfree /= factor;
3269 if (bsize > block_size) {
3270 uint64_t factor = bsize/block_size;
3271 bsize = block_size;
3272 dsize *= factor;
3273 dfree *= factor;
3275 bytes_per_sector = 512;
3276 sectors_per_unit = bsize/bytes_per_sector;
3277 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3278 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3279 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3280 SBIG_UINT(pdata,0,dsize);
3281 SBIG_UINT(pdata,8,dfree);
3282 SIVAL(pdata,16,sectors_per_unit);
3283 SIVAL(pdata,20,bytes_per_sector);
3284 *fixed_portion = 24;
3285 break;
3288 case SMB_FS_FULL_SIZE_INFORMATION:
3290 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3291 data_len = 32;
3292 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3293 return map_nt_error_from_unix(errno);
3295 block_size = lp_block_size(snum);
3296 if (bsize < block_size) {
3297 uint64_t factor = block_size/bsize;
3298 bsize = block_size;
3299 dsize /= factor;
3300 dfree /= factor;
3302 if (bsize > block_size) {
3303 uint64_t factor = bsize/block_size;
3304 bsize = block_size;
3305 dsize *= factor;
3306 dfree *= factor;
3308 bytes_per_sector = 512;
3309 sectors_per_unit = bsize/bytes_per_sector;
3310 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3311 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3312 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3313 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3314 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3315 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3316 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3317 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3318 *fixed_portion = 32;
3319 break;
3322 case SMB_QUERY_FS_DEVICE_INFO:
3323 case SMB_FS_DEVICE_INFORMATION:
3325 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3327 if (!CAN_WRITE(conn)) {
3328 characteristics |= FILE_READ_ONLY_DEVICE;
3330 data_len = 8;
3331 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3332 SIVAL(pdata,4,characteristics);
3333 *fixed_portion = 8;
3334 break;
3337 #ifdef HAVE_SYS_QUOTAS
3338 case SMB_FS_QUOTA_INFORMATION:
3340 * what we have to send --metze:
3342 * Unknown1: 24 NULL bytes
3343 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3344 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3345 * Quota Flags: 2 byte :
3346 * Unknown3: 6 NULL bytes
3348 * 48 bytes total
3350 * details for Quota Flags:
3352 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3353 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3354 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3355 * 0x0001 Enable Quotas: enable quota for this fs
3359 /* we need to fake up a fsp here,
3360 * because its not send in this call
3362 files_struct fsp;
3363 SMB_NTQUOTA_STRUCT quotas;
3365 ZERO_STRUCT(fsp);
3366 ZERO_STRUCT(quotas);
3368 fsp.conn = conn;
3369 fsp.fnum = FNUM_FIELD_INVALID;
3371 /* access check */
3372 if (get_current_uid(conn) != 0) {
3373 DEBUG(0,("set_user_quota: access_denied "
3374 "service [%s] user [%s]\n",
3375 lp_servicename(talloc_tos(), SNUM(conn)),
3376 conn->session_info->unix_info->unix_name));
3377 return NT_STATUS_ACCESS_DENIED;
3380 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3381 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3382 return map_nt_error_from_unix(errno);
3385 data_len = 48;
3387 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3388 lp_servicename(talloc_tos(), SNUM(conn))));
3390 /* Unknown1 24 NULL bytes*/
3391 SBIG_UINT(pdata,0,(uint64_t)0);
3392 SBIG_UINT(pdata,8,(uint64_t)0);
3393 SBIG_UINT(pdata,16,(uint64_t)0);
3395 /* Default Soft Quota 8 bytes */
3396 SBIG_UINT(pdata,24,quotas.softlim);
3398 /* Default Hard Quota 8 bytes */
3399 SBIG_UINT(pdata,32,quotas.hardlim);
3401 /* Quota flag 2 bytes */
3402 SSVAL(pdata,40,quotas.qflags);
3404 /* Unknown3 6 NULL bytes */
3405 SSVAL(pdata,42,0);
3406 SIVAL(pdata,44,0);
3408 break;
3410 #endif /* HAVE_SYS_QUOTAS */
3411 case SMB_FS_OBJECTID_INFORMATION:
3413 unsigned char objid[16];
3414 struct smb_extended_info extended_info;
3415 memcpy(pdata,create_volume_objectid(conn, objid),16);
3416 samba_extended_info_version (&extended_info);
3417 SIVAL(pdata,16,extended_info.samba_magic);
3418 SIVAL(pdata,20,extended_info.samba_version);
3419 SIVAL(pdata,24,extended_info.samba_subversion);
3420 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3421 memcpy(pdata+36,extended_info.samba_version_string,28);
3422 data_len = 64;
3423 break;
3427 * Query the version and capabilities of the CIFS UNIX extensions
3428 * in use.
3431 case SMB_QUERY_CIFS_UNIX_INFO:
3433 bool large_write = lp_min_receive_file_size() &&
3434 !srv_is_signing_active(conn->sconn);
3435 bool large_read = !srv_is_signing_active(conn->sconn);
3436 int encrypt_caps = 0;
3438 if (!lp_unix_extensions()) {
3439 return NT_STATUS_INVALID_LEVEL;
3442 switch (conn->encrypt_level) {
3443 case SMB_SIGNING_OFF:
3444 encrypt_caps = 0;
3445 break;
3446 case SMB_SIGNING_IF_REQUIRED:
3447 case SMB_SIGNING_DEFAULT:
3448 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3449 break;
3450 case SMB_SIGNING_REQUIRED:
3451 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3452 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3453 large_write = false;
3454 large_read = false;
3455 break;
3458 data_len = 12;
3459 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3460 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3462 /* We have POSIX ACLs, pathname, encryption,
3463 * large read/write, and locking capability. */
3465 SBIG_UINT(pdata,4,((uint64_t)(
3466 CIFS_UNIX_POSIX_ACLS_CAP|
3467 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3468 CIFS_UNIX_FCNTL_LOCKS_CAP|
3469 CIFS_UNIX_EXTATTR_CAP|
3470 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3471 encrypt_caps|
3472 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3473 (large_write ?
3474 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3475 break;
3478 case SMB_QUERY_POSIX_FS_INFO:
3480 int rc;
3481 vfs_statvfs_struct svfs;
3483 if (!lp_unix_extensions()) {
3484 return NT_STATUS_INVALID_LEVEL;
3487 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3489 if (!rc) {
3490 data_len = 56;
3491 SIVAL(pdata,0,svfs.OptimalTransferSize);
3492 SIVAL(pdata,4,svfs.BlockSize);
3493 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3494 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3495 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3496 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3497 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3498 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3499 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3500 #ifdef EOPNOTSUPP
3501 } else if (rc == EOPNOTSUPP) {
3502 return NT_STATUS_INVALID_LEVEL;
3503 #endif /* EOPNOTSUPP */
3504 } else {
3505 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3506 return NT_STATUS_DOS(ERRSRV, ERRerror);
3508 break;
3511 case SMB_QUERY_POSIX_WHOAMI:
3513 uint32_t flags = 0;
3514 uint32_t sid_bytes;
3515 int i;
3517 if (!lp_unix_extensions()) {
3518 return NT_STATUS_INVALID_LEVEL;
3521 if (max_data_bytes < 40) {
3522 return NT_STATUS_BUFFER_TOO_SMALL;
3525 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3526 flags |= SMB_WHOAMI_GUEST;
3529 /* NOTE: 8 bytes for UID/GID, irrespective of native
3530 * platform size. This matches
3531 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3533 data_len = 4 /* flags */
3534 + 4 /* flag mask */
3535 + 8 /* uid */
3536 + 8 /* gid */
3537 + 4 /* ngroups */
3538 + 4 /* num_sids */
3539 + 4 /* SID bytes */
3540 + 4 /* pad/reserved */
3541 + (conn->session_info->unix_token->ngroups * 8)
3542 /* groups list */
3543 + (conn->session_info->security_token->num_sids *
3544 SID_MAX_SIZE)
3545 /* SID list */;
3547 SIVAL(pdata, 0, flags);
3548 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3549 SBIG_UINT(pdata, 8,
3550 (uint64_t)conn->session_info->unix_token->uid);
3551 SBIG_UINT(pdata, 16,
3552 (uint64_t)conn->session_info->unix_token->gid);
3555 if (data_len >= max_data_bytes) {
3556 /* Potential overflow, skip the GIDs and SIDs. */
3558 SIVAL(pdata, 24, 0); /* num_groups */
3559 SIVAL(pdata, 28, 0); /* num_sids */
3560 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3561 SIVAL(pdata, 36, 0); /* reserved */
3563 data_len = 40;
3564 break;
3567 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3568 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3570 /* We walk the SID list twice, but this call is fairly
3571 * infrequent, and I don't expect that it's performance
3572 * sensitive -- jpeach
3574 for (i = 0, sid_bytes = 0;
3575 i < conn->session_info->security_token->num_sids; ++i) {
3576 sid_bytes += ndr_size_dom_sid(
3577 &conn->session_info->security_token->sids[i],
3581 /* SID list byte count */
3582 SIVAL(pdata, 32, sid_bytes);
3584 /* 4 bytes pad/reserved - must be zero */
3585 SIVAL(pdata, 36, 0);
3586 data_len = 40;
3588 /* GID list */
3589 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3590 SBIG_UINT(pdata, data_len,
3591 (uint64_t)conn->session_info->unix_token->groups[i]);
3592 data_len += 8;
3595 /* SID list */
3596 for (i = 0;
3597 i < conn->session_info->security_token->num_sids; ++i) {
3598 int sid_len = ndr_size_dom_sid(
3599 &conn->session_info->security_token->sids[i],
3602 sid_linearize(pdata + data_len, sid_len,
3603 &conn->session_info->security_token->sids[i]);
3604 data_len += sid_len;
3607 break;
3610 case SMB_MAC_QUERY_FS_INFO:
3612 * Thursby MAC extension... ONLY on NTFS filesystems
3613 * once we do streams then we don't need this
3615 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3616 data_len = 88;
3617 SIVAL(pdata,84,0x100); /* Don't support mac... */
3618 break;
3620 /* drop through */
3621 default:
3622 return NT_STATUS_INVALID_LEVEL;
3625 *ret_data_len = data_len;
3626 return status;
3629 /****************************************************************************
3630 Reply to a TRANS2_QFSINFO (query filesystem info).
3631 ****************************************************************************/
3633 static void call_trans2qfsinfo(connection_struct *conn,
3634 struct smb_request *req,
3635 char **pparams, int total_params,
3636 char **ppdata, int total_data,
3637 unsigned int max_data_bytes)
3639 char *params = *pparams;
3640 uint16_t info_level;
3641 int data_len = 0;
3642 size_t fixed_portion;
3643 NTSTATUS status;
3645 if (total_params < 2) {
3646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3647 return;
3650 info_level = SVAL(params,0);
3652 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3653 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3654 DEBUG(0,("call_trans2qfsinfo: encryption required "
3655 "and info level 0x%x sent.\n",
3656 (unsigned int)info_level));
3657 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3658 return;
3662 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3664 status = smbd_do_qfsinfo(conn, req,
3665 info_level,
3666 req->flags2,
3667 max_data_bytes,
3668 &fixed_portion,
3669 NULL,
3670 ppdata, &data_len);
3671 if (!NT_STATUS_IS_OK(status)) {
3672 reply_nterror(req, status);
3673 return;
3676 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3677 max_data_bytes);
3679 DEBUG( 4, ( "%s info_level = %d\n",
3680 smb_fn_name(req->cmd), info_level) );
3682 return;
3685 /****************************************************************************
3686 Reply to a TRANS2_SETFSINFO (set filesystem info).
3687 ****************************************************************************/
3689 static void call_trans2setfsinfo(connection_struct *conn,
3690 struct smb_request *req,
3691 char **pparams, int total_params,
3692 char **ppdata, int total_data,
3693 unsigned int max_data_bytes)
3695 struct smbd_server_connection *sconn = req->sconn;
3696 char *pdata = *ppdata;
3697 char *params = *pparams;
3698 uint16 info_level;
3700 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3701 lp_servicename(talloc_tos(), SNUM(conn))));
3703 /* */
3704 if (total_params < 4) {
3705 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3706 total_params));
3707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3708 return;
3711 info_level = SVAL(params,2);
3713 if (IS_IPC(conn)) {
3714 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3715 info_level != SMB_SET_CIFS_UNIX_INFO) {
3716 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3717 "info level (0x%x) on IPC$.\n",
3718 (unsigned int)info_level));
3719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3720 return;
3724 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3725 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3726 DEBUG(0,("call_trans2setfsinfo: encryption required "
3727 "and info level 0x%x sent.\n",
3728 (unsigned int)info_level));
3729 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3730 return;
3734 switch(info_level) {
3735 case SMB_SET_CIFS_UNIX_INFO:
3736 if (!lp_unix_extensions()) {
3737 DEBUG(2,("call_trans2setfsinfo: "
3738 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3739 "unix extensions off\n"));
3740 reply_nterror(req,
3741 NT_STATUS_INVALID_LEVEL);
3742 return;
3745 /* There should be 12 bytes of capabilities set. */
3746 if (total_data < 12) {
3747 reply_nterror(
3748 req,
3749 NT_STATUS_INVALID_PARAMETER);
3750 return;
3752 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3753 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3754 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3755 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3756 /* Just print these values for now. */
3757 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3758 "major = %u, minor = %u cap_low = 0x%x, "
3759 "cap_high = 0x%xn",
3760 (unsigned int)sconn->
3761 smb1.unix_info.client_major,
3762 (unsigned int)sconn->
3763 smb1.unix_info.client_minor,
3764 (unsigned int)sconn->
3765 smb1.unix_info.client_cap_low,
3766 (unsigned int)sconn->
3767 smb1.unix_info.client_cap_high));
3769 /* Here is where we must switch to posix pathname processing... */
3770 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3771 lp_set_posix_pathnames();
3772 mangle_change_to_posix();
3775 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3776 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3777 /* Client that knows how to do posix locks,
3778 * but not posix open/mkdir operations. Set a
3779 * default type for read/write checks. */
3781 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3784 break;
3786 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3788 NTSTATUS status;
3789 size_t param_len = 0;
3790 size_t data_len = total_data;
3792 if (!lp_unix_extensions()) {
3793 reply_nterror(
3794 req,
3795 NT_STATUS_INVALID_LEVEL);
3796 return;
3799 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3800 reply_nterror(
3801 req,
3802 NT_STATUS_NOT_SUPPORTED);
3803 return;
3806 if (req->sconn->smb1.echo_handler.trusted_fde) {
3807 DEBUG( 2,("call_trans2setfsinfo: "
3808 "request transport encryption disabled"
3809 "with 'fork echo handler = yes'\n"));
3810 reply_nterror(
3811 req,
3812 NT_STATUS_NOT_SUPPORTED);
3813 return;
3816 DEBUG( 4,("call_trans2setfsinfo: "
3817 "request transport encryption.\n"));
3819 status = srv_request_encryption_setup(conn,
3820 (unsigned char **)ppdata,
3821 &data_len,
3822 (unsigned char **)pparams,
3823 &param_len);
3825 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3826 !NT_STATUS_IS_OK(status)) {
3827 reply_nterror(req, status);
3828 return;
3831 send_trans2_replies(conn, req,
3832 NT_STATUS_OK,
3833 *pparams,
3834 param_len,
3835 *ppdata,
3836 data_len,
3837 max_data_bytes);
3839 if (NT_STATUS_IS_OK(status)) {
3840 /* Server-side transport
3841 * encryption is now *on*. */
3842 status = srv_encryption_start(conn);
3843 if (!NT_STATUS_IS_OK(status)) {
3844 char *reason = talloc_asprintf(talloc_tos(),
3845 "Failure in setting "
3846 "up encrypted transport: %s",
3847 nt_errstr(status));
3848 exit_server_cleanly(reason);
3851 return;
3854 case SMB_FS_QUOTA_INFORMATION:
3856 files_struct *fsp = NULL;
3857 SMB_NTQUOTA_STRUCT quotas;
3859 ZERO_STRUCT(quotas);
3861 /* access check */
3862 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3863 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3864 lp_servicename(talloc_tos(), SNUM(conn)),
3865 conn->session_info->unix_info->unix_name));
3866 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3867 return;
3870 /* note: normaly there're 48 bytes,
3871 * but we didn't use the last 6 bytes for now
3872 * --metze
3874 fsp = file_fsp(req, SVAL(params,0));
3876 if (!check_fsp_ntquota_handle(conn, req,
3877 fsp)) {
3878 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3879 reply_nterror(
3880 req, NT_STATUS_INVALID_HANDLE);
3881 return;
3884 if (total_data < 42) {
3885 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3886 total_data));
3887 reply_nterror(
3888 req,
3889 NT_STATUS_INVALID_PARAMETER);
3890 return;
3893 /* unknown_1 24 NULL bytes in pdata*/
3895 /* the soft quotas 8 bytes (uint64_t)*/
3896 quotas.softlim = BVAL(pdata,24);
3898 /* the hard quotas 8 bytes (uint64_t)*/
3899 quotas.hardlim = BVAL(pdata,32);
3901 /* quota_flags 2 bytes **/
3902 quotas.qflags = SVAL(pdata,40);
3904 /* unknown_2 6 NULL bytes follow*/
3906 /* now set the quotas */
3907 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3908 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3909 reply_nterror(req, map_nt_error_from_unix(errno));
3910 return;
3913 break;
3915 default:
3916 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3917 info_level));
3918 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3919 return;
3920 break;
3924 * sending this reply works fine,
3925 * but I'm not sure it's the same
3926 * like windows do...
3927 * --metze
3929 reply_outbuf(req, 10, 0);
3932 #if defined(HAVE_POSIX_ACLS)
3933 /****************************************************************************
3934 Utility function to count the number of entries in a POSIX acl.
3935 ****************************************************************************/
3937 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3939 unsigned int ace_count = 0;
3940 int entry_id = SMB_ACL_FIRST_ENTRY;
3941 SMB_ACL_ENTRY_T entry;
3943 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3944 /* get_next... */
3945 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3946 entry_id = SMB_ACL_NEXT_ENTRY;
3948 ace_count++;
3950 return ace_count;
3953 /****************************************************************************
3954 Utility function to marshall a POSIX acl into wire format.
3955 ****************************************************************************/
3957 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3959 int entry_id = SMB_ACL_FIRST_ENTRY;
3960 SMB_ACL_ENTRY_T entry;
3962 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3963 SMB_ACL_TAG_T tagtype;
3964 SMB_ACL_PERMSET_T permset;
3965 unsigned char perms = 0;
3966 unsigned int own_grp;
3968 /* get_next... */
3969 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3970 entry_id = SMB_ACL_NEXT_ENTRY;
3973 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3975 return False;
3978 if (sys_acl_get_permset(entry, &permset) == -1) {
3979 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3980 return False;
3983 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3984 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3985 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3987 SCVAL(pdata,1,perms);
3989 switch (tagtype) {
3990 case SMB_ACL_USER_OBJ:
3991 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3992 own_grp = (unsigned int)pst->st_ex_uid;
3993 SIVAL(pdata,2,own_grp);
3994 SIVAL(pdata,6,0);
3995 break;
3996 case SMB_ACL_USER:
3998 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3999 if (!puid) {
4000 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4001 return False;
4003 own_grp = (unsigned int)*puid;
4004 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4005 SIVAL(pdata,2,own_grp);
4006 SIVAL(pdata,6,0);
4007 break;
4009 case SMB_ACL_GROUP_OBJ:
4010 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4011 own_grp = (unsigned int)pst->st_ex_gid;
4012 SIVAL(pdata,2,own_grp);
4013 SIVAL(pdata,6,0);
4014 break;
4015 case SMB_ACL_GROUP:
4017 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4018 if (!pgid) {
4019 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4020 return False;
4022 own_grp = (unsigned int)*pgid;
4023 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4024 SIVAL(pdata,2,own_grp);
4025 SIVAL(pdata,6,0);
4026 break;
4028 case SMB_ACL_MASK:
4029 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4030 SIVAL(pdata,2,0xFFFFFFFF);
4031 SIVAL(pdata,6,0xFFFFFFFF);
4032 break;
4033 case SMB_ACL_OTHER:
4034 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4035 SIVAL(pdata,2,0xFFFFFFFF);
4036 SIVAL(pdata,6,0xFFFFFFFF);
4037 break;
4038 default:
4039 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4040 return False;
4042 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4045 return True;
4047 #endif
4049 /****************************************************************************
4050 Store the FILE_UNIX_BASIC info.
4051 ****************************************************************************/
4053 static char *store_file_unix_basic(connection_struct *conn,
4054 char *pdata,
4055 files_struct *fsp,
4056 const SMB_STRUCT_STAT *psbuf)
4058 uint64_t file_index = get_FileIndex(conn, psbuf);
4059 dev_t devno;
4061 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4062 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4064 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4065 pdata += 8;
4067 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4068 pdata += 8;
4070 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4071 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4072 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4073 pdata += 24;
4075 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4076 SIVAL(pdata,4,0);
4077 pdata += 8;
4079 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4080 SIVAL(pdata,4,0);
4081 pdata += 8;
4083 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4084 pdata += 4;
4086 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4087 devno = psbuf->st_ex_rdev;
4088 } else {
4089 devno = psbuf->st_ex_dev;
4092 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4093 SIVAL(pdata,4,0);
4094 pdata += 8;
4096 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4097 SIVAL(pdata,4,0);
4098 pdata += 8;
4100 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4101 pdata += 8;
4103 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4104 SIVAL(pdata,4,0);
4105 pdata += 8;
4107 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4108 SIVAL(pdata,4,0);
4109 pdata += 8;
4111 return pdata;
4114 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4115 * the chflags(2) (or equivalent) flags.
4117 * XXX: this really should be behind the VFS interface. To do this, we would
4118 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4119 * Each VFS module could then implement its own mapping as appropriate for the
4120 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4122 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4123 info2_flags_map[] =
4125 #ifdef UF_NODUMP
4126 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4127 #endif
4129 #ifdef UF_IMMUTABLE
4130 { UF_IMMUTABLE, EXT_IMMUTABLE },
4131 #endif
4133 #ifdef UF_APPEND
4134 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4135 #endif
4137 #ifdef UF_HIDDEN
4138 { UF_HIDDEN, EXT_HIDDEN },
4139 #endif
4141 /* Do not remove. We need to guarantee that this array has at least one
4142 * entry to build on HP-UX.
4144 { 0, 0 }
4148 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4149 uint32 *smb_fflags, uint32 *smb_fmask)
4151 int i;
4153 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4154 *smb_fmask |= info2_flags_map[i].smb_fflag;
4155 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4156 *smb_fflags |= info2_flags_map[i].smb_fflag;
4161 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4162 const uint32 smb_fflags,
4163 const uint32 smb_fmask,
4164 int *stat_fflags)
4166 uint32 max_fmask = 0;
4167 int i;
4169 *stat_fflags = psbuf->st_ex_flags;
4171 /* For each flags requested in smb_fmask, check the state of the
4172 * corresponding flag in smb_fflags and set or clear the matching
4173 * stat flag.
4176 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4177 max_fmask |= info2_flags_map[i].smb_fflag;
4178 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4179 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4180 *stat_fflags |= info2_flags_map[i].stat_fflag;
4181 } else {
4182 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4187 /* If smb_fmask is asking to set any bits that are not supported by
4188 * our flag mappings, we should fail.
4190 if ((smb_fmask & max_fmask) != smb_fmask) {
4191 return False;
4194 return True;
4198 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4199 * of file flags and birth (create) time.
4201 static char *store_file_unix_basic_info2(connection_struct *conn,
4202 char *pdata,
4203 files_struct *fsp,
4204 const SMB_STRUCT_STAT *psbuf)
4206 uint32 file_flags = 0;
4207 uint32 flags_mask = 0;
4209 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4211 /* Create (birth) time 64 bit */
4212 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4213 pdata += 8;
4215 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4216 SIVAL(pdata, 0, file_flags); /* flags */
4217 SIVAL(pdata, 4, flags_mask); /* mask */
4218 pdata += 8;
4220 return pdata;
4223 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4224 const struct stream_struct *streams,
4225 char *data,
4226 unsigned int max_data_bytes,
4227 unsigned int *data_size)
4229 unsigned int i;
4230 unsigned int ofs = 0;
4232 if (max_data_bytes < 32) {
4233 return NT_STATUS_INFO_LENGTH_MISMATCH;
4236 for (i = 0; i < num_streams; i++) {
4237 unsigned int next_offset;
4238 size_t namelen;
4239 smb_ucs2_t *namebuf;
4241 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4242 streams[i].name, &namelen) ||
4243 namelen <= 2)
4245 return NT_STATUS_INVALID_PARAMETER;
4249 * name_buf is now null-terminated, we need to marshall as not
4250 * terminated
4253 namelen -= 2;
4256 * We cannot overflow ...
4258 if ((ofs + 24 + namelen) > max_data_bytes) {
4259 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4260 i));
4261 TALLOC_FREE(namebuf);
4262 return STATUS_BUFFER_OVERFLOW;
4265 SIVAL(data, ofs+4, namelen);
4266 SOFF_T(data, ofs+8, streams[i].size);
4267 SOFF_T(data, ofs+16, streams[i].alloc_size);
4268 memcpy(data+ofs+24, namebuf, namelen);
4269 TALLOC_FREE(namebuf);
4271 next_offset = ofs + 24 + namelen;
4273 if (i == num_streams-1) {
4274 SIVAL(data, ofs, 0);
4276 else {
4277 unsigned int align = ndr_align_size(next_offset, 8);
4279 if ((next_offset + align) > max_data_bytes) {
4280 DEBUG(10, ("refusing to overflow align "
4281 "reply at stream %u\n",
4282 i));
4283 TALLOC_FREE(namebuf);
4284 return STATUS_BUFFER_OVERFLOW;
4287 memset(data+next_offset, 0, align);
4288 next_offset += align;
4290 SIVAL(data, ofs, next_offset - ofs);
4291 ofs = next_offset;
4294 ofs = next_offset;
4297 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4299 *data_size = ofs;
4301 return NT_STATUS_OK;
4304 /****************************************************************************
4305 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4306 ****************************************************************************/
4308 static void call_trans2qpipeinfo(connection_struct *conn,
4309 struct smb_request *req,
4310 unsigned int tran_call,
4311 char **pparams, int total_params,
4312 char **ppdata, int total_data,
4313 unsigned int max_data_bytes)
4315 char *params = *pparams;
4316 char *pdata = *ppdata;
4317 unsigned int data_size = 0;
4318 unsigned int param_size = 2;
4319 uint16 info_level;
4320 files_struct *fsp;
4322 if (!params) {
4323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4324 return;
4327 if (total_params < 4) {
4328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4329 return;
4332 fsp = file_fsp(req, SVAL(params,0));
4333 if (!fsp_is_np(fsp)) {
4334 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4335 return;
4338 info_level = SVAL(params,2);
4340 *pparams = (char *)SMB_REALLOC(*pparams,2);
4341 if (*pparams == NULL) {
4342 reply_nterror(req, NT_STATUS_NO_MEMORY);
4343 return;
4345 params = *pparams;
4346 SSVAL(params,0,0);
4347 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4348 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4349 if (*ppdata == NULL ) {
4350 reply_nterror(req, NT_STATUS_NO_MEMORY);
4351 return;
4353 pdata = *ppdata;
4355 switch (info_level) {
4356 case SMB_FILE_STANDARD_INFORMATION:
4357 memset(pdata,0,24);
4358 SOFF_T(pdata,0,4096LL);
4359 SIVAL(pdata,16,1);
4360 SIVAL(pdata,20,1);
4361 data_size = 24;
4362 break;
4364 default:
4365 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4366 return;
4369 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4370 max_data_bytes);
4372 return;
4375 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4376 TALLOC_CTX *mem_ctx,
4377 uint16_t info_level,
4378 files_struct *fsp,
4379 struct smb_filename *smb_fname,
4380 bool delete_pending,
4381 struct timespec write_time_ts,
4382 struct ea_list *ea_list,
4383 int lock_data_count,
4384 char *lock_data,
4385 uint16_t flags2,
4386 unsigned int max_data_bytes,
4387 size_t *fixed_portion,
4388 char **ppdata,
4389 unsigned int *pdata_size)
4391 char *pdata = *ppdata;
4392 char *dstart, *dend;
4393 unsigned int data_size;
4394 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4395 time_t create_time, mtime, atime, c_time;
4396 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4397 char *p;
4398 char *base_name;
4399 char *dos_fname;
4400 int mode;
4401 int nlink;
4402 NTSTATUS status;
4403 uint64_t file_size = 0;
4404 uint64_t pos = 0;
4405 uint64_t allocation_size = 0;
4406 uint64_t file_index = 0;
4407 uint32_t access_mask = 0;
4409 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4410 return NT_STATUS_INVALID_LEVEL;
4413 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4414 smb_fname_str_dbg(smb_fname),
4415 fsp_fnum_dbg(fsp),
4416 info_level, max_data_bytes));
4418 mode = dos_mode(conn, smb_fname);
4419 nlink = psbuf->st_ex_nlink;
4421 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4422 nlink = 1;
4425 if ((nlink > 0) && delete_pending) {
4426 nlink -= 1;
4429 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4430 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4431 if (*ppdata == NULL) {
4432 return NT_STATUS_NO_MEMORY;
4434 pdata = *ppdata;
4435 dstart = pdata;
4436 dend = dstart + data_size - 1;
4438 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4439 update_stat_ex_mtime(psbuf, write_time_ts);
4442 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4443 mtime_ts = psbuf->st_ex_mtime;
4444 atime_ts = psbuf->st_ex_atime;
4445 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4447 if (lp_dos_filetime_resolution(SNUM(conn))) {
4448 dos_filetime_timespec(&create_time_ts);
4449 dos_filetime_timespec(&mtime_ts);
4450 dos_filetime_timespec(&atime_ts);
4451 dos_filetime_timespec(&ctime_ts);
4454 create_time = convert_timespec_to_time_t(create_time_ts);
4455 mtime = convert_timespec_to_time_t(mtime_ts);
4456 atime = convert_timespec_to_time_t(atime_ts);
4457 c_time = convert_timespec_to_time_t(ctime_ts);
4459 p = strrchr_m(smb_fname->base_name,'/');
4460 if (!p)
4461 base_name = smb_fname->base_name;
4462 else
4463 base_name = p+1;
4465 /* NT expects the name to be in an exact form of the *full*
4466 filename. See the trans2 torture test */
4467 if (ISDOT(base_name)) {
4468 dos_fname = talloc_strdup(mem_ctx, "\\");
4469 if (!dos_fname) {
4470 return NT_STATUS_NO_MEMORY;
4472 } else {
4473 dos_fname = talloc_asprintf(mem_ctx,
4474 "\\%s",
4475 smb_fname->base_name);
4476 if (!dos_fname) {
4477 return NT_STATUS_NO_MEMORY;
4479 if (is_ntfs_stream_smb_fname(smb_fname)) {
4480 dos_fname = talloc_asprintf(dos_fname, "%s",
4481 smb_fname->stream_name);
4482 if (!dos_fname) {
4483 return NT_STATUS_NO_MEMORY;
4487 string_replace(dos_fname, '/', '\\');
4490 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4492 if (!fsp) {
4493 /* Do we have this path open ? */
4494 files_struct *fsp1;
4495 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4496 fsp1 = file_find_di_first(conn->sconn, fileid);
4497 if (fsp1 && fsp1->initial_allocation_size) {
4498 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4502 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4503 file_size = get_file_size_stat(psbuf);
4506 if (fsp) {
4507 pos = fsp->fh->position_information;
4510 if (fsp) {
4511 access_mask = fsp->access_mask;
4512 } else {
4513 /* GENERIC_EXECUTE mapping from Windows */
4514 access_mask = 0x12019F;
4517 /* This should be an index number - looks like
4518 dev/ino to me :-)
4520 I think this causes us to fail the IFSKIT
4521 BasicFileInformationTest. -tpot */
4522 file_index = get_FileIndex(conn, psbuf);
4524 *fixed_portion = 0;
4526 switch (info_level) {
4527 case SMB_INFO_STANDARD:
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4529 data_size = 22;
4530 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4531 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4532 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4533 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4534 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4535 SSVAL(pdata,l1_attrFile,mode);
4536 break;
4538 case SMB_INFO_QUERY_EA_SIZE:
4540 unsigned int ea_size =
4541 estimate_ea_size(conn, fsp,
4542 smb_fname);
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4544 data_size = 26;
4545 srv_put_dos_date2(pdata,0,create_time);
4546 srv_put_dos_date2(pdata,4,atime);
4547 srv_put_dos_date2(pdata,8,mtime); /* write time */
4548 SIVAL(pdata,12,(uint32)file_size);
4549 SIVAL(pdata,16,(uint32)allocation_size);
4550 SSVAL(pdata,20,mode);
4551 SIVAL(pdata,22,ea_size);
4552 break;
4555 case SMB_INFO_IS_NAME_VALID:
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4557 if (fsp) {
4558 /* os/2 needs this ? really ?*/
4559 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4561 /* This is only reached for qpathinfo */
4562 data_size = 0;
4563 break;
4565 case SMB_INFO_QUERY_EAS_FROM_LIST:
4567 size_t total_ea_len = 0;
4568 struct ea_list *ea_file_list = NULL;
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4571 status =
4572 get_ea_list_from_file(mem_ctx, conn, fsp,
4573 smb_fname,
4574 &total_ea_len, &ea_file_list);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 return status;
4579 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4581 if (!ea_list || (total_ea_len > data_size)) {
4582 data_size = 4;
4583 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4584 break;
4587 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4588 break;
4591 case SMB_INFO_QUERY_ALL_EAS:
4593 /* We have data_size bytes to put EA's into. */
4594 size_t total_ea_len = 0;
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4597 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4598 smb_fname,
4599 &total_ea_len, &ea_list);
4600 if (!NT_STATUS_IS_OK(status)) {
4601 return status;
4604 if (!ea_list || (total_ea_len > data_size)) {
4605 data_size = 4;
4606 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4607 break;
4610 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4611 break;
4614 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4616 /* This is FileFullEaInformation - 0xF which maps to
4617 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4619 /* We have data_size bytes to put EA's into. */
4620 size_t total_ea_len = 0;
4621 struct ea_list *ea_file_list = NULL;
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4625 /*TODO: add filtering and index handling */
4627 status =
4628 get_ea_list_from_file(mem_ctx, conn, fsp,
4629 smb_fname,
4630 &total_ea_len, &ea_file_list);
4631 if (!NT_STATUS_IS_OK(status)) {
4632 return status;
4634 if (!ea_file_list) {
4635 return NT_STATUS_NO_EAS_ON_FILE;
4638 status = fill_ea_chained_buffer(mem_ctx,
4639 pdata,
4640 data_size,
4641 &data_size,
4642 conn, ea_file_list);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 return status;
4646 break;
4649 case SMB_FILE_BASIC_INFORMATION:
4650 case SMB_QUERY_FILE_BASIC_INFO:
4652 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4654 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4655 } else {
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4657 data_size = 40;
4658 SIVAL(pdata,36,0);
4660 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4661 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4662 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4663 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4664 SIVAL(pdata,32,mode);
4666 DEBUG(5,("SMB_QFBI - "));
4667 DEBUG(5,("create: %s ", ctime(&create_time)));
4668 DEBUG(5,("access: %s ", ctime(&atime)));
4669 DEBUG(5,("write: %s ", ctime(&mtime)));
4670 DEBUG(5,("change: %s ", ctime(&c_time)));
4671 DEBUG(5,("mode: %x\n", mode));
4672 *fixed_portion = data_size;
4673 break;
4675 case SMB_FILE_STANDARD_INFORMATION:
4676 case SMB_QUERY_FILE_STANDARD_INFO:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4679 data_size = 24;
4680 SOFF_T(pdata,0,allocation_size);
4681 SOFF_T(pdata,8,file_size);
4682 SIVAL(pdata,16,nlink);
4683 SCVAL(pdata,20,delete_pending?1:0);
4684 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4685 SSVAL(pdata,22,0); /* Padding. */
4686 *fixed_portion = 24;
4687 break;
4689 case SMB_FILE_EA_INFORMATION:
4690 case SMB_QUERY_FILE_EA_INFO:
4692 unsigned int ea_size =
4693 estimate_ea_size(conn, fsp, smb_fname);
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4695 data_size = 4;
4696 *fixed_portion = 4;
4697 SIVAL(pdata,0,ea_size);
4698 break;
4701 /* Get the 8.3 name - used if NT SMB was negotiated. */
4702 case SMB_QUERY_FILE_ALT_NAME_INFO:
4703 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4705 int len;
4706 char mangled_name[13];
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4708 if (!name_to_8_3(base_name,mangled_name,
4709 True,conn->params)) {
4710 return NT_STATUS_NO_MEMORY;
4712 len = srvstr_push(dstart, flags2,
4713 pdata+4, mangled_name,
4714 PTR_DIFF(dend, pdata+4),
4715 STR_UNICODE);
4716 data_size = 4 + len;
4717 SIVAL(pdata,0,len);
4718 *fixed_portion = 8;
4719 break;
4722 case SMB_QUERY_FILE_NAME_INFO:
4724 int len;
4726 this must be *exactly* right for ACLs on mapped drives to work
4728 len = srvstr_push(dstart, flags2,
4729 pdata+4, dos_fname,
4730 PTR_DIFF(dend, pdata+4),
4731 STR_UNICODE);
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4733 data_size = 4 + len;
4734 SIVAL(pdata,0,len);
4735 break;
4738 case SMB_FILE_ALLOCATION_INFORMATION:
4739 case SMB_QUERY_FILE_ALLOCATION_INFO:
4740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4741 data_size = 8;
4742 SOFF_T(pdata,0,allocation_size);
4743 break;
4745 case SMB_FILE_END_OF_FILE_INFORMATION:
4746 case SMB_QUERY_FILE_END_OF_FILEINFO:
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4748 data_size = 8;
4749 SOFF_T(pdata,0,file_size);
4750 break;
4752 case SMB_QUERY_FILE_ALL_INFO:
4753 case SMB_FILE_ALL_INFORMATION:
4755 int len;
4756 unsigned int ea_size =
4757 estimate_ea_size(conn, fsp, smb_fname);
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4759 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4760 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4761 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4762 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4763 SIVAL(pdata,32,mode);
4764 SIVAL(pdata,36,0); /* padding. */
4765 pdata += 40;
4766 SOFF_T(pdata,0,allocation_size);
4767 SOFF_T(pdata,8,file_size);
4768 SIVAL(pdata,16,nlink);
4769 SCVAL(pdata,20,delete_pending);
4770 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4771 SSVAL(pdata,22,0);
4772 pdata += 24;
4773 SIVAL(pdata,0,ea_size);
4774 pdata += 4; /* EA info */
4775 len = srvstr_push(dstart, flags2,
4776 pdata+4, dos_fname,
4777 PTR_DIFF(dend, pdata+4),
4778 STR_UNICODE);
4779 SIVAL(pdata,0,len);
4780 pdata += 4 + len;
4781 data_size = PTR_DIFF(pdata,(*ppdata));
4782 *fixed_portion = 10;
4783 break;
4786 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4788 int len;
4789 unsigned int ea_size =
4790 estimate_ea_size(conn, fsp, smb_fname);
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4792 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4793 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4794 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4795 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4796 SIVAL(pdata, 0x20, mode);
4797 SIVAL(pdata, 0x24, 0); /* padding. */
4798 SBVAL(pdata, 0x28, allocation_size);
4799 SBVAL(pdata, 0x30, file_size);
4800 SIVAL(pdata, 0x38, nlink);
4801 SCVAL(pdata, 0x3C, delete_pending);
4802 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4803 SSVAL(pdata, 0x3E, 0); /* padding */
4804 SBVAL(pdata, 0x40, file_index);
4805 SIVAL(pdata, 0x48, ea_size);
4806 SIVAL(pdata, 0x4C, access_mask);
4807 SBVAL(pdata, 0x50, pos);
4808 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4809 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4811 pdata += 0x60;
4813 len = srvstr_push(dstart, flags2,
4814 pdata+4, dos_fname,
4815 PTR_DIFF(dend, pdata+4),
4816 STR_UNICODE);
4817 SIVAL(pdata,0,len);
4818 pdata += 4 + len;
4819 data_size = PTR_DIFF(pdata,(*ppdata));
4820 *fixed_portion = 104;
4821 break;
4823 case SMB_FILE_INTERNAL_INFORMATION:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4826 SBVAL(pdata, 0, file_index);
4827 data_size = 8;
4828 *fixed_portion = 8;
4829 break;
4831 case SMB_FILE_ACCESS_INFORMATION:
4832 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4833 SIVAL(pdata, 0, access_mask);
4834 data_size = 4;
4835 *fixed_portion = 4;
4836 break;
4838 case SMB_FILE_NAME_INFORMATION:
4839 /* Pathname with leading '\'. */
4841 size_t byte_len;
4842 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4844 SIVAL(pdata,0,byte_len);
4845 data_size = 4 + byte_len;
4846 break;
4849 case SMB_FILE_DISPOSITION_INFORMATION:
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4851 data_size = 1;
4852 SCVAL(pdata,0,delete_pending);
4853 *fixed_portion = 1;
4854 break;
4856 case SMB_FILE_POSITION_INFORMATION:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4858 data_size = 8;
4859 SOFF_T(pdata,0,pos);
4860 *fixed_portion = 8;
4861 break;
4863 case SMB_FILE_MODE_INFORMATION:
4864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4865 SIVAL(pdata,0,mode);
4866 data_size = 4;
4867 *fixed_portion = 4;
4868 break;
4870 case SMB_FILE_ALIGNMENT_INFORMATION:
4871 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4872 SIVAL(pdata,0,0); /* No alignment needed. */
4873 data_size = 4;
4874 *fixed_portion = 4;
4875 break;
4878 * NT4 server just returns "invalid query" to this - if we try
4879 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4880 * want this. JRA.
4882 /* The first statement above is false - verified using Thursby
4883 * client against NT4 -- gcolley.
4885 case SMB_QUERY_FILE_STREAM_INFO:
4886 case SMB_FILE_STREAM_INFORMATION: {
4887 unsigned int num_streams = 0;
4888 struct stream_struct *streams = NULL;
4890 DEBUG(10,("smbd_do_qfilepathinfo: "
4891 "SMB_FILE_STREAM_INFORMATION\n"));
4893 if (is_ntfs_stream_smb_fname(smb_fname)) {
4894 return NT_STATUS_INVALID_PARAMETER;
4897 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4898 talloc_tos(), &num_streams, &streams);
4900 if (!NT_STATUS_IS_OK(status)) {
4901 DEBUG(10, ("could not get stream info: %s\n",
4902 nt_errstr(status)));
4903 return status;
4906 status = marshall_stream_info(num_streams, streams,
4907 pdata, max_data_bytes,
4908 &data_size);
4910 if (!NT_STATUS_IS_OK(status)) {
4911 DEBUG(10, ("marshall_stream_info failed: %s\n",
4912 nt_errstr(status)));
4913 TALLOC_FREE(streams);
4914 return status;
4917 TALLOC_FREE(streams);
4919 *fixed_portion = 32;
4921 break;
4923 case SMB_QUERY_COMPRESSION_INFO:
4924 case SMB_FILE_COMPRESSION_INFORMATION:
4925 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4926 SOFF_T(pdata,0,file_size);
4927 SIVAL(pdata,8,0); /* ??? */
4928 SIVAL(pdata,12,0); /* ??? */
4929 data_size = 16;
4930 *fixed_portion = 16;
4931 break;
4933 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4934 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4935 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4936 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4937 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4938 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4939 SOFF_T(pdata,32,allocation_size);
4940 SOFF_T(pdata,40,file_size);
4941 SIVAL(pdata,48,mode);
4942 SIVAL(pdata,52,0); /* ??? */
4943 data_size = 56;
4944 *fixed_portion = 56;
4945 break;
4947 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4948 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4949 SIVAL(pdata,0,mode);
4950 SIVAL(pdata,4,0);
4951 data_size = 8;
4952 *fixed_portion = 8;
4953 break;
4956 * CIFS UNIX Extensions.
4959 case SMB_QUERY_FILE_UNIX_BASIC:
4961 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4962 data_size = PTR_DIFF(pdata,(*ppdata));
4964 DEBUG(4,("smbd_do_qfilepathinfo: "
4965 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4966 dump_data(4, (uint8_t *)(*ppdata), data_size);
4968 break;
4970 case SMB_QUERY_FILE_UNIX_INFO2:
4972 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4973 data_size = PTR_DIFF(pdata,(*ppdata));
4976 int i;
4977 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4979 for (i=0; i<100; i++)
4980 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4981 DEBUG(4,("\n"));
4984 break;
4986 case SMB_QUERY_FILE_UNIX_LINK:
4988 int len;
4989 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4991 if (!buffer) {
4992 return NT_STATUS_NO_MEMORY;
4995 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4996 #ifdef S_ISLNK
4997 if(!S_ISLNK(psbuf->st_ex_mode)) {
4998 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5000 #else
5001 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5002 #endif
5003 len = SMB_VFS_READLINK(conn,
5004 smb_fname->base_name,
5005 buffer, PATH_MAX);
5006 if (len == -1) {
5007 return map_nt_error_from_unix(errno);
5009 buffer[len] = 0;
5010 len = srvstr_push(dstart, flags2,
5011 pdata, buffer,
5012 PTR_DIFF(dend, pdata),
5013 STR_TERMINATE);
5014 pdata += len;
5015 data_size = PTR_DIFF(pdata,(*ppdata));
5017 break;
5020 #if defined(HAVE_POSIX_ACLS)
5021 case SMB_QUERY_POSIX_ACL:
5023 SMB_ACL_T file_acl = NULL;
5024 SMB_ACL_T def_acl = NULL;
5025 uint16 num_file_acls = 0;
5026 uint16 num_def_acls = 0;
5028 if (fsp && fsp->fh->fd != -1) {
5029 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5030 talloc_tos());
5031 } else {
5032 file_acl =
5033 SMB_VFS_SYS_ACL_GET_FILE(conn,
5034 smb_fname->base_name,
5035 SMB_ACL_TYPE_ACCESS,
5036 talloc_tos());
5039 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5040 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5041 "not implemented on "
5042 "filesystem containing %s\n",
5043 smb_fname->base_name));
5044 return NT_STATUS_NOT_IMPLEMENTED;
5047 if (S_ISDIR(psbuf->st_ex_mode)) {
5048 if (fsp && fsp->is_directory) {
5049 def_acl =
5050 SMB_VFS_SYS_ACL_GET_FILE(
5051 conn,
5052 fsp->fsp_name->base_name,
5053 SMB_ACL_TYPE_DEFAULT,
5054 talloc_tos());
5055 } else {
5056 def_acl =
5057 SMB_VFS_SYS_ACL_GET_FILE(
5058 conn,
5059 smb_fname->base_name,
5060 SMB_ACL_TYPE_DEFAULT,
5061 talloc_tos());
5063 def_acl = free_empty_sys_acl(conn, def_acl);
5066 num_file_acls = count_acl_entries(conn, file_acl);
5067 num_def_acls = count_acl_entries(conn, def_acl);
5069 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5070 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5071 data_size,
5072 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5073 SMB_POSIX_ACL_HEADER_SIZE) ));
5074 if (file_acl) {
5075 TALLOC_FREE(file_acl);
5077 if (def_acl) {
5078 TALLOC_FREE(def_acl);
5080 return NT_STATUS_BUFFER_TOO_SMALL;
5083 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5084 SSVAL(pdata,2,num_file_acls);
5085 SSVAL(pdata,4,num_def_acls);
5086 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5087 if (file_acl) {
5088 TALLOC_FREE(file_acl);
5090 if (def_acl) {
5091 TALLOC_FREE(def_acl);
5093 return NT_STATUS_INTERNAL_ERROR;
5095 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5096 if (file_acl) {
5097 TALLOC_FREE(file_acl);
5099 if (def_acl) {
5100 TALLOC_FREE(def_acl);
5102 return NT_STATUS_INTERNAL_ERROR;
5105 if (file_acl) {
5106 TALLOC_FREE(file_acl);
5108 if (def_acl) {
5109 TALLOC_FREE(def_acl);
5111 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5112 break;
5114 #endif
5117 case SMB_QUERY_POSIX_LOCK:
5119 uint64_t count;
5120 uint64_t offset;
5121 uint64_t smblctx;
5122 enum brl_type lock_type;
5124 /* We need an open file with a real fd for this. */
5125 if (!fsp || fsp->fh->fd == -1) {
5126 return NT_STATUS_INVALID_LEVEL;
5129 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5130 return NT_STATUS_INVALID_PARAMETER;
5133 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5134 case POSIX_LOCK_TYPE_READ:
5135 lock_type = READ_LOCK;
5136 break;
5137 case POSIX_LOCK_TYPE_WRITE:
5138 lock_type = WRITE_LOCK;
5139 break;
5140 case POSIX_LOCK_TYPE_UNLOCK:
5141 default:
5142 /* There's no point in asking for an unlock... */
5143 return NT_STATUS_INVALID_PARAMETER;
5146 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5147 #if defined(HAVE_LONGLONG)
5148 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5149 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5150 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5151 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5152 #else /* HAVE_LONGLONG */
5153 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5154 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5155 #endif /* HAVE_LONGLONG */
5157 status = query_lock(fsp,
5158 &smblctx,
5159 &count,
5160 &offset,
5161 &lock_type,
5162 POSIX_LOCK);
5164 if (ERROR_WAS_LOCK_DENIED(status)) {
5165 /* Here we need to report who has it locked... */
5166 data_size = POSIX_LOCK_DATA_SIZE;
5168 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5169 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5170 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5171 #if defined(HAVE_LONGLONG)
5172 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5173 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5174 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5175 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5176 #else /* HAVE_LONGLONG */
5177 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5178 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5179 #endif /* HAVE_LONGLONG */
5181 } else if (NT_STATUS_IS_OK(status)) {
5182 /* For success we just return a copy of what we sent
5183 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5184 data_size = POSIX_LOCK_DATA_SIZE;
5185 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5186 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5187 } else {
5188 return status;
5190 break;
5193 default:
5194 return NT_STATUS_INVALID_LEVEL;
5197 *pdata_size = data_size;
5198 return NT_STATUS_OK;
5201 /****************************************************************************
5202 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5203 file name or file id).
5204 ****************************************************************************/
5206 static void call_trans2qfilepathinfo(connection_struct *conn,
5207 struct smb_request *req,
5208 unsigned int tran_call,
5209 char **pparams, int total_params,
5210 char **ppdata, int total_data,
5211 unsigned int max_data_bytes)
5213 char *params = *pparams;
5214 char *pdata = *ppdata;
5215 uint16 info_level;
5216 unsigned int data_size = 0;
5217 unsigned int param_size = 2;
5218 struct smb_filename *smb_fname = NULL;
5219 bool delete_pending = False;
5220 struct timespec write_time_ts;
5221 files_struct *fsp = NULL;
5222 struct file_id fileid;
5223 struct ea_list *ea_list = NULL;
5224 int lock_data_count = 0;
5225 char *lock_data = NULL;
5226 size_t fixed_portion;
5227 NTSTATUS status = NT_STATUS_OK;
5229 if (!params) {
5230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5231 return;
5234 ZERO_STRUCT(write_time_ts);
5236 if (tran_call == TRANSACT2_QFILEINFO) {
5237 if (total_params < 4) {
5238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239 return;
5242 if (IS_IPC(conn)) {
5243 call_trans2qpipeinfo(conn, req, tran_call,
5244 pparams, total_params,
5245 ppdata, total_data,
5246 max_data_bytes);
5247 return;
5250 fsp = file_fsp(req, SVAL(params,0));
5251 info_level = SVAL(params,2);
5253 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5255 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5256 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5257 return;
5260 /* Initial check for valid fsp ptr. */
5261 if (!check_fsp_open(conn, req, fsp)) {
5262 return;
5265 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5266 if (smb_fname == NULL) {
5267 reply_nterror(req, NT_STATUS_NO_MEMORY);
5268 return;
5271 if(fsp->fake_file_handle) {
5273 * This is actually for the QUOTA_FAKE_FILE --metze
5276 /* We know this name is ok, it's already passed the checks. */
5278 } else if(fsp->fh->fd == -1) {
5280 * This is actually a QFILEINFO on a directory
5281 * handle (returned from an NT SMB). NT5.0 seems
5282 * to do this call. JRA.
5285 if (INFO_LEVEL_IS_UNIX(info_level)) {
5286 /* Always do lstat for UNIX calls. */
5287 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5288 DEBUG(3,("call_trans2qfilepathinfo: "
5289 "SMB_VFS_LSTAT of %s failed "
5290 "(%s)\n",
5291 smb_fname_str_dbg(smb_fname),
5292 strerror(errno)));
5293 reply_nterror(req,
5294 map_nt_error_from_unix(errno));
5295 return;
5297 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "SMB_VFS_STAT of %s failed (%s)\n",
5300 smb_fname_str_dbg(smb_fname),
5301 strerror(errno)));
5302 reply_nterror(req,
5303 map_nt_error_from_unix(errno));
5304 return;
5307 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5308 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5309 } else {
5311 * Original code - this is an open file.
5313 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5314 DEBUG(3, ("fstat of %s failed (%s)\n",
5315 fsp_fnum_dbg(fsp), strerror(errno)));
5316 reply_nterror(req,
5317 map_nt_error_from_unix(errno));
5318 return;
5320 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5321 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5324 } else {
5325 uint32_t name_hash;
5326 char *fname = NULL;
5327 uint32_t ucf_flags = 0;
5329 /* qpathinfo */
5330 if (total_params < 7) {
5331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5332 return;
5335 info_level = SVAL(params,0);
5337 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5339 if (INFO_LEVEL_IS_UNIX(info_level)) {
5340 if (!lp_unix_extensions()) {
5341 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5342 return;
5344 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5345 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5346 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5347 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5351 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5352 total_params - 6,
5353 STR_TERMINATE, &status);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 reply_nterror(req, status);
5356 return;
5359 status = filename_convert(req,
5360 conn,
5361 req->flags2 & FLAGS2_DFS_PATHNAMES,
5362 fname,
5363 ucf_flags,
5364 NULL,
5365 &smb_fname);
5366 if (!NT_STATUS_IS_OK(status)) {
5367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5368 reply_botherror(req,
5369 NT_STATUS_PATH_NOT_COVERED,
5370 ERRSRV, ERRbadpath);
5371 return;
5373 reply_nterror(req, status);
5374 return;
5377 /* If this is a stream, check if there is a delete_pending. */
5378 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5379 && is_ntfs_stream_smb_fname(smb_fname)) {
5380 struct smb_filename *smb_fname_base;
5382 /* Create an smb_filename with stream_name == NULL. */
5383 smb_fname_base = synthetic_smb_fname(
5384 talloc_tos(), smb_fname->base_name,
5385 NULL, NULL);
5386 if (smb_fname_base == NULL) {
5387 reply_nterror(req, NT_STATUS_NO_MEMORY);
5388 return;
5391 if (INFO_LEVEL_IS_UNIX(info_level)) {
5392 /* Always do lstat for UNIX calls. */
5393 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5394 DEBUG(3,("call_trans2qfilepathinfo: "
5395 "SMB_VFS_LSTAT of %s failed "
5396 "(%s)\n",
5397 smb_fname_str_dbg(smb_fname_base),
5398 strerror(errno)));
5399 TALLOC_FREE(smb_fname_base);
5400 reply_nterror(req,
5401 map_nt_error_from_unix(errno));
5402 return;
5404 } else {
5405 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5406 DEBUG(3,("call_trans2qfilepathinfo: "
5407 "fileinfo of %s failed "
5408 "(%s)\n",
5409 smb_fname_str_dbg(smb_fname_base),
5410 strerror(errno)));
5411 TALLOC_FREE(smb_fname_base);
5412 reply_nterror(req,
5413 map_nt_error_from_unix(errno));
5414 return;
5418 status = file_name_hash(conn,
5419 smb_fname_str_dbg(smb_fname_base),
5420 &name_hash);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 TALLOC_FREE(smb_fname_base);
5423 reply_nterror(req, status);
5424 return;
5427 fileid = vfs_file_id_from_sbuf(conn,
5428 &smb_fname_base->st);
5429 TALLOC_FREE(smb_fname_base);
5430 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5431 if (delete_pending) {
5432 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5433 return;
5437 if (INFO_LEVEL_IS_UNIX(info_level)) {
5438 /* Always do lstat for UNIX calls. */
5439 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5440 DEBUG(3,("call_trans2qfilepathinfo: "
5441 "SMB_VFS_LSTAT of %s failed (%s)\n",
5442 smb_fname_str_dbg(smb_fname),
5443 strerror(errno)));
5444 reply_nterror(req,
5445 map_nt_error_from_unix(errno));
5446 return;
5449 } else {
5450 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5451 DEBUG(3,("call_trans2qfilepathinfo: "
5452 "SMB_VFS_STAT of %s failed (%s)\n",
5453 smb_fname_str_dbg(smb_fname),
5454 strerror(errno)));
5455 reply_nterror(req,
5456 map_nt_error_from_unix(errno));
5457 return;
5461 status = file_name_hash(conn,
5462 smb_fname_str_dbg(smb_fname),
5463 &name_hash);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 reply_nterror(req, status);
5466 return;
5469 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5470 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5471 if (delete_pending) {
5472 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5473 return;
5477 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5478 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5479 fsp_fnum_dbg(fsp),
5480 info_level,tran_call,total_data));
5482 /* Pull out any data sent here before we realloc. */
5483 switch (info_level) {
5484 case SMB_INFO_QUERY_EAS_FROM_LIST:
5486 /* Pull any EA list from the data portion. */
5487 uint32 ea_size;
5489 if (total_data < 4) {
5490 reply_nterror(
5491 req, NT_STATUS_INVALID_PARAMETER);
5492 return;
5494 ea_size = IVAL(pdata,0);
5496 if (total_data > 0 && ea_size != total_data) {
5497 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5499 reply_nterror(
5500 req, NT_STATUS_INVALID_PARAMETER);
5501 return;
5504 if (!lp_ea_support(SNUM(conn))) {
5505 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5506 return;
5509 /* Pull out the list of names. */
5510 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5511 if (!ea_list) {
5512 reply_nterror(
5513 req, NT_STATUS_INVALID_PARAMETER);
5514 return;
5516 break;
5519 case SMB_QUERY_POSIX_LOCK:
5521 if (fsp == NULL || fsp->fh->fd == -1) {
5522 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5523 return;
5526 if (total_data != POSIX_LOCK_DATA_SIZE) {
5527 reply_nterror(
5528 req, NT_STATUS_INVALID_PARAMETER);
5529 return;
5532 /* Copy the lock range data. */
5533 lock_data = (char *)talloc_memdup(
5534 req, pdata, total_data);
5535 if (!lock_data) {
5536 reply_nterror(req, NT_STATUS_NO_MEMORY);
5537 return;
5539 lock_data_count = total_data;
5541 default:
5542 break;
5545 *pparams = (char *)SMB_REALLOC(*pparams,2);
5546 if (*pparams == NULL) {
5547 reply_nterror(req, NT_STATUS_NO_MEMORY);
5548 return;
5550 params = *pparams;
5551 SSVAL(params,0,0);
5554 * draft-leach-cifs-v1-spec-02.txt
5555 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5556 * says:
5558 * The requested information is placed in the Data portion of the
5559 * transaction response. For the information levels greater than 0x100,
5560 * the transaction response has 1 parameter word which should be
5561 * ignored by the client.
5563 * However Windows only follows this rule for the IS_NAME_VALID call.
5565 switch (info_level) {
5566 case SMB_INFO_IS_NAME_VALID:
5567 param_size = 0;
5568 break;
5571 if ((info_level & 0xFF00) == 0xFF00) {
5573 * We use levels that start with 0xFF00
5574 * internally to represent SMB2 specific levels
5576 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5577 return;
5580 status = smbd_do_qfilepathinfo(conn, req, info_level,
5581 fsp, smb_fname,
5582 delete_pending, write_time_ts,
5583 ea_list,
5584 lock_data_count, lock_data,
5585 req->flags2, max_data_bytes,
5586 &fixed_portion,
5587 ppdata, &data_size);
5588 if (!NT_STATUS_IS_OK(status)) {
5589 reply_nterror(req, status);
5590 return;
5592 if (fixed_portion > max_data_bytes) {
5593 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5594 return;
5597 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5598 max_data_bytes);
5600 return;
5603 /****************************************************************************
5604 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5605 code.
5606 ****************************************************************************/
5608 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5609 connection_struct *conn,
5610 struct smb_request *req,
5611 bool overwrite_if_exists,
5612 const struct smb_filename *smb_fname_old,
5613 struct smb_filename *smb_fname_new)
5615 NTSTATUS status = NT_STATUS_OK;
5617 /* source must already exist. */
5618 if (!VALID_STAT(smb_fname_old->st)) {
5619 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5622 if (VALID_STAT(smb_fname_new->st)) {
5623 if (overwrite_if_exists) {
5624 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5625 return NT_STATUS_FILE_IS_A_DIRECTORY;
5627 status = unlink_internals(conn,
5628 req,
5629 FILE_ATTRIBUTE_NORMAL,
5630 smb_fname_new,
5631 false);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 return status;
5635 } else {
5636 /* Disallow if newname already exists. */
5637 return NT_STATUS_OBJECT_NAME_COLLISION;
5641 /* No links from a directory. */
5642 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5643 return NT_STATUS_FILE_IS_A_DIRECTORY;
5646 /* Setting a hardlink to/from a stream isn't currently supported. */
5647 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5648 is_ntfs_stream_smb_fname(smb_fname_new)) {
5649 return NT_STATUS_INVALID_PARAMETER;
5652 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5653 smb_fname_old->base_name, smb_fname_new->base_name));
5655 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5656 smb_fname_new->base_name) != 0) {
5657 status = map_nt_error_from_unix(errno);
5658 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5659 nt_errstr(status), smb_fname_old->base_name,
5660 smb_fname_new->base_name));
5662 return status;
5665 /****************************************************************************
5666 Deal with setting the time from any of the setfilepathinfo functions.
5667 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5668 calling this function.
5669 ****************************************************************************/
5671 NTSTATUS smb_set_file_time(connection_struct *conn,
5672 files_struct *fsp,
5673 const struct smb_filename *smb_fname,
5674 struct smb_file_time *ft,
5675 bool setting_write_time)
5677 struct smb_filename smb_fname_base;
5678 uint32 action =
5679 FILE_NOTIFY_CHANGE_LAST_ACCESS
5680 |FILE_NOTIFY_CHANGE_LAST_WRITE
5681 |FILE_NOTIFY_CHANGE_CREATION;
5683 if (!VALID_STAT(smb_fname->st)) {
5684 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5687 /* get some defaults (no modifications) if any info is zero or -1. */
5688 if (null_timespec(ft->create_time)) {
5689 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5692 if (null_timespec(ft->atime)) {
5693 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5696 if (null_timespec(ft->mtime)) {
5697 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5700 if (!setting_write_time) {
5701 /* ft->mtime comes from change time, not write time. */
5702 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5705 /* Ensure the resolution is the correct for
5706 * what we can store on this filesystem. */
5708 round_timespec(conn->ts_res, &ft->create_time);
5709 round_timespec(conn->ts_res, &ft->ctime);
5710 round_timespec(conn->ts_res, &ft->atime);
5711 round_timespec(conn->ts_res, &ft->mtime);
5713 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5714 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5715 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5716 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5717 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5718 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5719 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5720 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5722 if (setting_write_time) {
5724 * This was a Windows setfileinfo on an open file.
5725 * NT does this a lot. We also need to
5726 * set the time here, as it can be read by
5727 * FindFirst/FindNext and with the patch for bug #2045
5728 * in smbd/fileio.c it ensures that this timestamp is
5729 * kept sticky even after a write. We save the request
5730 * away and will set it on file close and after a write. JRA.
5733 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5734 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5736 if (fsp != NULL) {
5737 if (fsp->base_fsp) {
5738 set_sticky_write_time_fsp(fsp->base_fsp,
5739 ft->mtime);
5740 } else {
5741 set_sticky_write_time_fsp(fsp, ft->mtime);
5743 } else {
5744 set_sticky_write_time_path(
5745 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5746 ft->mtime);
5750 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5752 /* Always call ntimes on the base, even if a stream was passed in. */
5753 smb_fname_base = *smb_fname;
5754 smb_fname_base.stream_name = NULL;
5756 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5757 return map_nt_error_from_unix(errno);
5760 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5761 smb_fname->base_name);
5762 return NT_STATUS_OK;
5765 /****************************************************************************
5766 Deal with setting the dosmode from any of the setfilepathinfo functions.
5767 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5768 done before calling this function.
5769 ****************************************************************************/
5771 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5772 const struct smb_filename *smb_fname,
5773 uint32 dosmode)
5775 struct smb_filename *smb_fname_base;
5776 NTSTATUS status;
5778 if (!VALID_STAT(smb_fname->st)) {
5779 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5782 /* Always operate on the base_name, even if a stream was passed in. */
5783 smb_fname_base = synthetic_smb_fname(
5784 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5785 if (smb_fname_base == NULL) {
5786 return NT_STATUS_NO_MEMORY;
5789 if (dosmode) {
5790 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5791 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5792 } else {
5793 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5797 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5799 /* check the mode isn't different, before changing it */
5800 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5801 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5802 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5803 (unsigned int)dosmode));
5805 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5806 false)) {
5807 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5808 "%s failed (%s)\n",
5809 smb_fname_str_dbg(smb_fname_base),
5810 strerror(errno)));
5811 status = map_nt_error_from_unix(errno);
5812 goto out;
5815 status = NT_STATUS_OK;
5816 out:
5817 TALLOC_FREE(smb_fname_base);
5818 return status;
5821 /****************************************************************************
5822 Deal with setting the size from any of the setfilepathinfo functions.
5823 ****************************************************************************/
5825 static NTSTATUS smb_set_file_size(connection_struct *conn,
5826 struct smb_request *req,
5827 files_struct *fsp,
5828 const struct smb_filename *smb_fname,
5829 const SMB_STRUCT_STAT *psbuf,
5830 off_t size,
5831 bool fail_after_createfile)
5833 NTSTATUS status = NT_STATUS_OK;
5834 struct smb_filename *smb_fname_tmp = NULL;
5835 files_struct *new_fsp = NULL;
5837 if (!VALID_STAT(*psbuf)) {
5838 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5841 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5843 if (size == get_file_size_stat(psbuf)) {
5844 return NT_STATUS_OK;
5847 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5848 smb_fname_str_dbg(smb_fname), (double)size));
5850 if (fsp && fsp->fh->fd != -1) {
5851 /* Handle based call. */
5852 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5853 return NT_STATUS_ACCESS_DENIED;
5856 if (vfs_set_filelen(fsp, size) == -1) {
5857 return map_nt_error_from_unix(errno);
5859 trigger_write_time_update_immediate(fsp);
5860 return NT_STATUS_OK;
5863 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5864 if (smb_fname_tmp == NULL) {
5865 return NT_STATUS_NO_MEMORY;
5868 smb_fname_tmp->st = *psbuf;
5870 status = SMB_VFS_CREATE_FILE(
5871 conn, /* conn */
5872 req, /* req */
5873 0, /* root_dir_fid */
5874 smb_fname_tmp, /* fname */
5875 FILE_WRITE_DATA, /* access_mask */
5876 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5877 FILE_SHARE_DELETE),
5878 FILE_OPEN, /* create_disposition*/
5879 0, /* create_options */
5880 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5881 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5882 0, /* allocation_size */
5883 0, /* private_flags */
5884 NULL, /* sd */
5885 NULL, /* ea_list */
5886 &new_fsp, /* result */
5887 NULL); /* pinfo */
5889 TALLOC_FREE(smb_fname_tmp);
5891 if (!NT_STATUS_IS_OK(status)) {
5892 /* NB. We check for open_was_deferred in the caller. */
5893 return status;
5896 /* See RAW-SFILEINFO-END-OF-FILE */
5897 if (fail_after_createfile) {
5898 close_file(req, new_fsp,NORMAL_CLOSE);
5899 return NT_STATUS_INVALID_LEVEL;
5902 if (vfs_set_filelen(new_fsp, size) == -1) {
5903 status = map_nt_error_from_unix(errno);
5904 close_file(req, new_fsp,NORMAL_CLOSE);
5905 return status;
5908 trigger_write_time_update_immediate(new_fsp);
5909 close_file(req, new_fsp,NORMAL_CLOSE);
5910 return NT_STATUS_OK;
5913 /****************************************************************************
5914 Deal with SMB_INFO_SET_EA.
5915 ****************************************************************************/
5917 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5918 const char *pdata,
5919 int total_data,
5920 files_struct *fsp,
5921 const struct smb_filename *smb_fname)
5923 struct ea_list *ea_list = NULL;
5924 TALLOC_CTX *ctx = NULL;
5925 NTSTATUS status = NT_STATUS_OK;
5927 if (total_data < 10) {
5929 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5930 length. They seem to have no effect. Bug #3212. JRA */
5932 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5933 /* We're done. We only get EA info in this call. */
5934 return NT_STATUS_OK;
5937 return NT_STATUS_INVALID_PARAMETER;
5940 if (IVAL(pdata,0) > total_data) {
5941 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5942 IVAL(pdata,0), (unsigned int)total_data));
5943 return NT_STATUS_INVALID_PARAMETER;
5946 ctx = talloc_tos();
5947 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5948 if (!ea_list) {
5949 return NT_STATUS_INVALID_PARAMETER;
5952 status = set_ea(conn, fsp, smb_fname, ea_list);
5954 return status;
5957 /****************************************************************************
5958 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5959 ****************************************************************************/
5961 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5962 const char *pdata,
5963 int total_data,
5964 files_struct *fsp)
5966 struct ea_list *ea_list = NULL;
5967 NTSTATUS status;
5969 if (!fsp) {
5970 return NT_STATUS_INVALID_HANDLE;
5973 if (!lp_ea_support(SNUM(conn))) {
5974 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5975 "EA's not supported.\n",
5976 (unsigned int)total_data));
5977 return NT_STATUS_EAS_NOT_SUPPORTED;
5980 if (total_data < 10) {
5981 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5982 "too small.\n",
5983 (unsigned int)total_data));
5984 return NT_STATUS_INVALID_PARAMETER;
5987 ea_list = read_nttrans_ea_list(talloc_tos(),
5988 pdata,
5989 total_data);
5991 if (!ea_list) {
5992 return NT_STATUS_INVALID_PARAMETER;
5995 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5997 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5998 smb_fname_str_dbg(fsp->fsp_name),
5999 nt_errstr(status) ));
6001 return status;
6005 /****************************************************************************
6006 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6007 ****************************************************************************/
6009 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6010 const char *pdata,
6011 int total_data,
6012 files_struct *fsp,
6013 struct smb_filename *smb_fname)
6015 NTSTATUS status = NT_STATUS_OK;
6016 bool delete_on_close;
6017 uint32 dosmode = 0;
6019 if (total_data < 1) {
6020 return NT_STATUS_INVALID_PARAMETER;
6023 if (fsp == NULL) {
6024 return NT_STATUS_INVALID_HANDLE;
6027 delete_on_close = (CVAL(pdata,0) ? True : False);
6028 dosmode = dos_mode(conn, smb_fname);
6030 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6031 "delete_on_close = %u\n",
6032 smb_fname_str_dbg(smb_fname),
6033 (unsigned int)dosmode,
6034 (unsigned int)delete_on_close ));
6036 if (delete_on_close) {
6037 status = can_set_delete_on_close(fsp, dosmode);
6038 if (!NT_STATUS_IS_OK(status)) {
6039 return status;
6043 /* The set is across all open files on this dev/inode pair. */
6044 if (!set_delete_on_close(fsp, delete_on_close,
6045 conn->session_info->security_token,
6046 conn->session_info->unix_token)) {
6047 return NT_STATUS_ACCESS_DENIED;
6049 return NT_STATUS_OK;
6052 /****************************************************************************
6053 Deal with SMB_FILE_POSITION_INFORMATION.
6054 ****************************************************************************/
6056 static NTSTATUS smb_file_position_information(connection_struct *conn,
6057 const char *pdata,
6058 int total_data,
6059 files_struct *fsp)
6061 uint64_t position_information;
6063 if (total_data < 8) {
6064 return NT_STATUS_INVALID_PARAMETER;
6067 if (fsp == NULL) {
6068 /* Ignore on pathname based set. */
6069 return NT_STATUS_OK;
6072 position_information = (uint64_t)IVAL(pdata,0);
6073 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6075 DEBUG(10,("smb_file_position_information: Set file position "
6076 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6077 (double)position_information));
6078 fsp->fh->position_information = position_information;
6079 return NT_STATUS_OK;
6082 /****************************************************************************
6083 Deal with SMB_FILE_MODE_INFORMATION.
6084 ****************************************************************************/
6086 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6087 const char *pdata,
6088 int total_data)
6090 uint32 mode;
6092 if (total_data < 4) {
6093 return NT_STATUS_INVALID_PARAMETER;
6095 mode = IVAL(pdata,0);
6096 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6097 return NT_STATUS_INVALID_PARAMETER;
6099 return NT_STATUS_OK;
6102 /****************************************************************************
6103 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6104 ****************************************************************************/
6106 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6107 struct smb_request *req,
6108 const char *pdata,
6109 int total_data,
6110 const struct smb_filename *smb_fname)
6112 char *link_target = NULL;
6113 const char *newname = smb_fname->base_name;
6114 TALLOC_CTX *ctx = talloc_tos();
6116 /* Set a symbolic link. */
6117 /* Don't allow this if follow links is false. */
6119 if (total_data == 0) {
6120 return NT_STATUS_INVALID_PARAMETER;
6123 if (!lp_symlinks(SNUM(conn))) {
6124 return NT_STATUS_ACCESS_DENIED;
6127 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6128 total_data, STR_TERMINATE);
6130 if (!link_target) {
6131 return NT_STATUS_INVALID_PARAMETER;
6134 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6135 newname, link_target ));
6137 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6138 return map_nt_error_from_unix(errno);
6141 return NT_STATUS_OK;
6144 /****************************************************************************
6145 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6146 ****************************************************************************/
6148 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6149 struct smb_request *req,
6150 const char *pdata, int total_data,
6151 struct smb_filename *smb_fname_new)
6153 char *oldname = NULL;
6154 struct smb_filename *smb_fname_old = NULL;
6155 TALLOC_CTX *ctx = talloc_tos();
6156 NTSTATUS status = NT_STATUS_OK;
6158 /* Set a hard link. */
6159 if (total_data == 0) {
6160 return NT_STATUS_INVALID_PARAMETER;
6163 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6164 total_data, STR_TERMINATE, &status);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 return status;
6169 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6170 smb_fname_str_dbg(smb_fname_new), oldname));
6172 status = filename_convert(ctx,
6173 conn,
6174 req->flags2 & FLAGS2_DFS_PATHNAMES,
6175 oldname,
6177 NULL,
6178 &smb_fname_old);
6179 if (!NT_STATUS_IS_OK(status)) {
6180 return status;
6183 return hardlink_internals(ctx, conn, req, false,
6184 smb_fname_old, smb_fname_new);
6187 /****************************************************************************
6188 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6189 ****************************************************************************/
6191 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6192 struct smb_request *req,
6193 const char *pdata,
6194 int total_data,
6195 files_struct *fsp,
6196 struct smb_filename *smb_fname_src)
6198 bool overwrite;
6199 uint32_t len;
6200 char *newname = NULL;
6201 struct smb_filename *smb_fname_dst = NULL;
6202 NTSTATUS status = NT_STATUS_OK;
6203 TALLOC_CTX *ctx = talloc_tos();
6205 if (!fsp) {
6206 return NT_STATUS_INVALID_HANDLE;
6209 if (total_data < 20) {
6210 return NT_STATUS_INVALID_PARAMETER;
6213 overwrite = (CVAL(pdata,0) ? True : False);
6214 len = IVAL(pdata,16);
6216 if (len > (total_data - 20) || (len == 0)) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6221 &pdata[20], len, STR_TERMINATE,
6222 &status);
6223 if (!NT_STATUS_IS_OK(status)) {
6224 return status;
6227 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6228 newname));
6230 status = filename_convert(ctx,
6231 conn,
6232 req->flags2 & FLAGS2_DFS_PATHNAMES,
6233 newname,
6234 UCF_SAVE_LCOMP,
6235 NULL,
6236 &smb_fname_dst);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 return status;
6241 if (fsp->base_fsp) {
6242 /* newname must be a stream name. */
6243 if (newname[0] != ':') {
6244 return NT_STATUS_NOT_SUPPORTED;
6247 /* Create an smb_fname to call rename_internals_fsp() with. */
6248 smb_fname_dst = synthetic_smb_fname(
6249 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6250 newname, NULL);
6251 if (smb_fname_dst == NULL) {
6252 status = NT_STATUS_NO_MEMORY;
6253 goto out;
6257 * Set the original last component, since
6258 * rename_internals_fsp() requires it.
6260 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6261 newname);
6262 if (smb_fname_dst->original_lcomp == NULL) {
6263 status = NT_STATUS_NO_MEMORY;
6264 goto out;
6269 DEBUG(10,("smb2_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6271 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6272 smb_fname_str_dbg(smb_fname_dst)));
6273 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6274 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6275 overwrite);
6277 out:
6278 TALLOC_FREE(smb_fname_dst);
6279 return status;
6282 static NTSTATUS smb_file_link_information(connection_struct *conn,
6283 struct smb_request *req,
6284 const char *pdata,
6285 int total_data,
6286 files_struct *fsp,
6287 struct smb_filename *smb_fname_src)
6289 bool overwrite;
6290 uint32_t len;
6291 char *newname = NULL;
6292 struct smb_filename *smb_fname_dst = NULL;
6293 NTSTATUS status = NT_STATUS_OK;
6294 TALLOC_CTX *ctx = talloc_tos();
6296 if (!fsp) {
6297 return NT_STATUS_INVALID_HANDLE;
6300 if (total_data < 20) {
6301 return NT_STATUS_INVALID_PARAMETER;
6304 overwrite = (CVAL(pdata,0) ? true : false);
6305 len = IVAL(pdata,16);
6307 if (len > (total_data - 20) || (len == 0)) {
6308 return NT_STATUS_INVALID_PARAMETER;
6311 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6312 &pdata[20], len, STR_TERMINATE,
6313 &status);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 return status;
6318 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6319 newname));
6321 status = filename_convert(ctx,
6322 conn,
6323 req->flags2 & FLAGS2_DFS_PATHNAMES,
6324 newname,
6325 UCF_SAVE_LCOMP,
6326 NULL,
6327 &smb_fname_dst);
6328 if (!NT_STATUS_IS_OK(status)) {
6329 return status;
6332 if (fsp->base_fsp) {
6333 /* No stream names. */
6334 return NT_STATUS_NOT_SUPPORTED;
6337 DEBUG(10,("smb_file_link_information: "
6338 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6339 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6340 smb_fname_str_dbg(smb_fname_dst)));
6341 status = hardlink_internals(ctx,
6342 conn,
6343 req,
6344 overwrite,
6345 fsp->fsp_name,
6346 smb_fname_dst);
6348 TALLOC_FREE(smb_fname_dst);
6349 return status;
6352 /****************************************************************************
6353 Deal with SMB_FILE_RENAME_INFORMATION.
6354 ****************************************************************************/
6356 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6357 struct smb_request *req,
6358 const char *pdata,
6359 int total_data,
6360 files_struct *fsp,
6361 struct smb_filename *smb_fname_src)
6363 bool overwrite;
6364 uint32 root_fid;
6365 uint32 len;
6366 char *newname = NULL;
6367 struct smb_filename *smb_fname_dst = NULL;
6368 bool dest_has_wcard = False;
6369 NTSTATUS status = NT_STATUS_OK;
6370 char *p;
6371 TALLOC_CTX *ctx = talloc_tos();
6373 if (total_data < 13) {
6374 return NT_STATUS_INVALID_PARAMETER;
6377 overwrite = (CVAL(pdata,0) ? True : False);
6378 root_fid = IVAL(pdata,4);
6379 len = IVAL(pdata,8);
6381 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6382 return NT_STATUS_INVALID_PARAMETER;
6385 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6386 len, 0, &status,
6387 &dest_has_wcard);
6388 if (!NT_STATUS_IS_OK(status)) {
6389 return status;
6392 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6393 newname));
6395 status = resolve_dfspath_wcard(ctx, conn,
6396 req->flags2 & FLAGS2_DFS_PATHNAMES,
6397 newname,
6398 true,
6399 !conn->sconn->using_smb2,
6400 &newname,
6401 &dest_has_wcard);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 return status;
6406 /* Check the new name has no '/' characters. */
6407 if (strchr_m(newname, '/')) {
6408 return NT_STATUS_NOT_SUPPORTED;
6411 if (fsp && fsp->base_fsp) {
6412 /* newname must be a stream name. */
6413 if (newname[0] != ':') {
6414 return NT_STATUS_NOT_SUPPORTED;
6417 /* Create an smb_fname to call rename_internals_fsp() with. */
6418 smb_fname_dst = synthetic_smb_fname(
6419 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6420 newname, NULL);
6421 if (smb_fname_dst == NULL) {
6422 status = NT_STATUS_NO_MEMORY;
6423 goto out;
6427 * Set the original last component, since
6428 * rename_internals_fsp() requires it.
6430 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6431 newname);
6432 if (smb_fname_dst->original_lcomp == NULL) {
6433 status = NT_STATUS_NO_MEMORY;
6434 goto out;
6437 } else {
6439 * Build up an smb_fname_dst based on the filename passed in.
6440 * We basically just strip off the last component, and put on
6441 * the newname instead.
6443 char *base_name = NULL;
6445 /* newname must *not* be a stream name. */
6446 if (newname[0] == ':') {
6447 return NT_STATUS_NOT_SUPPORTED;
6451 * Strip off the last component (filename) of the path passed
6452 * in.
6454 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6455 if (!base_name) {
6456 return NT_STATUS_NO_MEMORY;
6458 p = strrchr_m(base_name, '/');
6459 if (p) {
6460 p[1] = '\0';
6461 } else {
6462 base_name = talloc_strdup(ctx, "");
6463 if (!base_name) {
6464 return NT_STATUS_NO_MEMORY;
6467 /* Append the new name. */
6468 base_name = talloc_asprintf_append(base_name,
6469 "%s",
6470 newname);
6471 if (!base_name) {
6472 return NT_STATUS_NO_MEMORY;
6475 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6476 (UCF_SAVE_LCOMP |
6477 (dest_has_wcard ?
6478 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6479 0)));
6481 /* If an error we expect this to be
6482 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6484 if (!NT_STATUS_IS_OK(status)) {
6485 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6486 status)) {
6487 goto out;
6489 /* Create an smb_fname to call rename_internals_fsp() */
6490 smb_fname_dst = synthetic_smb_fname(
6491 ctx, base_name, NULL, NULL);
6492 if (smb_fname_dst == NULL) {
6493 status = NT_STATUS_NO_MEMORY;
6494 goto out;
6499 if (fsp) {
6500 DEBUG(10,("smb_file_rename_information: "
6501 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6502 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6503 smb_fname_str_dbg(smb_fname_dst)));
6504 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6505 overwrite);
6506 } else {
6507 DEBUG(10,("smb_file_rename_information: "
6508 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6509 smb_fname_str_dbg(smb_fname_src),
6510 smb_fname_str_dbg(smb_fname_dst)));
6511 status = rename_internals(ctx, conn, req, smb_fname_src,
6512 smb_fname_dst, 0, overwrite, false,
6513 dest_has_wcard,
6514 FILE_WRITE_ATTRIBUTES);
6516 out:
6517 TALLOC_FREE(smb_fname_dst);
6518 return status;
6521 /****************************************************************************
6522 Deal with SMB_SET_POSIX_ACL.
6523 ****************************************************************************/
6525 #if defined(HAVE_POSIX_ACLS)
6526 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6527 const char *pdata,
6528 int total_data,
6529 files_struct *fsp,
6530 const struct smb_filename *smb_fname)
6532 uint16 posix_acl_version;
6533 uint16 num_file_acls;
6534 uint16 num_def_acls;
6535 bool valid_file_acls = True;
6536 bool valid_def_acls = True;
6538 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6539 return NT_STATUS_INVALID_PARAMETER;
6541 posix_acl_version = SVAL(pdata,0);
6542 num_file_acls = SVAL(pdata,2);
6543 num_def_acls = SVAL(pdata,4);
6545 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6546 valid_file_acls = False;
6547 num_file_acls = 0;
6550 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6551 valid_def_acls = False;
6552 num_def_acls = 0;
6555 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6556 return NT_STATUS_INVALID_PARAMETER;
6559 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6560 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6561 return NT_STATUS_INVALID_PARAMETER;
6564 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6565 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6566 (unsigned int)num_file_acls,
6567 (unsigned int)num_def_acls));
6569 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6570 smb_fname->base_name, num_file_acls,
6571 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6572 return map_nt_error_from_unix(errno);
6575 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6576 smb_fname->base_name, &smb_fname->st, num_def_acls,
6577 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6578 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6579 return map_nt_error_from_unix(errno);
6581 return NT_STATUS_OK;
6583 #endif
6585 /****************************************************************************
6586 Deal with SMB_SET_POSIX_LOCK.
6587 ****************************************************************************/
6589 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6590 struct smb_request *req,
6591 const char *pdata,
6592 int total_data,
6593 files_struct *fsp)
6595 uint64_t count;
6596 uint64_t offset;
6597 uint64_t smblctx;
6598 bool blocking_lock = False;
6599 enum brl_type lock_type;
6601 NTSTATUS status = NT_STATUS_OK;
6603 if (fsp == NULL || fsp->fh->fd == -1) {
6604 return NT_STATUS_INVALID_HANDLE;
6607 if (total_data != POSIX_LOCK_DATA_SIZE) {
6608 return NT_STATUS_INVALID_PARAMETER;
6611 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6612 case POSIX_LOCK_TYPE_READ:
6613 lock_type = READ_LOCK;
6614 break;
6615 case POSIX_LOCK_TYPE_WRITE:
6616 /* Return the right POSIX-mappable error code for files opened read-only. */
6617 if (!fsp->can_write) {
6618 return NT_STATUS_INVALID_HANDLE;
6620 lock_type = WRITE_LOCK;
6621 break;
6622 case POSIX_LOCK_TYPE_UNLOCK:
6623 lock_type = UNLOCK_LOCK;
6624 break;
6625 default:
6626 return NT_STATUS_INVALID_PARAMETER;
6629 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6630 blocking_lock = False;
6631 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6632 blocking_lock = True;
6633 } else {
6634 return NT_STATUS_INVALID_PARAMETER;
6637 if (!lp_blocking_locks(SNUM(conn))) {
6638 blocking_lock = False;
6641 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6642 #if defined(HAVE_LONGLONG)
6643 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6644 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6645 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6646 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6647 #else /* HAVE_LONGLONG */
6648 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6649 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6650 #endif /* HAVE_LONGLONG */
6652 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6653 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6654 fsp_str_dbg(fsp),
6655 (unsigned int)lock_type,
6656 (unsigned long long)smblctx,
6657 (double)count,
6658 (double)offset ));
6660 if (lock_type == UNLOCK_LOCK) {
6661 status = do_unlock(req->sconn->msg_ctx,
6662 fsp,
6663 smblctx,
6664 count,
6665 offset,
6666 POSIX_LOCK);
6667 } else {
6668 uint64_t block_smblctx;
6670 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6671 fsp,
6672 smblctx,
6673 count,
6674 offset,
6675 lock_type,
6676 POSIX_LOCK,
6677 blocking_lock,
6678 &status,
6679 &block_smblctx,
6680 NULL);
6682 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6684 * A blocking lock was requested. Package up
6685 * this smb into a queued request and push it
6686 * onto the blocking lock queue.
6688 if(push_blocking_lock_request(br_lck,
6689 req,
6690 fsp,
6691 -1, /* infinite timeout. */
6693 smblctx,
6694 lock_type,
6695 POSIX_LOCK,
6696 offset,
6697 count,
6698 block_smblctx)) {
6699 TALLOC_FREE(br_lck);
6700 return status;
6703 TALLOC_FREE(br_lck);
6706 return status;
6709 /****************************************************************************
6710 Deal with SMB_SET_FILE_BASIC_INFO.
6711 ****************************************************************************/
6713 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6714 const char *pdata,
6715 int total_data,
6716 files_struct *fsp,
6717 const struct smb_filename *smb_fname)
6719 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6720 struct smb_file_time ft;
6721 uint32 dosmode = 0;
6722 NTSTATUS status = NT_STATUS_OK;
6724 ZERO_STRUCT(ft);
6726 if (total_data < 36) {
6727 return NT_STATUS_INVALID_PARAMETER;
6730 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 return status;
6735 /* Set the attributes */
6736 dosmode = IVAL(pdata,32);
6737 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6738 if (!NT_STATUS_IS_OK(status)) {
6739 return status;
6742 /* create time */
6743 ft.create_time = interpret_long_date(pdata);
6745 /* access time */
6746 ft.atime = interpret_long_date(pdata+8);
6748 /* write time. */
6749 ft.mtime = interpret_long_date(pdata+16);
6751 /* change time. */
6752 ft.ctime = interpret_long_date(pdata+24);
6754 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6755 smb_fname_str_dbg(smb_fname)));
6757 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6758 true);
6761 /****************************************************************************
6762 Deal with SMB_INFO_STANDARD.
6763 ****************************************************************************/
6765 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6766 const char *pdata,
6767 int total_data,
6768 files_struct *fsp,
6769 const struct smb_filename *smb_fname)
6771 NTSTATUS status;
6772 struct smb_file_time ft;
6774 ZERO_STRUCT(ft);
6776 if (total_data < 12) {
6777 return NT_STATUS_INVALID_PARAMETER;
6780 /* create time */
6781 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6782 /* access time */
6783 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6784 /* write time */
6785 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6787 DEBUG(10,("smb_set_info_standard: file %s\n",
6788 smb_fname_str_dbg(smb_fname)));
6790 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6791 if (!NT_STATUS_IS_OK(status)) {
6792 return status;
6795 return smb_set_file_time(conn,
6796 fsp,
6797 smb_fname,
6798 &ft,
6799 true);
6802 /****************************************************************************
6803 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6804 ****************************************************************************/
6806 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6807 struct smb_request *req,
6808 const char *pdata,
6809 int total_data,
6810 files_struct *fsp,
6811 struct smb_filename *smb_fname)
6813 uint64_t allocation_size = 0;
6814 NTSTATUS status = NT_STATUS_OK;
6815 files_struct *new_fsp = NULL;
6817 if (!VALID_STAT(smb_fname->st)) {
6818 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6821 if (total_data < 8) {
6822 return NT_STATUS_INVALID_PARAMETER;
6825 allocation_size = (uint64_t)IVAL(pdata,0);
6826 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6827 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6828 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6829 (double)allocation_size));
6831 if (allocation_size) {
6832 allocation_size = smb_roundup(conn, allocation_size);
6835 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6836 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6837 (double)allocation_size));
6839 if (fsp && fsp->fh->fd != -1) {
6840 /* Open file handle. */
6841 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6842 return NT_STATUS_ACCESS_DENIED;
6845 /* Only change if needed. */
6846 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6847 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6848 return map_nt_error_from_unix(errno);
6851 /* But always update the time. */
6853 * This is equivalent to a write. Ensure it's seen immediately
6854 * if there are no pending writes.
6856 trigger_write_time_update_immediate(fsp);
6857 return NT_STATUS_OK;
6860 /* Pathname or stat or directory file. */
6861 status = SMB_VFS_CREATE_FILE(
6862 conn, /* conn */
6863 req, /* req */
6864 0, /* root_dir_fid */
6865 smb_fname, /* fname */
6866 FILE_WRITE_DATA, /* access_mask */
6867 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6868 FILE_SHARE_DELETE),
6869 FILE_OPEN, /* create_disposition*/
6870 0, /* create_options */
6871 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6872 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6873 0, /* allocation_size */
6874 0, /* private_flags */
6875 NULL, /* sd */
6876 NULL, /* ea_list */
6877 &new_fsp, /* result */
6878 NULL); /* pinfo */
6880 if (!NT_STATUS_IS_OK(status)) {
6881 /* NB. We check for open_was_deferred in the caller. */
6882 return status;
6885 /* Only change if needed. */
6886 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6887 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6888 status = map_nt_error_from_unix(errno);
6889 close_file(req, new_fsp, NORMAL_CLOSE);
6890 return status;
6894 /* Changing the allocation size should set the last mod time. */
6896 * This is equivalent to a write. Ensure it's seen immediately
6897 * if there are no pending writes.
6899 trigger_write_time_update_immediate(new_fsp);
6901 close_file(req, new_fsp, NORMAL_CLOSE);
6902 return NT_STATUS_OK;
6905 /****************************************************************************
6906 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6907 ****************************************************************************/
6909 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6910 struct smb_request *req,
6911 const char *pdata,
6912 int total_data,
6913 files_struct *fsp,
6914 const struct smb_filename *smb_fname,
6915 bool fail_after_createfile)
6917 off_t size;
6919 if (total_data < 8) {
6920 return NT_STATUS_INVALID_PARAMETER;
6923 size = IVAL(pdata,0);
6924 size |= (((off_t)IVAL(pdata,4)) << 32);
6925 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6926 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6927 (double)size));
6929 return smb_set_file_size(conn, req,
6930 fsp,
6931 smb_fname,
6932 &smb_fname->st,
6933 size,
6934 fail_after_createfile);
6937 /****************************************************************************
6938 Allow a UNIX info mknod.
6939 ****************************************************************************/
6941 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6942 const char *pdata,
6943 int total_data,
6944 const struct smb_filename *smb_fname)
6946 uint32 file_type = IVAL(pdata,56);
6947 #if defined(HAVE_MAKEDEV)
6948 uint32 dev_major = IVAL(pdata,60);
6949 uint32 dev_minor = IVAL(pdata,68);
6950 #endif
6951 SMB_DEV_T dev = (SMB_DEV_T)0;
6952 uint32 raw_unixmode = IVAL(pdata,84);
6953 NTSTATUS status;
6954 mode_t unixmode;
6956 if (total_data < 100) {
6957 return NT_STATUS_INVALID_PARAMETER;
6960 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6961 PERM_NEW_FILE, &unixmode);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 return status;
6966 #if defined(HAVE_MAKEDEV)
6967 dev = makedev(dev_major, dev_minor);
6968 #endif
6970 switch (file_type) {
6971 #if defined(S_IFIFO)
6972 case UNIX_TYPE_FIFO:
6973 unixmode |= S_IFIFO;
6974 break;
6975 #endif
6976 #if defined(S_IFSOCK)
6977 case UNIX_TYPE_SOCKET:
6978 unixmode |= S_IFSOCK;
6979 break;
6980 #endif
6981 #if defined(S_IFCHR)
6982 case UNIX_TYPE_CHARDEV:
6983 unixmode |= S_IFCHR;
6984 break;
6985 #endif
6986 #if defined(S_IFBLK)
6987 case UNIX_TYPE_BLKDEV:
6988 unixmode |= S_IFBLK;
6989 break;
6990 #endif
6991 default:
6992 return NT_STATUS_INVALID_PARAMETER;
6995 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6996 "%.0f mode 0%o for file %s\n", (double)dev,
6997 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6999 /* Ok - do the mknod. */
7000 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7001 return map_nt_error_from_unix(errno);
7004 /* If any of the other "set" calls fail we
7005 * don't want to end up with a half-constructed mknod.
7008 if (lp_inherit_perms(SNUM(conn))) {
7009 char *parent;
7010 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7011 &parent, NULL)) {
7012 return NT_STATUS_NO_MEMORY;
7014 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7015 unixmode);
7016 TALLOC_FREE(parent);
7019 return NT_STATUS_OK;
7022 /****************************************************************************
7023 Deal with SMB_SET_FILE_UNIX_BASIC.
7024 ****************************************************************************/
7026 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7027 struct smb_request *req,
7028 const char *pdata,
7029 int total_data,
7030 files_struct *fsp,
7031 const struct smb_filename *smb_fname)
7033 struct smb_file_time ft;
7034 uint32 raw_unixmode;
7035 mode_t unixmode;
7036 off_t size = 0;
7037 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7038 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7039 NTSTATUS status = NT_STATUS_OK;
7040 bool delete_on_fail = False;
7041 enum perm_type ptype;
7042 files_struct *all_fsps = NULL;
7043 bool modify_mtime = true;
7044 struct file_id id;
7045 struct smb_filename *smb_fname_tmp = NULL;
7046 SMB_STRUCT_STAT sbuf;
7048 ZERO_STRUCT(ft);
7050 if (total_data < 100) {
7051 return NT_STATUS_INVALID_PARAMETER;
7054 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7055 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7056 size=IVAL(pdata,0); /* first 8 Bytes are size */
7057 size |= (((off_t)IVAL(pdata,4)) << 32);
7060 ft.atime = interpret_long_date(pdata+24); /* access_time */
7061 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7062 set_owner = (uid_t)IVAL(pdata,40);
7063 set_grp = (gid_t)IVAL(pdata,48);
7064 raw_unixmode = IVAL(pdata,84);
7066 if (VALID_STAT(smb_fname->st)) {
7067 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7068 ptype = PERM_EXISTING_DIR;
7069 } else {
7070 ptype = PERM_EXISTING_FILE;
7072 } else {
7073 ptype = PERM_NEW_FILE;
7076 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7077 ptype, &unixmode);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 return status;
7082 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7083 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7084 smb_fname_str_dbg(smb_fname), (double)size,
7085 (unsigned int)set_owner, (unsigned int)set_grp,
7086 (int)raw_unixmode));
7088 sbuf = smb_fname->st;
7090 if (!VALID_STAT(sbuf)) {
7092 * The only valid use of this is to create character and block
7093 * devices, and named pipes. This is deprecated (IMHO) and
7094 * a new info level should be used for mknod. JRA.
7097 status = smb_unix_mknod(conn,
7098 pdata,
7099 total_data,
7100 smb_fname);
7101 if (!NT_STATUS_IS_OK(status)) {
7102 return status;
7105 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7106 if (smb_fname_tmp == NULL) {
7107 return NT_STATUS_NO_MEMORY;
7110 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7111 status = map_nt_error_from_unix(errno);
7112 TALLOC_FREE(smb_fname_tmp);
7113 SMB_VFS_UNLINK(conn, smb_fname);
7114 return status;
7117 sbuf = smb_fname_tmp->st;
7118 smb_fname = smb_fname_tmp;
7120 /* Ensure we don't try and change anything else. */
7121 raw_unixmode = SMB_MODE_NO_CHANGE;
7122 size = get_file_size_stat(&sbuf);
7123 ft.atime = sbuf.st_ex_atime;
7124 ft.mtime = sbuf.st_ex_mtime;
7126 * We continue here as we might want to change the
7127 * owner uid/gid.
7129 delete_on_fail = True;
7132 #if 1
7133 /* Horrible backwards compatibility hack as an old server bug
7134 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7135 * */
7137 if (!size) {
7138 size = get_file_size_stat(&sbuf);
7140 #endif
7143 * Deal with the UNIX specific mode set.
7146 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7147 int ret;
7149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7150 "setting mode 0%o for file %s\n",
7151 (unsigned int)unixmode,
7152 smb_fname_str_dbg(smb_fname)));
7153 if (fsp && fsp->fh->fd != -1) {
7154 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7155 } else {
7156 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7158 if (ret != 0) {
7159 return map_nt_error_from_unix(errno);
7164 * Deal with the UNIX specific uid set.
7167 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7168 (sbuf.st_ex_uid != set_owner)) {
7169 int ret;
7171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7172 "changing owner %u for path %s\n",
7173 (unsigned int)set_owner,
7174 smb_fname_str_dbg(smb_fname)));
7176 if (fsp && fsp->fh->fd != -1) {
7177 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7178 } else {
7180 * UNIX extensions calls must always operate
7181 * on symlinks.
7183 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7184 set_owner, (gid_t)-1);
7187 if (ret != 0) {
7188 status = map_nt_error_from_unix(errno);
7189 if (delete_on_fail) {
7190 SMB_VFS_UNLINK(conn, smb_fname);
7192 return status;
7197 * Deal with the UNIX specific gid set.
7200 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7201 (sbuf.st_ex_gid != set_grp)) {
7202 int ret;
7204 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7205 "changing group %u for file %s\n",
7206 (unsigned int)set_owner,
7207 smb_fname_str_dbg(smb_fname)));
7208 if (fsp && fsp->fh->fd != -1) {
7209 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7210 } else {
7212 * UNIX extensions calls must always operate
7213 * on symlinks.
7215 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7216 set_grp);
7218 if (ret != 0) {
7219 status = map_nt_error_from_unix(errno);
7220 if (delete_on_fail) {
7221 SMB_VFS_UNLINK(conn, smb_fname);
7223 return status;
7227 /* Deal with any size changes. */
7229 status = smb_set_file_size(conn, req,
7230 fsp,
7231 smb_fname,
7232 &sbuf,
7233 size,
7234 false);
7235 if (!NT_STATUS_IS_OK(status)) {
7236 return status;
7239 /* Deal with any time changes. */
7240 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7241 /* No change, don't cancel anything. */
7242 return status;
7245 id = vfs_file_id_from_sbuf(conn, &sbuf);
7246 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7247 all_fsps = file_find_di_next(all_fsps)) {
7249 * We're setting the time explicitly for UNIX.
7250 * Cancel any pending changes over all handles.
7252 all_fsps->update_write_time_on_close = false;
7253 TALLOC_FREE(all_fsps->update_write_time_event);
7257 * Override the "setting_write_time"
7258 * parameter here as it almost does what
7259 * we need. Just remember if we modified
7260 * mtime and send the notify ourselves.
7262 if (null_timespec(ft.mtime)) {
7263 modify_mtime = false;
7266 status = smb_set_file_time(conn,
7267 fsp,
7268 smb_fname,
7269 &ft,
7270 false);
7271 if (modify_mtime) {
7272 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7273 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7275 return status;
7278 /****************************************************************************
7279 Deal with SMB_SET_FILE_UNIX_INFO2.
7280 ****************************************************************************/
7282 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7283 struct smb_request *req,
7284 const char *pdata,
7285 int total_data,
7286 files_struct *fsp,
7287 const struct smb_filename *smb_fname)
7289 NTSTATUS status;
7290 uint32 smb_fflags;
7291 uint32 smb_fmask;
7293 if (total_data < 116) {
7294 return NT_STATUS_INVALID_PARAMETER;
7297 /* Start by setting all the fields that are common between UNIX_BASIC
7298 * and UNIX_INFO2.
7300 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7301 fsp, smb_fname);
7302 if (!NT_STATUS_IS_OK(status)) {
7303 return status;
7306 smb_fflags = IVAL(pdata, 108);
7307 smb_fmask = IVAL(pdata, 112);
7309 /* NB: We should only attempt to alter the file flags if the client
7310 * sends a non-zero mask.
7312 if (smb_fmask != 0) {
7313 int stat_fflags = 0;
7315 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7316 smb_fmask, &stat_fflags)) {
7317 /* Client asked to alter a flag we don't understand. */
7318 return NT_STATUS_INVALID_PARAMETER;
7321 if (fsp && fsp->fh->fd != -1) {
7322 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7323 return NT_STATUS_NOT_SUPPORTED;
7324 } else {
7325 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7326 stat_fflags) != 0) {
7327 return map_nt_error_from_unix(errno);
7332 /* XXX: need to add support for changing the create_time here. You
7333 * can do this for paths on Darwin with setattrlist(2). The right way
7334 * to hook this up is probably by extending the VFS utimes interface.
7337 return NT_STATUS_OK;
7340 /****************************************************************************
7341 Create a directory with POSIX semantics.
7342 ****************************************************************************/
7344 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7345 struct smb_request *req,
7346 char **ppdata,
7347 int total_data,
7348 struct smb_filename *smb_fname,
7349 int *pdata_return_size)
7351 NTSTATUS status = NT_STATUS_OK;
7352 uint32 raw_unixmode = 0;
7353 uint32 mod_unixmode = 0;
7354 mode_t unixmode = (mode_t)0;
7355 files_struct *fsp = NULL;
7356 uint16 info_level_return = 0;
7357 int info;
7358 char *pdata = *ppdata;
7360 if (total_data < 18) {
7361 return NT_STATUS_INVALID_PARAMETER;
7364 raw_unixmode = IVAL(pdata,8);
7365 /* Next 4 bytes are not yet defined. */
7367 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7368 PERM_NEW_DIR, &unixmode);
7369 if (!NT_STATUS_IS_OK(status)) {
7370 return status;
7373 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7375 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7376 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7378 status = SMB_VFS_CREATE_FILE(
7379 conn, /* conn */
7380 req, /* req */
7381 0, /* root_dir_fid */
7382 smb_fname, /* fname */
7383 FILE_READ_ATTRIBUTES, /* access_mask */
7384 FILE_SHARE_NONE, /* share_access */
7385 FILE_CREATE, /* create_disposition*/
7386 FILE_DIRECTORY_FILE, /* create_options */
7387 mod_unixmode, /* file_attributes */
7388 0, /* oplock_request */
7389 0, /* allocation_size */
7390 0, /* private_flags */
7391 NULL, /* sd */
7392 NULL, /* ea_list */
7393 &fsp, /* result */
7394 &info); /* pinfo */
7396 if (NT_STATUS_IS_OK(status)) {
7397 close_file(req, fsp, NORMAL_CLOSE);
7400 info_level_return = SVAL(pdata,16);
7402 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7403 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7404 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7405 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7406 } else {
7407 *pdata_return_size = 12;
7410 /* Realloc the data size */
7411 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7412 if (*ppdata == NULL) {
7413 *pdata_return_size = 0;
7414 return NT_STATUS_NO_MEMORY;
7416 pdata = *ppdata;
7418 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7419 SSVAL(pdata,2,0); /* No fnum. */
7420 SIVAL(pdata,4,info); /* Was directory created. */
7422 switch (info_level_return) {
7423 case SMB_QUERY_FILE_UNIX_BASIC:
7424 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7425 SSVAL(pdata,10,0); /* Padding. */
7426 store_file_unix_basic(conn, pdata + 12, fsp,
7427 &smb_fname->st);
7428 break;
7429 case SMB_QUERY_FILE_UNIX_INFO2:
7430 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7431 SSVAL(pdata,10,0); /* Padding. */
7432 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7433 &smb_fname->st);
7434 break;
7435 default:
7436 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7437 SSVAL(pdata,10,0); /* Padding. */
7438 break;
7441 return status;
7444 /****************************************************************************
7445 Open/Create a file with POSIX semantics.
7446 ****************************************************************************/
7448 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7449 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7451 static NTSTATUS smb_posix_open(connection_struct *conn,
7452 struct smb_request *req,
7453 char **ppdata,
7454 int total_data,
7455 struct smb_filename *smb_fname,
7456 int *pdata_return_size)
7458 bool extended_oplock_granted = False;
7459 char *pdata = *ppdata;
7460 uint32 flags = 0;
7461 uint32 wire_open_mode = 0;
7462 uint32 raw_unixmode = 0;
7463 uint32 mod_unixmode = 0;
7464 uint32 create_disp = 0;
7465 uint32 access_mask = 0;
7466 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7467 NTSTATUS status = NT_STATUS_OK;
7468 mode_t unixmode = (mode_t)0;
7469 files_struct *fsp = NULL;
7470 int oplock_request = 0;
7471 int info = 0;
7472 uint16 info_level_return = 0;
7474 if (total_data < 18) {
7475 return NT_STATUS_INVALID_PARAMETER;
7478 flags = IVAL(pdata,0);
7479 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7480 if (oplock_request) {
7481 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7484 wire_open_mode = IVAL(pdata,4);
7486 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7487 return smb_posix_mkdir(conn, req,
7488 ppdata,
7489 total_data,
7490 smb_fname,
7491 pdata_return_size);
7494 switch (wire_open_mode & SMB_ACCMODE) {
7495 case SMB_O_RDONLY:
7496 access_mask = SMB_O_RDONLY_MAPPING;
7497 break;
7498 case SMB_O_WRONLY:
7499 access_mask = SMB_O_WRONLY_MAPPING;
7500 break;
7501 case SMB_O_RDWR:
7502 access_mask = (SMB_O_RDONLY_MAPPING|
7503 SMB_O_WRONLY_MAPPING);
7504 break;
7505 default:
7506 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7507 (unsigned int)wire_open_mode ));
7508 return NT_STATUS_INVALID_PARAMETER;
7511 wire_open_mode &= ~SMB_ACCMODE;
7513 /* First take care of O_CREAT|O_EXCL interactions. */
7514 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7515 case (SMB_O_CREAT | SMB_O_EXCL):
7516 /* File exists fail. File not exist create. */
7517 create_disp = FILE_CREATE;
7518 break;
7519 case SMB_O_CREAT:
7520 /* File exists open. File not exist create. */
7521 create_disp = FILE_OPEN_IF;
7522 break;
7523 case SMB_O_EXCL:
7524 /* O_EXCL on its own without O_CREAT is undefined.
7525 We deliberately ignore it as some versions of
7526 Linux CIFSFS can send a bare O_EXCL on the
7527 wire which other filesystems in the kernel
7528 ignore. See bug 9519 for details. */
7530 /* Fallthrough. */
7532 case 0:
7533 /* File exists open. File not exist fail. */
7534 create_disp = FILE_OPEN;
7535 break;
7536 default:
7537 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7538 (unsigned int)wire_open_mode ));
7539 return NT_STATUS_INVALID_PARAMETER;
7542 /* Next factor in the effects of O_TRUNC. */
7543 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7545 if (wire_open_mode & SMB_O_TRUNC) {
7546 switch (create_disp) {
7547 case FILE_CREATE:
7548 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7549 /* Leave create_disp alone as
7550 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7552 /* File exists fail. File not exist create. */
7553 break;
7554 case FILE_OPEN_IF:
7555 /* SMB_O_CREAT | SMB_O_TRUNC */
7556 /* File exists overwrite. File not exist create. */
7557 create_disp = FILE_OVERWRITE_IF;
7558 break;
7559 case FILE_OPEN:
7560 /* SMB_O_TRUNC */
7561 /* File exists overwrite. File not exist fail. */
7562 create_disp = FILE_OVERWRITE;
7563 break;
7564 default:
7565 /* Cannot get here. */
7566 smb_panic("smb_posix_open: logic error");
7567 return NT_STATUS_INVALID_PARAMETER;
7571 raw_unixmode = IVAL(pdata,8);
7572 /* Next 4 bytes are not yet defined. */
7574 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7575 (VALID_STAT(smb_fname->st) ?
7576 PERM_EXISTING_FILE : PERM_NEW_FILE),
7577 &unixmode);
7579 if (!NT_STATUS_IS_OK(status)) {
7580 return status;
7583 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7585 if (wire_open_mode & SMB_O_SYNC) {
7586 create_options |= FILE_WRITE_THROUGH;
7588 if (wire_open_mode & SMB_O_APPEND) {
7589 access_mask |= FILE_APPEND_DATA;
7591 if (wire_open_mode & SMB_O_DIRECT) {
7592 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7595 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7596 VALID_STAT_OF_DIR(smb_fname->st)) {
7597 if (access_mask != SMB_O_RDONLY_MAPPING) {
7598 return NT_STATUS_FILE_IS_A_DIRECTORY;
7600 create_options &= ~FILE_NON_DIRECTORY_FILE;
7601 create_options |= FILE_DIRECTORY_FILE;
7604 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7605 smb_fname_str_dbg(smb_fname),
7606 (unsigned int)wire_open_mode,
7607 (unsigned int)unixmode ));
7609 status = SMB_VFS_CREATE_FILE(
7610 conn, /* conn */
7611 req, /* req */
7612 0, /* root_dir_fid */
7613 smb_fname, /* fname */
7614 access_mask, /* access_mask */
7615 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7616 FILE_SHARE_DELETE),
7617 create_disp, /* create_disposition*/
7618 create_options, /* create_options */
7619 mod_unixmode, /* file_attributes */
7620 oplock_request, /* oplock_request */
7621 0, /* allocation_size */
7622 0, /* private_flags */
7623 NULL, /* sd */
7624 NULL, /* ea_list */
7625 &fsp, /* result */
7626 &info); /* pinfo */
7628 if (!NT_STATUS_IS_OK(status)) {
7629 return status;
7632 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7633 extended_oplock_granted = True;
7636 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7637 extended_oplock_granted = True;
7640 info_level_return = SVAL(pdata,16);
7642 /* Allocate the correct return size. */
7644 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7645 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7646 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7647 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7648 } else {
7649 *pdata_return_size = 12;
7652 /* Realloc the data size */
7653 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7654 if (*ppdata == NULL) {
7655 close_file(req, fsp, ERROR_CLOSE);
7656 *pdata_return_size = 0;
7657 return NT_STATUS_NO_MEMORY;
7659 pdata = *ppdata;
7661 if (extended_oplock_granted) {
7662 if (flags & REQUEST_BATCH_OPLOCK) {
7663 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7664 } else {
7665 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7667 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7668 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7669 } else {
7670 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7673 SSVAL(pdata,2,fsp->fnum);
7674 SIVAL(pdata,4,info); /* Was file created etc. */
7676 switch (info_level_return) {
7677 case SMB_QUERY_FILE_UNIX_BASIC:
7678 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7679 SSVAL(pdata,10,0); /* padding. */
7680 store_file_unix_basic(conn, pdata + 12, fsp,
7681 &smb_fname->st);
7682 break;
7683 case SMB_QUERY_FILE_UNIX_INFO2:
7684 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7685 SSVAL(pdata,10,0); /* padding. */
7686 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7687 &smb_fname->st);
7688 break;
7689 default:
7690 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7691 SSVAL(pdata,10,0); /* padding. */
7692 break;
7694 return NT_STATUS_OK;
7697 /****************************************************************************
7698 Delete a file with POSIX semantics.
7699 ****************************************************************************/
7701 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7702 struct smb_request *req,
7703 const char *pdata,
7704 int total_data,
7705 struct smb_filename *smb_fname)
7707 NTSTATUS status = NT_STATUS_OK;
7708 files_struct *fsp = NULL;
7709 uint16 flags = 0;
7710 char del = 1;
7711 int info = 0;
7712 int create_options = 0;
7713 int i;
7714 struct share_mode_lock *lck = NULL;
7716 if (total_data < 2) {
7717 return NT_STATUS_INVALID_PARAMETER;
7720 flags = SVAL(pdata,0);
7722 if (!VALID_STAT(smb_fname->st)) {
7723 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7726 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7727 !VALID_STAT_OF_DIR(smb_fname->st)) {
7728 return NT_STATUS_NOT_A_DIRECTORY;
7731 DEBUG(10,("smb_posix_unlink: %s %s\n",
7732 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7733 smb_fname_str_dbg(smb_fname)));
7735 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7736 create_options |= FILE_DIRECTORY_FILE;
7739 status = SMB_VFS_CREATE_FILE(
7740 conn, /* conn */
7741 req, /* req */
7742 0, /* root_dir_fid */
7743 smb_fname, /* fname */
7744 DELETE_ACCESS, /* access_mask */
7745 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7746 FILE_SHARE_DELETE),
7747 FILE_OPEN, /* create_disposition*/
7748 create_options, /* create_options */
7749 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7750 0, /* oplock_request */
7751 0, /* allocation_size */
7752 0, /* private_flags */
7753 NULL, /* sd */
7754 NULL, /* ea_list */
7755 &fsp, /* result */
7756 &info); /* pinfo */
7758 if (!NT_STATUS_IS_OK(status)) {
7759 return status;
7763 * Don't lie to client. If we can't really delete due to
7764 * non-POSIX opens return SHARING_VIOLATION.
7767 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7768 if (lck == NULL) {
7769 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7770 "lock for file %s\n", fsp_str_dbg(fsp)));
7771 close_file(req, fsp, NORMAL_CLOSE);
7772 return NT_STATUS_INVALID_PARAMETER;
7776 * See if others still have the file open. If this is the case, then
7777 * don't delete. If all opens are POSIX delete we can set the delete
7778 * on close disposition.
7780 for (i=0; i<lck->data->num_share_modes; i++) {
7781 struct share_mode_entry *e = &lck->data->share_modes[i];
7782 if (is_valid_share_mode_entry(e)) {
7783 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7784 continue;
7786 if (share_mode_stale_pid(lck->data, i)) {
7787 continue;
7789 /* Fail with sharing violation. */
7790 TALLOC_FREE(lck);
7791 close_file(req, fsp, NORMAL_CLOSE);
7792 return NT_STATUS_SHARING_VIOLATION;
7797 * Set the delete on close.
7799 status = smb_set_file_disposition_info(conn,
7800 &del,
7802 fsp,
7803 smb_fname);
7805 TALLOC_FREE(lck);
7807 if (!NT_STATUS_IS_OK(status)) {
7808 close_file(req, fsp, NORMAL_CLOSE);
7809 return status;
7811 return close_file(req, fsp, NORMAL_CLOSE);
7814 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7815 struct smb_request *req,
7816 TALLOC_CTX *mem_ctx,
7817 uint16_t info_level,
7818 files_struct *fsp,
7819 struct smb_filename *smb_fname,
7820 char **ppdata, int total_data,
7821 int *ret_data_size)
7823 char *pdata = *ppdata;
7824 NTSTATUS status = NT_STATUS_OK;
7825 int data_return_size = 0;
7827 *ret_data_size = 0;
7829 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7830 return NT_STATUS_INVALID_LEVEL;
7833 if (!CAN_WRITE(conn)) {
7834 /* Allow POSIX opens. The open path will deny
7835 * any non-readonly opens. */
7836 if (info_level != SMB_POSIX_PATH_OPEN) {
7837 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7841 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7842 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7843 fsp_fnum_dbg(fsp),
7844 info_level, total_data));
7846 switch (info_level) {
7848 case SMB_INFO_STANDARD:
7850 status = smb_set_info_standard(conn,
7851 pdata,
7852 total_data,
7853 fsp,
7854 smb_fname);
7855 break;
7858 case SMB_INFO_SET_EA:
7860 status = smb_info_set_ea(conn,
7861 pdata,
7862 total_data,
7863 fsp,
7864 smb_fname);
7865 break;
7868 case SMB_SET_FILE_BASIC_INFO:
7869 case SMB_FILE_BASIC_INFORMATION:
7871 status = smb_set_file_basic_info(conn,
7872 pdata,
7873 total_data,
7874 fsp,
7875 smb_fname);
7876 break;
7879 case SMB_FILE_ALLOCATION_INFORMATION:
7880 case SMB_SET_FILE_ALLOCATION_INFO:
7882 status = smb_set_file_allocation_info(conn, req,
7883 pdata,
7884 total_data,
7885 fsp,
7886 smb_fname);
7887 break;
7890 case SMB_FILE_END_OF_FILE_INFORMATION:
7891 case SMB_SET_FILE_END_OF_FILE_INFO:
7894 * XP/Win7 both fail after the createfile with
7895 * SMB_SET_FILE_END_OF_FILE_INFO but not
7896 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7897 * The level is known here, so pass it down
7898 * appropriately.
7900 bool should_fail =
7901 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7903 status = smb_set_file_end_of_file_info(conn, req,
7904 pdata,
7905 total_data,
7906 fsp,
7907 smb_fname,
7908 should_fail);
7909 break;
7912 case SMB_FILE_DISPOSITION_INFORMATION:
7913 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7915 #if 0
7916 /* JRA - We used to just ignore this on a path ?
7917 * Shouldn't this be invalid level on a pathname
7918 * based call ?
7920 if (tran_call != TRANSACT2_SETFILEINFO) {
7921 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7923 #endif
7924 status = smb_set_file_disposition_info(conn,
7925 pdata,
7926 total_data,
7927 fsp,
7928 smb_fname);
7929 break;
7932 case SMB_FILE_POSITION_INFORMATION:
7934 status = smb_file_position_information(conn,
7935 pdata,
7936 total_data,
7937 fsp);
7938 break;
7941 case SMB_FILE_FULL_EA_INFORMATION:
7943 status = smb_set_file_full_ea_info(conn,
7944 pdata,
7945 total_data,
7946 fsp);
7947 break;
7950 /* From tridge Samba4 :
7951 * MODE_INFORMATION in setfileinfo (I have no
7952 * idea what "mode information" on a file is - it takes a value of 0,
7953 * 2, 4 or 6. What could it be?).
7956 case SMB_FILE_MODE_INFORMATION:
7958 status = smb_file_mode_information(conn,
7959 pdata,
7960 total_data);
7961 break;
7965 * CIFS UNIX extensions.
7968 case SMB_SET_FILE_UNIX_BASIC:
7970 status = smb_set_file_unix_basic(conn, req,
7971 pdata,
7972 total_data,
7973 fsp,
7974 smb_fname);
7975 break;
7978 case SMB_SET_FILE_UNIX_INFO2:
7980 status = smb_set_file_unix_info2(conn, req,
7981 pdata,
7982 total_data,
7983 fsp,
7984 smb_fname);
7985 break;
7988 case SMB_SET_FILE_UNIX_LINK:
7990 if (fsp) {
7991 /* We must have a pathname for this. */
7992 return NT_STATUS_INVALID_LEVEL;
7994 status = smb_set_file_unix_link(conn, req, pdata,
7995 total_data, smb_fname);
7996 break;
7999 case SMB_SET_FILE_UNIX_HLINK:
8001 if (fsp) {
8002 /* We must have a pathname for this. */
8003 return NT_STATUS_INVALID_LEVEL;
8005 status = smb_set_file_unix_hlink(conn, req,
8006 pdata, total_data,
8007 smb_fname);
8008 break;
8011 case SMB_FILE_RENAME_INFORMATION:
8013 status = smb_file_rename_information(conn, req,
8014 pdata, total_data,
8015 fsp, smb_fname);
8016 break;
8019 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8021 /* SMB2 rename information. */
8022 status = smb2_file_rename_information(conn, req,
8023 pdata, total_data,
8024 fsp, smb_fname);
8025 break;
8028 case SMB_FILE_LINK_INFORMATION:
8030 status = smb_file_link_information(conn, req,
8031 pdata, total_data,
8032 fsp, smb_fname);
8033 break;
8036 #if defined(HAVE_POSIX_ACLS)
8037 case SMB_SET_POSIX_ACL:
8039 status = smb_set_posix_acl(conn,
8040 pdata,
8041 total_data,
8042 fsp,
8043 smb_fname);
8044 break;
8046 #endif
8048 case SMB_SET_POSIX_LOCK:
8050 if (!fsp) {
8051 return NT_STATUS_INVALID_LEVEL;
8053 status = smb_set_posix_lock(conn, req,
8054 pdata, total_data, fsp);
8055 break;
8058 case SMB_POSIX_PATH_OPEN:
8060 if (fsp) {
8061 /* We must have a pathname for this. */
8062 return NT_STATUS_INVALID_LEVEL;
8065 status = smb_posix_open(conn, req,
8066 ppdata,
8067 total_data,
8068 smb_fname,
8069 &data_return_size);
8070 break;
8073 case SMB_POSIX_PATH_UNLINK:
8075 if (fsp) {
8076 /* We must have a pathname for this. */
8077 return NT_STATUS_INVALID_LEVEL;
8080 status = smb_posix_unlink(conn, req,
8081 pdata,
8082 total_data,
8083 smb_fname);
8084 break;
8087 default:
8088 return NT_STATUS_INVALID_LEVEL;
8091 if (!NT_STATUS_IS_OK(status)) {
8092 return status;
8095 *ret_data_size = data_return_size;
8096 return NT_STATUS_OK;
8099 /****************************************************************************
8100 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8101 ****************************************************************************/
8103 static void call_trans2setfilepathinfo(connection_struct *conn,
8104 struct smb_request *req,
8105 unsigned int tran_call,
8106 char **pparams, int total_params,
8107 char **ppdata, int total_data,
8108 unsigned int max_data_bytes)
8110 char *params = *pparams;
8111 char *pdata = *ppdata;
8112 uint16 info_level;
8113 struct smb_filename *smb_fname = NULL;
8114 files_struct *fsp = NULL;
8115 NTSTATUS status = NT_STATUS_OK;
8116 int data_return_size = 0;
8118 if (!params) {
8119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8120 return;
8123 if (tran_call == TRANSACT2_SETFILEINFO) {
8124 if (total_params < 4) {
8125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8126 return;
8129 fsp = file_fsp(req, SVAL(params,0));
8130 /* Basic check for non-null fsp. */
8131 if (!check_fsp_open(conn, req, fsp)) {
8132 return;
8134 info_level = SVAL(params,2);
8136 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8137 if (smb_fname == NULL) {
8138 reply_nterror(req, NT_STATUS_NO_MEMORY);
8139 return;
8142 if(fsp->fh->fd == -1) {
8144 * This is actually a SETFILEINFO on a directory
8145 * handle (returned from an NT SMB). NT5.0 seems
8146 * to do this call. JRA.
8148 if (INFO_LEVEL_IS_UNIX(info_level)) {
8149 /* Always do lstat for UNIX calls. */
8150 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8151 DEBUG(3,("call_trans2setfilepathinfo: "
8152 "SMB_VFS_LSTAT of %s failed "
8153 "(%s)\n",
8154 smb_fname_str_dbg(smb_fname),
8155 strerror(errno)));
8156 reply_nterror(req, map_nt_error_from_unix(errno));
8157 return;
8159 } else {
8160 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8161 DEBUG(3,("call_trans2setfilepathinfo: "
8162 "fileinfo of %s failed (%s)\n",
8163 smb_fname_str_dbg(smb_fname),
8164 strerror(errno)));
8165 reply_nterror(req, map_nt_error_from_unix(errno));
8166 return;
8169 } else if (fsp->print_file) {
8171 * Doing a DELETE_ON_CLOSE should cancel a print job.
8173 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8174 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8176 DEBUG(3,("call_trans2setfilepathinfo: "
8177 "Cancelling print job (%s)\n",
8178 fsp_str_dbg(fsp)));
8180 SSVAL(params,0,0);
8181 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8182 *ppdata, 0,
8183 max_data_bytes);
8184 return;
8185 } else {
8186 reply_nterror(req,
8187 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8188 return;
8190 } else {
8192 * Original code - this is an open file.
8194 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8195 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8196 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8197 strerror(errno)));
8198 reply_nterror(req, map_nt_error_from_unix(errno));
8199 return;
8202 } else {
8203 char *fname = NULL;
8204 uint32_t ucf_flags = 0;
8206 /* set path info */
8207 if (total_params < 7) {
8208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8209 return;
8212 info_level = SVAL(params,0);
8213 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8214 total_params - 6, STR_TERMINATE,
8215 &status);
8216 if (!NT_STATUS_IS_OK(status)) {
8217 reply_nterror(req, status);
8218 return;
8221 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8222 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8223 info_level == SMB_FILE_RENAME_INFORMATION ||
8224 info_level == SMB_POSIX_PATH_UNLINK) {
8225 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8228 status = filename_convert(req, conn,
8229 req->flags2 & FLAGS2_DFS_PATHNAMES,
8230 fname,
8231 ucf_flags,
8232 NULL,
8233 &smb_fname);
8234 if (!NT_STATUS_IS_OK(status)) {
8235 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8236 reply_botherror(req,
8237 NT_STATUS_PATH_NOT_COVERED,
8238 ERRSRV, ERRbadpath);
8239 return;
8241 reply_nterror(req, status);
8242 return;
8245 if (INFO_LEVEL_IS_UNIX(info_level)) {
8247 * For CIFS UNIX extensions the target name may not exist.
8250 /* Always do lstat for UNIX calls. */
8251 SMB_VFS_LSTAT(conn, smb_fname);
8253 } else if (!VALID_STAT(smb_fname->st) &&
8254 SMB_VFS_STAT(conn, smb_fname)) {
8255 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8256 "%s failed (%s)\n",
8257 smb_fname_str_dbg(smb_fname),
8258 strerror(errno)));
8259 reply_nterror(req, map_nt_error_from_unix(errno));
8260 return;
8264 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8265 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8266 fsp_fnum_dbg(fsp),
8267 info_level,total_data));
8269 /* Realloc the parameter size */
8270 *pparams = (char *)SMB_REALLOC(*pparams,2);
8271 if (*pparams == NULL) {
8272 reply_nterror(req, NT_STATUS_NO_MEMORY);
8273 return;
8275 params = *pparams;
8277 SSVAL(params,0,0);
8279 status = smbd_do_setfilepathinfo(conn, req, req,
8280 info_level,
8281 fsp,
8282 smb_fname,
8283 ppdata, total_data,
8284 &data_return_size);
8285 if (!NT_STATUS_IS_OK(status)) {
8286 if (open_was_deferred(req->sconn, req->mid)) {
8287 /* We have re-scheduled this call. */
8288 return;
8290 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8291 /* We have re-scheduled this call. */
8292 return;
8294 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8295 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8296 ERRSRV, ERRbadpath);
8297 return;
8299 if (info_level == SMB_POSIX_PATH_OPEN) {
8300 reply_openerror(req, status);
8301 return;
8305 * Invalid EA name needs to return 2 param bytes,
8306 * not a zero-length error packet.
8308 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8309 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8310 max_data_bytes);
8311 } else {
8312 reply_nterror(req, status);
8314 return;
8317 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8318 max_data_bytes);
8320 return;
8323 /****************************************************************************
8324 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8325 ****************************************************************************/
8327 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8328 char **pparams, int total_params,
8329 char **ppdata, int total_data,
8330 unsigned int max_data_bytes)
8332 struct smb_filename *smb_dname = NULL;
8333 char *params = *pparams;
8334 char *pdata = *ppdata;
8335 char *directory = NULL;
8336 NTSTATUS status = NT_STATUS_OK;
8337 struct ea_list *ea_list = NULL;
8338 TALLOC_CTX *ctx = talloc_tos();
8340 if (!CAN_WRITE(conn)) {
8341 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8342 return;
8345 if (total_params < 5) {
8346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8347 return;
8350 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8351 total_params - 4, STR_TERMINATE,
8352 &status);
8353 if (!NT_STATUS_IS_OK(status)) {
8354 reply_nterror(req, status);
8355 return;
8358 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8360 status = filename_convert(ctx,
8361 conn,
8362 req->flags2 & FLAGS2_DFS_PATHNAMES,
8363 directory,
8365 NULL,
8366 &smb_dname);
8368 if (!NT_STATUS_IS_OK(status)) {
8369 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8370 reply_botherror(req,
8371 NT_STATUS_PATH_NOT_COVERED,
8372 ERRSRV, ERRbadpath);
8373 return;
8375 reply_nterror(req, status);
8376 return;
8380 * OS/2 workplace shell seems to send SET_EA requests of "null"
8381 * length (4 bytes containing IVAL 4).
8382 * They seem to have no effect. Bug #3212. JRA.
8385 if (total_data && (total_data != 4)) {
8386 /* Any data in this call is an EA list. */
8387 if (total_data < 10) {
8388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8389 goto out;
8392 if (IVAL(pdata,0) > total_data) {
8393 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8394 IVAL(pdata,0), (unsigned int)total_data));
8395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8396 goto out;
8399 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8400 total_data - 4);
8401 if (!ea_list) {
8402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8403 goto out;
8406 if (!lp_ea_support(SNUM(conn))) {
8407 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8408 goto out;
8411 /* If total_data == 4 Windows doesn't care what values
8412 * are placed in that field, it just ignores them.
8413 * The System i QNTC IBM SMB client puts bad values here,
8414 * so ignore them. */
8416 status = create_directory(conn, req, smb_dname);
8418 if (!NT_STATUS_IS_OK(status)) {
8419 reply_nterror(req, status);
8420 goto out;
8423 /* Try and set any given EA. */
8424 if (ea_list) {
8425 status = set_ea(conn, NULL, smb_dname, ea_list);
8426 if (!NT_STATUS_IS_OK(status)) {
8427 reply_nterror(req, status);
8428 goto out;
8432 /* Realloc the parameter and data sizes */
8433 *pparams = (char *)SMB_REALLOC(*pparams,2);
8434 if(*pparams == NULL) {
8435 reply_nterror(req, NT_STATUS_NO_MEMORY);
8436 goto out;
8438 params = *pparams;
8440 SSVAL(params,0,0);
8442 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8444 out:
8445 TALLOC_FREE(smb_dname);
8446 return;
8449 /****************************************************************************
8450 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8451 We don't actually do this - we just send a null response.
8452 ****************************************************************************/
8454 static void call_trans2findnotifyfirst(connection_struct *conn,
8455 struct smb_request *req,
8456 char **pparams, int total_params,
8457 char **ppdata, int total_data,
8458 unsigned int max_data_bytes)
8460 char *params = *pparams;
8461 uint16 info_level;
8463 if (total_params < 6) {
8464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8465 return;
8468 info_level = SVAL(params,4);
8469 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8471 switch (info_level) {
8472 case 1:
8473 case 2:
8474 break;
8475 default:
8476 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8477 return;
8480 /* Realloc the parameter and data sizes */
8481 *pparams = (char *)SMB_REALLOC(*pparams,6);
8482 if (*pparams == NULL) {
8483 reply_nterror(req, NT_STATUS_NO_MEMORY);
8484 return;
8486 params = *pparams;
8488 SSVAL(params,0,fnf_handle);
8489 SSVAL(params,2,0); /* No changes */
8490 SSVAL(params,4,0); /* No EA errors */
8492 fnf_handle++;
8494 if(fnf_handle == 0)
8495 fnf_handle = 257;
8497 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8499 return;
8502 /****************************************************************************
8503 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8504 changes). Currently this does nothing.
8505 ****************************************************************************/
8507 static void call_trans2findnotifynext(connection_struct *conn,
8508 struct smb_request *req,
8509 char **pparams, int total_params,
8510 char **ppdata, int total_data,
8511 unsigned int max_data_bytes)
8513 char *params = *pparams;
8515 DEBUG(3,("call_trans2findnotifynext\n"));
8517 /* Realloc the parameter and data sizes */
8518 *pparams = (char *)SMB_REALLOC(*pparams,4);
8519 if (*pparams == NULL) {
8520 reply_nterror(req, NT_STATUS_NO_MEMORY);
8521 return;
8523 params = *pparams;
8525 SSVAL(params,0,0); /* No changes */
8526 SSVAL(params,2,0); /* No EA errors */
8528 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8530 return;
8533 /****************************************************************************
8534 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8535 ****************************************************************************/
8537 static void call_trans2getdfsreferral(connection_struct *conn,
8538 struct smb_request *req,
8539 char **pparams, int total_params,
8540 char **ppdata, int total_data,
8541 unsigned int max_data_bytes)
8543 char *params = *pparams;
8544 char *pathname = NULL;
8545 int reply_size = 0;
8546 int max_referral_level;
8547 NTSTATUS status = NT_STATUS_OK;
8548 TALLOC_CTX *ctx = talloc_tos();
8550 DEBUG(10,("call_trans2getdfsreferral\n"));
8552 if (total_params < 3) {
8553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8554 return;
8557 max_referral_level = SVAL(params,0);
8559 if(!lp_host_msdfs()) {
8560 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8561 return;
8564 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8565 total_params - 2, STR_TERMINATE);
8566 if (!pathname) {
8567 reply_nterror(req, NT_STATUS_NOT_FOUND);
8568 return;
8570 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8571 ppdata,&status)) < 0) {
8572 reply_nterror(req, status);
8573 return;
8576 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8577 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8578 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8580 return;
8583 #define LMCAT_SPL 0x53
8584 #define LMFUNC_GETJOBID 0x60
8586 /****************************************************************************
8587 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8588 ****************************************************************************/
8590 static void call_trans2ioctl(connection_struct *conn,
8591 struct smb_request *req,
8592 char **pparams, int total_params,
8593 char **ppdata, int total_data,
8594 unsigned int max_data_bytes)
8596 char *pdata = *ppdata;
8597 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8599 /* check for an invalid fid before proceeding */
8601 if (!fsp) {
8602 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8603 return;
8606 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8607 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8608 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8609 if (*ppdata == NULL) {
8610 reply_nterror(req, NT_STATUS_NO_MEMORY);
8611 return;
8613 pdata = *ppdata;
8615 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8616 CAN ACCEPT THIS IN UNICODE. JRA. */
8618 /* Job number */
8619 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8621 srvstr_push(pdata, req->flags2, pdata + 2,
8622 lp_netbios_name(), 15,
8623 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8624 srvstr_push(pdata, req->flags2, pdata+18,
8625 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8626 STR_ASCII|STR_TERMINATE); /* Service name */
8627 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8628 max_data_bytes);
8629 return;
8632 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8633 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8636 /****************************************************************************
8637 Reply to a SMBfindclose (stop trans2 directory search).
8638 ****************************************************************************/
8640 void reply_findclose(struct smb_request *req)
8642 int dptr_num;
8643 struct smbd_server_connection *sconn = req->sconn;
8645 START_PROFILE(SMBfindclose);
8647 if (req->wct < 1) {
8648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8649 END_PROFILE(SMBfindclose);
8650 return;
8653 dptr_num = SVALS(req->vwv+0, 0);
8655 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8657 dptr_close(sconn, &dptr_num);
8659 reply_outbuf(req, 0, 0);
8661 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8663 END_PROFILE(SMBfindclose);
8664 return;
8667 /****************************************************************************
8668 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8669 ****************************************************************************/
8671 void reply_findnclose(struct smb_request *req)
8673 int dptr_num;
8675 START_PROFILE(SMBfindnclose);
8677 if (req->wct < 1) {
8678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8679 END_PROFILE(SMBfindnclose);
8680 return;
8683 dptr_num = SVAL(req->vwv+0, 0);
8685 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8687 /* We never give out valid handles for a
8688 findnotifyfirst - so any dptr_num is ok here.
8689 Just ignore it. */
8691 reply_outbuf(req, 0, 0);
8693 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8695 END_PROFILE(SMBfindnclose);
8696 return;
8699 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8700 struct trans_state *state)
8702 if (get_Protocol() >= PROTOCOL_NT1) {
8703 req->flags2 |= 0x40; /* IS_LONG_NAME */
8704 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8707 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8708 if (state->call != TRANSACT2_QFSINFO &&
8709 state->call != TRANSACT2_SETFSINFO) {
8710 DEBUG(0,("handle_trans2: encryption required "
8711 "with call 0x%x\n",
8712 (unsigned int)state->call));
8713 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8714 return;
8718 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8720 /* Now we must call the relevant TRANS2 function */
8721 switch(state->call) {
8722 case TRANSACT2_OPEN:
8724 START_PROFILE(Trans2_open);
8725 call_trans2open(conn, req,
8726 &state->param, state->total_param,
8727 &state->data, state->total_data,
8728 state->max_data_return);
8729 END_PROFILE(Trans2_open);
8730 break;
8733 case TRANSACT2_FINDFIRST:
8735 START_PROFILE(Trans2_findfirst);
8736 call_trans2findfirst(conn, req,
8737 &state->param, state->total_param,
8738 &state->data, state->total_data,
8739 state->max_data_return);
8740 END_PROFILE(Trans2_findfirst);
8741 break;
8744 case TRANSACT2_FINDNEXT:
8746 START_PROFILE(Trans2_findnext);
8747 call_trans2findnext(conn, req,
8748 &state->param, state->total_param,
8749 &state->data, state->total_data,
8750 state->max_data_return);
8751 END_PROFILE(Trans2_findnext);
8752 break;
8755 case TRANSACT2_QFSINFO:
8757 START_PROFILE(Trans2_qfsinfo);
8758 call_trans2qfsinfo(conn, req,
8759 &state->param, state->total_param,
8760 &state->data, state->total_data,
8761 state->max_data_return);
8762 END_PROFILE(Trans2_qfsinfo);
8763 break;
8766 case TRANSACT2_SETFSINFO:
8768 START_PROFILE(Trans2_setfsinfo);
8769 call_trans2setfsinfo(conn, req,
8770 &state->param, state->total_param,
8771 &state->data, state->total_data,
8772 state->max_data_return);
8773 END_PROFILE(Trans2_setfsinfo);
8774 break;
8777 case TRANSACT2_QPATHINFO:
8778 case TRANSACT2_QFILEINFO:
8780 START_PROFILE(Trans2_qpathinfo);
8781 call_trans2qfilepathinfo(conn, req, state->call,
8782 &state->param, state->total_param,
8783 &state->data, state->total_data,
8784 state->max_data_return);
8785 END_PROFILE(Trans2_qpathinfo);
8786 break;
8789 case TRANSACT2_SETPATHINFO:
8790 case TRANSACT2_SETFILEINFO:
8792 START_PROFILE(Trans2_setpathinfo);
8793 call_trans2setfilepathinfo(conn, req, state->call,
8794 &state->param, state->total_param,
8795 &state->data, state->total_data,
8796 state->max_data_return);
8797 END_PROFILE(Trans2_setpathinfo);
8798 break;
8801 case TRANSACT2_FINDNOTIFYFIRST:
8803 START_PROFILE(Trans2_findnotifyfirst);
8804 call_trans2findnotifyfirst(conn, req,
8805 &state->param, state->total_param,
8806 &state->data, state->total_data,
8807 state->max_data_return);
8808 END_PROFILE(Trans2_findnotifyfirst);
8809 break;
8812 case TRANSACT2_FINDNOTIFYNEXT:
8814 START_PROFILE(Trans2_findnotifynext);
8815 call_trans2findnotifynext(conn, req,
8816 &state->param, state->total_param,
8817 &state->data, state->total_data,
8818 state->max_data_return);
8819 END_PROFILE(Trans2_findnotifynext);
8820 break;
8823 case TRANSACT2_MKDIR:
8825 START_PROFILE(Trans2_mkdir);
8826 call_trans2mkdir(conn, req,
8827 &state->param, state->total_param,
8828 &state->data, state->total_data,
8829 state->max_data_return);
8830 END_PROFILE(Trans2_mkdir);
8831 break;
8834 case TRANSACT2_GET_DFS_REFERRAL:
8836 START_PROFILE(Trans2_get_dfs_referral);
8837 call_trans2getdfsreferral(conn, req,
8838 &state->param, state->total_param,
8839 &state->data, state->total_data,
8840 state->max_data_return);
8841 END_PROFILE(Trans2_get_dfs_referral);
8842 break;
8845 case TRANSACT2_IOCTL:
8847 START_PROFILE(Trans2_ioctl);
8848 call_trans2ioctl(conn, req,
8849 &state->param, state->total_param,
8850 &state->data, state->total_data,
8851 state->max_data_return);
8852 END_PROFILE(Trans2_ioctl);
8853 break;
8856 default:
8857 /* Error in request */
8858 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8859 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8863 /****************************************************************************
8864 Reply to a SMBtrans2.
8865 ****************************************************************************/
8867 void reply_trans2(struct smb_request *req)
8869 connection_struct *conn = req->conn;
8870 unsigned int dsoff;
8871 unsigned int dscnt;
8872 unsigned int psoff;
8873 unsigned int pscnt;
8874 unsigned int tran_call;
8875 struct trans_state *state;
8876 NTSTATUS result;
8878 START_PROFILE(SMBtrans2);
8880 if (req->wct < 14) {
8881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8882 END_PROFILE(SMBtrans2);
8883 return;
8886 dsoff = SVAL(req->vwv+12, 0);
8887 dscnt = SVAL(req->vwv+11, 0);
8888 psoff = SVAL(req->vwv+10, 0);
8889 pscnt = SVAL(req->vwv+9, 0);
8890 tran_call = SVAL(req->vwv+14, 0);
8892 result = allow_new_trans(conn->pending_trans, req->mid);
8893 if (!NT_STATUS_IS_OK(result)) {
8894 DEBUG(2, ("Got invalid trans2 request: %s\n",
8895 nt_errstr(result)));
8896 reply_nterror(req, result);
8897 END_PROFILE(SMBtrans2);
8898 return;
8901 if (IS_IPC(conn)) {
8902 switch (tran_call) {
8903 /* List the allowed trans2 calls on IPC$ */
8904 case TRANSACT2_OPEN:
8905 case TRANSACT2_GET_DFS_REFERRAL:
8906 case TRANSACT2_QFILEINFO:
8907 case TRANSACT2_QFSINFO:
8908 case TRANSACT2_SETFSINFO:
8909 break;
8910 default:
8911 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8912 END_PROFILE(SMBtrans2);
8913 return;
8917 if ((state = talloc(conn, struct trans_state)) == NULL) {
8918 DEBUG(0, ("talloc failed\n"));
8919 reply_nterror(req, NT_STATUS_NO_MEMORY);
8920 END_PROFILE(SMBtrans2);
8921 return;
8924 state->cmd = SMBtrans2;
8926 state->mid = req->mid;
8927 state->vuid = req->vuid;
8928 state->setup_count = SVAL(req->vwv+13, 0);
8929 state->setup = NULL;
8930 state->total_param = SVAL(req->vwv+0, 0);
8931 state->param = NULL;
8932 state->total_data = SVAL(req->vwv+1, 0);
8933 state->data = NULL;
8934 state->max_param_return = SVAL(req->vwv+2, 0);
8935 state->max_data_return = SVAL(req->vwv+3, 0);
8936 state->max_setup_return = SVAL(req->vwv+4, 0);
8937 state->close_on_completion = BITSETW(req->vwv+5, 0);
8938 state->one_way = BITSETW(req->vwv+5, 1);
8940 state->call = tran_call;
8942 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8943 is so as a sanity check */
8944 if (state->setup_count != 1) {
8946 * Need to have rc=0 for ioctl to get job id for OS/2.
8947 * Network printing will fail if function is not successful.
8948 * Similar function in reply.c will be used if protocol
8949 * is LANMAN1.0 instead of LM1.2X002.
8950 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8951 * outbuf doesn't have to be set(only job id is used).
8953 if ( (state->setup_count == 4)
8954 && (tran_call == TRANSACT2_IOCTL)
8955 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8956 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8957 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8958 } else {
8959 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8960 DEBUG(2,("Transaction is %d\n",tran_call));
8961 TALLOC_FREE(state);
8962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8963 END_PROFILE(SMBtrans2);
8964 return;
8968 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8969 goto bad_param;
8971 if (state->total_data) {
8973 if (trans_oob(state->total_data, 0, dscnt)
8974 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8975 goto bad_param;
8978 /* Can't use talloc here, the core routines do realloc on the
8979 * params and data. */
8980 state->data = (char *)SMB_MALLOC(state->total_data);
8981 if (state->data == NULL) {
8982 DEBUG(0,("reply_trans2: data malloc fail for %u "
8983 "bytes !\n", (unsigned int)state->total_data));
8984 TALLOC_FREE(state);
8985 reply_nterror(req, NT_STATUS_NO_MEMORY);
8986 END_PROFILE(SMBtrans2);
8987 return;
8990 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8993 if (state->total_param) {
8995 if (trans_oob(state->total_param, 0, pscnt)
8996 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8997 goto bad_param;
9000 /* Can't use talloc here, the core routines do realloc on the
9001 * params and data. */
9002 state->param = (char *)SMB_MALLOC(state->total_param);
9003 if (state->param == NULL) {
9004 DEBUG(0,("reply_trans: param malloc fail for %u "
9005 "bytes !\n", (unsigned int)state->total_param));
9006 SAFE_FREE(state->data);
9007 TALLOC_FREE(state);
9008 reply_nterror(req, NT_STATUS_NO_MEMORY);
9009 END_PROFILE(SMBtrans2);
9010 return;
9013 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9016 state->received_data = dscnt;
9017 state->received_param = pscnt;
9019 if ((state->received_param == state->total_param) &&
9020 (state->received_data == state->total_data)) {
9022 handle_trans2(conn, req, state);
9024 SAFE_FREE(state->data);
9025 SAFE_FREE(state->param);
9026 TALLOC_FREE(state);
9027 END_PROFILE(SMBtrans2);
9028 return;
9031 DLIST_ADD(conn->pending_trans, state);
9033 /* We need to send an interim response then receive the rest
9034 of the parameter/data bytes */
9035 reply_outbuf(req, 0, 0);
9036 show_msg((char *)req->outbuf);
9037 END_PROFILE(SMBtrans2);
9038 return;
9040 bad_param:
9042 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9043 SAFE_FREE(state->data);
9044 SAFE_FREE(state->param);
9045 TALLOC_FREE(state);
9046 END_PROFILE(SMBtrans2);
9047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9051 /****************************************************************************
9052 Reply to a SMBtranss2
9053 ****************************************************************************/
9055 void reply_transs2(struct smb_request *req)
9057 connection_struct *conn = req->conn;
9058 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9059 struct trans_state *state;
9061 START_PROFILE(SMBtranss2);
9063 show_msg((const char *)req->inbuf);
9065 /* Windows clients expect all replies to
9066 a transact secondary (SMBtranss2 0x33)
9067 to have a command code of transact
9068 (SMBtrans2 0x32). See bug #8989
9069 and also [MS-CIFS] section 2.2.4.47.2
9070 for details.
9072 req->cmd = SMBtrans2;
9074 if (req->wct < 8) {
9075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9076 END_PROFILE(SMBtranss2);
9077 return;
9080 for (state = conn->pending_trans; state != NULL;
9081 state = state->next) {
9082 if (state->mid == req->mid) {
9083 break;
9087 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9089 END_PROFILE(SMBtranss2);
9090 return;
9093 /* Revise state->total_param and state->total_data in case they have
9094 changed downwards */
9096 if (SVAL(req->vwv+0, 0) < state->total_param)
9097 state->total_param = SVAL(req->vwv+0, 0);
9098 if (SVAL(req->vwv+1, 0) < state->total_data)
9099 state->total_data = SVAL(req->vwv+1, 0);
9101 pcnt = SVAL(req->vwv+2, 0);
9102 poff = SVAL(req->vwv+3, 0);
9103 pdisp = SVAL(req->vwv+4, 0);
9105 dcnt = SVAL(req->vwv+5, 0);
9106 doff = SVAL(req->vwv+6, 0);
9107 ddisp = SVAL(req->vwv+7, 0);
9109 state->received_param += pcnt;
9110 state->received_data += dcnt;
9112 if ((state->received_data > state->total_data) ||
9113 (state->received_param > state->total_param))
9114 goto bad_param;
9116 if (pcnt) {
9117 if (trans_oob(state->total_param, pdisp, pcnt)
9118 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9119 goto bad_param;
9121 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9124 if (dcnt) {
9125 if (trans_oob(state->total_data, ddisp, dcnt)
9126 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9127 goto bad_param;
9129 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9132 if ((state->received_param < state->total_param) ||
9133 (state->received_data < state->total_data)) {
9134 END_PROFILE(SMBtranss2);
9135 return;
9138 handle_trans2(conn, req, state);
9140 DLIST_REMOVE(conn->pending_trans, state);
9141 SAFE_FREE(state->data);
9142 SAFE_FREE(state->param);
9143 TALLOC_FREE(state);
9145 END_PROFILE(SMBtranss2);
9146 return;
9148 bad_param:
9150 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9151 DLIST_REMOVE(conn->pending_trans, state);
9152 SAFE_FREE(state->data);
9153 SAFE_FREE(state->param);
9154 TALLOC_FREE(state);
9155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9156 END_PROFILE(SMBtranss2);
9157 return;