smbd: Fix error return for STREAM_INFO
[Samba.git] / source3 / smbd / trans2.c
blob3c8c06fa982a8ba591e29f2491aaa3f06589734c
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 "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "libsmb/libsmb.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
45 char *pdata,
46 files_struct *fsp,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
50 char *pdata,
51 files_struct *fsp,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 Roundup a value to the nearest allocation roundup size boundary.
56 Only do this for Windows clients.
57 ********************************************************************/
59 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
61 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
63 /* Only roundup for Windows clients. */
64 enum remote_arch_types ra_type = get_remote_arch();
65 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
66 val = SMB_ROUNDUP(val,rval);
68 return val;
71 /********************************************************************
72 Create a 64 bit FileIndex. If the file is on the same device as
73 the root of the share, just return the 64-bit inode. If it isn't,
74 mangle as we used to do.
75 ********************************************************************/
77 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
79 uint64_t file_index;
80 if (conn->base_share_dev == psbuf->st_ex_dev) {
81 return (uint64_t)psbuf->st_ex_ino;
83 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
84 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
85 return file_index;
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char * const prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
101 SAMBA_XATTR_MARKER,
102 XATTR_NTACL_NAME,
103 NULL
106 int i;
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 return true;
112 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
113 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
114 return true;
116 return false;
119 /****************************************************************************
120 Get one EA value. Fill in a struct ea_struct.
121 ****************************************************************************/
123 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
124 files_struct *fsp, const char *fname,
125 const char *ea_name, struct ea_struct *pea)
127 /* Get the value of this xattr. Max size is 64k. */
128 size_t attr_size = 256;
129 char *val = NULL;
130 ssize_t sizeret;
132 again:
134 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
135 if (!val) {
136 return NT_STATUS_NO_MEMORY;
139 if (fsp && fsp->fh->fd != -1) {
140 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
141 } else {
142 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
145 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
146 attr_size = 65536;
147 goto again;
150 if (sizeret == -1) {
151 return map_nt_error_from_unix(errno);
154 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
155 dump_data(10, (uint8 *)val, sizeret);
157 pea->flags = 0;
158 if (strnequal(ea_name, "user.", 5)) {
159 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
160 } else {
161 pea->name = talloc_strdup(mem_ctx, ea_name);
163 if (pea->name == NULL) {
164 TALLOC_FREE(val);
165 return NT_STATUS_NO_MEMORY;
167 pea->value.data = (unsigned char *)val;
168 pea->value.length = (size_t)sizeret;
169 return NT_STATUS_OK;
172 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
173 files_struct *fsp, const char *fname,
174 char ***pnames, size_t *pnum_names)
176 /* Get a list of all xattrs. Max namesize is 64k. */
177 size_t ea_namelist_size = 1024;
178 char *ea_namelist = NULL;
180 char *p;
181 char **names, **tmp;
182 size_t num_names;
183 ssize_t sizeret = -1;
185 if (!lp_ea_support(SNUM(conn))) {
186 if (pnames) {
187 *pnames = NULL;
189 *pnum_names = 0;
190 return NT_STATUS_OK;
194 * TALLOC the result early to get the talloc hierarchy right.
197 names = TALLOC_ARRAY(mem_ctx, char *, 1);
198 if (names == NULL) {
199 DEBUG(0, ("talloc failed\n"));
200 return NT_STATUS_NO_MEMORY;
203 while (ea_namelist_size <= 65536) {
205 ea_namelist = TALLOC_REALLOC_ARRAY(
206 names, ea_namelist, char, ea_namelist_size);
207 if (ea_namelist == NULL) {
208 DEBUG(0, ("talloc failed\n"));
209 TALLOC_FREE(names);
210 return NT_STATUS_NO_MEMORY;
213 if (fsp && fsp->fh->fd != -1) {
214 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
215 ea_namelist_size);
216 } else {
217 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
218 ea_namelist_size);
221 if ((sizeret == -1) && (errno == ERANGE)) {
222 ea_namelist_size *= 2;
224 else {
225 break;
229 if (sizeret == -1) {
230 TALLOC_FREE(names);
231 return map_nt_error_from_unix(errno);
234 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
235 (unsigned int)sizeret));
237 if (sizeret == 0) {
238 TALLOC_FREE(names);
239 if (pnames) {
240 *pnames = NULL;
242 *pnum_names = 0;
243 return NT_STATUS_OK;
247 * Ensure the result is 0-terminated
250 if (ea_namelist[sizeret-1] != '\0') {
251 TALLOC_FREE(names);
252 return NT_STATUS_INTERNAL_ERROR;
256 * count the names
258 num_names = 0;
260 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
261 num_names += 1;
264 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
265 if (tmp == NULL) {
266 DEBUG(0, ("talloc failed\n"));
267 TALLOC_FREE(names);
268 return NT_STATUS_NO_MEMORY;
271 names = tmp;
272 num_names = 0;
274 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
275 names[num_names++] = p;
278 if (pnames) {
279 *pnames = names;
280 } else {
281 TALLOC_FREE(names);
283 *pnum_names = num_names;
284 return NT_STATUS_OK;
287 /****************************************************************************
288 Return a linked list of the total EA's. Plus the total size
289 ****************************************************************************/
291 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
292 const char *fname, size_t *pea_total_len)
294 /* Get a list of all xattrs. Max namesize is 64k. */
295 size_t i, num_names;
296 char **names;
297 struct ea_list *ea_list_head = NULL;
298 NTSTATUS status;
300 *pea_total_len = 0;
302 if (!lp_ea_support(SNUM(conn))) {
303 return NULL;
306 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
307 &names, &num_names);
309 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
310 return NULL;
313 for (i=0; i<num_names; i++) {
314 struct ea_list *listp;
315 fstring dos_ea_name;
317 if (strnequal(names[i], "system.", 7)
318 || samba_private_attr_name(names[i]))
319 continue;
321 listp = TALLOC_P(mem_ctx, struct ea_list);
322 if (listp == NULL) {
323 return NULL;
326 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
327 fname, names[i],
328 &listp->ea))) {
329 return NULL;
332 if (listp->ea.value.length == 0) {
334 * We can never return a zero length EA.
335 * Windows reports the EA's as corrupted.
337 TALLOC_FREE(listp);
338 continue;
341 push_ascii_fstring(dos_ea_name, listp->ea.name);
343 *pea_total_len +=
344 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
346 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
347 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
348 (unsigned int)listp->ea.value.length));
350 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
354 /* Add on 4 for total length. */
355 if (*pea_total_len) {
356 *pea_total_len += 4;
359 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
360 (unsigned int)*pea_total_len));
362 return ea_list_head;
365 /****************************************************************************
366 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
367 that was filled.
368 ****************************************************************************/
370 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
371 connection_struct *conn, struct ea_list *ea_list)
373 unsigned int ret_data_size = 4;
374 char *p = pdata;
376 SMB_ASSERT(total_data_size >= 4);
378 if (!lp_ea_support(SNUM(conn))) {
379 SIVAL(pdata,4,0);
380 return 4;
383 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
384 size_t dos_namelen;
385 fstring dos_ea_name;
386 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
387 dos_namelen = strlen(dos_ea_name);
388 if (dos_namelen > 255 || dos_namelen == 0) {
389 break;
391 if (ea_list->ea.value.length > 65535) {
392 break;
394 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
395 break;
398 /* We know we have room. */
399 SCVAL(p,0,ea_list->ea.flags);
400 SCVAL(p,1,dos_namelen);
401 SSVAL(p,2,ea_list->ea.value.length);
402 fstrcpy(p+4, dos_ea_name);
403 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
405 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
406 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
409 ret_data_size = PTR_DIFF(p, pdata);
410 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
411 SIVAL(pdata,0,ret_data_size);
412 return ret_data_size;
415 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
416 char *pdata,
417 unsigned int total_data_size,
418 unsigned int *ret_data_size,
419 connection_struct *conn,
420 struct ea_list *ea_list)
422 uint8_t *p = (uint8_t *)pdata;
423 uint8_t *last_start = NULL;
424 bool store_data = (pdata != NULL);
426 *ret_data_size = 0;
428 if (!lp_ea_support(SNUM(conn))) {
429 return NT_STATUS_NO_EAS_ON_FILE;
432 for (; ea_list; ea_list = ea_list->next) {
433 size_t dos_namelen;
434 fstring dos_ea_name;
435 size_t this_size;
436 size_t pad = 0;
438 if (last_start && store_data) {
439 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
441 last_start = p;
443 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
444 dos_namelen = strlen(dos_ea_name);
445 if (dos_namelen > 255 || dos_namelen == 0) {
446 return NT_STATUS_INTERNAL_ERROR;
448 if (ea_list->ea.value.length > 65535) {
449 return NT_STATUS_INTERNAL_ERROR;
452 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
454 if (ea_list->next) {
455 pad = (4 - (this_size % 4)) % 4;
456 this_size += pad;
459 if (this_size > total_data_size) {
460 return NT_STATUS_INFO_LENGTH_MISMATCH;
463 /* We know we have room. */
464 if (store_data) {
465 SIVAL(p, 0x00, 0); /* next offset */
466 SCVAL(p, 0x04, ea_list->ea.flags);
467 SCVAL(p, 0x05, dos_namelen);
468 SSVAL(p, 0x06, ea_list->ea.value.length);
469 fstrcpy((char *)(p+0x08), dos_ea_name);
470 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
471 if (pad) {
472 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
473 '\0',
474 pad);
478 total_data_size -= this_size;
479 p += this_size;
482 *ret_data_size = PTR_DIFF(p, pdata);
483 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
484 return NT_STATUS_OK;
487 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
489 size_t total_ea_len = 0;
490 struct ea_list *ea_list = NULL;
491 TALLOC_CTX *mem_ctx = NULL;
493 if (!lp_ea_support(SNUM(conn))) {
494 return 0;
496 mem_ctx = talloc_tos();
497 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
498 if (ea_list == NULL) {
499 return 0;
501 if(conn->sconn->using_smb2) {
502 NTSTATUS status;
503 unsigned int ret_data_size;
505 * We're going to be using fill_ea_chained_buffer() to
506 * marshall EA's - this size is significantly larger
507 * than the SMB1 buffer. Re-calculate the size without
508 * marshalling.
510 status = fill_ea_chained_buffer(mem_ctx,
511 NULL,
512 65535,
513 &ret_data_size,
514 conn,
515 ea_list);
516 if (!NT_STATUS_IS_OK(status)) {
517 ret_data_size = 0;
519 total_ea_len = ret_data_size;
522 return total_ea_len;
525 /****************************************************************************
526 Ensure the EA name is case insensitive by matching any existing EA name.
527 ****************************************************************************/
529 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
531 size_t total_ea_len;
532 TALLOC_CTX *mem_ctx = talloc_tos();
533 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
535 for (; ea_list; ea_list = ea_list->next) {
536 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
537 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
538 &unix_ea_name[5], ea_list->ea.name));
539 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
540 break;
545 /****************************************************************************
546 Set or delete an extended attribute.
547 ****************************************************************************/
549 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
550 const struct smb_filename *smb_fname, struct ea_list *ea_list)
552 char *fname = NULL;
554 if (!lp_ea_support(SNUM(conn))) {
555 return NT_STATUS_EAS_NOT_SUPPORTED;
558 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
559 return NT_STATUS_ACCESS_DENIED;
562 /* For now setting EAs on streams isn't supported. */
563 fname = smb_fname->base_name;
565 for (;ea_list; ea_list = ea_list->next) {
566 int ret;
567 fstring unix_ea_name;
569 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
570 fstrcat(unix_ea_name, ea_list->ea.name);
572 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
574 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
576 if (samba_private_attr_name(unix_ea_name)) {
577 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
578 return NT_STATUS_ACCESS_DENIED;
581 if (ea_list->ea.value.length == 0) {
582 /* Remove the attribute. */
583 if (fsp && (fsp->fh->fd != -1)) {
584 DEBUG(10,("set_ea: deleting ea name %s on "
585 "file %s by file descriptor.\n",
586 unix_ea_name, fsp_str_dbg(fsp)));
587 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
588 } else {
589 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
590 unix_ea_name, fname));
591 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
593 #ifdef ENOATTR
594 /* Removing a non existent attribute always succeeds. */
595 if (ret == -1 && errno == ENOATTR) {
596 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
597 unix_ea_name));
598 ret = 0;
600 #endif
601 } else {
602 if (fsp && (fsp->fh->fd != -1)) {
603 DEBUG(10,("set_ea: setting ea name %s on file "
604 "%s by file descriptor.\n",
605 unix_ea_name, fsp_str_dbg(fsp)));
606 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
607 ea_list->ea.value.data, ea_list->ea.value.length, 0);
608 } else {
609 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
610 unix_ea_name, fname));
611 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
612 ea_list->ea.value.data, ea_list->ea.value.length, 0);
616 if (ret == -1) {
617 #ifdef ENOTSUP
618 if (errno == ENOTSUP) {
619 return NT_STATUS_EAS_NOT_SUPPORTED;
621 #endif
622 return map_nt_error_from_unix(errno);
626 return NT_STATUS_OK;
628 /****************************************************************************
629 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
630 ****************************************************************************/
632 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
634 struct ea_list *ea_list_head = NULL;
635 size_t converted_size, offset = 0;
637 while (offset + 2 < data_size) {
638 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
639 unsigned int namelen = CVAL(pdata,offset);
641 offset++; /* Go past the namelen byte. */
643 /* integer wrap paranioa. */
644 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
645 (offset > data_size) || (namelen > data_size) ||
646 (offset + namelen >= data_size)) {
647 break;
649 /* Ensure the name is null terminated. */
650 if (pdata[offset + namelen] != '\0') {
651 return NULL;
653 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
654 &converted_size)) {
655 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
656 "failed: %s", strerror(errno)));
658 if (!eal->ea.name) {
659 return NULL;
662 offset += (namelen + 1); /* Go past the name + terminating zero. */
663 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
664 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
667 return ea_list_head;
670 /****************************************************************************
671 Read one EA list entry from the buffer.
672 ****************************************************************************/
674 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
676 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
677 uint16 val_len;
678 unsigned int namelen;
679 size_t converted_size;
681 if (!eal) {
682 return NULL;
685 if (data_size < 6) {
686 return NULL;
689 eal->ea.flags = CVAL(pdata,0);
690 namelen = CVAL(pdata,1);
691 val_len = SVAL(pdata,2);
693 if (4 + namelen + 1 + val_len > data_size) {
694 return NULL;
697 /* Ensure the name is null terminated. */
698 if (pdata[namelen + 4] != '\0') {
699 return NULL;
701 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
702 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
703 strerror(errno)));
705 if (!eal->ea.name) {
706 return NULL;
709 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
710 if (!eal->ea.value.data) {
711 return NULL;
714 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
716 /* Ensure we're null terminated just in case we print the value. */
717 eal->ea.value.data[val_len] = '\0';
718 /* But don't count the null. */
719 eal->ea.value.length--;
721 if (pbytes_used) {
722 *pbytes_used = 4 + namelen + 1 + val_len;
725 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
726 dump_data(10, eal->ea.value.data, eal->ea.value.length);
728 return eal;
731 /****************************************************************************
732 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
733 ****************************************************************************/
735 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
737 struct ea_list *ea_list_head = NULL;
738 size_t offset = 0;
739 size_t bytes_used = 0;
741 while (offset < data_size) {
742 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
744 if (!eal) {
745 return NULL;
748 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
749 offset += bytes_used;
752 return ea_list_head;
755 /****************************************************************************
756 Count the total EA size needed.
757 ****************************************************************************/
759 static size_t ea_list_size(struct ea_list *ealist)
761 fstring dos_ea_name;
762 struct ea_list *listp;
763 size_t ret = 0;
765 for (listp = ealist; listp; listp = listp->next) {
766 push_ascii_fstring(dos_ea_name, listp->ea.name);
767 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
769 /* Add on 4 for total length. */
770 if (ret) {
771 ret += 4;
774 return ret;
777 /****************************************************************************
778 Return a union of EA's from a file list and a list of names.
779 The TALLOC context for the two lists *MUST* be identical as we steal
780 memory from one list to add to another. JRA.
781 ****************************************************************************/
783 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
785 struct ea_list *nlistp, *flistp;
787 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
788 for (flistp = file_list; flistp; flistp = flistp->next) {
789 if (strequal(nlistp->ea.name, flistp->ea.name)) {
790 break;
794 if (flistp) {
795 /* Copy the data from this entry. */
796 nlistp->ea.flags = flistp->ea.flags;
797 nlistp->ea.value = flistp->ea.value;
798 } else {
799 /* Null entry. */
800 nlistp->ea.flags = 0;
801 ZERO_STRUCT(nlistp->ea.value);
805 *total_ea_len = ea_list_size(name_list);
806 return name_list;
809 /****************************************************************************
810 Send the required number of replies back.
811 We assume all fields other than the data fields are
812 set correctly for the type of call.
813 HACK ! Always assumes smb_setup field is zero.
814 ****************************************************************************/
816 void send_trans2_replies(connection_struct *conn,
817 struct smb_request *req,
818 const char *params,
819 int paramsize,
820 const char *pdata,
821 int datasize,
822 int max_data_bytes)
824 /* As we are using a protocol > LANMAN1 then the max_send
825 variable must have been set in the sessetupX call.
826 This takes precedence over the max_xmit field in the
827 global struct. These different max_xmit variables should
828 be merged as this is now too confusing */
830 int data_to_send = datasize;
831 int params_to_send = paramsize;
832 int useable_space;
833 const char *pp = params;
834 const char *pd = pdata;
835 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
836 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
837 int data_alignment_offset = 0;
838 bool overflow = False;
839 struct smbd_server_connection *sconn = req->sconn;
840 int max_send = sconn->smb1.sessions.max_send;
842 /* Modify the data_to_send and datasize and set the error if
843 we're trying to send more than max_data_bytes. We still send
844 the part of the packet(s) that fit. Strange, but needed
845 for OS/2. */
847 if (max_data_bytes > 0 && datasize > max_data_bytes) {
848 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
849 max_data_bytes, datasize ));
850 datasize = data_to_send = max_data_bytes;
851 overflow = True;
854 /* If there genuinely are no parameters or data to send just send the empty packet */
856 if(params_to_send == 0 && data_to_send == 0) {
857 reply_outbuf(req, 10, 0);
858 show_msg((char *)req->outbuf);
859 if (!srv_send_smb(sconn,
860 (char *)req->outbuf,
861 true, req->seqnum+1,
862 IS_CONN_ENCRYPTED(conn),
863 &req->pcd)) {
864 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
866 TALLOC_FREE(req->outbuf);
867 return;
870 /* When sending params and data ensure that both are nicely aligned */
871 /* Only do this alignment when there is also data to send - else
872 can cause NT redirector problems. */
874 if (((params_to_send % 4) != 0) && (data_to_send != 0))
875 data_alignment_offset = 4 - (params_to_send % 4);
877 /* Space is bufsize minus Netbios over TCP header minus SMB header */
878 /* The alignment_offset is to align the param bytes on an even byte
879 boundary. NT 4.0 Beta needs this to work correctly. */
881 useable_space = max_send - (smb_size
882 + 2 * 10 /* wct */
883 + alignment_offset
884 + data_alignment_offset);
886 if (useable_space < 0) {
887 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
888 "= %d!!!", useable_space));
889 exit_server_cleanly("send_trans2_replies: Not enough space");
892 while (params_to_send || data_to_send) {
893 /* Calculate whether we will totally or partially fill this packet */
895 total_sent_thistime = params_to_send + data_to_send;
897 /* We can never send more than useable_space */
899 * Note that 'useable_space' does not include the alignment offsets,
900 * but we must include the alignment offsets in the calculation of
901 * the length of the data we send over the wire, as the alignment offsets
902 * are sent here. Fix from Marc_Jacobsen@hp.com.
905 total_sent_thistime = MIN(total_sent_thistime, useable_space);
907 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
908 + data_alignment_offset);
910 /* Set total params and data to be sent */
911 SSVAL(req->outbuf,smb_tprcnt,paramsize);
912 SSVAL(req->outbuf,smb_tdrcnt,datasize);
914 /* Calculate how many parameters and data we can fit into
915 * this packet. Parameters get precedence
918 params_sent_thistime = MIN(params_to_send,useable_space);
919 data_sent_thistime = useable_space - params_sent_thistime;
920 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
922 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
924 /* smb_proff is the offset from the start of the SMB header to the
925 parameter bytes, however the first 4 bytes of outbuf are
926 the Netbios over TCP header. Thus use smb_base() to subtract
927 them from the calculation */
929 SSVAL(req->outbuf,smb_proff,
930 ((smb_buf(req->outbuf)+alignment_offset)
931 - smb_base(req->outbuf)));
933 if(params_sent_thistime == 0)
934 SSVAL(req->outbuf,smb_prdisp,0);
935 else
936 /* Absolute displacement of param bytes sent in this packet */
937 SSVAL(req->outbuf,smb_prdisp,pp - params);
939 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
940 if(data_sent_thistime == 0) {
941 SSVAL(req->outbuf,smb_droff,0);
942 SSVAL(req->outbuf,smb_drdisp, 0);
943 } else {
944 /* The offset of the data bytes is the offset of the
945 parameter bytes plus the number of parameters being sent this time */
946 SSVAL(req->outbuf, smb_droff,
947 ((smb_buf(req->outbuf)+alignment_offset)
948 - smb_base(req->outbuf))
949 + params_sent_thistime + data_alignment_offset);
950 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
953 /* Initialize the padding for alignment */
955 if (alignment_offset != 0) {
956 memset(smb_buf(req->outbuf), 0, alignment_offset);
959 /* Copy the param bytes into the packet */
961 if(params_sent_thistime) {
962 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
963 params_sent_thistime);
966 /* Copy in the data bytes */
967 if(data_sent_thistime) {
968 if (data_alignment_offset != 0) {
969 memset((smb_buf(req->outbuf)+alignment_offset+
970 params_sent_thistime), 0,
971 data_alignment_offset);
973 memcpy(smb_buf(req->outbuf)+alignment_offset
974 +params_sent_thistime+data_alignment_offset,
975 pd,data_sent_thistime);
978 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
979 params_sent_thistime, data_sent_thistime, useable_space));
980 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
981 params_to_send, data_to_send, paramsize, datasize));
983 if (overflow) {
984 error_packet_set((char *)req->outbuf,
985 ERRDOS,ERRbufferoverflow,
986 STATUS_BUFFER_OVERFLOW,
987 __LINE__,__FILE__);
990 /* Send the packet */
991 show_msg((char *)req->outbuf);
992 if (!srv_send_smb(sconn,
993 (char *)req->outbuf,
994 true, req->seqnum+1,
995 IS_CONN_ENCRYPTED(conn),
996 &req->pcd))
997 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
999 TALLOC_FREE(req->outbuf);
1001 pp += params_sent_thistime;
1002 pd += data_sent_thistime;
1004 params_to_send -= params_sent_thistime;
1005 data_to_send -= data_sent_thistime;
1007 /* Sanity check */
1008 if(params_to_send < 0 || data_to_send < 0) {
1009 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1010 params_to_send, data_to_send));
1011 return;
1015 return;
1018 /****************************************************************************
1019 Reply to a TRANSACT2_OPEN.
1020 ****************************************************************************/
1022 static void call_trans2open(connection_struct *conn,
1023 struct smb_request *req,
1024 char **pparams, int total_params,
1025 char **ppdata, int total_data,
1026 unsigned int max_data_bytes)
1028 struct smb_filename *smb_fname = NULL;
1029 char *params = *pparams;
1030 char *pdata = *ppdata;
1031 int deny_mode;
1032 int32 open_attr;
1033 bool oplock_request;
1034 #if 0
1035 bool return_additional_info;
1036 int16 open_sattr;
1037 time_t open_time;
1038 #endif
1039 int open_ofun;
1040 uint32 open_size;
1041 char *pname;
1042 char *fname = NULL;
1043 SMB_OFF_T size=0;
1044 int fattr=0,mtime=0;
1045 SMB_INO_T inode = 0;
1046 int smb_action = 0;
1047 files_struct *fsp;
1048 struct ea_list *ea_list = NULL;
1049 uint16 flags = 0;
1050 NTSTATUS status;
1051 uint32 access_mask;
1052 uint32 share_mode;
1053 uint32 create_disposition;
1054 uint32 create_options = 0;
1055 uint32_t private_flags = 0;
1056 TALLOC_CTX *ctx = talloc_tos();
1059 * Ensure we have enough parameters to perform the operation.
1062 if (total_params < 29) {
1063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1064 goto out;
1067 flags = SVAL(params, 0);
1068 deny_mode = SVAL(params, 2);
1069 open_attr = SVAL(params,6);
1070 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1071 if (oplock_request) {
1072 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1075 #if 0
1076 return_additional_info = BITSETW(params,0);
1077 open_sattr = SVAL(params, 4);
1078 open_time = make_unix_date3(params+8);
1079 #endif
1080 open_ofun = SVAL(params,12);
1081 open_size = IVAL(params,14);
1082 pname = &params[28];
1084 if (IS_IPC(conn)) {
1085 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1086 goto out;
1089 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1090 total_params - 28, STR_TERMINATE,
1091 &status);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 reply_nterror(req, status);
1094 goto out;
1097 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1098 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1099 (unsigned int)open_ofun, open_size));
1101 status = filename_convert(ctx,
1102 conn,
1103 req->flags2 & FLAGS2_DFS_PATHNAMES,
1104 fname,
1106 NULL,
1107 &smb_fname);
1108 if (!NT_STATUS_IS_OK(status)) {
1109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1110 reply_botherror(req,
1111 NT_STATUS_PATH_NOT_COVERED,
1112 ERRSRV, ERRbadpath);
1113 goto out;
1115 reply_nterror(req, status);
1116 goto out;
1119 if (open_ofun == 0) {
1120 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1121 goto out;
1124 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1125 open_ofun,
1126 &access_mask, &share_mode,
1127 &create_disposition,
1128 &create_options,
1129 &private_flags)) {
1130 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1131 goto out;
1134 /* Any data in this call is an EA list. */
1135 if (total_data && (total_data != 4)) {
1136 if (total_data < 10) {
1137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1138 goto out;
1141 if (IVAL(pdata,0) > total_data) {
1142 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1143 IVAL(pdata,0), (unsigned int)total_data));
1144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1145 goto out;
1148 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1149 total_data - 4);
1150 if (!ea_list) {
1151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1152 goto out;
1155 if (!lp_ea_support(SNUM(conn))) {
1156 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1157 goto out;
1161 status = SMB_VFS_CREATE_FILE(
1162 conn, /* conn */
1163 req, /* req */
1164 0, /* root_dir_fid */
1165 smb_fname, /* fname */
1166 access_mask, /* access_mask */
1167 share_mode, /* share_access */
1168 create_disposition, /* create_disposition*/
1169 create_options, /* create_options */
1170 open_attr, /* file_attributes */
1171 oplock_request, /* oplock_request */
1172 open_size, /* allocation_size */
1173 private_flags,
1174 NULL, /* sd */
1175 ea_list, /* ea_list */
1176 &fsp, /* result */
1177 &smb_action); /* psbuf */
1179 if (!NT_STATUS_IS_OK(status)) {
1180 if (open_was_deferred(req->mid)) {
1181 /* We have re-scheduled this call. */
1182 goto out;
1184 reply_openerror(req, status);
1185 goto out;
1188 size = get_file_size_stat(&smb_fname->st);
1189 fattr = dos_mode(conn, smb_fname);
1190 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1191 inode = smb_fname->st.st_ex_ino;
1192 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1193 close_file(req, fsp, ERROR_CLOSE);
1194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1195 goto out;
1198 /* Realloc the size of parameters and data we will return */
1199 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1200 if(*pparams == NULL ) {
1201 reply_nterror(req, NT_STATUS_NO_MEMORY);
1202 goto out;
1204 params = *pparams;
1206 SSVAL(params,0,fsp->fnum);
1207 SSVAL(params,2,fattr);
1208 srv_put_dos_date2(params,4, mtime);
1209 SIVAL(params,8, (uint32)size);
1210 SSVAL(params,12,deny_mode);
1211 SSVAL(params,14,0); /* open_type - file or directory. */
1212 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1214 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1215 smb_action |= EXTENDED_OPLOCK_GRANTED;
1218 SSVAL(params,18,smb_action);
1221 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1223 SIVAL(params,20,inode);
1224 SSVAL(params,24,0); /* Padding. */
1225 if (flags & 8) {
1226 uint32 ea_size = estimate_ea_size(conn, fsp,
1227 fsp->fsp_name->base_name);
1228 SIVAL(params, 26, ea_size);
1229 } else {
1230 SIVAL(params, 26, 0);
1233 /* Send the required number of replies */
1234 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1235 out:
1236 TALLOC_FREE(smb_fname);
1239 /*********************************************************
1240 Routine to check if a given string matches exactly.
1241 as a special case a mask of "." does NOT match. That
1242 is required for correct wildcard semantics
1243 Case can be significant or not.
1244 **********************************************************/
1246 static bool exact_match(bool has_wild,
1247 bool case_sensitive,
1248 const char *str,
1249 const char *mask)
1251 if (mask[0] == '.' && mask[1] == 0) {
1252 return false;
1255 if (has_wild) {
1256 return false;
1259 if (case_sensitive) {
1260 return strcmp(str,mask)==0;
1261 } else {
1262 return StrCaseCmp(str,mask) == 0;
1266 /****************************************************************************
1267 Return the filetype for UNIX extensions.
1268 ****************************************************************************/
1270 static uint32 unix_filetype(mode_t mode)
1272 if(S_ISREG(mode))
1273 return UNIX_TYPE_FILE;
1274 else if(S_ISDIR(mode))
1275 return UNIX_TYPE_DIR;
1276 #ifdef S_ISLNK
1277 else if(S_ISLNK(mode))
1278 return UNIX_TYPE_SYMLINK;
1279 #endif
1280 #ifdef S_ISCHR
1281 else if(S_ISCHR(mode))
1282 return UNIX_TYPE_CHARDEV;
1283 #endif
1284 #ifdef S_ISBLK
1285 else if(S_ISBLK(mode))
1286 return UNIX_TYPE_BLKDEV;
1287 #endif
1288 #ifdef S_ISFIFO
1289 else if(S_ISFIFO(mode))
1290 return UNIX_TYPE_FIFO;
1291 #endif
1292 #ifdef S_ISSOCK
1293 else if(S_ISSOCK(mode))
1294 return UNIX_TYPE_SOCKET;
1295 #endif
1297 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1298 return UNIX_TYPE_UNKNOWN;
1301 /****************************************************************************
1302 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1303 ****************************************************************************/
1305 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1307 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1308 const SMB_STRUCT_STAT *psbuf,
1309 uint32 perms,
1310 enum perm_type ptype,
1311 mode_t *ret_perms)
1313 mode_t ret = 0;
1315 if (perms == SMB_MODE_NO_CHANGE) {
1316 if (!VALID_STAT(*psbuf)) {
1317 return NT_STATUS_INVALID_PARAMETER;
1318 } else {
1319 *ret_perms = psbuf->st_ex_mode;
1320 return NT_STATUS_OK;
1324 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1325 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1326 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1327 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1328 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1329 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1330 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1331 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1332 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1333 #ifdef S_ISVTX
1334 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1335 #endif
1336 #ifdef S_ISGID
1337 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1338 #endif
1339 #ifdef S_ISUID
1340 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1341 #endif
1343 switch (ptype) {
1344 case PERM_NEW_FILE:
1345 /* Apply mode mask */
1346 ret &= lp_create_mask(SNUM(conn));
1347 /* Add in force bits */
1348 ret |= lp_force_create_mode(SNUM(conn));
1349 break;
1350 case PERM_NEW_DIR:
1351 ret &= lp_dir_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_mode(SNUM(conn));
1354 break;
1355 case PERM_EXISTING_FILE:
1356 /* Apply mode mask */
1357 ret &= lp_security_mask(SNUM(conn));
1358 /* Add in force bits */
1359 ret |= lp_force_security_mode(SNUM(conn));
1360 break;
1361 case PERM_EXISTING_DIR:
1362 /* Apply mode mask */
1363 ret &= lp_dir_security_mask(SNUM(conn));
1364 /* Add in force bits */
1365 ret |= lp_force_dir_security_mode(SNUM(conn));
1366 break;
1369 *ret_perms = ret;
1370 return NT_STATUS_OK;
1373 /****************************************************************************
1374 Needed to show the msdfs symlinks as directories. Modifies psbuf
1375 to be a directory if it's a msdfs link.
1376 ****************************************************************************/
1378 static bool check_msdfs_link(connection_struct *conn,
1379 const char *pathname,
1380 SMB_STRUCT_STAT *psbuf)
1382 int saved_errno = errno;
1383 if(lp_host_msdfs() &&
1384 lp_msdfs_root(SNUM(conn)) &&
1385 is_msdfs_link(conn, pathname, psbuf)) {
1387 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1388 "as a directory\n",
1389 pathname));
1390 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1391 errno = saved_errno;
1392 return true;
1394 errno = saved_errno;
1395 return false;
1399 /****************************************************************************
1400 Get a level dependent lanman2 dir entry.
1401 ****************************************************************************/
1403 struct smbd_dirptr_lanman2_state {
1404 connection_struct *conn;
1405 uint32_t info_level;
1406 bool check_mangled_names;
1407 bool has_wild;
1408 bool got_exact_match;
1411 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1412 void *private_data,
1413 const char *dname,
1414 const char *mask,
1415 char **_fname)
1417 struct smbd_dirptr_lanman2_state *state =
1418 (struct smbd_dirptr_lanman2_state *)private_data;
1419 bool ok;
1420 char mangled_name[13]; /* mangled 8.3 name. */
1421 bool got_match;
1422 const char *fname;
1424 /* Mangle fname if it's an illegal name. */
1425 if (mangle_must_mangle(dname, state->conn->params)) {
1426 ok = name_to_8_3(dname, mangled_name,
1427 true, state->conn->params);
1428 if (!ok) {
1429 return false;
1431 fname = mangled_name;
1432 } else {
1433 fname = dname;
1436 got_match = exact_match(state->has_wild,
1437 state->conn->case_sensitive,
1438 fname, mask);
1439 state->got_exact_match = got_match;
1440 if (!got_match) {
1441 got_match = mask_match(fname, mask,
1442 state->conn->case_sensitive);
1445 if(!got_match && state->check_mangled_names &&
1446 !mangle_is_8_3(fname, false, state->conn->params)) {
1448 * It turns out that NT matches wildcards against
1449 * both long *and* short names. This may explain some
1450 * of the wildcard wierdness from old DOS clients
1451 * that some people have been seeing.... JRA.
1453 /* Force the mangling into 8.3. */
1454 ok = name_to_8_3(fname, mangled_name,
1455 false, state->conn->params);
1456 if (!ok) {
1457 return false;
1460 got_match = exact_match(state->has_wild,
1461 state->conn->case_sensitive,
1462 mangled_name, mask);
1463 state->got_exact_match = got_match;
1464 if (!got_match) {
1465 got_match = mask_match(mangled_name, mask,
1466 state->conn->case_sensitive);
1470 if (!got_match) {
1471 return false;
1474 *_fname = talloc_strdup(ctx, fname);
1475 if (*_fname == NULL) {
1476 return false;
1479 return true;
1482 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1483 void *private_data,
1484 struct smb_filename *smb_fname,
1485 uint32_t *_mode)
1487 struct smbd_dirptr_lanman2_state *state =
1488 (struct smbd_dirptr_lanman2_state *)private_data;
1489 bool ms_dfs_link = false;
1490 uint32_t mode = 0;
1492 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1493 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1494 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1495 "Couldn't lstat [%s] (%s)\n",
1496 smb_fname_str_dbg(smb_fname),
1497 strerror(errno)));
1498 return false;
1500 } else if (!VALID_STAT(smb_fname->st) &&
1501 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1502 /* Needed to show the msdfs symlinks as
1503 * directories */
1505 ms_dfs_link = check_msdfs_link(state->conn,
1506 smb_fname->base_name,
1507 &smb_fname->st);
1508 if (!ms_dfs_link) {
1509 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1510 "Couldn't stat [%s] (%s)\n",
1511 smb_fname_str_dbg(smb_fname),
1512 strerror(errno)));
1513 return false;
1517 if (ms_dfs_link) {
1518 mode = dos_mode_msdfs(state->conn, smb_fname);
1519 } else {
1520 mode = dos_mode(state->conn, smb_fname);
1523 *_mode = mode;
1524 return true;
1527 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1528 connection_struct *conn,
1529 uint16_t flags2,
1530 uint32_t info_level,
1531 struct ea_list *name_list,
1532 bool check_mangled_names,
1533 bool requires_resume_key,
1534 uint32_t mode,
1535 const char *fname,
1536 const struct smb_filename *smb_fname,
1537 int space_remaining,
1538 uint8_t align,
1539 bool do_pad,
1540 char *base_data,
1541 char **ppdata,
1542 char *end_data,
1543 bool *out_of_space,
1544 uint64_t *last_entry_off)
1546 char *p, *q, *pdata = *ppdata;
1547 uint32_t reskey=0;
1548 uint64_t file_size = 0;
1549 uint64_t allocation_size = 0;
1550 uint64_t file_index = 0;
1551 uint32_t len;
1552 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1553 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1554 time_t c_date = (time_t)0;
1555 char *nameptr;
1556 char *last_entry_ptr;
1557 bool was_8_3;
1558 int off;
1559 int pad = 0;
1561 *out_of_space = false;
1563 ZERO_STRUCT(mdate_ts);
1564 ZERO_STRUCT(adate_ts);
1565 ZERO_STRUCT(create_date_ts);
1566 ZERO_STRUCT(cdate_ts);
1568 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1569 file_size = get_file_size_stat(&smb_fname->st);
1571 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1573 file_index = get_FileIndex(conn, &smb_fname->st);
1575 mdate_ts = smb_fname->st.st_ex_mtime;
1576 adate_ts = smb_fname->st.st_ex_atime;
1577 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1578 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1580 if (lp_dos_filetime_resolution(SNUM(conn))) {
1581 dos_filetime_timespec(&create_date_ts);
1582 dos_filetime_timespec(&mdate_ts);
1583 dos_filetime_timespec(&adate_ts);
1584 dos_filetime_timespec(&cdate_ts);
1587 create_date = convert_timespec_to_time_t(create_date_ts);
1588 mdate = convert_timespec_to_time_t(mdate_ts);
1589 adate = convert_timespec_to_time_t(adate_ts);
1590 c_date = convert_timespec_to_time_t(cdate_ts);
1592 /* align the record */
1593 SMB_ASSERT(align >= 1);
1595 off = (int)PTR_DIFF(pdata, base_data);
1596 pad = (off + (align-1)) & ~(align-1);
1597 pad -= off;
1599 if (pad && pad > space_remaining) {
1600 *out_of_space = true;
1601 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1602 "for padding (wanted %u, had %d)\n",
1603 (unsigned int)pad,
1604 space_remaining ));
1605 return false; /* Not finished - just out of space */
1608 off += pad;
1609 /* initialize padding to 0 */
1610 if (pad) {
1611 memset(pdata, 0, pad);
1613 space_remaining -= pad;
1615 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1616 space_remaining ));
1618 pdata += pad;
1619 p = pdata;
1620 last_entry_ptr = p;
1622 pad = 0;
1623 off = 0;
1625 switch (info_level) {
1626 case SMB_FIND_INFO_STANDARD:
1627 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1628 if(requires_resume_key) {
1629 SIVAL(p,0,reskey);
1630 p += 4;
1632 srv_put_dos_date2(p,0,create_date);
1633 srv_put_dos_date2(p,4,adate);
1634 srv_put_dos_date2(p,8,mdate);
1635 SIVAL(p,12,(uint32)file_size);
1636 SIVAL(p,16,(uint32)allocation_size);
1637 SSVAL(p,20,mode);
1638 p += 23;
1639 nameptr = p;
1640 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1641 p += ucs2_align(base_data, p, 0);
1643 len = srvstr_push(base_data, flags2, p,
1644 fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE);
1646 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1647 if (len > 2) {
1648 SCVAL(nameptr, -1, len - 2);
1649 } else {
1650 SCVAL(nameptr, -1, 0);
1652 } else {
1653 if (len > 1) {
1654 SCVAL(nameptr, -1, len - 1);
1655 } else {
1656 SCVAL(nameptr, -1, 0);
1659 p += len;
1660 break;
1662 case SMB_FIND_EA_SIZE:
1663 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1664 if (requires_resume_key) {
1665 SIVAL(p,0,reskey);
1666 p += 4;
1668 srv_put_dos_date2(p,0,create_date);
1669 srv_put_dos_date2(p,4,adate);
1670 srv_put_dos_date2(p,8,mdate);
1671 SIVAL(p,12,(uint32)file_size);
1672 SIVAL(p,16,(uint32)allocation_size);
1673 SSVAL(p,20,mode);
1675 unsigned int ea_size = estimate_ea_size(conn, NULL,
1676 smb_fname->base_name);
1677 SIVAL(p,22,ea_size); /* Extended attributes */
1679 p += 27;
1680 nameptr = p - 1;
1681 len = srvstr_push(base_data, flags2,
1682 p, fname, PTR_DIFF(end_data, p),
1683 STR_TERMINATE | STR_NOALIGN);
1684 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1685 if (len > 2) {
1686 len -= 2;
1687 } else {
1688 len = 0;
1690 } else {
1691 if (len > 1) {
1692 len -= 1;
1693 } else {
1694 len = 0;
1697 SCVAL(nameptr,0,len);
1698 p += len;
1699 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1700 break;
1702 case SMB_FIND_EA_LIST:
1704 struct ea_list *file_list = NULL;
1705 size_t ea_len = 0;
1707 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1708 if (!name_list) {
1709 return false;
1711 if (requires_resume_key) {
1712 SIVAL(p,0,reskey);
1713 p += 4;
1715 srv_put_dos_date2(p,0,create_date);
1716 srv_put_dos_date2(p,4,adate);
1717 srv_put_dos_date2(p,8,mdate);
1718 SIVAL(p,12,(uint32)file_size);
1719 SIVAL(p,16,(uint32)allocation_size);
1720 SSVAL(p,20,mode);
1721 p += 22; /* p now points to the EA area. */
1723 file_list = get_ea_list_from_file(ctx, conn, NULL,
1724 smb_fname->base_name,
1725 &ea_len);
1726 name_list = ea_list_union(name_list, file_list, &ea_len);
1728 /* We need to determine if this entry will fit in the space available. */
1729 /* Max string size is 255 bytes. */
1730 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1731 *out_of_space = true;
1732 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1733 "(wanted %u, had %d)\n",
1734 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1735 space_remaining ));
1736 return False; /* Not finished - just out of space */
1739 /* Push the ea_data followed by the name. */
1740 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1741 nameptr = p;
1742 len = srvstr_push(base_data, flags2,
1743 p + 1, fname, PTR_DIFF(end_data, p+1),
1744 STR_TERMINATE | STR_NOALIGN);
1745 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1746 if (len > 2) {
1747 len -= 2;
1748 } else {
1749 len = 0;
1751 } else {
1752 if (len > 1) {
1753 len -= 1;
1754 } else {
1755 len = 0;
1758 SCVAL(nameptr,0,len);
1759 p += len + 1;
1760 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1761 break;
1764 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1765 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1766 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1767 p += 4;
1768 SIVAL(p,0,reskey); p += 4;
1769 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1770 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1771 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1772 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1773 SOFF_T(p,0,file_size); p += 8;
1774 SOFF_T(p,0,allocation_size); p += 8;
1775 SIVAL(p,0,mode); p += 4;
1776 q = p; p += 4; /* q is placeholder for name length. */
1777 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1778 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1779 } else {
1780 unsigned int ea_size = estimate_ea_size(conn, NULL,
1781 smb_fname->base_name);
1782 SIVAL(p,0,ea_size); /* Extended attributes */
1784 p += 4;
1785 /* Clear the short name buffer. This is
1786 * IMPORTANT as not doing so will trigger
1787 * a Win2k client bug. JRA.
1789 if (!was_8_3 && check_mangled_names) {
1790 char mangled_name[13]; /* mangled 8.3 name. */
1791 if (!name_to_8_3(fname,mangled_name,True,
1792 conn->params)) {
1793 /* Error - mangle failed ! */
1794 memset(mangled_name,'\0',12);
1796 mangled_name[12] = 0;
1797 len = srvstr_push(base_data, flags2,
1798 p+2, mangled_name, 24,
1799 STR_UPPER|STR_UNICODE);
1800 if (len < 24) {
1801 memset(p + 2 + len,'\0',24 - len);
1803 SSVAL(p, 0, len);
1804 } else {
1805 memset(p,'\0',26);
1807 p += 2 + 24;
1808 len = srvstr_push(base_data, flags2, p,
1809 fname, PTR_DIFF(end_data, p),
1810 STR_TERMINATE_ASCII);
1811 SIVAL(q,0,len);
1812 p += len;
1814 len = PTR_DIFF(p, pdata);
1815 pad = (len + (align-1)) & ~(align-1);
1817 * offset to the next entry, the caller
1818 * will overwrite it for the last entry
1819 * that's why we always include the padding
1821 SIVAL(pdata,0,pad);
1823 * set padding to zero
1825 if (do_pad) {
1826 memset(p, 0, pad - len);
1827 p = pdata + pad;
1828 } else {
1829 p = pdata + len;
1831 break;
1833 case SMB_FIND_FILE_DIRECTORY_INFO:
1834 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1835 p += 4;
1836 SIVAL(p,0,reskey); p += 4;
1837 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1838 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1839 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1840 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1841 SOFF_T(p,0,file_size); p += 8;
1842 SOFF_T(p,0,allocation_size); p += 8;
1843 SIVAL(p,0,mode); p += 4;
1844 len = srvstr_push(base_data, flags2,
1845 p + 4, fname, PTR_DIFF(end_data, p+4),
1846 STR_TERMINATE_ASCII);
1847 SIVAL(p,0,len);
1848 p += 4 + len;
1850 len = PTR_DIFF(p, pdata);
1851 pad = (len + (align-1)) & ~(align-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1857 SIVAL(pdata,0,pad);
1859 * set padding to zero
1861 if (do_pad) {
1862 memset(p, 0, pad - len);
1863 p = pdata + pad;
1864 } else {
1865 p = pdata + len;
1867 break;
1869 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1871 p += 4;
1872 SIVAL(p,0,reskey); p += 4;
1873 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1877 SOFF_T(p,0,file_size); p += 8;
1878 SOFF_T(p,0,allocation_size); p += 8;
1879 SIVAL(p,0,mode); p += 4;
1880 q = p; p += 4; /* q is placeholder for name length. */
1882 unsigned int ea_size = estimate_ea_size(conn, NULL,
1883 smb_fname->base_name);
1884 SIVAL(p,0,ea_size); /* Extended attributes */
1885 p +=4;
1887 len = srvstr_push(base_data, flags2, p,
1888 fname, PTR_DIFF(end_data, p),
1889 STR_TERMINATE_ASCII);
1890 SIVAL(q, 0, len);
1891 p += len;
1893 len = PTR_DIFF(p, pdata);
1894 pad = (len + (align-1)) & ~(align-1);
1896 * offset to the next entry, the caller
1897 * will overwrite it for the last entry
1898 * that's why we always include the padding
1900 SIVAL(pdata,0,pad);
1902 * set padding to zero
1904 if (do_pad) {
1905 memset(p, 0, pad - len);
1906 p = pdata + pad;
1907 } else {
1908 p = pdata + len;
1910 break;
1912 case SMB_FIND_FILE_NAMES_INFO:
1913 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1914 p += 4;
1915 SIVAL(p,0,reskey); p += 4;
1916 p += 4;
1917 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1918 acl on a dir (tridge) */
1919 len = srvstr_push(base_data, flags2, p,
1920 fname, PTR_DIFF(end_data, p),
1921 STR_TERMINATE_ASCII);
1922 SIVAL(p, -4, len);
1923 p += len;
1925 len = PTR_DIFF(p, pdata);
1926 pad = (len + (align-1)) & ~(align-1);
1928 * offset to the next entry, the caller
1929 * will overwrite it for the last entry
1930 * that's why we always include the padding
1932 SIVAL(pdata,0,pad);
1934 * set padding to zero
1936 if (do_pad) {
1937 memset(p, 0, pad - len);
1938 p = pdata + pad;
1939 } else {
1940 p = pdata + len;
1942 break;
1944 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1945 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1946 p += 4;
1947 SIVAL(p,0,reskey); p += 4;
1948 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1949 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1950 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1951 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1952 SOFF_T(p,0,file_size); p += 8;
1953 SOFF_T(p,0,allocation_size); p += 8;
1954 SIVAL(p,0,mode); p += 4;
1955 q = p; p += 4; /* q is placeholder for name length. */
1956 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1957 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1958 } else {
1959 unsigned int ea_size = estimate_ea_size(conn, NULL,
1960 smb_fname->base_name);
1961 SIVAL(p,0,ea_size); /* Extended attributes */
1963 p +=4;
1964 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1965 SBVAL(p,0,file_index); p += 8;
1966 len = srvstr_push(base_data, flags2, p,
1967 fname, PTR_DIFF(end_data, p),
1968 STR_TERMINATE_ASCII);
1969 SIVAL(q, 0, len);
1970 p += len;
1972 len = PTR_DIFF(p, pdata);
1973 pad = (len + (align-1)) & ~(align-1);
1975 * offset to the next entry, the caller
1976 * will overwrite it for the last entry
1977 * that's why we always include the padding
1979 SIVAL(pdata,0,pad);
1981 * set padding to zero
1983 if (do_pad) {
1984 memset(p, 0, pad - len);
1985 p = pdata + pad;
1986 } else {
1987 p = pdata + len;
1989 break;
1991 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1992 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1993 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1994 p += 4;
1995 SIVAL(p,0,reskey); p += 4;
1996 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1998 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1999 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2000 SOFF_T(p,0,file_size); p += 8;
2001 SOFF_T(p,0,allocation_size); p += 8;
2002 SIVAL(p,0,mode); p += 4;
2003 q = p; p += 4; /* q is placeholder for name length */
2004 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2005 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2006 } else {
2007 unsigned int ea_size = estimate_ea_size(conn, NULL,
2008 smb_fname->base_name);
2009 SIVAL(p,0,ea_size); /* Extended attributes */
2011 p +=4;
2012 /* Clear the short name buffer. This is
2013 * IMPORTANT as not doing so will trigger
2014 * a Win2k client bug. JRA.
2016 if (!was_8_3 && check_mangled_names) {
2017 char mangled_name[13]; /* mangled 8.3 name. */
2018 if (!name_to_8_3(fname,mangled_name,True,
2019 conn->params)) {
2020 /* Error - mangle failed ! */
2021 memset(mangled_name,'\0',12);
2023 mangled_name[12] = 0;
2024 len = srvstr_push(base_data, flags2,
2025 p+2, mangled_name, 24,
2026 STR_UPPER|STR_UNICODE);
2027 SSVAL(p, 0, len);
2028 if (len < 24) {
2029 memset(p + 2 + len,'\0',24 - len);
2031 SSVAL(p, 0, len);
2032 } else {
2033 memset(p,'\0',26);
2035 p += 26;
2036 SSVAL(p,0,0); p += 2; /* Reserved ? */
2037 SBVAL(p,0,file_index); p += 8;
2038 len = srvstr_push(base_data, flags2, p,
2039 fname, PTR_DIFF(end_data, p),
2040 STR_TERMINATE_ASCII);
2041 SIVAL(q,0,len);
2042 p += len;
2044 len = PTR_DIFF(p, pdata);
2045 pad = (len + (align-1)) & ~(align-1);
2047 * offset to the next entry, the caller
2048 * will overwrite it for the last entry
2049 * that's why we always include the padding
2051 SIVAL(pdata,0,pad);
2053 * set padding to zero
2055 if (do_pad) {
2056 memset(p, 0, pad - len);
2057 p = pdata + pad;
2058 } else {
2059 p = pdata + len;
2061 break;
2063 /* CIFS UNIX Extension. */
2065 case SMB_FIND_FILE_UNIX:
2066 case SMB_FIND_FILE_UNIX_INFO2:
2067 p+= 4;
2068 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2070 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (info_level == SMB_FIND_FILE_UNIX) {
2073 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2074 p = store_file_unix_basic(conn, p,
2075 NULL, &smb_fname->st);
2076 len = srvstr_push(base_data, flags2, p,
2077 fname, PTR_DIFF(end_data, p),
2078 STR_TERMINATE);
2079 } else {
2080 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2081 p = store_file_unix_basic_info2(conn, p,
2082 NULL, &smb_fname->st);
2083 nameptr = p;
2084 p += 4;
2085 len = srvstr_push(base_data, flags2, p, fname,
2086 PTR_DIFF(end_data, p), 0);
2087 SIVAL(nameptr, 0, len);
2090 p += len;
2092 len = PTR_DIFF(p, pdata);
2093 pad = (len + (align-1)) & ~(align-1);
2095 * offset to the next entry, the caller
2096 * will overwrite it for the last entry
2097 * that's why we always include the padding
2099 SIVAL(pdata,0,pad);
2101 * set padding to zero
2103 if (do_pad) {
2104 memset(p, 0, pad - len);
2105 p = pdata + pad;
2106 } else {
2107 p = pdata + len;
2109 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2111 break;
2113 default:
2114 return false;
2117 if (PTR_DIFF(p,pdata) > space_remaining) {
2118 *out_of_space = true;
2119 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2120 "(wanted %u, had %d)\n",
2121 (unsigned int)PTR_DIFF(p,pdata),
2122 space_remaining ));
2123 return false; /* Not finished - just out of space */
2126 /* Setup the last entry pointer, as an offset from base_data */
2127 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2128 /* Advance the data pointer to the next slot */
2129 *ppdata = p;
2131 return true;
2134 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2135 connection_struct *conn,
2136 struct dptr_struct *dirptr,
2137 uint16 flags2,
2138 const char *path_mask,
2139 uint32 dirtype,
2140 int info_level,
2141 int requires_resume_key,
2142 bool dont_descend,
2143 bool ask_sharemode,
2144 uint8_t align,
2145 bool do_pad,
2146 char **ppdata,
2147 char *base_data,
2148 char *end_data,
2149 int space_remaining,
2150 bool *out_of_space,
2151 bool *got_exact_match,
2152 int *_last_entry_off,
2153 struct ea_list *name_list)
2155 const char *p;
2156 const char *mask = NULL;
2157 long prev_dirpos = 0;
2158 uint32_t mode = 0;
2159 char *fname = NULL;
2160 struct smb_filename *smb_fname = NULL;
2161 struct smbd_dirptr_lanman2_state state;
2162 bool ok;
2163 uint64_t last_entry_off = 0;
2165 ZERO_STRUCT(state);
2166 state.conn = conn;
2167 state.info_level = info_level;
2168 state.check_mangled_names = lp_manglednames(conn->params);
2169 state.has_wild = dptr_has_wild(dirptr);
2170 state.got_exact_match = false;
2172 *out_of_space = false;
2173 *got_exact_match = false;
2175 p = strrchr_m(path_mask,'/');
2176 if(p != NULL) {
2177 if(p[1] == '\0') {
2178 mask = "*.*";
2179 } else {
2180 mask = p+1;
2182 } else {
2183 mask = path_mask;
2186 ok = smbd_dirptr_get_entry(ctx,
2187 dirptr,
2188 mask,
2189 dirtype,
2190 dont_descend,
2191 ask_sharemode,
2192 smbd_dirptr_lanman2_match_fn,
2193 smbd_dirptr_lanman2_mode_fn,
2194 &state,
2195 &fname,
2196 &smb_fname,
2197 &mode,
2198 &prev_dirpos);
2199 if (!ok) {
2200 return false;
2203 *got_exact_match = state.got_exact_match;
2205 ok = smbd_marshall_dir_entry(ctx,
2206 conn,
2207 flags2,
2208 info_level,
2209 name_list,
2210 state.check_mangled_names,
2211 requires_resume_key,
2212 mode,
2213 fname,
2214 smb_fname,
2215 space_remaining,
2216 align,
2217 do_pad,
2218 base_data,
2219 ppdata,
2220 end_data,
2221 out_of_space,
2222 &last_entry_off);
2223 TALLOC_FREE(fname);
2224 TALLOC_FREE(smb_fname);
2225 if (*out_of_space) {
2226 dptr_SeekDir(dirptr, prev_dirpos);
2227 return false;
2229 if (!ok) {
2230 return false;
2233 *_last_entry_off = last_entry_off;
2234 return true;
2237 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2238 connection_struct *conn,
2239 struct dptr_struct *dirptr,
2240 uint16 flags2,
2241 const char *path_mask,
2242 uint32 dirtype,
2243 int info_level,
2244 bool requires_resume_key,
2245 bool dont_descend,
2246 bool ask_sharemode,
2247 char **ppdata,
2248 char *base_data,
2249 char *end_data,
2250 int space_remaining,
2251 bool *out_of_space,
2252 bool *got_exact_match,
2253 int *last_entry_off,
2254 struct ea_list *name_list)
2256 uint8_t align = 4;
2257 const bool do_pad = true;
2259 if (info_level >= 1 && info_level <= 3) {
2260 /* No alignment on earlier info levels. */
2261 align = 1;
2264 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2265 path_mask, dirtype, info_level,
2266 requires_resume_key, dont_descend, ask_sharemode,
2267 align, do_pad,
2268 ppdata, base_data, end_data,
2269 space_remaining,
2270 out_of_space, got_exact_match,
2271 last_entry_off, name_list);
2274 /****************************************************************************
2275 Reply to a TRANS2_FINDFIRST.
2276 ****************************************************************************/
2278 static void call_trans2findfirst(connection_struct *conn,
2279 struct smb_request *req,
2280 char **pparams, int total_params,
2281 char **ppdata, int total_data,
2282 unsigned int max_data_bytes)
2284 /* We must be careful here that we don't return more than the
2285 allowed number of data bytes. If this means returning fewer than
2286 maxentries then so be it. We assume that the redirector has
2287 enough room for the fixed number of parameter bytes it has
2288 requested. */
2289 struct smb_filename *smb_dname = NULL;
2290 char *params = *pparams;
2291 char *pdata = *ppdata;
2292 char *data_end;
2293 uint32 dirtype;
2294 int maxentries;
2295 uint16 findfirst_flags;
2296 bool close_after_first;
2297 bool close_if_end;
2298 bool requires_resume_key;
2299 int info_level;
2300 char *directory = NULL;
2301 char *mask = NULL;
2302 char *p;
2303 int last_entry_off=0;
2304 int dptr_num = -1;
2305 int numentries = 0;
2306 int i;
2307 bool finished = False;
2308 bool dont_descend = False;
2309 bool out_of_space = False;
2310 int space_remaining;
2311 bool mask_contains_wcard = False;
2312 struct ea_list *ea_list = NULL;
2313 NTSTATUS ntstatus = NT_STATUS_OK;
2314 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2315 TALLOC_CTX *ctx = talloc_tos();
2316 struct dptr_struct *dirptr = NULL;
2317 struct smbd_server_connection *sconn = req->sconn;
2318 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2320 if (total_params < 13) {
2321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2322 goto out;
2325 dirtype = SVAL(params,0);
2326 maxentries = SVAL(params,2);
2327 findfirst_flags = SVAL(params,4);
2328 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2329 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2330 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2331 info_level = SVAL(params,6);
2333 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2334 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2335 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2336 info_level, max_data_bytes));
2338 if (!maxentries) {
2339 /* W2K3 seems to treat zero as 1. */
2340 maxentries = 1;
2343 switch (info_level) {
2344 case SMB_FIND_INFO_STANDARD:
2345 case SMB_FIND_EA_SIZE:
2346 case SMB_FIND_EA_LIST:
2347 case SMB_FIND_FILE_DIRECTORY_INFO:
2348 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2349 case SMB_FIND_FILE_NAMES_INFO:
2350 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2351 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2352 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2353 break;
2354 case SMB_FIND_FILE_UNIX:
2355 case SMB_FIND_FILE_UNIX_INFO2:
2356 /* Always use filesystem for UNIX mtime query. */
2357 ask_sharemode = false;
2358 if (!lp_unix_extensions()) {
2359 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2360 goto out;
2362 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2363 break;
2364 default:
2365 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2366 goto out;
2369 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2370 params+12, total_params - 12,
2371 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2372 if (!NT_STATUS_IS_OK(ntstatus)) {
2373 reply_nterror(req, ntstatus);
2374 goto out;
2377 ntstatus = filename_convert(ctx, conn,
2378 req->flags2 & FLAGS2_DFS_PATHNAMES,
2379 directory,
2380 ucf_flags,
2381 &mask_contains_wcard,
2382 &smb_dname);
2383 if (!NT_STATUS_IS_OK(ntstatus)) {
2384 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2385 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2386 ERRSRV, ERRbadpath);
2387 goto out;
2389 reply_nterror(req, ntstatus);
2390 goto out;
2393 mask = smb_dname->original_lcomp;
2395 directory = smb_dname->base_name;
2397 p = strrchr_m(directory,'/');
2398 if(p == NULL) {
2399 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2400 if((directory[0] == '.') && (directory[1] == '\0')) {
2401 mask = talloc_strdup(ctx,"*");
2402 if (!mask) {
2403 reply_nterror(req, NT_STATUS_NO_MEMORY);
2404 goto out;
2406 mask_contains_wcard = True;
2408 } else {
2409 *p = 0;
2412 if (p == NULL || p == directory) {
2413 /* Ensure we don't have a directory name of "". */
2414 directory = talloc_strdup(talloc_tos(), ".");
2415 if (!directory) {
2416 reply_nterror(req, NT_STATUS_NO_MEMORY);
2417 goto out;
2421 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2423 if (info_level == SMB_FIND_EA_LIST) {
2424 uint32 ea_size;
2426 if (total_data < 4) {
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2428 goto out;
2431 ea_size = IVAL(pdata,0);
2432 if (ea_size != total_data) {
2433 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2434 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2436 goto out;
2439 if (!lp_ea_support(SNUM(conn))) {
2440 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2441 goto out;
2444 /* Pull out the list of names. */
2445 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2446 if (!ea_list) {
2447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2448 goto out;
2452 *ppdata = (char *)SMB_REALLOC(
2453 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2454 if(*ppdata == NULL ) {
2455 reply_nterror(req, NT_STATUS_NO_MEMORY);
2456 goto out;
2458 pdata = *ppdata;
2459 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2461 /* Realloc the params space */
2462 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2463 if (*pparams == NULL) {
2464 reply_nterror(req, NT_STATUS_NO_MEMORY);
2465 goto out;
2467 params = *pparams;
2469 /* Save the wildcard match and attribs we are using on this directory -
2470 needed as lanman2 assumes these are being saved between calls */
2472 ntstatus = dptr_create(conn,
2473 NULL, /* fsp */
2474 directory,
2475 False,
2476 True,
2477 req->smbpid,
2478 mask,
2479 mask_contains_wcard,
2480 dirtype,
2481 &dirptr);
2483 if (!NT_STATUS_IS_OK(ntstatus)) {
2484 reply_nterror(req, ntstatus);
2485 goto out;
2488 dptr_num = dptr_dnum(dirptr);
2489 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2491 /* Initialize per TRANS2_FIND_FIRST operation data */
2492 dptr_init_search_op(dirptr);
2494 /* We don't need to check for VOL here as this is returned by
2495 a different TRANS2 call. */
2497 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2498 directory,lp_dontdescend(SNUM(conn))));
2499 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2500 dont_descend = True;
2502 p = pdata;
2503 space_remaining = max_data_bytes;
2504 out_of_space = False;
2506 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2507 bool got_exact_match = False;
2509 /* this is a heuristic to avoid seeking the dirptr except when
2510 absolutely necessary. It allows for a filename of about 40 chars */
2511 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2512 out_of_space = True;
2513 finished = False;
2514 } else {
2515 finished = !get_lanman2_dir_entry(ctx,
2516 conn,
2517 dirptr,
2518 req->flags2,
2519 mask,dirtype,info_level,
2520 requires_resume_key,dont_descend,
2521 ask_sharemode,
2522 &p,pdata,data_end,
2523 space_remaining, &out_of_space,
2524 &got_exact_match,
2525 &last_entry_off, ea_list);
2528 if (finished && out_of_space)
2529 finished = False;
2531 if (!finished && !out_of_space)
2532 numentries++;
2535 * As an optimisation if we know we aren't looking
2536 * for a wildcard name (ie. the name matches the wildcard exactly)
2537 * then we can finish on any (first) match.
2538 * This speeds up large directory searches. JRA.
2541 if(got_exact_match)
2542 finished = True;
2544 /* Ensure space_remaining never goes -ve. */
2545 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2546 space_remaining = 0;
2547 out_of_space = true;
2548 } else {
2549 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2553 /* Check if we can close the dirptr */
2554 if(close_after_first || (finished && close_if_end)) {
2555 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2556 dptr_close(sconn, &dptr_num);
2560 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2561 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2562 * the protocol level is less than NT1. Tested with smbclient. JRA.
2563 * This should fix the OS/2 client bug #2335.
2566 if(numentries == 0) {
2567 dptr_close(sconn, &dptr_num);
2568 if (get_Protocol() < PROTOCOL_NT1) {
2569 reply_force_doserror(req, ERRDOS, ERRnofiles);
2570 goto out;
2571 } else {
2572 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2573 ERRDOS, ERRbadfile);
2574 goto out;
2578 /* At this point pdata points to numentries directory entries. */
2580 /* Set up the return parameter block */
2581 SSVAL(params,0,dptr_num);
2582 SSVAL(params,2,numentries);
2583 SSVAL(params,4,finished);
2584 SSVAL(params,6,0); /* Never an EA error */
2585 SSVAL(params,8,last_entry_off);
2587 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2588 max_data_bytes);
2590 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2591 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2592 if (!directory) {
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2597 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2598 smb_fn_name(req->cmd),
2599 mask, directory, dirtype, numentries ) );
2602 * Force a name mangle here to ensure that the
2603 * mask as an 8.3 name is top of the mangled cache.
2604 * The reasons for this are subtle. Don't remove
2605 * this code unless you know what you are doing
2606 * (see PR#13758). JRA.
2609 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2610 char mangled_name[13];
2611 name_to_8_3(mask, mangled_name, True, conn->params);
2613 out:
2614 TALLOC_FREE(smb_dname);
2615 return;
2618 /****************************************************************************
2619 Reply to a TRANS2_FINDNEXT.
2620 ****************************************************************************/
2622 static void call_trans2findnext(connection_struct *conn,
2623 struct smb_request *req,
2624 char **pparams, int total_params,
2625 char **ppdata, int total_data,
2626 unsigned int max_data_bytes)
2628 /* We must be careful here that we don't return more than the
2629 allowed number of data bytes. If this means returning fewer than
2630 maxentries then so be it. We assume that the redirector has
2631 enough room for the fixed number of parameter bytes it has
2632 requested. */
2633 char *params = *pparams;
2634 char *pdata = *ppdata;
2635 char *data_end;
2636 int dptr_num;
2637 int maxentries;
2638 uint16 info_level;
2639 uint32 resume_key;
2640 uint16 findnext_flags;
2641 bool close_after_request;
2642 bool close_if_end;
2643 bool requires_resume_key;
2644 bool continue_bit;
2645 bool mask_contains_wcard = False;
2646 char *resume_name = NULL;
2647 const char *mask = NULL;
2648 const char *directory = NULL;
2649 char *p = NULL;
2650 uint16 dirtype;
2651 int numentries = 0;
2652 int i, last_entry_off=0;
2653 bool finished = False;
2654 bool dont_descend = False;
2655 bool out_of_space = False;
2656 int space_remaining;
2657 struct ea_list *ea_list = NULL;
2658 NTSTATUS ntstatus = NT_STATUS_OK;
2659 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2660 TALLOC_CTX *ctx = talloc_tos();
2661 struct dptr_struct *dirptr;
2662 struct smbd_server_connection *sconn = req->sconn;
2664 if (total_params < 13) {
2665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2666 return;
2669 dptr_num = SVAL(params,0);
2670 maxentries = SVAL(params,2);
2671 info_level = SVAL(params,4);
2672 resume_key = IVAL(params,6);
2673 findnext_flags = SVAL(params,10);
2674 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2675 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2676 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2677 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2679 if (!continue_bit) {
2680 /* We only need resume_name if continue_bit is zero. */
2681 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2682 params+12,
2683 total_params - 12, STR_TERMINATE, &ntstatus,
2684 &mask_contains_wcard);
2685 if (!NT_STATUS_IS_OK(ntstatus)) {
2686 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2687 complain (it thinks we're asking for the directory above the shared
2688 path or an invalid name). Catch this as the resume name is only compared, never used in
2689 a file access. JRA. */
2690 srvstr_pull_talloc(ctx, params, req->flags2,
2691 &resume_name, params+12,
2692 total_params - 12,
2693 STR_TERMINATE);
2695 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2696 reply_nterror(req, ntstatus);
2697 return;
2702 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2703 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2704 resume_key = %d resume name = %s continue=%d level = %d\n",
2705 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2706 requires_resume_key, resume_key,
2707 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2709 if (!maxentries) {
2710 /* W2K3 seems to treat zero as 1. */
2711 maxentries = 1;
2714 switch (info_level) {
2715 case SMB_FIND_INFO_STANDARD:
2716 case SMB_FIND_EA_SIZE:
2717 case SMB_FIND_EA_LIST:
2718 case SMB_FIND_FILE_DIRECTORY_INFO:
2719 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2720 case SMB_FIND_FILE_NAMES_INFO:
2721 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2722 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2723 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2724 break;
2725 case SMB_FIND_FILE_UNIX:
2726 case SMB_FIND_FILE_UNIX_INFO2:
2727 /* Always use filesystem for UNIX mtime query. */
2728 ask_sharemode = false;
2729 if (!lp_unix_extensions()) {
2730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2731 return;
2733 break;
2734 default:
2735 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2736 return;
2739 if (info_level == SMB_FIND_EA_LIST) {
2740 uint32 ea_size;
2742 if (total_data < 4) {
2743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2744 return;
2747 ea_size = IVAL(pdata,0);
2748 if (ea_size != total_data) {
2749 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2750 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2752 return;
2755 if (!lp_ea_support(SNUM(conn))) {
2756 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2757 return;
2760 /* Pull out the list of names. */
2761 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2762 if (!ea_list) {
2763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2764 return;
2768 *ppdata = (char *)SMB_REALLOC(
2769 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2770 if(*ppdata == NULL) {
2771 reply_nterror(req, NT_STATUS_NO_MEMORY);
2772 return;
2775 pdata = *ppdata;
2776 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2778 /* Realloc the params space */
2779 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2780 if(*pparams == NULL ) {
2781 reply_nterror(req, NT_STATUS_NO_MEMORY);
2782 return;
2785 params = *pparams;
2787 /* Check that the dptr is valid */
2788 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2789 reply_nterror(req, STATUS_NO_MORE_FILES);
2790 return;
2793 directory = dptr_path(sconn, dptr_num);
2795 /* Get the wildcard mask from the dptr */
2796 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2797 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2798 reply_nterror(req, STATUS_NO_MORE_FILES);
2799 return;
2802 mask = p;
2804 /* Get the attr mask from the dptr */
2805 dirtype = dptr_attr(sconn, dptr_num);
2807 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2808 dptr_num, mask, dirtype,
2809 (long)dirptr,
2810 dptr_TellDir(dirptr)));
2812 /* Initialize per TRANS2_FIND_NEXT operation data */
2813 dptr_init_search_op(dirptr);
2815 /* We don't need to check for VOL here as this is returned by
2816 a different TRANS2 call. */
2818 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2819 directory,lp_dontdescend(SNUM(conn))));
2820 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2821 dont_descend = True;
2823 p = pdata;
2824 space_remaining = max_data_bytes;
2825 out_of_space = False;
2828 * Seek to the correct position. We no longer use the resume key but
2829 * depend on the last file name instead.
2832 if(!continue_bit && resume_name && *resume_name) {
2833 SMB_STRUCT_STAT st;
2835 long current_pos = 0;
2837 * Remember, name_to_8_3 is called by
2838 * get_lanman2_dir_entry(), so the resume name
2839 * could be mangled. Ensure we check the unmangled name.
2842 if (mangle_is_mangled(resume_name, conn->params)) {
2843 char *new_resume_name = NULL;
2844 mangle_lookup_name_from_8_3(ctx,
2845 resume_name,
2846 &new_resume_name,
2847 conn->params);
2848 if (new_resume_name) {
2849 resume_name = new_resume_name;
2854 * Fix for NT redirector problem triggered by resume key indexes
2855 * changing between directory scans. We now return a resume key of 0
2856 * and instead look for the filename to continue from (also given
2857 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2858 * findfirst/findnext (as is usual) then the directory pointer
2859 * should already be at the correct place.
2862 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2863 } /* end if resume_name && !continue_bit */
2865 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2866 bool got_exact_match = False;
2868 /* this is a heuristic to avoid seeking the dirptr except when
2869 absolutely necessary. It allows for a filename of about 40 chars */
2870 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2871 out_of_space = True;
2872 finished = False;
2873 } else {
2874 finished = !get_lanman2_dir_entry(ctx,
2875 conn,
2876 dirptr,
2877 req->flags2,
2878 mask,dirtype,info_level,
2879 requires_resume_key,dont_descend,
2880 ask_sharemode,
2881 &p,pdata,data_end,
2882 space_remaining, &out_of_space,
2883 &got_exact_match,
2884 &last_entry_off, ea_list);
2887 if (finished && out_of_space)
2888 finished = False;
2890 if (!finished && !out_of_space)
2891 numentries++;
2894 * As an optimisation if we know we aren't looking
2895 * for a wildcard name (ie. the name matches the wildcard exactly)
2896 * then we can finish on any (first) match.
2897 * This speeds up large directory searches. JRA.
2900 if(got_exact_match)
2901 finished = True;
2903 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2906 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2907 smb_fn_name(req->cmd),
2908 mask, directory, dirtype, numentries ) );
2910 /* Check if we can close the dirptr */
2911 if(close_after_request || (finished && close_if_end)) {
2912 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2913 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2916 /* Set up the return parameter block */
2917 SSVAL(params,0,numentries);
2918 SSVAL(params,2,finished);
2919 SSVAL(params,4,0); /* Never an EA error */
2920 SSVAL(params,6,last_entry_off);
2922 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2923 max_data_bytes);
2925 return;
2928 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2930 E_md4hash(lp_servicename(SNUM(conn)),objid);
2931 return objid;
2934 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2936 SMB_ASSERT(extended_info != NULL);
2938 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2939 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2940 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2941 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2942 #ifdef SAMBA_VERSION_REVISION
2943 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2944 #endif
2945 extended_info->samba_subversion = 0;
2946 #ifdef SAMBA_VERSION_RC_RELEASE
2947 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2948 #else
2949 #ifdef SAMBA_VERSION_PRE_RELEASE
2950 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2951 #endif
2952 #endif
2953 #ifdef SAMBA_VERSION_VENDOR_PATCH
2954 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2955 #endif
2956 extended_info->samba_gitcommitdate = 0;
2957 #ifdef SAMBA_VERSION_COMMIT_TIME
2958 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2959 #endif
2961 memset(extended_info->samba_version_string, 0,
2962 sizeof(extended_info->samba_version_string));
2964 snprintf (extended_info->samba_version_string,
2965 sizeof(extended_info->samba_version_string),
2966 "%s", samba_version_string());
2969 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2970 TALLOC_CTX *mem_ctx,
2971 uint16_t info_level,
2972 uint16_t flags2,
2973 unsigned int max_data_bytes,
2974 size_t *fixed_portion,
2975 struct smb_filename *fname,
2976 char **ppdata,
2977 int *ret_data_len)
2979 char *pdata, *end_data;
2980 int data_len = 0, len;
2981 const char *vname = volume_label(SNUM(conn));
2982 int snum = SNUM(conn);
2983 char *fstype = lp_fstype(SNUM(conn));
2984 const char *filename = NULL;
2985 uint32 additional_flags = 0;
2986 struct smb_filename smb_fname;
2987 SMB_STRUCT_STAT st;
2988 NTSTATUS status = NT_STATUS_OK;
2990 if (fname == NULL || fname->base_name == NULL) {
2991 filename = ".";
2992 } else {
2993 filename = fname->base_name;
2996 if (IS_IPC(conn)) {
2997 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2998 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2999 "info level (0x%x) on IPC$.\n",
3000 (unsigned int)info_level));
3001 return NT_STATUS_ACCESS_DENIED;
3005 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3007 ZERO_STRUCT(smb_fname);
3008 smb_fname.base_name = discard_const_p(char, filename);
3010 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3011 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3012 return map_nt_error_from_unix(errno);
3015 st = smb_fname.st;
3017 *ppdata = (char *)SMB_REALLOC(
3018 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3019 if (*ppdata == NULL) {
3020 return NT_STATUS_NO_MEMORY;
3023 pdata = *ppdata;
3024 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3025 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3027 *fixed_portion = 0;
3029 switch (info_level) {
3030 case SMB_INFO_ALLOCATION:
3032 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3033 data_len = 18;
3034 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3035 return map_nt_error_from_unix(errno);
3038 block_size = lp_block_size(snum);
3039 if (bsize < block_size) {
3040 uint64_t factor = block_size/bsize;
3041 bsize = block_size;
3042 dsize /= factor;
3043 dfree /= factor;
3045 if (bsize > block_size) {
3046 uint64_t factor = bsize/block_size;
3047 bsize = block_size;
3048 dsize *= factor;
3049 dfree *= factor;
3051 bytes_per_sector = 512;
3052 sectors_per_unit = bsize/bytes_per_sector;
3054 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3055 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3056 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3058 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3059 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3060 SIVAL(pdata,l1_cUnit,dsize);
3061 SIVAL(pdata,l1_cUnitAvail,dfree);
3062 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3063 break;
3066 case SMB_INFO_VOLUME:
3067 /* Return volume name */
3069 * Add volume serial number - hash of a combination of
3070 * the called hostname and the service name.
3072 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3074 * Win2k3 and previous mess this up by sending a name length
3075 * one byte short. I believe only older clients (OS/2 Win9x) use
3076 * this call so try fixing this by adding a terminating null to
3077 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3079 len = srvstr_push(
3080 pdata, flags2,
3081 pdata+l2_vol_szVolLabel, vname,
3082 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3083 STR_NOALIGN|STR_TERMINATE);
3084 SCVAL(pdata,l2_vol_cch,len);
3085 data_len = l2_vol_szVolLabel + len;
3086 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3087 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3088 len, vname));
3089 break;
3091 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3092 case SMB_FS_ATTRIBUTE_INFORMATION:
3094 additional_flags = 0;
3095 #if defined(HAVE_SYS_QUOTAS)
3096 additional_flags |= FILE_VOLUME_QUOTAS;
3097 #endif
3099 if(lp_nt_acl_support(SNUM(conn))) {
3100 additional_flags |= FILE_PERSISTENT_ACLS;
3103 /* Capabilities are filled in at connection time through STATVFS call */
3104 additional_flags |= conn->fs_capabilities;
3105 additional_flags |= lp_parm_int(conn->params->service,
3106 "share", "fake_fscaps",
3109 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3110 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3111 additional_flags); /* FS ATTRIBUTES */
3113 SIVAL(pdata,4,255); /* Max filename component length */
3114 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3115 and will think we can't do long filenames */
3116 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3117 PTR_DIFF(end_data, pdata+12),
3118 STR_UNICODE);
3119 SIVAL(pdata,8,len);
3120 data_len = 12 + len;
3121 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3122 /* the client only requested a portion of the
3123 file system name */
3124 data_len = max_data_bytes;
3125 status = STATUS_BUFFER_OVERFLOW;
3127 *fixed_portion = 16;
3128 break;
3130 case SMB_QUERY_FS_LABEL_INFO:
3131 case SMB_FS_LABEL_INFORMATION:
3132 len = srvstr_push(pdata, flags2, pdata+4, vname,
3133 PTR_DIFF(end_data, pdata+4), 0);
3134 data_len = 4 + len;
3135 SIVAL(pdata,0,len);
3136 break;
3138 case SMB_QUERY_FS_VOLUME_INFO:
3139 case SMB_FS_VOLUME_INFORMATION:
3142 * Add volume serial number - hash of a combination of
3143 * the called hostname and the service name.
3145 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3146 (str_checksum(get_local_machine_name())<<16));
3148 /* Max label len is 32 characters. */
3149 len = srvstr_push(pdata, flags2, pdata+18, vname,
3150 PTR_DIFF(end_data, pdata+18),
3151 STR_UNICODE);
3152 SIVAL(pdata,12,len);
3153 data_len = 18+len;
3155 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3156 (int)strlen(vname),vname, lp_servicename(snum)));
3157 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3158 /* the client only requested a portion of the
3159 volume label */
3160 data_len = max_data_bytes;
3161 status = STATUS_BUFFER_OVERFLOW;
3164 break;
3166 case SMB_QUERY_FS_SIZE_INFO:
3167 case SMB_FS_SIZE_INFORMATION:
3169 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3170 data_len = 24;
3171 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3172 return map_nt_error_from_unix(errno);
3174 block_size = lp_block_size(snum);
3175 if (bsize < block_size) {
3176 uint64_t factor = block_size/bsize;
3177 bsize = block_size;
3178 dsize /= factor;
3179 dfree /= factor;
3181 if (bsize > block_size) {
3182 uint64_t factor = bsize/block_size;
3183 bsize = block_size;
3184 dsize *= factor;
3185 dfree *= factor;
3187 bytes_per_sector = 512;
3188 sectors_per_unit = bsize/bytes_per_sector;
3189 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3190 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3191 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3192 SBIG_UINT(pdata,0,dsize);
3193 SBIG_UINT(pdata,8,dfree);
3194 SIVAL(pdata,16,sectors_per_unit);
3195 SIVAL(pdata,20,bytes_per_sector);
3196 *fixed_portion = 24;
3197 break;
3200 case SMB_FS_FULL_SIZE_INFORMATION:
3202 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3203 data_len = 32;
3204 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3205 return map_nt_error_from_unix(errno);
3207 block_size = lp_block_size(snum);
3208 if (bsize < block_size) {
3209 uint64_t factor = block_size/bsize;
3210 bsize = block_size;
3211 dsize /= factor;
3212 dfree /= factor;
3214 if (bsize > block_size) {
3215 uint64_t factor = bsize/block_size;
3216 bsize = block_size;
3217 dsize *= factor;
3218 dfree *= factor;
3220 bytes_per_sector = 512;
3221 sectors_per_unit = bsize/bytes_per_sector;
3222 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3224 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3225 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3226 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3227 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3228 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3229 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3230 *fixed_portion = 32;
3231 break;
3234 case SMB_QUERY_FS_DEVICE_INFO:
3235 case SMB_FS_DEVICE_INFORMATION:
3237 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3239 if (!CAN_WRITE(conn)) {
3240 characteristics |= FILE_READ_ONLY_DEVICE;
3242 data_len = 8;
3243 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3244 SIVAL(pdata,4,characteristics);
3245 *fixed_portion = 8;
3246 break;
3249 #ifdef HAVE_SYS_QUOTAS
3250 case SMB_FS_QUOTA_INFORMATION:
3252 * what we have to send --metze:
3254 * Unknown1: 24 NULL bytes
3255 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3256 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3257 * Quota Flags: 2 byte :
3258 * Unknown3: 6 NULL bytes
3260 * 48 bytes total
3262 * details for Quota Flags:
3264 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3265 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3266 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3267 * 0x0001 Enable Quotas: enable quota for this fs
3271 /* we need to fake up a fsp here,
3272 * because its not send in this call
3274 files_struct fsp;
3275 SMB_NTQUOTA_STRUCT quotas;
3277 ZERO_STRUCT(fsp);
3278 ZERO_STRUCT(quotas);
3280 fsp.conn = conn;
3281 fsp.fnum = -1;
3283 /* access check */
3284 if (get_current_uid(conn) != 0) {
3285 DEBUG(0,("set_user_quota: access_denied "
3286 "service [%s] user [%s]\n",
3287 lp_servicename(SNUM(conn)),
3288 conn->session_info->unix_name));
3289 return NT_STATUS_ACCESS_DENIED;
3292 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3293 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3294 return map_nt_error_from_unix(errno);
3297 data_len = 48;
3299 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3300 lp_servicename(SNUM(conn))));
3302 /* Unknown1 24 NULL bytes*/
3303 SBIG_UINT(pdata,0,(uint64_t)0);
3304 SBIG_UINT(pdata,8,(uint64_t)0);
3305 SBIG_UINT(pdata,16,(uint64_t)0);
3307 /* Default Soft Quota 8 bytes */
3308 SBIG_UINT(pdata,24,quotas.softlim);
3310 /* Default Hard Quota 8 bytes */
3311 SBIG_UINT(pdata,32,quotas.hardlim);
3313 /* Quota flag 2 bytes */
3314 SSVAL(pdata,40,quotas.qflags);
3316 /* Unknown3 6 NULL bytes */
3317 SSVAL(pdata,42,0);
3318 SIVAL(pdata,44,0);
3320 break;
3322 #endif /* HAVE_SYS_QUOTAS */
3323 case SMB_FS_OBJECTID_INFORMATION:
3325 unsigned char objid[16];
3326 struct smb_extended_info extended_info;
3327 memcpy(pdata,create_volume_objectid(conn, objid),16);
3328 samba_extended_info_version (&extended_info);
3329 SIVAL(pdata,16,extended_info.samba_magic);
3330 SIVAL(pdata,20,extended_info.samba_version);
3331 SIVAL(pdata,24,extended_info.samba_subversion);
3332 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3333 memcpy(pdata+36,extended_info.samba_version_string,28);
3334 data_len = 64;
3335 break;
3339 * Query the version and capabilities of the CIFS UNIX extensions
3340 * in use.
3343 case SMB_QUERY_CIFS_UNIX_INFO:
3345 bool large_write = lp_min_receive_file_size() &&
3346 !srv_is_signing_active(conn->sconn);
3347 bool large_read = !srv_is_signing_active(conn->sconn);
3348 int encrypt_caps = 0;
3350 if (!lp_unix_extensions()) {
3351 return NT_STATUS_INVALID_LEVEL;
3354 switch (conn->encrypt_level) {
3355 case 0:
3356 encrypt_caps = 0;
3357 break;
3358 case 1:
3359 case Auto:
3360 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3361 break;
3362 case Required:
3363 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3364 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3365 large_write = false;
3366 large_read = false;
3367 break;
3370 data_len = 12;
3371 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3372 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3374 /* We have POSIX ACLs, pathname, encryption,
3375 * large read/write, and locking capability. */
3377 SBIG_UINT(pdata,4,((uint64_t)(
3378 CIFS_UNIX_POSIX_ACLS_CAP|
3379 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3380 CIFS_UNIX_FCNTL_LOCKS_CAP|
3381 CIFS_UNIX_EXTATTR_CAP|
3382 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3383 encrypt_caps|
3384 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3385 (large_write ?
3386 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3387 break;
3390 case SMB_QUERY_POSIX_FS_INFO:
3392 int rc;
3393 vfs_statvfs_struct svfs;
3395 if (!lp_unix_extensions()) {
3396 return NT_STATUS_INVALID_LEVEL;
3399 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3401 if (!rc) {
3402 data_len = 56;
3403 SIVAL(pdata,0,svfs.OptimalTransferSize);
3404 SIVAL(pdata,4,svfs.BlockSize);
3405 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3406 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3407 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3408 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3409 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3410 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3411 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3412 #ifdef EOPNOTSUPP
3413 } else if (rc == EOPNOTSUPP) {
3414 return NT_STATUS_INVALID_LEVEL;
3415 #endif /* EOPNOTSUPP */
3416 } else {
3417 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3418 return NT_STATUS_DOS(ERRSRV, ERRerror);
3420 *fixed_portion = 24;
3421 break;
3424 case SMB_QUERY_POSIX_WHOAMI:
3426 uint32_t flags = 0;
3427 uint32_t sid_bytes;
3428 int i;
3430 if (!lp_unix_extensions()) {
3431 return NT_STATUS_INVALID_LEVEL;
3434 if (max_data_bytes < 40) {
3435 return NT_STATUS_BUFFER_TOO_SMALL;
3438 /* We ARE guest if global_sid_Builtin_Guests is
3439 * in our list of SIDs.
3441 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3442 conn->session_info->security_token)) {
3443 flags |= SMB_WHOAMI_GUEST;
3446 /* We are NOT guest if global_sid_Authenticated_Users
3447 * is in our list of SIDs.
3449 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3450 conn->session_info->security_token)) {
3451 flags &= ~SMB_WHOAMI_GUEST;
3454 /* NOTE: 8 bytes for UID/GID, irrespective of native
3455 * platform size. This matches
3456 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3458 data_len = 4 /* flags */
3459 + 4 /* flag mask */
3460 + 8 /* uid */
3461 + 8 /* gid */
3462 + 4 /* ngroups */
3463 + 4 /* num_sids */
3464 + 4 /* SID bytes */
3465 + 4 /* pad/reserved */
3466 + (conn->session_info->utok.ngroups * 8)
3467 /* groups list */
3468 + (conn->session_info->security_token->num_sids *
3469 SID_MAX_SIZE)
3470 /* SID list */;
3472 SIVAL(pdata, 0, flags);
3473 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3474 SBIG_UINT(pdata, 8,
3475 (uint64_t)conn->session_info->utok.uid);
3476 SBIG_UINT(pdata, 16,
3477 (uint64_t)conn->session_info->utok.gid);
3480 if (data_len >= max_data_bytes) {
3481 /* Potential overflow, skip the GIDs and SIDs. */
3483 SIVAL(pdata, 24, 0); /* num_groups */
3484 SIVAL(pdata, 28, 0); /* num_sids */
3485 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3486 SIVAL(pdata, 36, 0); /* reserved */
3488 data_len = 40;
3489 break;
3492 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3493 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3495 /* We walk the SID list twice, but this call is fairly
3496 * infrequent, and I don't expect that it's performance
3497 * sensitive -- jpeach
3499 for (i = 0, sid_bytes = 0;
3500 i < conn->session_info->security_token->num_sids; ++i) {
3501 sid_bytes += ndr_size_dom_sid(
3502 &conn->session_info->security_token->sids[i],
3506 /* SID list byte count */
3507 SIVAL(pdata, 32, sid_bytes);
3509 /* 4 bytes pad/reserved - must be zero */
3510 SIVAL(pdata, 36, 0);
3511 data_len = 40;
3513 /* GID list */
3514 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3515 SBIG_UINT(pdata, data_len,
3516 (uint64_t)conn->session_info->utok.groups[i]);
3517 data_len += 8;
3520 /* SID list */
3521 for (i = 0;
3522 i < conn->session_info->security_token->num_sids; ++i) {
3523 int sid_len = ndr_size_dom_sid(
3524 &conn->session_info->security_token->sids[i],
3527 sid_linearize(pdata + data_len, sid_len,
3528 &conn->session_info->security_token->sids[i]);
3529 data_len += sid_len;
3532 break;
3535 case SMB_MAC_QUERY_FS_INFO:
3537 * Thursby MAC extension... ONLY on NTFS filesystems
3538 * once we do streams then we don't need this
3540 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3541 data_len = 88;
3542 SIVAL(pdata,84,0x100); /* Don't support mac... */
3543 break;
3545 /* drop through */
3546 default:
3547 return NT_STATUS_INVALID_LEVEL;
3550 *ret_data_len = data_len;
3551 return status;
3554 /****************************************************************************
3555 Reply to a TRANS2_QFSINFO (query filesystem info).
3556 ****************************************************************************/
3558 static void call_trans2qfsinfo(connection_struct *conn,
3559 struct smb_request *req,
3560 char **pparams, int total_params,
3561 char **ppdata, int total_data,
3562 unsigned int max_data_bytes)
3564 char *params = *pparams;
3565 uint16_t info_level;
3566 int data_len = 0;
3567 size_t fixed_portion;
3568 NTSTATUS status;
3570 if (total_params < 2) {
3571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3572 return;
3575 info_level = SVAL(params,0);
3577 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3578 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3579 DEBUG(0,("call_trans2qfsinfo: encryption required "
3580 "and info level 0x%x sent.\n",
3581 (unsigned int)info_level));
3582 exit_server_cleanly("encryption required "
3583 "on connection");
3584 return;
3588 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3590 status = smbd_do_qfsinfo(conn, req,
3591 info_level,
3592 req->flags2,
3593 max_data_bytes,
3594 &fixed_portion,
3595 NULL,
3596 ppdata, &data_len);
3597 if (!NT_STATUS_IS_OK(status)) {
3598 reply_nterror(req, status);
3599 return;
3602 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3603 max_data_bytes);
3605 DEBUG( 4, ( "%s info_level = %d\n",
3606 smb_fn_name(req->cmd), info_level) );
3608 return;
3611 /****************************************************************************
3612 Reply to a TRANS2_SETFSINFO (set filesystem info).
3613 ****************************************************************************/
3615 static void call_trans2setfsinfo(connection_struct *conn,
3616 struct smb_request *req,
3617 char **pparams, int total_params,
3618 char **ppdata, int total_data,
3619 unsigned int max_data_bytes)
3621 char *pdata = *ppdata;
3622 char *params = *pparams;
3623 uint16 info_level;
3625 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3627 /* */
3628 if (total_params < 4) {
3629 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3630 total_params));
3631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3632 return;
3635 info_level = SVAL(params,2);
3637 if (IS_IPC(conn)) {
3638 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3639 info_level != SMB_SET_CIFS_UNIX_INFO) {
3640 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3641 "info level (0x%x) on IPC$.\n",
3642 (unsigned int)info_level));
3643 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3644 return;
3648 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3649 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3650 DEBUG(0,("call_trans2setfsinfo: encryption required "
3651 "and info level 0x%x sent.\n",
3652 (unsigned int)info_level));
3653 exit_server_cleanly("encryption required "
3654 "on connection");
3655 return;
3659 switch(info_level) {
3660 case SMB_SET_CIFS_UNIX_INFO:
3662 uint16 client_unix_major;
3663 uint16 client_unix_minor;
3664 uint32 client_unix_cap_low;
3665 uint32 client_unix_cap_high;
3667 if (!lp_unix_extensions()) {
3668 reply_nterror(req,
3669 NT_STATUS_INVALID_LEVEL);
3670 return;
3673 /* There should be 12 bytes of capabilities set. */
3674 if (total_data < 8) {
3675 reply_nterror(
3676 req,
3677 NT_STATUS_INVALID_PARAMETER);
3678 return;
3680 client_unix_major = SVAL(pdata,0);
3681 client_unix_minor = SVAL(pdata,2);
3682 client_unix_cap_low = IVAL(pdata,4);
3683 client_unix_cap_high = IVAL(pdata,8);
3684 /* Just print these values for now. */
3685 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3686 cap_low = 0x%x, cap_high = 0x%x\n",
3687 (unsigned int)client_unix_major,
3688 (unsigned int)client_unix_minor,
3689 (unsigned int)client_unix_cap_low,
3690 (unsigned int)client_unix_cap_high ));
3692 /* Here is where we must switch to posix pathname processing... */
3693 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3694 lp_set_posix_pathnames();
3695 mangle_change_to_posix();
3698 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3699 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3700 /* Client that knows how to do posix locks,
3701 * but not posix open/mkdir operations. Set a
3702 * default type for read/write checks. */
3704 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3707 break;
3710 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3712 NTSTATUS status;
3713 size_t param_len = 0;
3714 size_t data_len = total_data;
3716 if (!lp_unix_extensions()) {
3717 reply_nterror(
3718 req,
3719 NT_STATUS_INVALID_LEVEL);
3720 return;
3723 if (lp_smb_encrypt(SNUM(conn)) == false) {
3724 reply_nterror(
3725 req,
3726 NT_STATUS_NOT_SUPPORTED);
3727 return;
3730 if (req->sconn->smb1.echo_handler.trusted_fde) {
3731 DEBUG( 2,("call_trans2setfsinfo: "
3732 "request transport encryption disabled"
3733 "with 'fork echo handler = yes'\n"));
3734 reply_nterror(
3735 req,
3736 NT_STATUS_NOT_SUPPORTED);
3737 return;
3740 DEBUG( 4,("call_trans2setfsinfo: "
3741 "request transport encryption.\n"));
3743 status = srv_request_encryption_setup(conn,
3744 (unsigned char **)ppdata,
3745 &data_len,
3746 (unsigned char **)pparams,
3747 &param_len);
3749 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3750 !NT_STATUS_IS_OK(status)) {
3751 reply_nterror(req, status);
3752 return;
3755 send_trans2_replies(conn, req,
3756 *pparams,
3757 param_len,
3758 *ppdata,
3759 data_len,
3760 max_data_bytes);
3762 if (NT_STATUS_IS_OK(status)) {
3763 /* Server-side transport
3764 * encryption is now *on*. */
3765 status = srv_encryption_start(conn);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 exit_server_cleanly(
3768 "Failure in setting "
3769 "up encrypted transport");
3772 return;
3775 case SMB_FS_QUOTA_INFORMATION:
3777 files_struct *fsp = NULL;
3778 SMB_NTQUOTA_STRUCT quotas;
3780 ZERO_STRUCT(quotas);
3782 /* access check */
3783 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3784 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3785 lp_servicename(SNUM(conn)),
3786 conn->session_info->unix_name));
3787 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3788 return;
3791 /* note: normaly there're 48 bytes,
3792 * but we didn't use the last 6 bytes for now
3793 * --metze
3795 fsp = file_fsp(req, SVAL(params,0));
3797 if (!check_fsp_ntquota_handle(conn, req,
3798 fsp)) {
3799 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3800 reply_nterror(
3801 req, NT_STATUS_INVALID_HANDLE);
3802 return;
3805 if (total_data < 42) {
3806 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3807 total_data));
3808 reply_nterror(
3809 req,
3810 NT_STATUS_INVALID_PARAMETER);
3811 return;
3814 /* unknown_1 24 NULL bytes in pdata*/
3816 /* the soft quotas 8 bytes (uint64_t)*/
3817 quotas.softlim = BVAL(pdata,24);
3819 /* the hard quotas 8 bytes (uint64_t)*/
3820 quotas.hardlim = BVAL(pdata,32);
3822 /* quota_flags 2 bytes **/
3823 quotas.qflags = SVAL(pdata,40);
3825 /* unknown_2 6 NULL bytes follow*/
3827 /* now set the quotas */
3828 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3829 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3830 reply_nterror(req, map_nt_error_from_unix(errno));
3831 return;
3834 break;
3836 default:
3837 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3838 info_level));
3839 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3840 return;
3841 break;
3845 * sending this reply works fine,
3846 * but I'm not sure it's the same
3847 * like windows do...
3848 * --metze
3850 reply_outbuf(req, 10, 0);
3853 #if defined(HAVE_POSIX_ACLS)
3854 /****************************************************************************
3855 Utility function to count the number of entries in a POSIX acl.
3856 ****************************************************************************/
3858 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3860 unsigned int ace_count = 0;
3861 int entry_id = SMB_ACL_FIRST_ENTRY;
3862 SMB_ACL_ENTRY_T entry;
3864 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3865 /* get_next... */
3866 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3867 entry_id = SMB_ACL_NEXT_ENTRY;
3869 ace_count++;
3871 return ace_count;
3874 /****************************************************************************
3875 Utility function to marshall a POSIX acl into wire format.
3876 ****************************************************************************/
3878 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3880 int entry_id = SMB_ACL_FIRST_ENTRY;
3881 SMB_ACL_ENTRY_T entry;
3883 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3884 SMB_ACL_TAG_T tagtype;
3885 SMB_ACL_PERMSET_T permset;
3886 unsigned char perms = 0;
3887 unsigned int own_grp;
3889 /* get_next... */
3890 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3891 entry_id = SMB_ACL_NEXT_ENTRY;
3894 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3895 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3896 return False;
3899 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3900 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3901 return False;
3904 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3905 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3906 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3908 SCVAL(pdata,1,perms);
3910 switch (tagtype) {
3911 case SMB_ACL_USER_OBJ:
3912 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3913 own_grp = (unsigned int)pst->st_ex_uid;
3914 SIVAL(pdata,2,own_grp);
3915 SIVAL(pdata,6,0);
3916 break;
3917 case SMB_ACL_USER:
3919 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3920 if (!puid) {
3921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3922 return False;
3924 own_grp = (unsigned int)*puid;
3925 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3926 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3927 SIVAL(pdata,2,own_grp);
3928 SIVAL(pdata,6,0);
3929 break;
3931 case SMB_ACL_GROUP_OBJ:
3932 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3933 own_grp = (unsigned int)pst->st_ex_gid;
3934 SIVAL(pdata,2,own_grp);
3935 SIVAL(pdata,6,0);
3936 break;
3937 case SMB_ACL_GROUP:
3939 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3940 if (!pgid) {
3941 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3942 return False;
3944 own_grp = (unsigned int)*pgid;
3945 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3946 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3947 SIVAL(pdata,2,own_grp);
3948 SIVAL(pdata,6,0);
3949 break;
3951 case SMB_ACL_MASK:
3952 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3953 SIVAL(pdata,2,0xFFFFFFFF);
3954 SIVAL(pdata,6,0xFFFFFFFF);
3955 break;
3956 case SMB_ACL_OTHER:
3957 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3958 SIVAL(pdata,2,0xFFFFFFFF);
3959 SIVAL(pdata,6,0xFFFFFFFF);
3960 break;
3961 default:
3962 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3963 return False;
3965 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3968 return True;
3970 #endif
3972 /****************************************************************************
3973 Store the FILE_UNIX_BASIC info.
3974 ****************************************************************************/
3976 static char *store_file_unix_basic(connection_struct *conn,
3977 char *pdata,
3978 files_struct *fsp,
3979 const SMB_STRUCT_STAT *psbuf)
3981 uint64_t file_index = get_FileIndex(conn, psbuf);
3983 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3984 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3986 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3987 pdata += 8;
3989 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3990 pdata += 8;
3992 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3993 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3994 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3995 pdata += 24;
3997 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3998 SIVAL(pdata,4,0);
3999 pdata += 8;
4001 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4002 SIVAL(pdata,4,0);
4003 pdata += 8;
4005 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4006 pdata += 4;
4008 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
4009 SIVAL(pdata,4,0);
4010 pdata += 8;
4012 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
4013 SIVAL(pdata,4,0);
4014 pdata += 8;
4016 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4017 pdata += 8;
4019 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4020 SIVAL(pdata,4,0);
4021 pdata += 8;
4023 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4024 SIVAL(pdata,4,0);
4025 pdata += 8;
4027 return pdata;
4030 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4031 * the chflags(2) (or equivalent) flags.
4033 * XXX: this really should be behind the VFS interface. To do this, we would
4034 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4035 * Each VFS module could then implement its own mapping as appropriate for the
4036 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4038 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4039 info2_flags_map[] =
4041 #ifdef UF_NODUMP
4042 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4043 #endif
4045 #ifdef UF_IMMUTABLE
4046 { UF_IMMUTABLE, EXT_IMMUTABLE },
4047 #endif
4049 #ifdef UF_APPEND
4050 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4051 #endif
4053 #ifdef UF_HIDDEN
4054 { UF_HIDDEN, EXT_HIDDEN },
4055 #endif
4057 /* Do not remove. We need to guarantee that this array has at least one
4058 * entry to build on HP-UX.
4060 { 0, 0 }
4064 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4065 uint32 *smb_fflags, uint32 *smb_fmask)
4067 int i;
4069 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4070 *smb_fmask |= info2_flags_map[i].smb_fflag;
4071 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4072 *smb_fflags |= info2_flags_map[i].smb_fflag;
4077 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4078 const uint32 smb_fflags,
4079 const uint32 smb_fmask,
4080 int *stat_fflags)
4082 uint32 max_fmask = 0;
4083 int i;
4085 *stat_fflags = psbuf->st_ex_flags;
4087 /* For each flags requested in smb_fmask, check the state of the
4088 * corresponding flag in smb_fflags and set or clear the matching
4089 * stat flag.
4092 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4093 max_fmask |= info2_flags_map[i].smb_fflag;
4094 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4095 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4096 *stat_fflags |= info2_flags_map[i].stat_fflag;
4097 } else {
4098 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4103 /* If smb_fmask is asking to set any bits that are not supported by
4104 * our flag mappings, we should fail.
4106 if ((smb_fmask & max_fmask) != smb_fmask) {
4107 return False;
4110 return True;
4114 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4115 * of file flags and birth (create) time.
4117 static char *store_file_unix_basic_info2(connection_struct *conn,
4118 char *pdata,
4119 files_struct *fsp,
4120 const SMB_STRUCT_STAT *psbuf)
4122 uint32 file_flags = 0;
4123 uint32 flags_mask = 0;
4125 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4127 /* Create (birth) time 64 bit */
4128 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4129 pdata += 8;
4131 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4132 SIVAL(pdata, 0, file_flags); /* flags */
4133 SIVAL(pdata, 4, flags_mask); /* mask */
4134 pdata += 8;
4136 return pdata;
4139 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4140 const struct stream_struct *streams,
4141 char *data,
4142 unsigned int max_data_bytes,
4143 unsigned int *data_size)
4145 unsigned int i;
4146 unsigned int ofs = 0;
4148 if (max_data_bytes < 32) {
4149 return NT_STATUS_INFO_LENGTH_MISMATCH;
4152 for (i = 0; i < num_streams; i++) {
4153 unsigned int next_offset;
4154 size_t namelen;
4155 smb_ucs2_t *namebuf;
4157 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4158 streams[i].name, &namelen) ||
4159 namelen <= 2)
4161 return NT_STATUS_INVALID_PARAMETER;
4165 * name_buf is now null-terminated, we need to marshall as not
4166 * terminated
4169 namelen -= 2;
4172 * We cannot overflow ...
4174 if ((ofs + 24 + namelen) > max_data_bytes) {
4175 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4176 i));
4177 TALLOC_FREE(namebuf);
4178 return STATUS_BUFFER_OVERFLOW;
4181 SIVAL(data, ofs+4, namelen);
4182 SOFF_T(data, ofs+8, streams[i].size);
4183 SOFF_T(data, ofs+16, streams[i].alloc_size);
4184 memcpy(data+ofs+24, namebuf, namelen);
4185 TALLOC_FREE(namebuf);
4187 next_offset = ofs + 24 + namelen;
4189 if (i == num_streams-1) {
4190 SIVAL(data, ofs, 0);
4192 else {
4193 unsigned int align = ndr_align_size(next_offset, 8);
4195 if ((next_offset + align) > max_data_bytes) {
4196 DEBUG(10, ("refusing to overflow align "
4197 "reply at stream %u\n",
4198 i));
4199 TALLOC_FREE(namebuf);
4200 return STATUS_BUFFER_OVERFLOW;
4203 memset(data+next_offset, 0, align);
4204 next_offset += align;
4206 SIVAL(data, ofs, next_offset - ofs);
4207 ofs = next_offset;
4210 ofs = next_offset;
4213 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4215 *data_size = ofs;
4217 return NT_STATUS_OK;
4220 /****************************************************************************
4221 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4222 ****************************************************************************/
4224 static void call_trans2qpipeinfo(connection_struct *conn,
4225 struct smb_request *req,
4226 unsigned int tran_call,
4227 char **pparams, int total_params,
4228 char **ppdata, int total_data,
4229 unsigned int max_data_bytes)
4231 char *params = *pparams;
4232 char *pdata = *ppdata;
4233 unsigned int data_size = 0;
4234 unsigned int param_size = 2;
4235 uint16 info_level;
4236 files_struct *fsp;
4238 if (!params) {
4239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4240 return;
4243 if (total_params < 4) {
4244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4245 return;
4248 fsp = file_fsp(req, SVAL(params,0));
4249 if (!fsp_is_np(fsp)) {
4250 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4251 return;
4254 info_level = SVAL(params,2);
4256 *pparams = (char *)SMB_REALLOC(*pparams,2);
4257 if (*pparams == NULL) {
4258 reply_nterror(req, NT_STATUS_NO_MEMORY);
4259 return;
4261 params = *pparams;
4262 SSVAL(params,0,0);
4263 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4264 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4265 if (*ppdata == NULL ) {
4266 reply_nterror(req, NT_STATUS_NO_MEMORY);
4267 return;
4269 pdata = *ppdata;
4271 switch (info_level) {
4272 case SMB_FILE_STANDARD_INFORMATION:
4273 memset(pdata,0,24);
4274 SOFF_T(pdata,0,4096LL);
4275 SIVAL(pdata,16,1);
4276 SIVAL(pdata,20,1);
4277 data_size = 24;
4278 break;
4280 default:
4281 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4282 return;
4285 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4286 max_data_bytes);
4288 return;
4291 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4292 TALLOC_CTX *mem_ctx,
4293 uint16_t info_level,
4294 files_struct *fsp,
4295 struct smb_filename *smb_fname,
4296 bool delete_pending,
4297 struct timespec write_time_ts,
4298 struct ea_list *ea_list,
4299 int lock_data_count,
4300 char *lock_data,
4301 uint16_t flags2,
4302 unsigned int max_data_bytes,
4303 size_t *fixed_portion,
4304 char **ppdata,
4305 unsigned int *pdata_size)
4307 char *pdata = *ppdata;
4308 char *dstart, *dend;
4309 unsigned int data_size;
4310 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4311 time_t create_time, mtime, atime, c_time;
4312 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4313 char *p;
4314 char *base_name;
4315 char *dos_fname;
4316 int mode;
4317 int nlink;
4318 NTSTATUS status;
4319 uint64_t file_size = 0;
4320 uint64_t pos = 0;
4321 uint64_t allocation_size = 0;
4322 uint64_t file_index = 0;
4323 uint32_t access_mask = 0;
4325 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4326 return NT_STATUS_INVALID_LEVEL;
4329 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4330 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4331 info_level, max_data_bytes));
4333 mode = dos_mode(conn, smb_fname);
4334 nlink = psbuf->st_ex_nlink;
4336 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4337 nlink = 1;
4340 if ((nlink > 0) && delete_pending) {
4341 nlink -= 1;
4344 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4345 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4346 if (*ppdata == NULL) {
4347 return NT_STATUS_NO_MEMORY;
4349 pdata = *ppdata;
4350 dstart = pdata;
4351 dend = dstart + data_size - 1;
4353 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4354 update_stat_ex_mtime(psbuf, write_time_ts);
4357 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4358 mtime_ts = psbuf->st_ex_mtime;
4359 atime_ts = psbuf->st_ex_atime;
4360 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4362 if (lp_dos_filetime_resolution(SNUM(conn))) {
4363 dos_filetime_timespec(&create_time_ts);
4364 dos_filetime_timespec(&mtime_ts);
4365 dos_filetime_timespec(&atime_ts);
4366 dos_filetime_timespec(&ctime_ts);
4369 create_time = convert_timespec_to_time_t(create_time_ts);
4370 mtime = convert_timespec_to_time_t(mtime_ts);
4371 atime = convert_timespec_to_time_t(atime_ts);
4372 c_time = convert_timespec_to_time_t(ctime_ts);
4374 p = strrchr_m(smb_fname->base_name,'/');
4375 if (!p)
4376 base_name = smb_fname->base_name;
4377 else
4378 base_name = p+1;
4380 /* NT expects the name to be in an exact form of the *full*
4381 filename. See the trans2 torture test */
4382 if (ISDOT(base_name)) {
4383 dos_fname = talloc_strdup(mem_ctx, "\\");
4384 if (!dos_fname) {
4385 return NT_STATUS_NO_MEMORY;
4387 } else {
4388 dos_fname = talloc_asprintf(mem_ctx,
4389 "\\%s",
4390 smb_fname->base_name);
4391 if (!dos_fname) {
4392 return NT_STATUS_NO_MEMORY;
4394 if (is_ntfs_stream_smb_fname(smb_fname)) {
4395 dos_fname = talloc_asprintf(dos_fname, "%s",
4396 smb_fname->stream_name);
4397 if (!dos_fname) {
4398 return NT_STATUS_NO_MEMORY;
4402 string_replace(dos_fname, '/', '\\');
4405 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4407 if (!fsp) {
4408 /* Do we have this path open ? */
4409 files_struct *fsp1;
4410 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4411 fsp1 = file_find_di_first(conn->sconn, fileid);
4412 if (fsp1 && fsp1->initial_allocation_size) {
4413 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4417 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4418 file_size = get_file_size_stat(psbuf);
4421 if (fsp) {
4422 pos = fsp->fh->position_information;
4425 if (fsp) {
4426 access_mask = fsp->access_mask;
4427 } else {
4428 /* GENERIC_EXECUTE mapping from Windows */
4429 access_mask = 0x12019F;
4432 /* This should be an index number - looks like
4433 dev/ino to me :-)
4435 I think this causes us to fail the IFSKIT
4436 BasicFileInformationTest. -tpot */
4437 file_index = get_FileIndex(conn, psbuf);
4439 *fixed_portion = 0;
4441 switch (info_level) {
4442 case SMB_INFO_STANDARD:
4443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4444 data_size = 22;
4445 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4446 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4447 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4448 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4449 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4450 SSVAL(pdata,l1_attrFile,mode);
4451 break;
4453 case SMB_INFO_QUERY_EA_SIZE:
4455 unsigned int ea_size =
4456 estimate_ea_size(conn, fsp,
4457 smb_fname->base_name);
4458 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4459 data_size = 26;
4460 srv_put_dos_date2(pdata,0,create_time);
4461 srv_put_dos_date2(pdata,4,atime);
4462 srv_put_dos_date2(pdata,8,mtime); /* write time */
4463 SIVAL(pdata,12,(uint32)file_size);
4464 SIVAL(pdata,16,(uint32)allocation_size);
4465 SSVAL(pdata,20,mode);
4466 SIVAL(pdata,22,ea_size);
4467 break;
4470 case SMB_INFO_IS_NAME_VALID:
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4472 if (fsp) {
4473 /* os/2 needs this ? really ?*/
4474 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4476 /* This is only reached for qpathinfo */
4477 data_size = 0;
4478 break;
4480 case SMB_INFO_QUERY_EAS_FROM_LIST:
4482 size_t total_ea_len = 0;
4483 struct ea_list *ea_file_list = NULL;
4485 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4487 ea_file_list =
4488 get_ea_list_from_file(mem_ctx, conn, fsp,
4489 smb_fname->base_name,
4490 &total_ea_len);
4491 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4493 if (!ea_list || (total_ea_len > data_size)) {
4494 data_size = 4;
4495 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4496 break;
4499 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4500 break;
4503 case SMB_INFO_QUERY_ALL_EAS:
4505 /* We have data_size bytes to put EA's into. */
4506 size_t total_ea_len = 0;
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4510 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4511 smb_fname->base_name,
4512 &total_ea_len);
4513 if (!ea_list || (total_ea_len > data_size)) {
4514 data_size = 4;
4515 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4516 break;
4519 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4520 break;
4523 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4525 /* This is FileFullEaInformation - 0xF which maps to
4526 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4528 /* We have data_size bytes to put EA's into. */
4529 size_t total_ea_len = 0;
4530 struct ea_list *ea_file_list = NULL;
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4534 /*TODO: add filtering and index handling */
4536 ea_file_list =
4537 get_ea_list_from_file(mem_ctx, conn, fsp,
4538 smb_fname->base_name,
4539 &total_ea_len);
4540 if (!ea_file_list) {
4541 return NT_STATUS_NO_EAS_ON_FILE;
4544 status = fill_ea_chained_buffer(mem_ctx,
4545 pdata,
4546 data_size,
4547 &data_size,
4548 conn, ea_file_list);
4549 if (!NT_STATUS_IS_OK(status)) {
4550 return status;
4552 break;
4555 case SMB_FILE_BASIC_INFORMATION:
4556 case SMB_QUERY_FILE_BASIC_INFO:
4558 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4560 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4561 } else {
4562 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4563 data_size = 40;
4564 SIVAL(pdata,36,0);
4566 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4567 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4568 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4569 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4570 SIVAL(pdata,32,mode);
4572 DEBUG(5,("SMB_QFBI - "));
4573 DEBUG(5,("create: %s ", ctime(&create_time)));
4574 DEBUG(5,("access: %s ", ctime(&atime)));
4575 DEBUG(5,("write: %s ", ctime(&mtime)));
4576 DEBUG(5,("change: %s ", ctime(&c_time)));
4577 DEBUG(5,("mode: %x\n", mode));
4578 *fixed_portion = data_size;
4579 break;
4581 case SMB_FILE_STANDARD_INFORMATION:
4582 case SMB_QUERY_FILE_STANDARD_INFO:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4585 data_size = 24;
4586 SOFF_T(pdata,0,allocation_size);
4587 SOFF_T(pdata,8,file_size);
4588 SIVAL(pdata,16,nlink);
4589 SCVAL(pdata,20,delete_pending?1:0);
4590 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4591 SSVAL(pdata,22,0); /* Padding. */
4592 *fixed_portion = 24;
4593 break;
4595 case SMB_FILE_EA_INFORMATION:
4596 case SMB_QUERY_FILE_EA_INFO:
4598 unsigned int ea_size =
4599 estimate_ea_size(conn, fsp, smb_fname->base_name);
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4601 data_size = 4;
4602 *fixed_portion = 4;
4603 SIVAL(pdata,0,ea_size);
4604 break;
4607 /* Get the 8.3 name - used if NT SMB was negotiated. */
4608 case SMB_QUERY_FILE_ALT_NAME_INFO:
4609 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4611 int len;
4612 char mangled_name[13];
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4614 if (!name_to_8_3(base_name,mangled_name,
4615 True,conn->params)) {
4616 return NT_STATUS_NO_MEMORY;
4618 len = srvstr_push(dstart, flags2,
4619 pdata+4, mangled_name,
4620 PTR_DIFF(dend, pdata+4),
4621 STR_UNICODE);
4622 data_size = 4 + len;
4623 SIVAL(pdata,0,len);
4624 *fixed_portion = 8;
4625 break;
4628 case SMB_QUERY_FILE_NAME_INFO:
4630 int len;
4632 this must be *exactly* right for ACLs on mapped drives to work
4634 len = srvstr_push(dstart, flags2,
4635 pdata+4, dos_fname,
4636 PTR_DIFF(dend, pdata+4),
4637 STR_UNICODE);
4638 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4639 data_size = 4 + len;
4640 SIVAL(pdata,0,len);
4641 break;
4644 case SMB_FILE_ALLOCATION_INFORMATION:
4645 case SMB_QUERY_FILE_ALLOCATION_INFO:
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4647 data_size = 8;
4648 SOFF_T(pdata,0,allocation_size);
4649 break;
4651 case SMB_FILE_END_OF_FILE_INFORMATION:
4652 case SMB_QUERY_FILE_END_OF_FILEINFO:
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4654 data_size = 8;
4655 SOFF_T(pdata,0,file_size);
4656 break;
4658 case SMB_QUERY_FILE_ALL_INFO:
4659 case SMB_FILE_ALL_INFORMATION:
4661 int len;
4662 unsigned int ea_size =
4663 estimate_ea_size(conn, fsp, smb_fname->base_name);
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4665 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4666 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4667 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4668 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4669 SIVAL(pdata,32,mode);
4670 SIVAL(pdata,36,0); /* padding. */
4671 pdata += 40;
4672 SOFF_T(pdata,0,allocation_size);
4673 SOFF_T(pdata,8,file_size);
4674 SIVAL(pdata,16,nlink);
4675 SCVAL(pdata,20,delete_pending);
4676 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4677 SSVAL(pdata,22,0);
4678 pdata += 24;
4679 SIVAL(pdata,0,ea_size);
4680 pdata += 4; /* EA info */
4681 len = srvstr_push(dstart, flags2,
4682 pdata+4, dos_fname,
4683 PTR_DIFF(dend, pdata+4),
4684 STR_UNICODE);
4685 SIVAL(pdata,0,len);
4686 pdata += 4 + len;
4687 data_size = PTR_DIFF(pdata,(*ppdata));
4688 *fixed_portion = 10;
4689 break;
4692 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4694 int len;
4695 unsigned int ea_size =
4696 estimate_ea_size(conn, fsp, smb_fname->base_name);
4697 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4698 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4699 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4700 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4701 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4702 SIVAL(pdata, 0x20, mode);
4703 SIVAL(pdata, 0x24, 0); /* padding. */
4704 SBVAL(pdata, 0x28, allocation_size);
4705 SBVAL(pdata, 0x30, file_size);
4706 SIVAL(pdata, 0x38, nlink);
4707 SCVAL(pdata, 0x3C, delete_pending);
4708 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4709 SSVAL(pdata, 0x3E, 0); /* padding */
4710 SBVAL(pdata, 0x40, file_index);
4711 SIVAL(pdata, 0x48, ea_size);
4712 SIVAL(pdata, 0x4C, access_mask);
4713 SBVAL(pdata, 0x50, pos);
4714 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4715 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4717 pdata += 0x60;
4719 len = srvstr_push(dstart, flags2,
4720 pdata+4, dos_fname,
4721 PTR_DIFF(dend, pdata+4),
4722 STR_UNICODE);
4723 SIVAL(pdata,0,len);
4724 pdata += 4 + len;
4725 data_size = PTR_DIFF(pdata,(*ppdata));
4726 *fixed_portion = 104;
4727 break;
4729 case SMB_FILE_INTERNAL_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4732 SBVAL(pdata, 0, file_index);
4733 data_size = 8;
4734 *fixed_portion = 8;
4735 break;
4737 case SMB_FILE_ACCESS_INFORMATION:
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4739 SIVAL(pdata, 0, access_mask);
4740 data_size = 4;
4741 *fixed_portion = 4;
4742 break;
4744 case SMB_FILE_NAME_INFORMATION:
4745 /* Pathname with leading '\'. */
4747 size_t byte_len;
4748 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4750 SIVAL(pdata,0,byte_len);
4751 data_size = 4 + byte_len;
4752 break;
4755 case SMB_FILE_DISPOSITION_INFORMATION:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4757 data_size = 1;
4758 SCVAL(pdata,0,delete_pending);
4759 *fixed_portion = 1;
4760 break;
4762 case SMB_FILE_POSITION_INFORMATION:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4764 data_size = 8;
4765 SOFF_T(pdata,0,pos);
4766 *fixed_portion = 8;
4767 break;
4769 case SMB_FILE_MODE_INFORMATION:
4770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4771 SIVAL(pdata,0,mode);
4772 data_size = 4;
4773 *fixed_portion = 4;
4774 break;
4776 case SMB_FILE_ALIGNMENT_INFORMATION:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4778 SIVAL(pdata,0,0); /* No alignment needed. */
4779 data_size = 4;
4780 *fixed_portion = 4;
4781 break;
4784 * NT4 server just returns "invalid query" to this - if we try
4785 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4786 * want this. JRA.
4788 /* The first statement above is false - verified using Thursby
4789 * client against NT4 -- gcolley.
4791 case SMB_QUERY_FILE_STREAM_INFO:
4792 case SMB_FILE_STREAM_INFORMATION: {
4793 unsigned int num_streams = 0;
4794 struct stream_struct *streams = NULL;
4796 DEBUG(10,("smbd_do_qfilepathinfo: "
4797 "SMB_FILE_STREAM_INFORMATION\n"));
4799 if (is_ntfs_stream_smb_fname(smb_fname)) {
4800 return NT_STATUS_INVALID_PARAMETER;
4803 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4804 talloc_tos(), &num_streams, &streams);
4806 if (!NT_STATUS_IS_OK(status)) {
4807 DEBUG(10, ("could not get stream info: %s\n",
4808 nt_errstr(status)));
4809 return status;
4812 status = marshall_stream_info(num_streams, streams,
4813 pdata, max_data_bytes,
4814 &data_size);
4816 if (!NT_STATUS_IS_OK(status)) {
4817 DEBUG(10, ("marshall_stream_info failed: %s\n",
4818 nt_errstr(status)));
4819 TALLOC_FREE(streams);
4820 return status;
4823 TALLOC_FREE(streams);
4825 *fixed_portion = 32;
4827 break;
4829 case SMB_QUERY_COMPRESSION_INFO:
4830 case SMB_FILE_COMPRESSION_INFORMATION:
4831 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4832 SOFF_T(pdata,0,file_size);
4833 SIVAL(pdata,8,0); /* ??? */
4834 SIVAL(pdata,12,0); /* ??? */
4835 data_size = 16;
4836 *fixed_portion = 16;
4837 break;
4839 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4841 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4842 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4843 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4844 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4845 SOFF_T(pdata,32,allocation_size);
4846 SOFF_T(pdata,40,file_size);
4847 SIVAL(pdata,48,mode);
4848 SIVAL(pdata,52,0); /* ??? */
4849 data_size = 56;
4850 *fixed_portion = 56;
4851 break;
4853 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4855 SIVAL(pdata,0,mode);
4856 SIVAL(pdata,4,0);
4857 data_size = 8;
4858 *fixed_portion = 8;
4859 break;
4862 * CIFS UNIX Extensions.
4865 case SMB_QUERY_FILE_UNIX_BASIC:
4867 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4868 data_size = PTR_DIFF(pdata,(*ppdata));
4870 DEBUG(4,("smbd_do_qfilepathinfo: "
4871 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4872 dump_data(4, (uint8_t *)(*ppdata), data_size);
4874 break;
4876 case SMB_QUERY_FILE_UNIX_INFO2:
4878 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4879 data_size = PTR_DIFF(pdata,(*ppdata));
4882 int i;
4883 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4885 for (i=0; i<100; i++)
4886 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4887 DEBUG(4,("\n"));
4890 break;
4892 case SMB_QUERY_FILE_UNIX_LINK:
4894 int len;
4895 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4897 if (!buffer) {
4898 return NT_STATUS_NO_MEMORY;
4901 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4902 #ifdef S_ISLNK
4903 if(!S_ISLNK(psbuf->st_ex_mode)) {
4904 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4906 #else
4907 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4908 #endif
4909 len = SMB_VFS_READLINK(conn,
4910 smb_fname->base_name,
4911 buffer, PATH_MAX);
4912 if (len == -1) {
4913 return map_nt_error_from_unix(errno);
4915 buffer[len] = 0;
4916 len = srvstr_push(dstart, flags2,
4917 pdata, buffer,
4918 PTR_DIFF(dend, pdata),
4919 STR_TERMINATE);
4920 pdata += len;
4921 data_size = PTR_DIFF(pdata,(*ppdata));
4923 break;
4926 #if defined(HAVE_POSIX_ACLS)
4927 case SMB_QUERY_POSIX_ACL:
4929 SMB_ACL_T file_acl = NULL;
4930 SMB_ACL_T def_acl = NULL;
4931 uint16 num_file_acls = 0;
4932 uint16 num_def_acls = 0;
4934 if (fsp && fsp->fh->fd != -1) {
4935 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4936 } else {
4937 file_acl =
4938 SMB_VFS_SYS_ACL_GET_FILE(conn,
4939 smb_fname->base_name,
4940 SMB_ACL_TYPE_ACCESS);
4943 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4944 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4945 "not implemented on "
4946 "filesystem containing %s\n",
4947 smb_fname->base_name));
4948 return NT_STATUS_NOT_IMPLEMENTED;
4951 if (S_ISDIR(psbuf->st_ex_mode)) {
4952 if (fsp && fsp->is_directory) {
4953 def_acl =
4954 SMB_VFS_SYS_ACL_GET_FILE(
4955 conn,
4956 fsp->fsp_name->base_name,
4957 SMB_ACL_TYPE_DEFAULT);
4958 } else {
4959 def_acl =
4960 SMB_VFS_SYS_ACL_GET_FILE(
4961 conn,
4962 smb_fname->base_name,
4963 SMB_ACL_TYPE_DEFAULT);
4965 def_acl = free_empty_sys_acl(conn, def_acl);
4968 num_file_acls = count_acl_entries(conn, file_acl);
4969 num_def_acls = count_acl_entries(conn, def_acl);
4971 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4972 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4973 data_size,
4974 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4975 SMB_POSIX_ACL_HEADER_SIZE) ));
4976 if (file_acl) {
4977 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4979 if (def_acl) {
4980 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4982 return NT_STATUS_BUFFER_TOO_SMALL;
4985 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4986 SSVAL(pdata,2,num_file_acls);
4987 SSVAL(pdata,4,num_def_acls);
4988 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4989 if (file_acl) {
4990 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4992 if (def_acl) {
4993 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4995 return NT_STATUS_INTERNAL_ERROR;
4997 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4998 if (file_acl) {
4999 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
5001 if (def_acl) {
5002 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
5004 return NT_STATUS_INTERNAL_ERROR;
5007 if (file_acl) {
5008 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
5010 if (def_acl) {
5011 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
5013 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5014 break;
5016 #endif
5019 case SMB_QUERY_POSIX_LOCK:
5021 uint64_t count;
5022 uint64_t offset;
5023 uint64_t smblctx;
5024 enum brl_type lock_type;
5026 /* We need an open file with a real fd for this. */
5027 if (!fsp || fsp->fh->fd == -1) {
5028 return NT_STATUS_INVALID_LEVEL;
5031 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5032 return NT_STATUS_INVALID_PARAMETER;
5035 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5036 case POSIX_LOCK_TYPE_READ:
5037 lock_type = READ_LOCK;
5038 break;
5039 case POSIX_LOCK_TYPE_WRITE:
5040 lock_type = WRITE_LOCK;
5041 break;
5042 case POSIX_LOCK_TYPE_UNLOCK:
5043 default:
5044 /* There's no point in asking for an unlock... */
5045 return NT_STATUS_INVALID_PARAMETER;
5048 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5049 #if defined(HAVE_LONGLONG)
5050 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5051 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5052 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5053 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5054 #else /* HAVE_LONGLONG */
5055 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5056 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5057 #endif /* HAVE_LONGLONG */
5059 status = query_lock(fsp,
5060 &smblctx,
5061 &count,
5062 &offset,
5063 &lock_type,
5064 POSIX_LOCK);
5066 if (ERROR_WAS_LOCK_DENIED(status)) {
5067 /* Here we need to report who has it locked... */
5068 data_size = POSIX_LOCK_DATA_SIZE;
5070 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5071 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5072 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5073 #if defined(HAVE_LONGLONG)
5074 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5075 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5076 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5077 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5078 #else /* HAVE_LONGLONG */
5079 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5080 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5081 #endif /* HAVE_LONGLONG */
5083 } else if (NT_STATUS_IS_OK(status)) {
5084 /* For success we just return a copy of what we sent
5085 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5086 data_size = POSIX_LOCK_DATA_SIZE;
5087 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5088 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5089 } else {
5090 return status;
5092 break;
5095 default:
5096 return NT_STATUS_INVALID_LEVEL;
5099 *pdata_size = data_size;
5100 return NT_STATUS_OK;
5103 /****************************************************************************
5104 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5105 file name or file id).
5106 ****************************************************************************/
5108 static void call_trans2qfilepathinfo(connection_struct *conn,
5109 struct smb_request *req,
5110 unsigned int tran_call,
5111 char **pparams, int total_params,
5112 char **ppdata, int total_data,
5113 unsigned int max_data_bytes)
5115 char *params = *pparams;
5116 char *pdata = *ppdata;
5117 uint16 info_level;
5118 unsigned int data_size = 0;
5119 unsigned int param_size = 2;
5120 struct smb_filename *smb_fname = NULL;
5121 bool delete_pending = False;
5122 struct timespec write_time_ts;
5123 files_struct *fsp = NULL;
5124 struct file_id fileid;
5125 struct ea_list *ea_list = NULL;
5126 int lock_data_count = 0;
5127 char *lock_data = NULL;
5128 size_t fixed_portion;
5129 NTSTATUS status = NT_STATUS_OK;
5131 if (!params) {
5132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133 return;
5136 ZERO_STRUCT(write_time_ts);
5138 if (tran_call == TRANSACT2_QFILEINFO) {
5139 if (total_params < 4) {
5140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5141 return;
5144 if (IS_IPC(conn)) {
5145 call_trans2qpipeinfo(conn, req, tran_call,
5146 pparams, total_params,
5147 ppdata, total_data,
5148 max_data_bytes);
5149 return;
5152 fsp = file_fsp(req, SVAL(params,0));
5153 info_level = SVAL(params,2);
5155 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5157 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5158 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5159 return;
5162 /* Initial check for valid fsp ptr. */
5163 if (!check_fsp_open(conn, req, fsp)) {
5164 return;
5167 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5168 &smb_fname);
5169 if (!NT_STATUS_IS_OK(status)) {
5170 reply_nterror(req, status);
5171 return;
5174 if(fsp->fake_file_handle) {
5176 * This is actually for the QUOTA_FAKE_FILE --metze
5179 /* We know this name is ok, it's already passed the checks. */
5181 } else if(fsp->fh->fd == -1) {
5183 * This is actually a QFILEINFO on a directory
5184 * handle (returned from an NT SMB). NT5.0 seems
5185 * to do this call. JRA.
5188 if (INFO_LEVEL_IS_UNIX(info_level)) {
5189 /* Always do lstat for UNIX calls. */
5190 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5191 DEBUG(3,("call_trans2qfilepathinfo: "
5192 "SMB_VFS_LSTAT of %s failed "
5193 "(%s)\n",
5194 smb_fname_str_dbg(smb_fname),
5195 strerror(errno)));
5196 reply_nterror(req,
5197 map_nt_error_from_unix(errno));
5198 return;
5200 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5201 DEBUG(3,("call_trans2qfilepathinfo: "
5202 "SMB_VFS_STAT of %s failed (%s)\n",
5203 smb_fname_str_dbg(smb_fname),
5204 strerror(errno)));
5205 reply_nterror(req,
5206 map_nt_error_from_unix(errno));
5207 return;
5210 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5211 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5212 } else {
5214 * Original code - this is an open file.
5216 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5217 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5218 fsp->fnum, strerror(errno)));
5219 reply_nterror(req,
5220 map_nt_error_from_unix(errno));
5221 return;
5223 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5224 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5227 } else {
5228 uint32_t name_hash;
5229 char *fname = NULL;
5230 uint32_t ucf_flags = 0;
5232 /* qpathinfo */
5233 if (total_params < 7) {
5234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5235 return;
5238 info_level = SVAL(params,0);
5240 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5242 if (INFO_LEVEL_IS_UNIX(info_level)) {
5243 if (!lp_unix_extensions()) {
5244 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5245 return;
5247 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5248 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5249 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5250 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5254 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5255 total_params - 6,
5256 STR_TERMINATE, &status);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 reply_nterror(req, status);
5259 return;
5262 status = filename_convert(req,
5263 conn,
5264 req->flags2 & FLAGS2_DFS_PATHNAMES,
5265 fname,
5266 ucf_flags,
5267 NULL,
5268 &smb_fname);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5271 reply_botherror(req,
5272 NT_STATUS_PATH_NOT_COVERED,
5273 ERRSRV, ERRbadpath);
5274 return;
5276 reply_nterror(req, status);
5277 return;
5280 /* If this is a stream, check if there is a delete_pending. */
5281 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5282 && is_ntfs_stream_smb_fname(smb_fname)) {
5283 struct smb_filename *smb_fname_base = NULL;
5285 /* Create an smb_filename with stream_name == NULL. */
5286 status =
5287 create_synthetic_smb_fname(talloc_tos(),
5288 smb_fname->base_name,
5289 NULL, NULL,
5290 &smb_fname_base);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 reply_nterror(req, status);
5293 return;
5296 if (INFO_LEVEL_IS_UNIX(info_level)) {
5297 /* Always do lstat for UNIX calls. */
5298 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_LSTAT of %s failed "
5301 "(%s)\n",
5302 smb_fname_str_dbg(smb_fname_base),
5303 strerror(errno)));
5304 TALLOC_FREE(smb_fname_base);
5305 reply_nterror(req,
5306 map_nt_error_from_unix(errno));
5307 return;
5309 } else {
5310 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "fileinfo of %s failed "
5313 "(%s)\n",
5314 smb_fname_str_dbg(smb_fname_base),
5315 strerror(errno)));
5316 TALLOC_FREE(smb_fname_base);
5317 reply_nterror(req,
5318 map_nt_error_from_unix(errno));
5319 return;
5323 status = file_name_hash(conn,
5324 smb_fname_str_dbg(smb_fname_base),
5325 &name_hash);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 TALLOC_FREE(smb_fname_base);
5328 reply_nterror(req, status);
5329 return;
5332 fileid = vfs_file_id_from_sbuf(conn,
5333 &smb_fname_base->st);
5334 TALLOC_FREE(smb_fname_base);
5335 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5336 if (delete_pending) {
5337 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5338 return;
5342 if (INFO_LEVEL_IS_UNIX(info_level)) {
5343 /* Always do lstat for UNIX calls. */
5344 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5345 DEBUG(3,("call_trans2qfilepathinfo: "
5346 "SMB_VFS_LSTAT of %s failed (%s)\n",
5347 smb_fname_str_dbg(smb_fname),
5348 strerror(errno)));
5349 reply_nterror(req,
5350 map_nt_error_from_unix(errno));
5351 return;
5354 } else {
5355 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5356 DEBUG(3,("call_trans2qfilepathinfo: "
5357 "SMB_VFS_STAT of %s failed (%s)\n",
5358 smb_fname_str_dbg(smb_fname),
5359 strerror(errno)));
5360 reply_nterror(req,
5361 map_nt_error_from_unix(errno));
5362 return;
5366 status = file_name_hash(conn,
5367 smb_fname_str_dbg(smb_fname),
5368 &name_hash);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 reply_nterror(req, status);
5371 return;
5374 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5375 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5376 if (delete_pending) {
5377 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5378 return;
5382 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5383 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5384 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5386 /* Pull out any data sent here before we realloc. */
5387 switch (info_level) {
5388 case SMB_INFO_QUERY_EAS_FROM_LIST:
5390 /* Pull any EA list from the data portion. */
5391 uint32 ea_size;
5393 if (total_data < 4) {
5394 reply_nterror(
5395 req, NT_STATUS_INVALID_PARAMETER);
5396 return;
5398 ea_size = IVAL(pdata,0);
5400 if (total_data > 0 && ea_size != total_data) {
5401 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5402 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5403 reply_nterror(
5404 req, NT_STATUS_INVALID_PARAMETER);
5405 return;
5408 if (!lp_ea_support(SNUM(conn))) {
5409 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5410 return;
5413 /* Pull out the list of names. */
5414 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5415 if (!ea_list) {
5416 reply_nterror(
5417 req, NT_STATUS_INVALID_PARAMETER);
5418 return;
5420 break;
5423 case SMB_QUERY_POSIX_LOCK:
5425 if (fsp == NULL || fsp->fh->fd == -1) {
5426 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5427 return;
5430 if (total_data != POSIX_LOCK_DATA_SIZE) {
5431 reply_nterror(
5432 req, NT_STATUS_INVALID_PARAMETER);
5433 return;
5436 /* Copy the lock range data. */
5437 lock_data = (char *)TALLOC_MEMDUP(
5438 req, pdata, total_data);
5439 if (!lock_data) {
5440 reply_nterror(req, NT_STATUS_NO_MEMORY);
5441 return;
5443 lock_data_count = total_data;
5445 default:
5446 break;
5449 *pparams = (char *)SMB_REALLOC(*pparams,2);
5450 if (*pparams == NULL) {
5451 reply_nterror(req, NT_STATUS_NO_MEMORY);
5452 return;
5454 params = *pparams;
5455 SSVAL(params,0,0);
5458 * draft-leach-cifs-v1-spec-02.txt
5459 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5460 * says:
5462 * The requested information is placed in the Data portion of the
5463 * transaction response. For the information levels greater than 0x100,
5464 * the transaction response has 1 parameter word which should be
5465 * ignored by the client.
5467 * However Windows only follows this rule for the IS_NAME_VALID call.
5469 switch (info_level) {
5470 case SMB_INFO_IS_NAME_VALID:
5471 param_size = 0;
5472 break;
5475 if ((info_level & 0xFF00) == 0xFF00) {
5477 * We use levels that start with 0xFF00
5478 * internally to represent SMB2 specific levels
5480 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5481 return;
5484 status = smbd_do_qfilepathinfo(conn, req, info_level,
5485 fsp, smb_fname,
5486 delete_pending, write_time_ts,
5487 ea_list,
5488 lock_data_count, lock_data,
5489 req->flags2, max_data_bytes,
5490 &fixed_portion,
5491 ppdata, &data_size);
5492 if (!NT_STATUS_IS_OK(status)) {
5493 reply_nterror(req, status);
5494 return;
5497 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5498 max_data_bytes);
5500 return;
5503 /****************************************************************************
5504 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5505 code.
5506 ****************************************************************************/
5508 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5509 connection_struct *conn,
5510 struct smb_request *req,
5511 bool overwrite_if_exists,
5512 const struct smb_filename *smb_fname_old,
5513 struct smb_filename *smb_fname_new)
5515 NTSTATUS status = NT_STATUS_OK;
5517 /* source must already exist. */
5518 if (!VALID_STAT(smb_fname_old->st)) {
5519 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5522 if (VALID_STAT(smb_fname_new->st)) {
5523 if (overwrite_if_exists) {
5524 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5525 return NT_STATUS_FILE_IS_A_DIRECTORY;
5527 status = unlink_internals(conn,
5528 req,
5529 FILE_ATTRIBUTE_NORMAL,
5530 smb_fname_new,
5531 false);
5532 if (!NT_STATUS_IS_OK(status)) {
5533 return status;
5535 } else {
5536 /* Disallow if newname already exists. */
5537 return NT_STATUS_OBJECT_NAME_COLLISION;
5541 /* No links from a directory. */
5542 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5543 return NT_STATUS_FILE_IS_A_DIRECTORY;
5546 /* Setting a hardlink to/from a stream isn't currently supported. */
5547 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5548 is_ntfs_stream_smb_fname(smb_fname_new)) {
5549 return NT_STATUS_INVALID_PARAMETER;
5552 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5553 smb_fname_old->base_name, smb_fname_new->base_name));
5555 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5556 smb_fname_new->base_name) != 0) {
5557 status = map_nt_error_from_unix(errno);
5558 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5559 nt_errstr(status), smb_fname_old->base_name,
5560 smb_fname_new->base_name));
5562 return status;
5565 /****************************************************************************
5566 Deal with setting the time from any of the setfilepathinfo functions.
5567 ****************************************************************************/
5569 NTSTATUS smb_set_file_time(connection_struct *conn,
5570 files_struct *fsp,
5571 const struct smb_filename *smb_fname,
5572 struct smb_file_time *ft,
5573 bool setting_write_time)
5575 struct smb_filename smb_fname_base;
5576 uint32 action =
5577 FILE_NOTIFY_CHANGE_LAST_ACCESS
5578 |FILE_NOTIFY_CHANGE_LAST_WRITE
5579 |FILE_NOTIFY_CHANGE_CREATION;
5581 if (!VALID_STAT(smb_fname->st)) {
5582 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5585 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5586 return NT_STATUS_ACCESS_DENIED;
5589 /* get some defaults (no modifications) if any info is zero or -1. */
5590 if (null_timespec(ft->create_time)) {
5591 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5594 if (null_timespec(ft->atime)) {
5595 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5598 if (null_timespec(ft->mtime)) {
5599 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5602 if (!setting_write_time) {
5603 /* ft->mtime comes from change time, not write time. */
5604 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5607 /* Ensure the resolution is the correct for
5608 * what we can store on this filesystem. */
5610 round_timespec(conn->ts_res, &ft->create_time);
5611 round_timespec(conn->ts_res, &ft->ctime);
5612 round_timespec(conn->ts_res, &ft->atime);
5613 round_timespec(conn->ts_res, &ft->mtime);
5615 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5616 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5617 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5618 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5619 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5620 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5621 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5622 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5624 if (setting_write_time) {
5626 * This was a Windows setfileinfo on an open file.
5627 * NT does this a lot. We also need to
5628 * set the time here, as it can be read by
5629 * FindFirst/FindNext and with the patch for bug #2045
5630 * in smbd/fileio.c it ensures that this timestamp is
5631 * kept sticky even after a write. We save the request
5632 * away and will set it on file close and after a write. JRA.
5635 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5636 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5638 if (fsp != NULL) {
5639 if (fsp->base_fsp) {
5640 set_sticky_write_time_fsp(fsp->base_fsp,
5641 ft->mtime);
5642 } else {
5643 set_sticky_write_time_fsp(fsp, ft->mtime);
5645 } else {
5646 set_sticky_write_time_path(
5647 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5648 ft->mtime);
5652 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5654 /* Always call ntimes on the base, even if a stream was passed in. */
5655 smb_fname_base = *smb_fname;
5656 smb_fname_base.stream_name = NULL;
5658 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5659 return map_nt_error_from_unix(errno);
5662 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5663 smb_fname->base_name);
5664 return NT_STATUS_OK;
5667 /****************************************************************************
5668 Deal with setting the dosmode from any of the setfilepathinfo functions.
5669 ****************************************************************************/
5671 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5672 const struct smb_filename *smb_fname,
5673 uint32 dosmode)
5675 struct smb_filename *smb_fname_base = NULL;
5676 NTSTATUS status;
5678 if (!VALID_STAT(smb_fname->st)) {
5679 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5682 /* Always operate on the base_name, even if a stream was passed in. */
5683 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5684 NULL, &smb_fname->st,
5685 &smb_fname_base);
5686 if (!NT_STATUS_IS_OK(status)) {
5687 return status;
5690 if (dosmode) {
5691 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5692 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5693 } else {
5694 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5698 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5700 /* check the mode isn't different, before changing it */
5701 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5702 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5703 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5704 (unsigned int)dosmode));
5706 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5707 false)) {
5708 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5709 "%s failed (%s)\n",
5710 smb_fname_str_dbg(smb_fname_base),
5711 strerror(errno)));
5712 status = map_nt_error_from_unix(errno);
5713 goto out;
5716 status = NT_STATUS_OK;
5717 out:
5718 TALLOC_FREE(smb_fname_base);
5719 return status;
5722 /****************************************************************************
5723 Deal with setting the size from any of the setfilepathinfo functions.
5724 ****************************************************************************/
5726 static NTSTATUS smb_set_file_size(connection_struct *conn,
5727 struct smb_request *req,
5728 files_struct *fsp,
5729 const struct smb_filename *smb_fname,
5730 const SMB_STRUCT_STAT *psbuf,
5731 SMB_OFF_T size,
5732 bool fail_after_createfile)
5734 NTSTATUS status = NT_STATUS_OK;
5735 struct smb_filename *smb_fname_tmp = NULL;
5736 files_struct *new_fsp = NULL;
5738 if (!VALID_STAT(*psbuf)) {
5739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5742 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5743 return NT_STATUS_ACCESS_DENIED;
5746 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5748 if (size == get_file_size_stat(psbuf)) {
5749 return NT_STATUS_OK;
5752 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5753 smb_fname_str_dbg(smb_fname), (double)size));
5755 if (fsp && fsp->fh->fd != -1) {
5756 /* Handle based call. */
5757 if (vfs_set_filelen(fsp, size) == -1) {
5758 return map_nt_error_from_unix(errno);
5760 trigger_write_time_update_immediate(fsp);
5761 return NT_STATUS_OK;
5764 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5765 if (!NT_STATUS_IS_OK(status)) {
5766 return status;
5769 smb_fname_tmp->st = *psbuf;
5771 status = SMB_VFS_CREATE_FILE(
5772 conn, /* conn */
5773 req, /* req */
5774 0, /* root_dir_fid */
5775 smb_fname_tmp, /* fname */
5776 FILE_WRITE_DATA, /* access_mask */
5777 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5778 FILE_SHARE_DELETE),
5779 FILE_OPEN, /* create_disposition*/
5780 0, /* create_options */
5781 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5782 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5783 0, /* allocation_size */
5784 0, /* private_flags */
5785 NULL, /* sd */
5786 NULL, /* ea_list */
5787 &new_fsp, /* result */
5788 NULL); /* pinfo */
5790 TALLOC_FREE(smb_fname_tmp);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 /* NB. We check for open_was_deferred in the caller. */
5794 return status;
5797 /* See RAW-SFILEINFO-END-OF-FILE */
5798 if (fail_after_createfile) {
5799 close_file(req, new_fsp,NORMAL_CLOSE);
5800 return NT_STATUS_INVALID_LEVEL;
5803 if (vfs_set_filelen(new_fsp, size) == -1) {
5804 status = map_nt_error_from_unix(errno);
5805 close_file(req, new_fsp,NORMAL_CLOSE);
5806 return status;
5809 trigger_write_time_update_immediate(new_fsp);
5810 close_file(req, new_fsp,NORMAL_CLOSE);
5811 return NT_STATUS_OK;
5814 /****************************************************************************
5815 Deal with SMB_INFO_SET_EA.
5816 ****************************************************************************/
5818 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5819 const char *pdata,
5820 int total_data,
5821 files_struct *fsp,
5822 const struct smb_filename *smb_fname)
5824 struct ea_list *ea_list = NULL;
5825 TALLOC_CTX *ctx = NULL;
5826 NTSTATUS status = NT_STATUS_OK;
5828 if (total_data < 10) {
5830 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5831 length. They seem to have no effect. Bug #3212. JRA */
5833 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5834 /* We're done. We only get EA info in this call. */
5835 return NT_STATUS_OK;
5838 return NT_STATUS_INVALID_PARAMETER;
5841 if (IVAL(pdata,0) > total_data) {
5842 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5843 IVAL(pdata,0), (unsigned int)total_data));
5844 return NT_STATUS_INVALID_PARAMETER;
5847 ctx = talloc_tos();
5848 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5849 if (!ea_list) {
5850 return NT_STATUS_INVALID_PARAMETER;
5853 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5854 return NT_STATUS_ACCESS_DENIED;
5857 status = set_ea(conn, fsp, smb_fname, ea_list);
5859 return status;
5862 /****************************************************************************
5863 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5864 ****************************************************************************/
5866 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5867 const char *pdata,
5868 int total_data,
5869 files_struct *fsp)
5871 struct ea_list *ea_list = NULL;
5872 NTSTATUS status;
5874 if (!fsp) {
5875 return NT_STATUS_INVALID_HANDLE;
5878 if (!lp_ea_support(SNUM(conn))) {
5879 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5880 "EA's not supported.\n",
5881 (unsigned int)total_data));
5882 return NT_STATUS_EAS_NOT_SUPPORTED;
5885 if (total_data < 10) {
5886 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5887 "too small.\n",
5888 (unsigned int)total_data));
5889 return NT_STATUS_INVALID_PARAMETER;
5892 ea_list = read_nttrans_ea_list(talloc_tos(),
5893 pdata,
5894 total_data);
5896 if (!ea_list) {
5897 return NT_STATUS_INVALID_PARAMETER;
5900 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5901 return NT_STATUS_ACCESS_DENIED;
5904 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5906 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5907 smb_fname_str_dbg(fsp->fsp_name),
5908 nt_errstr(status) ));
5910 return status;
5914 /****************************************************************************
5915 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5916 ****************************************************************************/
5918 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5919 const char *pdata,
5920 int total_data,
5921 files_struct *fsp,
5922 struct smb_filename *smb_fname)
5924 NTSTATUS status = NT_STATUS_OK;
5925 bool delete_on_close;
5926 uint32 dosmode = 0;
5928 if (total_data < 1) {
5929 return NT_STATUS_INVALID_PARAMETER;
5932 if (fsp == NULL) {
5933 return NT_STATUS_INVALID_HANDLE;
5936 delete_on_close = (CVAL(pdata,0) ? True : False);
5937 dosmode = dos_mode(conn, smb_fname);
5939 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5940 "delete_on_close = %u\n",
5941 smb_fname_str_dbg(smb_fname),
5942 (unsigned int)dosmode,
5943 (unsigned int)delete_on_close ));
5945 if (delete_on_close) {
5946 status = can_set_delete_on_close(fsp, dosmode);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return status;
5952 /* The set is across all open files on this dev/inode pair. */
5953 if (!set_delete_on_close(fsp, delete_on_close,
5954 conn->session_info->security_token,
5955 &conn->session_info->utok)) {
5956 return NT_STATUS_ACCESS_DENIED;
5958 return NT_STATUS_OK;
5961 /****************************************************************************
5962 Deal with SMB_FILE_POSITION_INFORMATION.
5963 ****************************************************************************/
5965 static NTSTATUS smb_file_position_information(connection_struct *conn,
5966 const char *pdata,
5967 int total_data,
5968 files_struct *fsp)
5970 uint64_t position_information;
5972 if (total_data < 8) {
5973 return NT_STATUS_INVALID_PARAMETER;
5976 if (fsp == NULL) {
5977 /* Ignore on pathname based set. */
5978 return NT_STATUS_OK;
5981 position_information = (uint64_t)IVAL(pdata,0);
5982 #ifdef LARGE_SMB_OFF_T
5983 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5984 #else /* LARGE_SMB_OFF_T */
5985 if (IVAL(pdata,4) != 0) {
5986 /* more than 32 bits? */
5987 return NT_STATUS_INVALID_PARAMETER;
5989 #endif /* LARGE_SMB_OFF_T */
5991 DEBUG(10,("smb_file_position_information: Set file position "
5992 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5993 (double)position_information));
5994 fsp->fh->position_information = position_information;
5995 return NT_STATUS_OK;
5998 /****************************************************************************
5999 Deal with SMB_FILE_MODE_INFORMATION.
6000 ****************************************************************************/
6002 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6003 const char *pdata,
6004 int total_data)
6006 uint32 mode;
6008 if (total_data < 4) {
6009 return NT_STATUS_INVALID_PARAMETER;
6011 mode = IVAL(pdata,0);
6012 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6013 return NT_STATUS_INVALID_PARAMETER;
6015 return NT_STATUS_OK;
6018 /****************************************************************************
6019 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6020 ****************************************************************************/
6022 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6023 struct smb_request *req,
6024 const char *pdata,
6025 int total_data,
6026 const struct smb_filename *smb_fname)
6028 char *link_target = NULL;
6029 const char *newname = smb_fname->base_name;
6030 TALLOC_CTX *ctx = talloc_tos();
6032 /* Set a symbolic link. */
6033 /* Don't allow this if follow links is false. */
6035 if (total_data == 0) {
6036 return NT_STATUS_INVALID_PARAMETER;
6039 if (!lp_symlinks(SNUM(conn))) {
6040 return NT_STATUS_ACCESS_DENIED;
6043 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6044 total_data, STR_TERMINATE);
6046 if (!link_target) {
6047 return NT_STATUS_INVALID_PARAMETER;
6050 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6051 newname, link_target ));
6053 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6054 return map_nt_error_from_unix(errno);
6057 return NT_STATUS_OK;
6060 /****************************************************************************
6061 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6062 ****************************************************************************/
6064 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6065 struct smb_request *req,
6066 const char *pdata, int total_data,
6067 struct smb_filename *smb_fname_new)
6069 char *oldname = NULL;
6070 struct smb_filename *smb_fname_old = NULL;
6071 TALLOC_CTX *ctx = talloc_tos();
6072 NTSTATUS status = NT_STATUS_OK;
6074 /* Set a hard link. */
6075 if (total_data == 0) {
6076 return NT_STATUS_INVALID_PARAMETER;
6079 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6080 total_data, STR_TERMINATE, &status);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 return status;
6085 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6086 smb_fname_str_dbg(smb_fname_new), oldname));
6088 status = filename_convert(ctx,
6089 conn,
6090 req->flags2 & FLAGS2_DFS_PATHNAMES,
6091 oldname,
6093 NULL,
6094 &smb_fname_old);
6095 if (!NT_STATUS_IS_OK(status)) {
6096 return status;
6099 return hardlink_internals(ctx, conn, req, false,
6100 smb_fname_old, smb_fname_new);
6103 /****************************************************************************
6104 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6105 ****************************************************************************/
6107 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6108 struct smb_request *req,
6109 const char *pdata,
6110 int total_data,
6111 files_struct *fsp,
6112 struct smb_filename *smb_fname_src)
6114 bool overwrite;
6115 uint32_t len;
6116 char *newname = NULL;
6117 struct smb_filename *smb_fname_dst = NULL;
6118 NTSTATUS status = NT_STATUS_OK;
6119 TALLOC_CTX *ctx = talloc_tos();
6121 if (!fsp) {
6122 return NT_STATUS_INVALID_HANDLE;
6125 if (total_data < 20) {
6126 return NT_STATUS_INVALID_PARAMETER;
6129 overwrite = (CVAL(pdata,0) ? True : False);
6130 len = IVAL(pdata,16);
6132 if (len > (total_data - 20) || (len == 0)) {
6133 return NT_STATUS_INVALID_PARAMETER;
6136 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6137 &pdata[20], len, STR_TERMINATE,
6138 &status);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 return status;
6143 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6144 newname));
6146 status = filename_convert(ctx,
6147 conn,
6148 req->flags2 & FLAGS2_DFS_PATHNAMES,
6149 newname,
6150 UCF_SAVE_LCOMP,
6151 NULL,
6152 &smb_fname_dst);
6153 if (!NT_STATUS_IS_OK(status)) {
6154 return status;
6157 if (fsp->base_fsp) {
6158 /* newname must be a stream name. */
6159 if (newname[0] != ':') {
6160 return NT_STATUS_NOT_SUPPORTED;
6163 /* Create an smb_fname to call rename_internals_fsp() with. */
6164 status = create_synthetic_smb_fname(talloc_tos(),
6165 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6166 &smb_fname_dst);
6167 if (!NT_STATUS_IS_OK(status)) {
6168 goto out;
6172 * Set the original last component, since
6173 * rename_internals_fsp() requires it.
6175 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6176 newname);
6177 if (smb_fname_dst->original_lcomp == NULL) {
6178 status = NT_STATUS_NO_MEMORY;
6179 goto out;
6184 DEBUG(10,("smb2_file_rename_information: "
6185 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6186 fsp->fnum, fsp_str_dbg(fsp),
6187 smb_fname_str_dbg(smb_fname_dst)));
6188 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6189 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6190 overwrite);
6192 out:
6193 TALLOC_FREE(smb_fname_dst);
6194 return status;
6197 static NTSTATUS smb_file_link_information(connection_struct *conn,
6198 struct smb_request *req,
6199 const char *pdata,
6200 int total_data,
6201 files_struct *fsp,
6202 struct smb_filename *smb_fname_src)
6204 bool overwrite;
6205 uint32_t len;
6206 char *newname = NULL;
6207 struct smb_filename *smb_fname_dst = NULL;
6208 NTSTATUS status = NT_STATUS_OK;
6209 TALLOC_CTX *ctx = talloc_tos();
6211 if (!fsp) {
6212 return NT_STATUS_INVALID_HANDLE;
6215 if (total_data < 20) {
6216 return NT_STATUS_INVALID_PARAMETER;
6219 overwrite = (CVAL(pdata,0) ? true : false);
6220 len = IVAL(pdata,16);
6222 if (len > (total_data - 20) || (len == 0)) {
6223 return NT_STATUS_INVALID_PARAMETER;
6226 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6227 &pdata[20], len, STR_TERMINATE,
6228 &status);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 return status;
6233 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6234 newname));
6236 status = filename_convert(ctx,
6237 conn,
6238 req->flags2 & FLAGS2_DFS_PATHNAMES,
6239 newname,
6240 UCF_SAVE_LCOMP,
6241 NULL,
6242 &smb_fname_dst);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 return status;
6247 if (fsp->base_fsp) {
6248 /* No stream names. */
6249 return NT_STATUS_NOT_SUPPORTED;
6252 DEBUG(10,("smb_file_link_information: "
6253 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6254 fsp->fnum, fsp_str_dbg(fsp),
6255 smb_fname_str_dbg(smb_fname_dst)));
6256 status = hardlink_internals(ctx,
6257 conn,
6258 req,
6259 overwrite,
6260 fsp->fsp_name,
6261 smb_fname_dst);
6263 TALLOC_FREE(smb_fname_dst);
6264 return status;
6267 /****************************************************************************
6268 Deal with SMB_FILE_RENAME_INFORMATION.
6269 ****************************************************************************/
6271 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6272 struct smb_request *req,
6273 const char *pdata,
6274 int total_data,
6275 files_struct *fsp,
6276 struct smb_filename *smb_fname_src)
6278 bool overwrite;
6279 uint32 root_fid;
6280 uint32 len;
6281 char *newname = NULL;
6282 struct smb_filename *smb_fname_dst = NULL;
6283 bool dest_has_wcard = False;
6284 NTSTATUS status = NT_STATUS_OK;
6285 char *p;
6286 TALLOC_CTX *ctx = talloc_tos();
6288 if (total_data < 13) {
6289 return NT_STATUS_INVALID_PARAMETER;
6292 overwrite = (CVAL(pdata,0) ? True : False);
6293 root_fid = IVAL(pdata,4);
6294 len = IVAL(pdata,8);
6296 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6297 return NT_STATUS_INVALID_PARAMETER;
6300 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6301 len, 0, &status,
6302 &dest_has_wcard);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 return status;
6307 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6308 newname));
6310 status = resolve_dfspath_wcard(ctx, conn,
6311 req->flags2 & FLAGS2_DFS_PATHNAMES,
6312 newname,
6313 true,
6314 &newname,
6315 &dest_has_wcard);
6316 if (!NT_STATUS_IS_OK(status)) {
6317 return status;
6320 /* Check the new name has no '/' characters. */
6321 if (strchr_m(newname, '/')) {
6322 return NT_STATUS_NOT_SUPPORTED;
6325 if (fsp && fsp->base_fsp) {
6326 /* newname must be a stream name. */
6327 if (newname[0] != ':') {
6328 return NT_STATUS_NOT_SUPPORTED;
6331 /* Create an smb_fname to call rename_internals_fsp() with. */
6332 status = create_synthetic_smb_fname(talloc_tos(),
6333 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6334 &smb_fname_dst);
6335 if (!NT_STATUS_IS_OK(status)) {
6336 goto out;
6340 * Set the original last component, since
6341 * rename_internals_fsp() requires it.
6343 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6344 newname);
6345 if (smb_fname_dst->original_lcomp == NULL) {
6346 status = NT_STATUS_NO_MEMORY;
6347 goto out;
6350 } else {
6352 * Build up an smb_fname_dst based on the filename passed in.
6353 * We basically just strip off the last component, and put on
6354 * the newname instead.
6356 char *base_name = NULL;
6358 /* newname must *not* be a stream name. */
6359 if (newname[0] == ':') {
6360 return NT_STATUS_NOT_SUPPORTED;
6364 * Strip off the last component (filename) of the path passed
6365 * in.
6367 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6368 if (!base_name) {
6369 return NT_STATUS_NO_MEMORY;
6371 p = strrchr_m(base_name, '/');
6372 if (p) {
6373 p[1] = '\0';
6374 } else {
6375 base_name = talloc_strdup(ctx, "");
6376 if (!base_name) {
6377 return NT_STATUS_NO_MEMORY;
6380 /* Append the new name. */
6381 base_name = talloc_asprintf_append(base_name,
6382 "%s",
6383 newname);
6384 if (!base_name) {
6385 return NT_STATUS_NO_MEMORY;
6388 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6389 (UCF_SAVE_LCOMP |
6390 (dest_has_wcard ?
6391 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6392 0)));
6394 /* If an error we expect this to be
6395 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6397 if (!NT_STATUS_IS_OK(status)) {
6398 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6399 status)) {
6400 goto out;
6402 /* Create an smb_fname to call rename_internals_fsp() */
6403 status = create_synthetic_smb_fname(ctx,
6404 base_name, NULL,
6405 NULL,
6406 &smb_fname_dst);
6407 if (!NT_STATUS_IS_OK(status)) {
6408 goto out;
6413 if (fsp) {
6414 DEBUG(10,("smb_file_rename_information: "
6415 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6416 fsp->fnum, fsp_str_dbg(fsp),
6417 smb_fname_str_dbg(smb_fname_dst)));
6418 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6419 overwrite);
6420 } else {
6421 DEBUG(10,("smb_file_rename_information: "
6422 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6423 smb_fname_str_dbg(smb_fname_src),
6424 smb_fname_str_dbg(smb_fname_dst)));
6425 status = rename_internals(ctx, conn, req, smb_fname_src,
6426 smb_fname_dst, 0, overwrite, false,
6427 dest_has_wcard,
6428 FILE_WRITE_ATTRIBUTES);
6430 out:
6431 TALLOC_FREE(smb_fname_dst);
6432 return status;
6435 /****************************************************************************
6436 Deal with SMB_SET_POSIX_ACL.
6437 ****************************************************************************/
6439 #if defined(HAVE_POSIX_ACLS)
6440 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6441 const char *pdata,
6442 int total_data,
6443 files_struct *fsp,
6444 const struct smb_filename *smb_fname)
6446 uint16 posix_acl_version;
6447 uint16 num_file_acls;
6448 uint16 num_def_acls;
6449 bool valid_file_acls = True;
6450 bool valid_def_acls = True;
6452 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6453 return NT_STATUS_INVALID_PARAMETER;
6455 posix_acl_version = SVAL(pdata,0);
6456 num_file_acls = SVAL(pdata,2);
6457 num_def_acls = SVAL(pdata,4);
6459 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6460 valid_file_acls = False;
6461 num_file_acls = 0;
6464 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6465 valid_def_acls = False;
6466 num_def_acls = 0;
6469 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6470 return NT_STATUS_INVALID_PARAMETER;
6473 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6474 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6475 return NT_STATUS_INVALID_PARAMETER;
6478 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6479 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6480 (unsigned int)num_file_acls,
6481 (unsigned int)num_def_acls));
6483 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6484 smb_fname->base_name, num_file_acls,
6485 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6486 return map_nt_error_from_unix(errno);
6489 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6490 smb_fname->base_name, &smb_fname->st, num_def_acls,
6491 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6492 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6493 return map_nt_error_from_unix(errno);
6495 return NT_STATUS_OK;
6497 #endif
6499 /****************************************************************************
6500 Deal with SMB_SET_POSIX_LOCK.
6501 ****************************************************************************/
6503 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6504 struct smb_request *req,
6505 const char *pdata,
6506 int total_data,
6507 files_struct *fsp)
6509 uint64_t count;
6510 uint64_t offset;
6511 uint64_t smblctx;
6512 bool blocking_lock = False;
6513 enum brl_type lock_type;
6515 NTSTATUS status = NT_STATUS_OK;
6517 if (fsp == NULL || fsp->fh->fd == -1) {
6518 return NT_STATUS_INVALID_HANDLE;
6521 if (total_data != POSIX_LOCK_DATA_SIZE) {
6522 return NT_STATUS_INVALID_PARAMETER;
6525 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6526 case POSIX_LOCK_TYPE_READ:
6527 lock_type = READ_LOCK;
6528 break;
6529 case POSIX_LOCK_TYPE_WRITE:
6530 /* Return the right POSIX-mappable error code for files opened read-only. */
6531 if (!fsp->can_write) {
6532 return NT_STATUS_INVALID_HANDLE;
6534 lock_type = WRITE_LOCK;
6535 break;
6536 case POSIX_LOCK_TYPE_UNLOCK:
6537 lock_type = UNLOCK_LOCK;
6538 break;
6539 default:
6540 return NT_STATUS_INVALID_PARAMETER;
6543 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6544 blocking_lock = False;
6545 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6546 blocking_lock = True;
6547 } else {
6548 return NT_STATUS_INVALID_PARAMETER;
6551 if (!lp_blocking_locks(SNUM(conn))) {
6552 blocking_lock = False;
6555 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6556 #if defined(HAVE_LONGLONG)
6557 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6558 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6559 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6560 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6561 #else /* HAVE_LONGLONG */
6562 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6563 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6564 #endif /* HAVE_LONGLONG */
6566 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6567 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6568 fsp_str_dbg(fsp),
6569 (unsigned int)lock_type,
6570 (unsigned long long)smblctx,
6571 (double)count,
6572 (double)offset ));
6574 if (lock_type == UNLOCK_LOCK) {
6575 status = do_unlock(req->sconn->msg_ctx,
6576 fsp,
6577 smblctx,
6578 count,
6579 offset,
6580 POSIX_LOCK);
6581 } else {
6582 uint64_t block_smblctx;
6584 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6585 fsp,
6586 smblctx,
6587 count,
6588 offset,
6589 lock_type,
6590 POSIX_LOCK,
6591 blocking_lock,
6592 &status,
6593 &block_smblctx,
6594 NULL);
6596 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6598 * A blocking lock was requested. Package up
6599 * this smb into a queued request and push it
6600 * onto the blocking lock queue.
6602 if(push_blocking_lock_request(br_lck,
6603 req,
6604 fsp,
6605 -1, /* infinite timeout. */
6607 smblctx,
6608 lock_type,
6609 POSIX_LOCK,
6610 offset,
6611 count,
6612 block_smblctx)) {
6613 TALLOC_FREE(br_lck);
6614 return status;
6617 TALLOC_FREE(br_lck);
6620 return status;
6623 /****************************************************************************
6624 Deal with SMB_SET_FILE_BASIC_INFO.
6625 ****************************************************************************/
6627 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6628 const char *pdata,
6629 int total_data,
6630 files_struct *fsp,
6631 const struct smb_filename *smb_fname)
6633 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6634 struct smb_file_time ft;
6635 uint32 dosmode = 0;
6636 NTSTATUS status = NT_STATUS_OK;
6638 ZERO_STRUCT(ft);
6640 if (total_data < 36) {
6641 return NT_STATUS_INVALID_PARAMETER;
6644 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6645 return NT_STATUS_ACCESS_DENIED;
6648 /* Set the attributes */
6649 dosmode = IVAL(pdata,32);
6650 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 return status;
6655 /* create time */
6656 ft.create_time = interpret_long_date(pdata);
6658 /* access time */
6659 ft.atime = interpret_long_date(pdata+8);
6661 /* write time. */
6662 ft.mtime = interpret_long_date(pdata+16);
6664 /* change time. */
6665 ft.ctime = interpret_long_date(pdata+24);
6667 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6668 smb_fname_str_dbg(smb_fname)));
6670 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6671 true);
6674 /****************************************************************************
6675 Deal with SMB_INFO_STANDARD.
6676 ****************************************************************************/
6678 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6679 const char *pdata,
6680 int total_data,
6681 files_struct *fsp,
6682 const struct smb_filename *smb_fname)
6684 struct smb_file_time ft;
6686 ZERO_STRUCT(ft);
6688 if (total_data < 12) {
6689 return NT_STATUS_INVALID_PARAMETER;
6692 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6693 return NT_STATUS_ACCESS_DENIED;
6696 /* create time */
6697 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6698 /* access time */
6699 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6700 /* write time */
6701 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6703 DEBUG(10,("smb_set_info_standard: file %s\n",
6704 smb_fname_str_dbg(smb_fname)));
6706 return smb_set_file_time(conn,
6707 fsp,
6708 smb_fname,
6709 &ft,
6710 true);
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6718 struct smb_request *req,
6719 const char *pdata,
6720 int total_data,
6721 files_struct *fsp,
6722 struct smb_filename *smb_fname)
6724 uint64_t allocation_size = 0;
6725 NTSTATUS status = NT_STATUS_OK;
6726 files_struct *new_fsp = NULL;
6728 if (!VALID_STAT(smb_fname->st)) {
6729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6732 if (total_data < 8) {
6733 return NT_STATUS_INVALID_PARAMETER;
6736 allocation_size = (uint64_t)IVAL(pdata,0);
6737 #ifdef LARGE_SMB_OFF_T
6738 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6739 #else /* LARGE_SMB_OFF_T */
6740 if (IVAL(pdata,4) != 0) {
6741 /* more than 32 bits? */
6742 return NT_STATUS_INVALID_PARAMETER;
6744 #endif /* LARGE_SMB_OFF_T */
6746 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6747 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6748 (double)allocation_size));
6750 if (allocation_size) {
6751 allocation_size = smb_roundup(conn, allocation_size);
6754 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6755 return NT_STATUS_ACCESS_DENIED;
6758 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6759 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6760 (double)allocation_size));
6762 if (fsp && fsp->fh->fd != -1) {
6763 /* Open file handle. */
6764 /* Only change if needed. */
6765 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6766 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6767 return map_nt_error_from_unix(errno);
6770 /* But always update the time. */
6772 * This is equivalent to a write. Ensure it's seen immediately
6773 * if there are no pending writes.
6775 trigger_write_time_update_immediate(fsp);
6776 return NT_STATUS_OK;
6779 /* Pathname or stat or directory file. */
6780 status = SMB_VFS_CREATE_FILE(
6781 conn, /* conn */
6782 req, /* req */
6783 0, /* root_dir_fid */
6784 smb_fname, /* fname */
6785 FILE_WRITE_DATA, /* access_mask */
6786 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6787 FILE_SHARE_DELETE),
6788 FILE_OPEN, /* create_disposition*/
6789 0, /* create_options */
6790 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6791 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6792 0, /* allocation_size */
6793 0, /* private_flags */
6794 NULL, /* sd */
6795 NULL, /* ea_list */
6796 &new_fsp, /* result */
6797 NULL); /* pinfo */
6799 if (!NT_STATUS_IS_OK(status)) {
6800 /* NB. We check for open_was_deferred in the caller. */
6801 return status;
6804 /* Only change if needed. */
6805 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6806 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6807 status = map_nt_error_from_unix(errno);
6808 close_file(req, new_fsp, NORMAL_CLOSE);
6809 return status;
6813 /* Changing the allocation size should set the last mod time. */
6815 * This is equivalent to a write. Ensure it's seen immediately
6816 * if there are no pending writes.
6818 trigger_write_time_update_immediate(new_fsp);
6820 close_file(req, new_fsp, NORMAL_CLOSE);
6821 return NT_STATUS_OK;
6824 /****************************************************************************
6825 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6826 ****************************************************************************/
6828 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6829 struct smb_request *req,
6830 const char *pdata,
6831 int total_data,
6832 files_struct *fsp,
6833 const struct smb_filename *smb_fname,
6834 bool fail_after_createfile)
6836 SMB_OFF_T size;
6838 if (total_data < 8) {
6839 return NT_STATUS_INVALID_PARAMETER;
6842 size = IVAL(pdata,0);
6843 #ifdef LARGE_SMB_OFF_T
6844 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6845 #else /* LARGE_SMB_OFF_T */
6846 if (IVAL(pdata,4) != 0) {
6847 /* more than 32 bits? */
6848 return NT_STATUS_INVALID_PARAMETER;
6850 #endif /* LARGE_SMB_OFF_T */
6851 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6852 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6853 (double)size));
6855 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6856 return NT_STATUS_ACCESS_DENIED;
6859 return smb_set_file_size(conn, req,
6860 fsp,
6861 smb_fname,
6862 &smb_fname->st,
6863 size,
6864 fail_after_createfile);
6867 /****************************************************************************
6868 Allow a UNIX info mknod.
6869 ****************************************************************************/
6871 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6872 const char *pdata,
6873 int total_data,
6874 const struct smb_filename *smb_fname)
6876 uint32 file_type = IVAL(pdata,56);
6877 #if defined(HAVE_MAKEDEV)
6878 uint32 dev_major = IVAL(pdata,60);
6879 uint32 dev_minor = IVAL(pdata,68);
6880 #endif
6881 SMB_DEV_T dev = (SMB_DEV_T)0;
6882 uint32 raw_unixmode = IVAL(pdata,84);
6883 NTSTATUS status;
6884 mode_t unixmode;
6886 if (total_data < 100) {
6887 return NT_STATUS_INVALID_PARAMETER;
6890 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6891 PERM_NEW_FILE, &unixmode);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 return status;
6896 #if defined(HAVE_MAKEDEV)
6897 dev = makedev(dev_major, dev_minor);
6898 #endif
6900 switch (file_type) {
6901 #if defined(S_IFIFO)
6902 case UNIX_TYPE_FIFO:
6903 unixmode |= S_IFIFO;
6904 break;
6905 #endif
6906 #if defined(S_IFSOCK)
6907 case UNIX_TYPE_SOCKET:
6908 unixmode |= S_IFSOCK;
6909 break;
6910 #endif
6911 #if defined(S_IFCHR)
6912 case UNIX_TYPE_CHARDEV:
6913 unixmode |= S_IFCHR;
6914 break;
6915 #endif
6916 #if defined(S_IFBLK)
6917 case UNIX_TYPE_BLKDEV:
6918 unixmode |= S_IFBLK;
6919 break;
6920 #endif
6921 default:
6922 return NT_STATUS_INVALID_PARAMETER;
6925 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6926 "%.0f mode 0%o for file %s\n", (double)dev,
6927 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6929 /* Ok - do the mknod. */
6930 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6931 return map_nt_error_from_unix(errno);
6934 /* If any of the other "set" calls fail we
6935 * don't want to end up with a half-constructed mknod.
6938 if (lp_inherit_perms(SNUM(conn))) {
6939 char *parent;
6940 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6941 &parent, NULL)) {
6942 return NT_STATUS_NO_MEMORY;
6944 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6945 unixmode);
6946 TALLOC_FREE(parent);
6949 return NT_STATUS_OK;
6952 /****************************************************************************
6953 Deal with SMB_SET_FILE_UNIX_BASIC.
6954 ****************************************************************************/
6956 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6957 struct smb_request *req,
6958 const char *pdata,
6959 int total_data,
6960 files_struct *fsp,
6961 const struct smb_filename *smb_fname)
6963 struct smb_file_time ft;
6964 uint32 raw_unixmode;
6965 mode_t unixmode;
6966 SMB_OFF_T size = 0;
6967 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6968 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6969 NTSTATUS status = NT_STATUS_OK;
6970 bool delete_on_fail = False;
6971 enum perm_type ptype;
6972 files_struct *all_fsps = NULL;
6973 bool modify_mtime = true;
6974 struct file_id id;
6975 struct smb_filename *smb_fname_tmp = NULL;
6976 SMB_STRUCT_STAT sbuf;
6978 ZERO_STRUCT(ft);
6980 if (total_data < 100) {
6981 return NT_STATUS_INVALID_PARAMETER;
6984 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6985 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6986 size=IVAL(pdata,0); /* first 8 Bytes are size */
6987 #ifdef LARGE_SMB_OFF_T
6988 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6989 #else /* LARGE_SMB_OFF_T */
6990 if (IVAL(pdata,4) != 0) {
6991 /* more than 32 bits? */
6992 return NT_STATUS_INVALID_PARAMETER;
6994 #endif /* LARGE_SMB_OFF_T */
6997 ft.atime = interpret_long_date(pdata+24); /* access_time */
6998 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6999 set_owner = (uid_t)IVAL(pdata,40);
7000 set_grp = (gid_t)IVAL(pdata,48);
7001 raw_unixmode = IVAL(pdata,84);
7003 if (VALID_STAT(smb_fname->st)) {
7004 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7005 ptype = PERM_EXISTING_DIR;
7006 } else {
7007 ptype = PERM_EXISTING_FILE;
7009 } else {
7010 ptype = PERM_NEW_FILE;
7013 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7014 ptype, &unixmode);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 return status;
7019 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7020 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7021 smb_fname_str_dbg(smb_fname), (double)size,
7022 (unsigned int)set_owner, (unsigned int)set_grp,
7023 (int)raw_unixmode));
7025 sbuf = smb_fname->st;
7027 if (!VALID_STAT(sbuf)) {
7029 * The only valid use of this is to create character and block
7030 * devices, and named pipes. This is deprecated (IMHO) and
7031 * a new info level should be used for mknod. JRA.
7034 status = smb_unix_mknod(conn,
7035 pdata,
7036 total_data,
7037 smb_fname);
7038 if (!NT_STATUS_IS_OK(status)) {
7039 return status;
7042 status = copy_smb_filename(talloc_tos(), smb_fname,
7043 &smb_fname_tmp);
7044 if (!NT_STATUS_IS_OK(status)) {
7045 return status;
7048 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7049 status = map_nt_error_from_unix(errno);
7050 TALLOC_FREE(smb_fname_tmp);
7051 SMB_VFS_UNLINK(conn, smb_fname);
7052 return status;
7055 sbuf = smb_fname_tmp->st;
7056 smb_fname = smb_fname_tmp;
7058 /* Ensure we don't try and change anything else. */
7059 raw_unixmode = SMB_MODE_NO_CHANGE;
7060 size = get_file_size_stat(&sbuf);
7061 ft.atime = sbuf.st_ex_atime;
7062 ft.mtime = sbuf.st_ex_mtime;
7064 * We continue here as we might want to change the
7065 * owner uid/gid.
7067 delete_on_fail = True;
7070 #if 1
7071 /* Horrible backwards compatibility hack as an old server bug
7072 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7073 * */
7075 if (!size) {
7076 size = get_file_size_stat(&sbuf);
7078 #endif
7081 * Deal with the UNIX specific mode set.
7084 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7085 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7086 "setting mode 0%o for file %s\n",
7087 (unsigned int)unixmode,
7088 smb_fname_str_dbg(smb_fname)));
7089 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7090 return map_nt_error_from_unix(errno);
7095 * Deal with the UNIX specific uid set.
7098 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7099 (sbuf.st_ex_uid != set_owner)) {
7100 int ret;
7102 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7103 "changing owner %u for path %s\n",
7104 (unsigned int)set_owner,
7105 smb_fname_str_dbg(smb_fname)));
7107 if (S_ISLNK(sbuf.st_ex_mode)) {
7108 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7109 set_owner, (gid_t)-1);
7110 } else {
7111 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7112 set_owner, (gid_t)-1);
7115 if (ret != 0) {
7116 status = map_nt_error_from_unix(errno);
7117 if (delete_on_fail) {
7118 SMB_VFS_UNLINK(conn, smb_fname);
7120 return status;
7125 * Deal with the UNIX specific gid set.
7128 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7129 (sbuf.st_ex_gid != set_grp)) {
7130 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7131 "changing group %u for file %s\n",
7132 (unsigned int)set_owner,
7133 smb_fname_str_dbg(smb_fname)));
7134 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7135 set_grp) != 0) {
7136 status = map_nt_error_from_unix(errno);
7137 if (delete_on_fail) {
7138 SMB_VFS_UNLINK(conn, smb_fname);
7140 return status;
7144 /* Deal with any size changes. */
7146 status = smb_set_file_size(conn, req,
7147 fsp,
7148 smb_fname,
7149 &sbuf,
7150 size,
7151 false);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 return status;
7156 /* Deal with any time changes. */
7157 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7158 /* No change, don't cancel anything. */
7159 return status;
7162 id = vfs_file_id_from_sbuf(conn, &sbuf);
7163 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7164 all_fsps = file_find_di_next(all_fsps)) {
7166 * We're setting the time explicitly for UNIX.
7167 * Cancel any pending changes over all handles.
7169 all_fsps->update_write_time_on_close = false;
7170 TALLOC_FREE(all_fsps->update_write_time_event);
7174 * Override the "setting_write_time"
7175 * parameter here as it almost does what
7176 * we need. Just remember if we modified
7177 * mtime and send the notify ourselves.
7179 if (null_timespec(ft.mtime)) {
7180 modify_mtime = false;
7183 status = smb_set_file_time(conn,
7184 fsp,
7185 smb_fname,
7186 &ft,
7187 false);
7188 if (modify_mtime) {
7189 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7190 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7192 return status;
7195 /****************************************************************************
7196 Deal with SMB_SET_FILE_UNIX_INFO2.
7197 ****************************************************************************/
7199 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7200 struct smb_request *req,
7201 const char *pdata,
7202 int total_data,
7203 files_struct *fsp,
7204 const struct smb_filename *smb_fname)
7206 NTSTATUS status;
7207 uint32 smb_fflags;
7208 uint32 smb_fmask;
7210 if (total_data < 116) {
7211 return NT_STATUS_INVALID_PARAMETER;
7214 /* Start by setting all the fields that are common between UNIX_BASIC
7215 * and UNIX_INFO2.
7217 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7218 fsp, smb_fname);
7219 if (!NT_STATUS_IS_OK(status)) {
7220 return status;
7223 smb_fflags = IVAL(pdata, 108);
7224 smb_fmask = IVAL(pdata, 112);
7226 /* NB: We should only attempt to alter the file flags if the client
7227 * sends a non-zero mask.
7229 if (smb_fmask != 0) {
7230 int stat_fflags = 0;
7232 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7233 smb_fmask, &stat_fflags)) {
7234 /* Client asked to alter a flag we don't understand. */
7235 return NT_STATUS_INVALID_PARAMETER;
7238 if (fsp && fsp->fh->fd != -1) {
7239 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7240 return NT_STATUS_NOT_SUPPORTED;
7241 } else {
7242 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7243 stat_fflags) != 0) {
7244 return map_nt_error_from_unix(errno);
7249 /* XXX: need to add support for changing the create_time here. You
7250 * can do this for paths on Darwin with setattrlist(2). The right way
7251 * to hook this up is probably by extending the VFS utimes interface.
7254 return NT_STATUS_OK;
7257 /****************************************************************************
7258 Create a directory with POSIX semantics.
7259 ****************************************************************************/
7261 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7262 struct smb_request *req,
7263 char **ppdata,
7264 int total_data,
7265 struct smb_filename *smb_fname,
7266 int *pdata_return_size)
7268 NTSTATUS status = NT_STATUS_OK;
7269 uint32 raw_unixmode = 0;
7270 uint32 mod_unixmode = 0;
7271 mode_t unixmode = (mode_t)0;
7272 files_struct *fsp = NULL;
7273 uint16 info_level_return = 0;
7274 int info;
7275 char *pdata = *ppdata;
7277 if (total_data < 18) {
7278 return NT_STATUS_INVALID_PARAMETER;
7281 raw_unixmode = IVAL(pdata,8);
7282 /* Next 4 bytes are not yet defined. */
7284 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7285 PERM_NEW_DIR, &unixmode);
7286 if (!NT_STATUS_IS_OK(status)) {
7287 return status;
7290 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7292 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7293 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7295 status = SMB_VFS_CREATE_FILE(
7296 conn, /* conn */
7297 req, /* req */
7298 0, /* root_dir_fid */
7299 smb_fname, /* fname */
7300 FILE_READ_ATTRIBUTES, /* access_mask */
7301 FILE_SHARE_NONE, /* share_access */
7302 FILE_CREATE, /* create_disposition*/
7303 FILE_DIRECTORY_FILE, /* create_options */
7304 mod_unixmode, /* file_attributes */
7305 0, /* oplock_request */
7306 0, /* allocation_size */
7307 0, /* private_flags */
7308 NULL, /* sd */
7309 NULL, /* ea_list */
7310 &fsp, /* result */
7311 &info); /* pinfo */
7313 if (NT_STATUS_IS_OK(status)) {
7314 close_file(req, fsp, NORMAL_CLOSE);
7317 info_level_return = SVAL(pdata,16);
7319 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7320 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7321 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7322 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7323 } else {
7324 *pdata_return_size = 12;
7327 /* Realloc the data size */
7328 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7329 if (*ppdata == NULL) {
7330 *pdata_return_size = 0;
7331 return NT_STATUS_NO_MEMORY;
7333 pdata = *ppdata;
7335 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7336 SSVAL(pdata,2,0); /* No fnum. */
7337 SIVAL(pdata,4,info); /* Was directory created. */
7339 switch (info_level_return) {
7340 case SMB_QUERY_FILE_UNIX_BASIC:
7341 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7342 SSVAL(pdata,10,0); /* Padding. */
7343 store_file_unix_basic(conn, pdata + 12, fsp,
7344 &smb_fname->st);
7345 break;
7346 case SMB_QUERY_FILE_UNIX_INFO2:
7347 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7348 SSVAL(pdata,10,0); /* Padding. */
7349 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7350 &smb_fname->st);
7351 break;
7352 default:
7353 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7354 SSVAL(pdata,10,0); /* Padding. */
7355 break;
7358 return status;
7361 /****************************************************************************
7362 Open/Create a file with POSIX semantics.
7363 ****************************************************************************/
7365 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7366 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7368 static NTSTATUS smb_posix_open(connection_struct *conn,
7369 struct smb_request *req,
7370 char **ppdata,
7371 int total_data,
7372 struct smb_filename *smb_fname,
7373 int *pdata_return_size)
7375 bool extended_oplock_granted = False;
7376 char *pdata = *ppdata;
7377 uint32 flags = 0;
7378 uint32 wire_open_mode = 0;
7379 uint32 raw_unixmode = 0;
7380 uint32 mod_unixmode = 0;
7381 uint32 create_disp = 0;
7382 uint32 access_mask = 0;
7383 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7384 NTSTATUS status = NT_STATUS_OK;
7385 mode_t unixmode = (mode_t)0;
7386 files_struct *fsp = NULL;
7387 int oplock_request = 0;
7388 int info = 0;
7389 uint16 info_level_return = 0;
7391 if (total_data < 18) {
7392 return NT_STATUS_INVALID_PARAMETER;
7395 flags = IVAL(pdata,0);
7396 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7397 if (oplock_request) {
7398 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7401 wire_open_mode = IVAL(pdata,4);
7403 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7404 return smb_posix_mkdir(conn, req,
7405 ppdata,
7406 total_data,
7407 smb_fname,
7408 pdata_return_size);
7411 switch (wire_open_mode & SMB_ACCMODE) {
7412 case SMB_O_RDONLY:
7413 access_mask = SMB_O_RDONLY_MAPPING;
7414 break;
7415 case SMB_O_WRONLY:
7416 access_mask = SMB_O_WRONLY_MAPPING;
7417 break;
7418 case SMB_O_RDWR:
7419 access_mask = (SMB_O_RDONLY_MAPPING|
7420 SMB_O_WRONLY_MAPPING);
7421 break;
7422 default:
7423 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7424 (unsigned int)wire_open_mode ));
7425 return NT_STATUS_INVALID_PARAMETER;
7428 wire_open_mode &= ~SMB_ACCMODE;
7430 /* First take care of O_CREAT|O_EXCL interactions. */
7431 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7432 case (SMB_O_CREAT | SMB_O_EXCL):
7433 /* File exists fail. File not exist create. */
7434 create_disp = FILE_CREATE;
7435 break;
7436 case SMB_O_CREAT:
7437 /* File exists open. File not exist create. */
7438 create_disp = FILE_OPEN_IF;
7439 break;
7440 case SMB_O_EXCL:
7441 /* O_EXCL on its own without O_CREAT is undefined.
7442 We deliberately ignore it as some versions of
7443 Linux CIFSFS can send a bare O_EXCL on the
7444 wire which other filesystems in the kernel
7445 ignore. See bug 9519 for details. */
7447 /* Fallthrough. */
7449 case 0:
7450 /* File exists open. File not exist fail. */
7451 create_disp = FILE_OPEN;
7452 break;
7453 default:
7454 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7455 (unsigned int)wire_open_mode ));
7456 return NT_STATUS_INVALID_PARAMETER;
7459 /* Next factor in the effects of O_TRUNC. */
7460 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7462 if (wire_open_mode & SMB_O_TRUNC) {
7463 switch (create_disp) {
7464 case FILE_CREATE:
7465 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7466 /* Leave create_disp alone as
7467 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7469 /* File exists fail. File not exist create. */
7470 break;
7471 case FILE_OPEN_IF:
7472 /* SMB_O_CREAT | SMB_O_TRUNC */
7473 /* File exists overwrite. File not exist create. */
7474 create_disp = FILE_OVERWRITE_IF;
7475 break;
7476 case FILE_OPEN:
7477 /* SMB_O_TRUNC */
7478 /* File exists overwrite. File not exist fail. */
7479 create_disp = FILE_OVERWRITE;
7480 break;
7481 default:
7482 /* Cannot get here. */
7483 smb_panic("smb_posix_open: logic error");
7484 return NT_STATUS_INVALID_PARAMETER;
7488 raw_unixmode = IVAL(pdata,8);
7489 /* Next 4 bytes are not yet defined. */
7491 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7492 (VALID_STAT(smb_fname->st) ?
7493 PERM_EXISTING_FILE : PERM_NEW_FILE),
7494 &unixmode);
7496 if (!NT_STATUS_IS_OK(status)) {
7497 return status;
7500 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7502 if (wire_open_mode & SMB_O_SYNC) {
7503 create_options |= FILE_WRITE_THROUGH;
7505 if (wire_open_mode & SMB_O_APPEND) {
7506 access_mask |= FILE_APPEND_DATA;
7508 if (wire_open_mode & SMB_O_DIRECT) {
7509 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7512 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7513 VALID_STAT_OF_DIR(smb_fname->st)) {
7514 if (access_mask != SMB_O_RDONLY_MAPPING) {
7515 return NT_STATUS_FILE_IS_A_DIRECTORY;
7517 create_options &= ~FILE_NON_DIRECTORY_FILE;
7518 create_options |= FILE_DIRECTORY_FILE;
7521 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7522 smb_fname_str_dbg(smb_fname),
7523 (unsigned int)wire_open_mode,
7524 (unsigned int)unixmode ));
7526 status = SMB_VFS_CREATE_FILE(
7527 conn, /* conn */
7528 req, /* req */
7529 0, /* root_dir_fid */
7530 smb_fname, /* fname */
7531 access_mask, /* access_mask */
7532 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7533 FILE_SHARE_DELETE),
7534 create_disp, /* create_disposition*/
7535 create_options, /* create_options */
7536 mod_unixmode, /* file_attributes */
7537 oplock_request, /* oplock_request */
7538 0, /* allocation_size */
7539 0, /* private_flags */
7540 NULL, /* sd */
7541 NULL, /* ea_list */
7542 &fsp, /* result */
7543 &info); /* pinfo */
7545 if (!NT_STATUS_IS_OK(status)) {
7546 return status;
7549 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7550 extended_oplock_granted = True;
7553 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7554 extended_oplock_granted = True;
7557 info_level_return = SVAL(pdata,16);
7559 /* Allocate the correct return size. */
7561 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7562 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7563 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7564 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7565 } else {
7566 *pdata_return_size = 12;
7569 /* Realloc the data size */
7570 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7571 if (*ppdata == NULL) {
7572 close_file(req, fsp, ERROR_CLOSE);
7573 *pdata_return_size = 0;
7574 return NT_STATUS_NO_MEMORY;
7576 pdata = *ppdata;
7578 if (extended_oplock_granted) {
7579 if (flags & REQUEST_BATCH_OPLOCK) {
7580 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7581 } else {
7582 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7584 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7585 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7586 } else {
7587 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7590 SSVAL(pdata,2,fsp->fnum);
7591 SIVAL(pdata,4,info); /* Was file created etc. */
7593 switch (info_level_return) {
7594 case SMB_QUERY_FILE_UNIX_BASIC:
7595 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7596 SSVAL(pdata,10,0); /* padding. */
7597 store_file_unix_basic(conn, pdata + 12, fsp,
7598 &smb_fname->st);
7599 break;
7600 case SMB_QUERY_FILE_UNIX_INFO2:
7601 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7602 SSVAL(pdata,10,0); /* padding. */
7603 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7604 &smb_fname->st);
7605 break;
7606 default:
7607 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7608 SSVAL(pdata,10,0); /* padding. */
7609 break;
7611 return NT_STATUS_OK;
7614 /****************************************************************************
7615 Delete a file with POSIX semantics.
7616 ****************************************************************************/
7618 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7619 struct smb_request *req,
7620 const char *pdata,
7621 int total_data,
7622 struct smb_filename *smb_fname)
7624 NTSTATUS status = NT_STATUS_OK;
7625 files_struct *fsp = NULL;
7626 uint16 flags = 0;
7627 char del = 1;
7628 int info = 0;
7629 int create_options = 0;
7630 int i;
7631 struct share_mode_lock *lck = NULL;
7633 if (total_data < 2) {
7634 return NT_STATUS_INVALID_PARAMETER;
7637 flags = SVAL(pdata,0);
7639 if (!VALID_STAT(smb_fname->st)) {
7640 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7643 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7644 !VALID_STAT_OF_DIR(smb_fname->st)) {
7645 return NT_STATUS_NOT_A_DIRECTORY;
7648 DEBUG(10,("smb_posix_unlink: %s %s\n",
7649 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7650 smb_fname_str_dbg(smb_fname)));
7652 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7653 create_options |= FILE_DIRECTORY_FILE;
7656 status = SMB_VFS_CREATE_FILE(
7657 conn, /* conn */
7658 req, /* req */
7659 0, /* root_dir_fid */
7660 smb_fname, /* fname */
7661 DELETE_ACCESS, /* access_mask */
7662 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7663 FILE_SHARE_DELETE),
7664 FILE_OPEN, /* create_disposition*/
7665 create_options, /* create_options */
7666 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7667 0, /* oplock_request */
7668 0, /* allocation_size */
7669 0, /* private_flags */
7670 NULL, /* sd */
7671 NULL, /* ea_list */
7672 &fsp, /* result */
7673 &info); /* pinfo */
7675 if (!NT_STATUS_IS_OK(status)) {
7676 return status;
7680 * Don't lie to client. If we can't really delete due to
7681 * non-POSIX opens return SHARING_VIOLATION.
7684 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7685 NULL);
7686 if (lck == NULL) {
7687 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7688 "lock for file %s\n", fsp_str_dbg(fsp)));
7689 close_file(req, fsp, NORMAL_CLOSE);
7690 return NT_STATUS_INVALID_PARAMETER;
7694 * See if others still have the file open. If this is the case, then
7695 * don't delete. If all opens are POSIX delete we can set the delete
7696 * on close disposition.
7698 for (i=0; i<lck->num_share_modes; i++) {
7699 struct share_mode_entry *e = &lck->share_modes[i];
7700 if (is_valid_share_mode_entry(e)) {
7701 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7702 continue;
7704 /* Fail with sharing violation. */
7705 TALLOC_FREE(lck);
7706 close_file(req, fsp, NORMAL_CLOSE);
7707 return NT_STATUS_SHARING_VIOLATION;
7712 * Set the delete on close.
7714 status = smb_set_file_disposition_info(conn,
7715 &del,
7717 fsp,
7718 smb_fname);
7720 TALLOC_FREE(lck);
7722 if (!NT_STATUS_IS_OK(status)) {
7723 close_file(req, fsp, NORMAL_CLOSE);
7724 return status;
7726 return close_file(req, fsp, NORMAL_CLOSE);
7729 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7730 struct smb_request *req,
7731 TALLOC_CTX *mem_ctx,
7732 uint16_t info_level,
7733 files_struct *fsp,
7734 struct smb_filename *smb_fname,
7735 char **ppdata, int total_data,
7736 int *ret_data_size)
7738 char *pdata = *ppdata;
7739 NTSTATUS status = NT_STATUS_OK;
7740 int data_return_size = 0;
7742 *ret_data_size = 0;
7744 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7745 return NT_STATUS_INVALID_LEVEL;
7748 if (!CAN_WRITE(conn)) {
7749 /* Allow POSIX opens. The open path will deny
7750 * any non-readonly opens. */
7751 if (info_level != SMB_POSIX_PATH_OPEN) {
7752 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7756 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7757 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7758 fsp ? fsp->fnum : -1, info_level, total_data));
7760 switch (info_level) {
7762 case SMB_INFO_STANDARD:
7764 status = smb_set_info_standard(conn,
7765 pdata,
7766 total_data,
7767 fsp,
7768 smb_fname);
7769 break;
7772 case SMB_INFO_SET_EA:
7774 status = smb_info_set_ea(conn,
7775 pdata,
7776 total_data,
7777 fsp,
7778 smb_fname);
7779 break;
7782 case SMB_SET_FILE_BASIC_INFO:
7783 case SMB_FILE_BASIC_INFORMATION:
7785 status = smb_set_file_basic_info(conn,
7786 pdata,
7787 total_data,
7788 fsp,
7789 smb_fname);
7790 break;
7793 case SMB_FILE_ALLOCATION_INFORMATION:
7794 case SMB_SET_FILE_ALLOCATION_INFO:
7796 status = smb_set_file_allocation_info(conn, req,
7797 pdata,
7798 total_data,
7799 fsp,
7800 smb_fname);
7801 break;
7804 case SMB_FILE_END_OF_FILE_INFORMATION:
7805 case SMB_SET_FILE_END_OF_FILE_INFO:
7808 * XP/Win7 both fail after the createfile with
7809 * SMB_SET_FILE_END_OF_FILE_INFO but not
7810 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7811 * The level is known here, so pass it down
7812 * appropriately.
7814 bool should_fail =
7815 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7817 status = smb_set_file_end_of_file_info(conn, req,
7818 pdata,
7819 total_data,
7820 fsp,
7821 smb_fname,
7822 should_fail);
7823 break;
7826 case SMB_FILE_DISPOSITION_INFORMATION:
7827 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7829 #if 0
7830 /* JRA - We used to just ignore this on a path ?
7831 * Shouldn't this be invalid level on a pathname
7832 * based call ?
7834 if (tran_call != TRANSACT2_SETFILEINFO) {
7835 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7837 #endif
7838 status = smb_set_file_disposition_info(conn,
7839 pdata,
7840 total_data,
7841 fsp,
7842 smb_fname);
7843 break;
7846 case SMB_FILE_POSITION_INFORMATION:
7848 status = smb_file_position_information(conn,
7849 pdata,
7850 total_data,
7851 fsp);
7852 break;
7855 case SMB_FILE_FULL_EA_INFORMATION:
7857 status = smb_set_file_full_ea_info(conn,
7858 pdata,
7859 total_data,
7860 fsp);
7861 break;
7864 /* From tridge Samba4 :
7865 * MODE_INFORMATION in setfileinfo (I have no
7866 * idea what "mode information" on a file is - it takes a value of 0,
7867 * 2, 4 or 6. What could it be?).
7870 case SMB_FILE_MODE_INFORMATION:
7872 status = smb_file_mode_information(conn,
7873 pdata,
7874 total_data);
7875 break;
7879 * CIFS UNIX extensions.
7882 case SMB_SET_FILE_UNIX_BASIC:
7884 status = smb_set_file_unix_basic(conn, req,
7885 pdata,
7886 total_data,
7887 fsp,
7888 smb_fname);
7889 break;
7892 case SMB_SET_FILE_UNIX_INFO2:
7894 status = smb_set_file_unix_info2(conn, req,
7895 pdata,
7896 total_data,
7897 fsp,
7898 smb_fname);
7899 break;
7902 case SMB_SET_FILE_UNIX_LINK:
7904 if (fsp) {
7905 /* We must have a pathname for this. */
7906 return NT_STATUS_INVALID_LEVEL;
7908 status = smb_set_file_unix_link(conn, req, pdata,
7909 total_data, smb_fname);
7910 break;
7913 case SMB_SET_FILE_UNIX_HLINK:
7915 if (fsp) {
7916 /* We must have a pathname for this. */
7917 return NT_STATUS_INVALID_LEVEL;
7919 status = smb_set_file_unix_hlink(conn, req,
7920 pdata, total_data,
7921 smb_fname);
7922 break;
7925 case SMB_FILE_RENAME_INFORMATION:
7927 status = smb_file_rename_information(conn, req,
7928 pdata, total_data,
7929 fsp, smb_fname);
7930 break;
7933 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7935 /* SMB2 rename information. */
7936 status = smb2_file_rename_information(conn, req,
7937 pdata, total_data,
7938 fsp, smb_fname);
7939 break;
7942 case SMB_FILE_LINK_INFORMATION:
7944 status = smb_file_link_information(conn, req,
7945 pdata, total_data,
7946 fsp, smb_fname);
7947 break;
7950 #if defined(HAVE_POSIX_ACLS)
7951 case SMB_SET_POSIX_ACL:
7953 status = smb_set_posix_acl(conn,
7954 pdata,
7955 total_data,
7956 fsp,
7957 smb_fname);
7958 break;
7960 #endif
7962 case SMB_SET_POSIX_LOCK:
7964 if (!fsp) {
7965 return NT_STATUS_INVALID_LEVEL;
7967 status = smb_set_posix_lock(conn, req,
7968 pdata, total_data, fsp);
7969 break;
7972 case SMB_POSIX_PATH_OPEN:
7974 if (fsp) {
7975 /* We must have a pathname for this. */
7976 return NT_STATUS_INVALID_LEVEL;
7979 status = smb_posix_open(conn, req,
7980 ppdata,
7981 total_data,
7982 smb_fname,
7983 &data_return_size);
7984 break;
7987 case SMB_POSIX_PATH_UNLINK:
7989 if (fsp) {
7990 /* We must have a pathname for this. */
7991 return NT_STATUS_INVALID_LEVEL;
7994 status = smb_posix_unlink(conn, req,
7995 pdata,
7996 total_data,
7997 smb_fname);
7998 break;
8001 default:
8002 return NT_STATUS_INVALID_LEVEL;
8005 if (!NT_STATUS_IS_OK(status)) {
8006 return status;
8009 *ret_data_size = data_return_size;
8010 return NT_STATUS_OK;
8013 /****************************************************************************
8014 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8015 ****************************************************************************/
8017 static void call_trans2setfilepathinfo(connection_struct *conn,
8018 struct smb_request *req,
8019 unsigned int tran_call,
8020 char **pparams, int total_params,
8021 char **ppdata, int total_data,
8022 unsigned int max_data_bytes)
8024 char *params = *pparams;
8025 char *pdata = *ppdata;
8026 uint16 info_level;
8027 struct smb_filename *smb_fname = NULL;
8028 files_struct *fsp = NULL;
8029 NTSTATUS status = NT_STATUS_OK;
8030 int data_return_size = 0;
8032 if (!params) {
8033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8034 return;
8037 if (tran_call == TRANSACT2_SETFILEINFO) {
8038 if (total_params < 4) {
8039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8040 return;
8043 fsp = file_fsp(req, SVAL(params,0));
8044 /* Basic check for non-null fsp. */
8045 if (!check_fsp_open(conn, req, fsp)) {
8046 return;
8048 info_level = SVAL(params,2);
8050 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8051 &smb_fname);
8052 if (!NT_STATUS_IS_OK(status)) {
8053 reply_nterror(req, status);
8054 return;
8057 if(fsp->fh->fd == -1) {
8059 * This is actually a SETFILEINFO on a directory
8060 * handle (returned from an NT SMB). NT5.0 seems
8061 * to do this call. JRA.
8063 if (INFO_LEVEL_IS_UNIX(info_level)) {
8064 /* Always do lstat for UNIX calls. */
8065 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8066 DEBUG(3,("call_trans2setfilepathinfo: "
8067 "SMB_VFS_LSTAT of %s failed "
8068 "(%s)\n",
8069 smb_fname_str_dbg(smb_fname),
8070 strerror(errno)));
8071 reply_nterror(req, map_nt_error_from_unix(errno));
8072 return;
8074 } else {
8075 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8076 DEBUG(3,("call_trans2setfilepathinfo: "
8077 "fileinfo of %s failed (%s)\n",
8078 smb_fname_str_dbg(smb_fname),
8079 strerror(errno)));
8080 reply_nterror(req, map_nt_error_from_unix(errno));
8081 return;
8084 } else if (fsp->print_file) {
8086 * Doing a DELETE_ON_CLOSE should cancel a print job.
8088 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8089 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8091 DEBUG(3,("call_trans2setfilepathinfo: "
8092 "Cancelling print job (%s)\n",
8093 fsp_str_dbg(fsp)));
8095 SSVAL(params,0,0);
8096 send_trans2_replies(conn, req, params, 2,
8097 *ppdata, 0,
8098 max_data_bytes);
8099 return;
8100 } else {
8101 reply_nterror(req,
8102 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8103 return;
8105 } else {
8107 * Original code - this is an open file.
8109 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8110 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8111 "of fnum %d failed (%s)\n", fsp->fnum,
8112 strerror(errno)));
8113 reply_nterror(req, map_nt_error_from_unix(errno));
8114 return;
8117 } else {
8118 char *fname = NULL;
8119 uint32_t ucf_flags = 0;
8121 /* set path info */
8122 if (total_params < 7) {
8123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8124 return;
8127 info_level = SVAL(params,0);
8128 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8129 total_params - 6, STR_TERMINATE,
8130 &status);
8131 if (!NT_STATUS_IS_OK(status)) {
8132 reply_nterror(req, status);
8133 return;
8136 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8137 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8138 info_level == SMB_FILE_RENAME_INFORMATION ||
8139 info_level == SMB_POSIX_PATH_UNLINK) {
8140 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8143 status = filename_convert(req, conn,
8144 req->flags2 & FLAGS2_DFS_PATHNAMES,
8145 fname,
8146 ucf_flags,
8147 NULL,
8148 &smb_fname);
8149 if (!NT_STATUS_IS_OK(status)) {
8150 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8151 reply_botherror(req,
8152 NT_STATUS_PATH_NOT_COVERED,
8153 ERRSRV, ERRbadpath);
8154 return;
8156 reply_nterror(req, status);
8157 return;
8160 if (INFO_LEVEL_IS_UNIX(info_level)) {
8162 * For CIFS UNIX extensions the target name may not exist.
8165 /* Always do lstat for UNIX calls. */
8166 SMB_VFS_LSTAT(conn, smb_fname);
8168 } else if (!VALID_STAT(smb_fname->st) &&
8169 SMB_VFS_STAT(conn, smb_fname)) {
8170 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8171 "%s failed (%s)\n",
8172 smb_fname_str_dbg(smb_fname),
8173 strerror(errno)));
8174 reply_nterror(req, map_nt_error_from_unix(errno));
8175 return;
8179 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8180 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8181 fsp ? fsp->fnum : -1, info_level,total_data));
8183 /* Realloc the parameter size */
8184 *pparams = (char *)SMB_REALLOC(*pparams,2);
8185 if (*pparams == NULL) {
8186 reply_nterror(req, NT_STATUS_NO_MEMORY);
8187 return;
8189 params = *pparams;
8191 SSVAL(params,0,0);
8193 status = smbd_do_setfilepathinfo(conn, req, req,
8194 info_level,
8195 fsp,
8196 smb_fname,
8197 ppdata, total_data,
8198 &data_return_size);
8199 if (!NT_STATUS_IS_OK(status)) {
8200 if (open_was_deferred(req->mid)) {
8201 /* We have re-scheduled this call. */
8202 return;
8204 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8205 /* We have re-scheduled this call. */
8206 return;
8208 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8209 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8210 ERRSRV, ERRbadpath);
8211 return;
8213 if (info_level == SMB_POSIX_PATH_OPEN) {
8214 reply_openerror(req, status);
8215 return;
8218 reply_nterror(req, status);
8219 return;
8222 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8223 max_data_bytes);
8225 return;
8228 /****************************************************************************
8229 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8230 ****************************************************************************/
8232 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8233 char **pparams, int total_params,
8234 char **ppdata, int total_data,
8235 unsigned int max_data_bytes)
8237 struct smb_filename *smb_dname = NULL;
8238 char *params = *pparams;
8239 char *pdata = *ppdata;
8240 char *directory = NULL;
8241 NTSTATUS status = NT_STATUS_OK;
8242 struct ea_list *ea_list = NULL;
8243 TALLOC_CTX *ctx = talloc_tos();
8245 if (!CAN_WRITE(conn)) {
8246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8247 return;
8250 if (total_params < 5) {
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8252 return;
8255 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8256 total_params - 4, STR_TERMINATE,
8257 &status);
8258 if (!NT_STATUS_IS_OK(status)) {
8259 reply_nterror(req, status);
8260 return;
8263 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8265 status = filename_convert(ctx,
8266 conn,
8267 req->flags2 & FLAGS2_DFS_PATHNAMES,
8268 directory,
8270 NULL,
8271 &smb_dname);
8273 if (!NT_STATUS_IS_OK(status)) {
8274 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8275 reply_botherror(req,
8276 NT_STATUS_PATH_NOT_COVERED,
8277 ERRSRV, ERRbadpath);
8278 return;
8280 reply_nterror(req, status);
8281 return;
8285 * OS/2 workplace shell seems to send SET_EA requests of "null"
8286 * length (4 bytes containing IVAL 4).
8287 * They seem to have no effect. Bug #3212. JRA.
8290 if (total_data && (total_data != 4)) {
8291 /* Any data in this call is an EA list. */
8292 if (total_data < 10) {
8293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8294 goto out;
8297 if (IVAL(pdata,0) > total_data) {
8298 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8299 IVAL(pdata,0), (unsigned int)total_data));
8300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8301 goto out;
8304 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8305 total_data - 4);
8306 if (!ea_list) {
8307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8308 goto out;
8311 if (!lp_ea_support(SNUM(conn))) {
8312 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8313 goto out;
8316 /* If total_data == 4 Windows doesn't care what values
8317 * are placed in that field, it just ignores them.
8318 * The System i QNTC IBM SMB client puts bad values here,
8319 * so ignore them. */
8321 status = create_directory(conn, req, smb_dname);
8323 if (!NT_STATUS_IS_OK(status)) {
8324 reply_nterror(req, status);
8325 goto out;
8328 /* Try and set any given EA. */
8329 if (ea_list) {
8330 status = set_ea(conn, NULL, smb_dname, ea_list);
8331 if (!NT_STATUS_IS_OK(status)) {
8332 reply_nterror(req, status);
8333 goto out;
8337 /* Realloc the parameter and data sizes */
8338 *pparams = (char *)SMB_REALLOC(*pparams,2);
8339 if(*pparams == NULL) {
8340 reply_nterror(req, NT_STATUS_NO_MEMORY);
8341 goto out;
8343 params = *pparams;
8345 SSVAL(params,0,0);
8347 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8349 out:
8350 TALLOC_FREE(smb_dname);
8351 return;
8354 /****************************************************************************
8355 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8356 We don't actually do this - we just send a null response.
8357 ****************************************************************************/
8359 static void call_trans2findnotifyfirst(connection_struct *conn,
8360 struct smb_request *req,
8361 char **pparams, int total_params,
8362 char **ppdata, int total_data,
8363 unsigned int max_data_bytes)
8365 char *params = *pparams;
8366 uint16 info_level;
8368 if (total_params < 6) {
8369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8370 return;
8373 info_level = SVAL(params,4);
8374 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8376 switch (info_level) {
8377 case 1:
8378 case 2:
8379 break;
8380 default:
8381 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8382 return;
8385 /* Realloc the parameter and data sizes */
8386 *pparams = (char *)SMB_REALLOC(*pparams,6);
8387 if (*pparams == NULL) {
8388 reply_nterror(req, NT_STATUS_NO_MEMORY);
8389 return;
8391 params = *pparams;
8393 SSVAL(params,0,fnf_handle);
8394 SSVAL(params,2,0); /* No changes */
8395 SSVAL(params,4,0); /* No EA errors */
8397 fnf_handle++;
8399 if(fnf_handle == 0)
8400 fnf_handle = 257;
8402 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8404 return;
8407 /****************************************************************************
8408 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8409 changes). Currently this does nothing.
8410 ****************************************************************************/
8412 static void call_trans2findnotifynext(connection_struct *conn,
8413 struct smb_request *req,
8414 char **pparams, int total_params,
8415 char **ppdata, int total_data,
8416 unsigned int max_data_bytes)
8418 char *params = *pparams;
8420 DEBUG(3,("call_trans2findnotifynext\n"));
8422 /* Realloc the parameter and data sizes */
8423 *pparams = (char *)SMB_REALLOC(*pparams,4);
8424 if (*pparams == NULL) {
8425 reply_nterror(req, NT_STATUS_NO_MEMORY);
8426 return;
8428 params = *pparams;
8430 SSVAL(params,0,0); /* No changes */
8431 SSVAL(params,2,0); /* No EA errors */
8433 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8435 return;
8438 /****************************************************************************
8439 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8440 ****************************************************************************/
8442 static void call_trans2getdfsreferral(connection_struct *conn,
8443 struct smb_request *req,
8444 char **pparams, int total_params,
8445 char **ppdata, int total_data,
8446 unsigned int max_data_bytes)
8448 char *params = *pparams;
8449 char *pathname = NULL;
8450 int reply_size = 0;
8451 int max_referral_level;
8452 NTSTATUS status = NT_STATUS_OK;
8453 TALLOC_CTX *ctx = talloc_tos();
8455 DEBUG(10,("call_trans2getdfsreferral\n"));
8457 if (total_params < 3) {
8458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8459 return;
8462 max_referral_level = SVAL(params,0);
8464 if(!lp_host_msdfs()) {
8465 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8466 return;
8469 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8470 total_params - 2, STR_TERMINATE);
8471 if (!pathname) {
8472 reply_nterror(req, NT_STATUS_NOT_FOUND);
8473 return;
8475 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8476 ppdata,&status)) < 0) {
8477 reply_nterror(req, status);
8478 return;
8481 SSVAL(req->inbuf, smb_flg2,
8482 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8483 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8485 return;
8488 #define LMCAT_SPL 0x53
8489 #define LMFUNC_GETJOBID 0x60
8491 /****************************************************************************
8492 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8493 ****************************************************************************/
8495 static void call_trans2ioctl(connection_struct *conn,
8496 struct smb_request *req,
8497 char **pparams, int total_params,
8498 char **ppdata, int total_data,
8499 unsigned int max_data_bytes)
8501 char *pdata = *ppdata;
8502 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8504 /* check for an invalid fid before proceeding */
8506 if (!fsp) {
8507 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8508 return;
8511 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8512 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8513 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8514 if (*ppdata == NULL) {
8515 reply_nterror(req, NT_STATUS_NO_MEMORY);
8516 return;
8518 pdata = *ppdata;
8520 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8521 CAN ACCEPT THIS IN UNICODE. JRA. */
8523 /* Job number */
8524 if (fsp->print_file) {
8525 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8526 } else {
8527 SSVAL(pdata, 0, 0);
8529 srvstr_push(pdata, req->flags2, pdata + 2,
8530 global_myname(), 15,
8531 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8532 srvstr_push(pdata, req->flags2, pdata+18,
8533 lp_servicename(SNUM(conn)), 13,
8534 STR_ASCII|STR_TERMINATE); /* Service name */
8535 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8536 max_data_bytes);
8537 return;
8540 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8541 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8544 /****************************************************************************
8545 Reply to a SMBfindclose (stop trans2 directory search).
8546 ****************************************************************************/
8548 void reply_findclose(struct smb_request *req)
8550 int dptr_num;
8551 struct smbd_server_connection *sconn = req->sconn;
8553 START_PROFILE(SMBfindclose);
8555 if (req->wct < 1) {
8556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8557 END_PROFILE(SMBfindclose);
8558 return;
8561 dptr_num = SVALS(req->vwv+0, 0);
8563 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8565 dptr_close(sconn, &dptr_num);
8567 reply_outbuf(req, 0, 0);
8569 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8571 END_PROFILE(SMBfindclose);
8572 return;
8575 /****************************************************************************
8576 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8577 ****************************************************************************/
8579 void reply_findnclose(struct smb_request *req)
8581 int dptr_num;
8583 START_PROFILE(SMBfindnclose);
8585 if (req->wct < 1) {
8586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8587 END_PROFILE(SMBfindnclose);
8588 return;
8591 dptr_num = SVAL(req->vwv+0, 0);
8593 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8595 /* We never give out valid handles for a
8596 findnotifyfirst - so any dptr_num is ok here.
8597 Just ignore it. */
8599 reply_outbuf(req, 0, 0);
8601 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8603 END_PROFILE(SMBfindnclose);
8604 return;
8607 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8608 struct trans_state *state)
8610 if (get_Protocol() >= PROTOCOL_NT1) {
8611 req->flags2 |= 0x40; /* IS_LONG_NAME */
8612 SSVAL(req->inbuf,smb_flg2,req->flags2);
8615 if (conn->encrypt_level == Required && !req->encrypted) {
8616 if (state->call != TRANSACT2_QFSINFO &&
8617 state->call != TRANSACT2_SETFSINFO) {
8618 DEBUG(0,("handle_trans2: encryption required "
8619 "with call 0x%x\n",
8620 (unsigned int)state->call));
8621 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8622 return;
8626 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8628 /* Now we must call the relevant TRANS2 function */
8629 switch(state->call) {
8630 case TRANSACT2_OPEN:
8632 START_PROFILE(Trans2_open);
8633 call_trans2open(conn, req,
8634 &state->param, state->total_param,
8635 &state->data, state->total_data,
8636 state->max_data_return);
8637 END_PROFILE(Trans2_open);
8638 break;
8641 case TRANSACT2_FINDFIRST:
8643 START_PROFILE(Trans2_findfirst);
8644 call_trans2findfirst(conn, req,
8645 &state->param, state->total_param,
8646 &state->data, state->total_data,
8647 state->max_data_return);
8648 END_PROFILE(Trans2_findfirst);
8649 break;
8652 case TRANSACT2_FINDNEXT:
8654 START_PROFILE(Trans2_findnext);
8655 call_trans2findnext(conn, req,
8656 &state->param, state->total_param,
8657 &state->data, state->total_data,
8658 state->max_data_return);
8659 END_PROFILE(Trans2_findnext);
8660 break;
8663 case TRANSACT2_QFSINFO:
8665 START_PROFILE(Trans2_qfsinfo);
8666 call_trans2qfsinfo(conn, req,
8667 &state->param, state->total_param,
8668 &state->data, state->total_data,
8669 state->max_data_return);
8670 END_PROFILE(Trans2_qfsinfo);
8671 break;
8674 case TRANSACT2_SETFSINFO:
8676 START_PROFILE(Trans2_setfsinfo);
8677 call_trans2setfsinfo(conn, req,
8678 &state->param, state->total_param,
8679 &state->data, state->total_data,
8680 state->max_data_return);
8681 END_PROFILE(Trans2_setfsinfo);
8682 break;
8685 case TRANSACT2_QPATHINFO:
8686 case TRANSACT2_QFILEINFO:
8688 START_PROFILE(Trans2_qpathinfo);
8689 call_trans2qfilepathinfo(conn, req, state->call,
8690 &state->param, state->total_param,
8691 &state->data, state->total_data,
8692 state->max_data_return);
8693 END_PROFILE(Trans2_qpathinfo);
8694 break;
8697 case TRANSACT2_SETPATHINFO:
8698 case TRANSACT2_SETFILEINFO:
8700 START_PROFILE(Trans2_setpathinfo);
8701 call_trans2setfilepathinfo(conn, req, state->call,
8702 &state->param, state->total_param,
8703 &state->data, state->total_data,
8704 state->max_data_return);
8705 END_PROFILE(Trans2_setpathinfo);
8706 break;
8709 case TRANSACT2_FINDNOTIFYFIRST:
8711 START_PROFILE(Trans2_findnotifyfirst);
8712 call_trans2findnotifyfirst(conn, req,
8713 &state->param, state->total_param,
8714 &state->data, state->total_data,
8715 state->max_data_return);
8716 END_PROFILE(Trans2_findnotifyfirst);
8717 break;
8720 case TRANSACT2_FINDNOTIFYNEXT:
8722 START_PROFILE(Trans2_findnotifynext);
8723 call_trans2findnotifynext(conn, req,
8724 &state->param, state->total_param,
8725 &state->data, state->total_data,
8726 state->max_data_return);
8727 END_PROFILE(Trans2_findnotifynext);
8728 break;
8731 case TRANSACT2_MKDIR:
8733 START_PROFILE(Trans2_mkdir);
8734 call_trans2mkdir(conn, req,
8735 &state->param, state->total_param,
8736 &state->data, state->total_data,
8737 state->max_data_return);
8738 END_PROFILE(Trans2_mkdir);
8739 break;
8742 case TRANSACT2_GET_DFS_REFERRAL:
8744 START_PROFILE(Trans2_get_dfs_referral);
8745 call_trans2getdfsreferral(conn, req,
8746 &state->param, state->total_param,
8747 &state->data, state->total_data,
8748 state->max_data_return);
8749 END_PROFILE(Trans2_get_dfs_referral);
8750 break;
8753 case TRANSACT2_IOCTL:
8755 START_PROFILE(Trans2_ioctl);
8756 call_trans2ioctl(conn, req,
8757 &state->param, state->total_param,
8758 &state->data, state->total_data,
8759 state->max_data_return);
8760 END_PROFILE(Trans2_ioctl);
8761 break;
8764 default:
8765 /* Error in request */
8766 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8767 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8771 /****************************************************************************
8772 Reply to a SMBtrans2.
8773 ****************************************************************************/
8775 void reply_trans2(struct smb_request *req)
8777 connection_struct *conn = req->conn;
8778 unsigned int dsoff;
8779 unsigned int dscnt;
8780 unsigned int psoff;
8781 unsigned int pscnt;
8782 unsigned int tran_call;
8783 struct trans_state *state;
8784 NTSTATUS result;
8786 START_PROFILE(SMBtrans2);
8788 if (req->wct < 14) {
8789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8790 END_PROFILE(SMBtrans2);
8791 return;
8794 dsoff = SVAL(req->vwv+12, 0);
8795 dscnt = SVAL(req->vwv+11, 0);
8796 psoff = SVAL(req->vwv+10, 0);
8797 pscnt = SVAL(req->vwv+9, 0);
8798 tran_call = SVAL(req->vwv+14, 0);
8800 result = allow_new_trans(conn->pending_trans, req->mid);
8801 if (!NT_STATUS_IS_OK(result)) {
8802 DEBUG(2, ("Got invalid trans2 request: %s\n",
8803 nt_errstr(result)));
8804 reply_nterror(req, result);
8805 END_PROFILE(SMBtrans2);
8806 return;
8809 if (IS_IPC(conn)) {
8810 switch (tran_call) {
8811 /* List the allowed trans2 calls on IPC$ */
8812 case TRANSACT2_OPEN:
8813 case TRANSACT2_GET_DFS_REFERRAL:
8814 case TRANSACT2_QFILEINFO:
8815 case TRANSACT2_QFSINFO:
8816 case TRANSACT2_SETFSINFO:
8817 break;
8818 default:
8819 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8820 END_PROFILE(SMBtrans2);
8821 return;
8825 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8826 DEBUG(0, ("talloc failed\n"));
8827 reply_nterror(req, NT_STATUS_NO_MEMORY);
8828 END_PROFILE(SMBtrans2);
8829 return;
8832 state->cmd = SMBtrans2;
8834 state->mid = req->mid;
8835 state->vuid = req->vuid;
8836 state->setup_count = SVAL(req->vwv+13, 0);
8837 state->setup = NULL;
8838 state->total_param = SVAL(req->vwv+0, 0);
8839 state->param = NULL;
8840 state->total_data = SVAL(req->vwv+1, 0);
8841 state->data = NULL;
8842 state->max_param_return = SVAL(req->vwv+2, 0);
8843 state->max_data_return = SVAL(req->vwv+3, 0);
8844 state->max_setup_return = SVAL(req->vwv+4, 0);
8845 state->close_on_completion = BITSETW(req->vwv+5, 0);
8846 state->one_way = BITSETW(req->vwv+5, 1);
8848 state->call = tran_call;
8850 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8851 is so as a sanity check */
8852 if (state->setup_count != 1) {
8854 * Need to have rc=0 for ioctl to get job id for OS/2.
8855 * Network printing will fail if function is not successful.
8856 * Similar function in reply.c will be used if protocol
8857 * is LANMAN1.0 instead of LM1.2X002.
8858 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8859 * outbuf doesn't have to be set(only job id is used).
8861 if ( (state->setup_count == 4)
8862 && (tran_call == TRANSACT2_IOCTL)
8863 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8864 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8865 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8866 } else {
8867 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8868 DEBUG(2,("Transaction is %d\n",tran_call));
8869 TALLOC_FREE(state);
8870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8871 END_PROFILE(SMBtrans2);
8872 return;
8876 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8877 goto bad_param;
8879 if (state->total_data) {
8881 if (trans_oob(state->total_data, 0, dscnt)
8882 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8883 goto bad_param;
8886 /* Can't use talloc here, the core routines do realloc on the
8887 * params and data. */
8888 state->data = (char *)SMB_MALLOC(state->total_data);
8889 if (state->data == NULL) {
8890 DEBUG(0,("reply_trans2: data malloc fail for %u "
8891 "bytes !\n", (unsigned int)state->total_data));
8892 TALLOC_FREE(state);
8893 reply_nterror(req, NT_STATUS_NO_MEMORY);
8894 END_PROFILE(SMBtrans2);
8895 return;
8898 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8901 if (state->total_param) {
8903 if (trans_oob(state->total_param, 0, pscnt)
8904 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8905 goto bad_param;
8908 /* Can't use talloc here, the core routines do realloc on the
8909 * params and data. */
8910 state->param = (char *)SMB_MALLOC(state->total_param);
8911 if (state->param == NULL) {
8912 DEBUG(0,("reply_trans: param malloc fail for %u "
8913 "bytes !\n", (unsigned int)state->total_param));
8914 SAFE_FREE(state->data);
8915 TALLOC_FREE(state);
8916 reply_nterror(req, NT_STATUS_NO_MEMORY);
8917 END_PROFILE(SMBtrans2);
8918 return;
8921 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8924 state->received_data = dscnt;
8925 state->received_param = pscnt;
8927 if ((state->received_param == state->total_param) &&
8928 (state->received_data == state->total_data)) {
8930 handle_trans2(conn, req, state);
8932 SAFE_FREE(state->data);
8933 SAFE_FREE(state->param);
8934 TALLOC_FREE(state);
8935 END_PROFILE(SMBtrans2);
8936 return;
8939 DLIST_ADD(conn->pending_trans, state);
8941 /* We need to send an interim response then receive the rest
8942 of the parameter/data bytes */
8943 reply_outbuf(req, 0, 0);
8944 show_msg((char *)req->outbuf);
8945 END_PROFILE(SMBtrans2);
8946 return;
8948 bad_param:
8950 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8951 SAFE_FREE(state->data);
8952 SAFE_FREE(state->param);
8953 TALLOC_FREE(state);
8954 END_PROFILE(SMBtrans2);
8955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8959 /****************************************************************************
8960 Reply to a SMBtranss2
8961 ****************************************************************************/
8963 void reply_transs2(struct smb_request *req)
8965 connection_struct *conn = req->conn;
8966 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8967 struct trans_state *state;
8969 START_PROFILE(SMBtranss2);
8971 show_msg((char *)req->inbuf);
8973 /* Windows clients expect all replies to
8974 a transact secondary (SMBtranss2 0x33)
8975 to have a command code of transact
8976 (SMBtrans2 0x32). See bug #8989
8977 and also [MS-CIFS] section 2.2.4.47.2
8978 for details.
8980 req->cmd = SMBtrans2;
8982 if (req->wct < 8) {
8983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8984 END_PROFILE(SMBtranss2);
8985 return;
8988 for (state = conn->pending_trans; state != NULL;
8989 state = state->next) {
8990 if (state->mid == req->mid) {
8991 break;
8995 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8997 END_PROFILE(SMBtranss2);
8998 return;
9001 /* Revise state->total_param and state->total_data in case they have
9002 changed downwards */
9004 if (SVAL(req->vwv+0, 0) < state->total_param)
9005 state->total_param = SVAL(req->vwv+0, 0);
9006 if (SVAL(req->vwv+1, 0) < state->total_data)
9007 state->total_data = SVAL(req->vwv+1, 0);
9009 pcnt = SVAL(req->vwv+2, 0);
9010 poff = SVAL(req->vwv+3, 0);
9011 pdisp = SVAL(req->vwv+4, 0);
9013 dcnt = SVAL(req->vwv+5, 0);
9014 doff = SVAL(req->vwv+6, 0);
9015 ddisp = SVAL(req->vwv+7, 0);
9017 state->received_param += pcnt;
9018 state->received_data += dcnt;
9020 if ((state->received_data > state->total_data) ||
9021 (state->received_param > state->total_param))
9022 goto bad_param;
9024 if (pcnt) {
9025 if (trans_oob(state->total_param, pdisp, pcnt)
9026 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9027 goto bad_param;
9029 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9032 if (dcnt) {
9033 if (trans_oob(state->total_data, ddisp, dcnt)
9034 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9035 goto bad_param;
9037 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9040 if ((state->received_param < state->total_param) ||
9041 (state->received_data < state->total_data)) {
9042 END_PROFILE(SMBtranss2);
9043 return;
9046 handle_trans2(conn, req, state);
9048 DLIST_REMOVE(conn->pending_trans, state);
9049 SAFE_FREE(state->data);
9050 SAFE_FREE(state->param);
9051 TALLOC_FREE(state);
9053 END_PROFILE(SMBtranss2);
9054 return;
9056 bad_param:
9058 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9059 DLIST_REMOVE(conn->pending_trans, state);
9060 SAFE_FREE(state->data);
9061 SAFE_FREE(state->param);
9062 TALLOC_FREE(state);
9063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9064 END_PROFILE(SMBtranss2);
9065 return;