smbd: qfilepathinfo has fixed/variable buffers
[Samba.git] / source3 / smbd / trans2.c
blobf1da13eb3de18ffc2e8de51f2733096b5d4e9fd4
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 struct smb_filename *fname,
2975 char **ppdata,
2976 int *ret_data_len)
2978 char *pdata, *end_data;
2979 int data_len = 0, len;
2980 const char *vname = volume_label(SNUM(conn));
2981 int snum = SNUM(conn);
2982 char *fstype = lp_fstype(SNUM(conn));
2983 const char *filename = NULL;
2984 uint32 additional_flags = 0;
2985 struct smb_filename smb_fname;
2986 SMB_STRUCT_STAT st;
2987 NTSTATUS status = NT_STATUS_OK;
2989 if (fname == NULL || fname->base_name == NULL) {
2990 filename = ".";
2991 } else {
2992 filename = fname->base_name;
2995 if (IS_IPC(conn)) {
2996 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2997 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2998 "info level (0x%x) on IPC$.\n",
2999 (unsigned int)info_level));
3000 return NT_STATUS_ACCESS_DENIED;
3004 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3006 ZERO_STRUCT(smb_fname);
3007 smb_fname.base_name = discard_const_p(char, filename);
3009 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3010 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3011 return map_nt_error_from_unix(errno);
3014 st = smb_fname.st;
3016 *ppdata = (char *)SMB_REALLOC(
3017 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3018 if (*ppdata == NULL) {
3019 return NT_STATUS_NO_MEMORY;
3022 pdata = *ppdata;
3023 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3024 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3026 switch (info_level) {
3027 case SMB_INFO_ALLOCATION:
3029 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3030 data_len = 18;
3031 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3032 return map_nt_error_from_unix(errno);
3035 block_size = lp_block_size(snum);
3036 if (bsize < block_size) {
3037 uint64_t factor = block_size/bsize;
3038 bsize = block_size;
3039 dsize /= factor;
3040 dfree /= factor;
3042 if (bsize > block_size) {
3043 uint64_t factor = bsize/block_size;
3044 bsize = block_size;
3045 dsize *= factor;
3046 dfree *= factor;
3048 bytes_per_sector = 512;
3049 sectors_per_unit = bsize/bytes_per_sector;
3051 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3052 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3053 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3055 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3056 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3057 SIVAL(pdata,l1_cUnit,dsize);
3058 SIVAL(pdata,l1_cUnitAvail,dfree);
3059 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3060 break;
3063 case SMB_INFO_VOLUME:
3064 /* Return volume name */
3066 * Add volume serial number - hash of a combination of
3067 * the called hostname and the service name.
3069 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3071 * Win2k3 and previous mess this up by sending a name length
3072 * one byte short. I believe only older clients (OS/2 Win9x) use
3073 * this call so try fixing this by adding a terminating null to
3074 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3076 len = srvstr_push(
3077 pdata, flags2,
3078 pdata+l2_vol_szVolLabel, vname,
3079 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3080 STR_NOALIGN|STR_TERMINATE);
3081 SCVAL(pdata,l2_vol_cch,len);
3082 data_len = l2_vol_szVolLabel + len;
3083 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3084 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3085 len, vname));
3086 break;
3088 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3089 case SMB_FS_ATTRIBUTE_INFORMATION:
3091 additional_flags = 0;
3092 #if defined(HAVE_SYS_QUOTAS)
3093 additional_flags |= FILE_VOLUME_QUOTAS;
3094 #endif
3096 if(lp_nt_acl_support(SNUM(conn))) {
3097 additional_flags |= FILE_PERSISTENT_ACLS;
3100 /* Capabilities are filled in at connection time through STATVFS call */
3101 additional_flags |= conn->fs_capabilities;
3102 additional_flags |= lp_parm_int(conn->params->service,
3103 "share", "fake_fscaps",
3106 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3107 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3108 additional_flags); /* FS ATTRIBUTES */
3110 SIVAL(pdata,4,255); /* Max filename component length */
3111 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3112 and will think we can't do long filenames */
3113 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3114 PTR_DIFF(end_data, pdata+12),
3115 STR_UNICODE);
3116 SIVAL(pdata,8,len);
3117 data_len = 12 + len;
3118 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3119 /* the client only requested a portion of the
3120 file system name */
3121 data_len = max_data_bytes;
3122 status = STATUS_BUFFER_OVERFLOW;
3124 break;
3126 case SMB_QUERY_FS_LABEL_INFO:
3127 case SMB_FS_LABEL_INFORMATION:
3128 len = srvstr_push(pdata, flags2, pdata+4, vname,
3129 PTR_DIFF(end_data, pdata+4), 0);
3130 data_len = 4 + len;
3131 SIVAL(pdata,0,len);
3132 break;
3134 case SMB_QUERY_FS_VOLUME_INFO:
3135 case SMB_FS_VOLUME_INFORMATION:
3138 * Add volume serial number - hash of a combination of
3139 * the called hostname and the service name.
3141 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3142 (str_checksum(get_local_machine_name())<<16));
3144 /* Max label len is 32 characters. */
3145 len = srvstr_push(pdata, flags2, pdata+18, vname,
3146 PTR_DIFF(end_data, pdata+18),
3147 STR_UNICODE);
3148 SIVAL(pdata,12,len);
3149 data_len = 18+len;
3151 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3152 (int)strlen(vname),vname, lp_servicename(snum)));
3153 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3154 /* the client only requested a portion of the
3155 volume label */
3156 data_len = max_data_bytes;
3157 status = STATUS_BUFFER_OVERFLOW;
3160 break;
3162 case SMB_QUERY_FS_SIZE_INFO:
3163 case SMB_FS_SIZE_INFORMATION:
3165 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3166 data_len = 24;
3167 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3168 return map_nt_error_from_unix(errno);
3170 block_size = lp_block_size(snum);
3171 if (bsize < block_size) {
3172 uint64_t factor = block_size/bsize;
3173 bsize = block_size;
3174 dsize /= factor;
3175 dfree /= factor;
3177 if (bsize > block_size) {
3178 uint64_t factor = bsize/block_size;
3179 bsize = block_size;
3180 dsize *= factor;
3181 dfree *= factor;
3183 bytes_per_sector = 512;
3184 sectors_per_unit = bsize/bytes_per_sector;
3185 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3186 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3187 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3188 SBIG_UINT(pdata,0,dsize);
3189 SBIG_UINT(pdata,8,dfree);
3190 SIVAL(pdata,16,sectors_per_unit);
3191 SIVAL(pdata,20,bytes_per_sector);
3192 break;
3195 case SMB_FS_FULL_SIZE_INFORMATION:
3197 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3198 data_len = 32;
3199 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3200 return map_nt_error_from_unix(errno);
3202 block_size = lp_block_size(snum);
3203 if (bsize < block_size) {
3204 uint64_t factor = block_size/bsize;
3205 bsize = block_size;
3206 dsize /= factor;
3207 dfree /= factor;
3209 if (bsize > block_size) {
3210 uint64_t factor = bsize/block_size;
3211 bsize = block_size;
3212 dsize *= factor;
3213 dfree *= factor;
3215 bytes_per_sector = 512;
3216 sectors_per_unit = bsize/bytes_per_sector;
3217 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3218 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3219 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3220 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3221 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3222 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3223 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3224 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3225 break;
3228 case SMB_QUERY_FS_DEVICE_INFO:
3229 case SMB_FS_DEVICE_INFORMATION:
3231 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3233 if (!CAN_WRITE(conn)) {
3234 characteristics |= FILE_READ_ONLY_DEVICE;
3236 data_len = 8;
3237 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3238 SIVAL(pdata,4,characteristics);
3239 break;
3242 #ifdef HAVE_SYS_QUOTAS
3243 case SMB_FS_QUOTA_INFORMATION:
3245 * what we have to send --metze:
3247 * Unknown1: 24 NULL bytes
3248 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3249 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3250 * Quota Flags: 2 byte :
3251 * Unknown3: 6 NULL bytes
3253 * 48 bytes total
3255 * details for Quota Flags:
3257 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3258 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3259 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3260 * 0x0001 Enable Quotas: enable quota for this fs
3264 /* we need to fake up a fsp here,
3265 * because its not send in this call
3267 files_struct fsp;
3268 SMB_NTQUOTA_STRUCT quotas;
3270 ZERO_STRUCT(fsp);
3271 ZERO_STRUCT(quotas);
3273 fsp.conn = conn;
3274 fsp.fnum = -1;
3276 /* access check */
3277 if (get_current_uid(conn) != 0) {
3278 DEBUG(0,("set_user_quota: access_denied "
3279 "service [%s] user [%s]\n",
3280 lp_servicename(SNUM(conn)),
3281 conn->session_info->unix_name));
3282 return NT_STATUS_ACCESS_DENIED;
3285 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3286 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3287 return map_nt_error_from_unix(errno);
3290 data_len = 48;
3292 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3293 lp_servicename(SNUM(conn))));
3295 /* Unknown1 24 NULL bytes*/
3296 SBIG_UINT(pdata,0,(uint64_t)0);
3297 SBIG_UINT(pdata,8,(uint64_t)0);
3298 SBIG_UINT(pdata,16,(uint64_t)0);
3300 /* Default Soft Quota 8 bytes */
3301 SBIG_UINT(pdata,24,quotas.softlim);
3303 /* Default Hard Quota 8 bytes */
3304 SBIG_UINT(pdata,32,quotas.hardlim);
3306 /* Quota flag 2 bytes */
3307 SSVAL(pdata,40,quotas.qflags);
3309 /* Unknown3 6 NULL bytes */
3310 SSVAL(pdata,42,0);
3311 SIVAL(pdata,44,0);
3313 break;
3315 #endif /* HAVE_SYS_QUOTAS */
3316 case SMB_FS_OBJECTID_INFORMATION:
3318 unsigned char objid[16];
3319 struct smb_extended_info extended_info;
3320 memcpy(pdata,create_volume_objectid(conn, objid),16);
3321 samba_extended_info_version (&extended_info);
3322 SIVAL(pdata,16,extended_info.samba_magic);
3323 SIVAL(pdata,20,extended_info.samba_version);
3324 SIVAL(pdata,24,extended_info.samba_subversion);
3325 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3326 memcpy(pdata+36,extended_info.samba_version_string,28);
3327 data_len = 64;
3328 break;
3332 * Query the version and capabilities of the CIFS UNIX extensions
3333 * in use.
3336 case SMB_QUERY_CIFS_UNIX_INFO:
3338 bool large_write = lp_min_receive_file_size() &&
3339 !srv_is_signing_active(conn->sconn);
3340 bool large_read = !srv_is_signing_active(conn->sconn);
3341 int encrypt_caps = 0;
3343 if (!lp_unix_extensions()) {
3344 return NT_STATUS_INVALID_LEVEL;
3347 switch (conn->encrypt_level) {
3348 case 0:
3349 encrypt_caps = 0;
3350 break;
3351 case 1:
3352 case Auto:
3353 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3354 break;
3355 case Required:
3356 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3357 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3358 large_write = false;
3359 large_read = false;
3360 break;
3363 data_len = 12;
3364 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3365 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3367 /* We have POSIX ACLs, pathname, encryption,
3368 * large read/write, and locking capability. */
3370 SBIG_UINT(pdata,4,((uint64_t)(
3371 CIFS_UNIX_POSIX_ACLS_CAP|
3372 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3373 CIFS_UNIX_FCNTL_LOCKS_CAP|
3374 CIFS_UNIX_EXTATTR_CAP|
3375 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3376 encrypt_caps|
3377 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3378 (large_write ?
3379 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3380 break;
3383 case SMB_QUERY_POSIX_FS_INFO:
3385 int rc;
3386 vfs_statvfs_struct svfs;
3388 if (!lp_unix_extensions()) {
3389 return NT_STATUS_INVALID_LEVEL;
3392 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3394 if (!rc) {
3395 data_len = 56;
3396 SIVAL(pdata,0,svfs.OptimalTransferSize);
3397 SIVAL(pdata,4,svfs.BlockSize);
3398 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3399 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3400 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3401 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3402 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3403 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3405 #ifdef EOPNOTSUPP
3406 } else if (rc == EOPNOTSUPP) {
3407 return NT_STATUS_INVALID_LEVEL;
3408 #endif /* EOPNOTSUPP */
3409 } else {
3410 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3411 return NT_STATUS_DOS(ERRSRV, ERRerror);
3413 break;
3416 case SMB_QUERY_POSIX_WHOAMI:
3418 uint32_t flags = 0;
3419 uint32_t sid_bytes;
3420 int i;
3422 if (!lp_unix_extensions()) {
3423 return NT_STATUS_INVALID_LEVEL;
3426 if (max_data_bytes < 40) {
3427 return NT_STATUS_BUFFER_TOO_SMALL;
3430 /* We ARE guest if global_sid_Builtin_Guests is
3431 * in our list of SIDs.
3433 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3434 conn->session_info->security_token)) {
3435 flags |= SMB_WHOAMI_GUEST;
3438 /* We are NOT guest if global_sid_Authenticated_Users
3439 * is in our list of SIDs.
3441 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3442 conn->session_info->security_token)) {
3443 flags &= ~SMB_WHOAMI_GUEST;
3446 /* NOTE: 8 bytes for UID/GID, irrespective of native
3447 * platform size. This matches
3448 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3450 data_len = 4 /* flags */
3451 + 4 /* flag mask */
3452 + 8 /* uid */
3453 + 8 /* gid */
3454 + 4 /* ngroups */
3455 + 4 /* num_sids */
3456 + 4 /* SID bytes */
3457 + 4 /* pad/reserved */
3458 + (conn->session_info->utok.ngroups * 8)
3459 /* groups list */
3460 + (conn->session_info->security_token->num_sids *
3461 SID_MAX_SIZE)
3462 /* SID list */;
3464 SIVAL(pdata, 0, flags);
3465 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3466 SBIG_UINT(pdata, 8,
3467 (uint64_t)conn->session_info->utok.uid);
3468 SBIG_UINT(pdata, 16,
3469 (uint64_t)conn->session_info->utok.gid);
3472 if (data_len >= max_data_bytes) {
3473 /* Potential overflow, skip the GIDs and SIDs. */
3475 SIVAL(pdata, 24, 0); /* num_groups */
3476 SIVAL(pdata, 28, 0); /* num_sids */
3477 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3478 SIVAL(pdata, 36, 0); /* reserved */
3480 data_len = 40;
3481 break;
3484 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3485 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3487 /* We walk the SID list twice, but this call is fairly
3488 * infrequent, and I don't expect that it's performance
3489 * sensitive -- jpeach
3491 for (i = 0, sid_bytes = 0;
3492 i < conn->session_info->security_token->num_sids; ++i) {
3493 sid_bytes += ndr_size_dom_sid(
3494 &conn->session_info->security_token->sids[i],
3498 /* SID list byte count */
3499 SIVAL(pdata, 32, sid_bytes);
3501 /* 4 bytes pad/reserved - must be zero */
3502 SIVAL(pdata, 36, 0);
3503 data_len = 40;
3505 /* GID list */
3506 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3507 SBIG_UINT(pdata, data_len,
3508 (uint64_t)conn->session_info->utok.groups[i]);
3509 data_len += 8;
3512 /* SID list */
3513 for (i = 0;
3514 i < conn->session_info->security_token->num_sids; ++i) {
3515 int sid_len = ndr_size_dom_sid(
3516 &conn->session_info->security_token->sids[i],
3519 sid_linearize(pdata + data_len, sid_len,
3520 &conn->session_info->security_token->sids[i]);
3521 data_len += sid_len;
3524 break;
3527 case SMB_MAC_QUERY_FS_INFO:
3529 * Thursby MAC extension... ONLY on NTFS filesystems
3530 * once we do streams then we don't need this
3532 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3533 data_len = 88;
3534 SIVAL(pdata,84,0x100); /* Don't support mac... */
3535 break;
3537 /* drop through */
3538 default:
3539 return NT_STATUS_INVALID_LEVEL;
3542 *ret_data_len = data_len;
3543 return status;
3546 /****************************************************************************
3547 Reply to a TRANS2_QFSINFO (query filesystem info).
3548 ****************************************************************************/
3550 static void call_trans2qfsinfo(connection_struct *conn,
3551 struct smb_request *req,
3552 char **pparams, int total_params,
3553 char **ppdata, int total_data,
3554 unsigned int max_data_bytes)
3556 char *params = *pparams;
3557 uint16_t info_level;
3558 int data_len = 0;
3559 NTSTATUS status;
3561 if (total_params < 2) {
3562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3563 return;
3566 info_level = SVAL(params,0);
3568 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3569 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3570 DEBUG(0,("call_trans2qfsinfo: encryption required "
3571 "and info level 0x%x sent.\n",
3572 (unsigned int)info_level));
3573 exit_server_cleanly("encryption required "
3574 "on connection");
3575 return;
3579 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3581 status = smbd_do_qfsinfo(conn, req,
3582 info_level,
3583 req->flags2,
3584 max_data_bytes,
3585 NULL,
3586 ppdata, &data_len);
3587 if (!NT_STATUS_IS_OK(status)) {
3588 reply_nterror(req, status);
3589 return;
3592 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3593 max_data_bytes);
3595 DEBUG( 4, ( "%s info_level = %d\n",
3596 smb_fn_name(req->cmd), info_level) );
3598 return;
3601 /****************************************************************************
3602 Reply to a TRANS2_SETFSINFO (set filesystem info).
3603 ****************************************************************************/
3605 static void call_trans2setfsinfo(connection_struct *conn,
3606 struct smb_request *req,
3607 char **pparams, int total_params,
3608 char **ppdata, int total_data,
3609 unsigned int max_data_bytes)
3611 char *pdata = *ppdata;
3612 char *params = *pparams;
3613 uint16 info_level;
3615 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3617 /* */
3618 if (total_params < 4) {
3619 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3620 total_params));
3621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3622 return;
3625 info_level = SVAL(params,2);
3627 if (IS_IPC(conn)) {
3628 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3629 info_level != SMB_SET_CIFS_UNIX_INFO) {
3630 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3631 "info level (0x%x) on IPC$.\n",
3632 (unsigned int)info_level));
3633 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3634 return;
3638 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3639 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3640 DEBUG(0,("call_trans2setfsinfo: encryption required "
3641 "and info level 0x%x sent.\n",
3642 (unsigned int)info_level));
3643 exit_server_cleanly("encryption required "
3644 "on connection");
3645 return;
3649 switch(info_level) {
3650 case SMB_SET_CIFS_UNIX_INFO:
3652 uint16 client_unix_major;
3653 uint16 client_unix_minor;
3654 uint32 client_unix_cap_low;
3655 uint32 client_unix_cap_high;
3657 if (!lp_unix_extensions()) {
3658 reply_nterror(req,
3659 NT_STATUS_INVALID_LEVEL);
3660 return;
3663 /* There should be 12 bytes of capabilities set. */
3664 if (total_data < 8) {
3665 reply_nterror(
3666 req,
3667 NT_STATUS_INVALID_PARAMETER);
3668 return;
3670 client_unix_major = SVAL(pdata,0);
3671 client_unix_minor = SVAL(pdata,2);
3672 client_unix_cap_low = IVAL(pdata,4);
3673 client_unix_cap_high = IVAL(pdata,8);
3674 /* Just print these values for now. */
3675 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3676 cap_low = 0x%x, cap_high = 0x%x\n",
3677 (unsigned int)client_unix_major,
3678 (unsigned int)client_unix_minor,
3679 (unsigned int)client_unix_cap_low,
3680 (unsigned int)client_unix_cap_high ));
3682 /* Here is where we must switch to posix pathname processing... */
3683 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3684 lp_set_posix_pathnames();
3685 mangle_change_to_posix();
3688 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3689 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3690 /* Client that knows how to do posix locks,
3691 * but not posix open/mkdir operations. Set a
3692 * default type for read/write checks. */
3694 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3697 break;
3700 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3702 NTSTATUS status;
3703 size_t param_len = 0;
3704 size_t data_len = total_data;
3706 if (!lp_unix_extensions()) {
3707 reply_nterror(
3708 req,
3709 NT_STATUS_INVALID_LEVEL);
3710 return;
3713 if (lp_smb_encrypt(SNUM(conn)) == false) {
3714 reply_nterror(
3715 req,
3716 NT_STATUS_NOT_SUPPORTED);
3717 return;
3720 if (req->sconn->smb1.echo_handler.trusted_fde) {
3721 DEBUG( 2,("call_trans2setfsinfo: "
3722 "request transport encryption disabled"
3723 "with 'fork echo handler = yes'\n"));
3724 reply_nterror(
3725 req,
3726 NT_STATUS_NOT_SUPPORTED);
3727 return;
3730 DEBUG( 4,("call_trans2setfsinfo: "
3731 "request transport encryption.\n"));
3733 status = srv_request_encryption_setup(conn,
3734 (unsigned char **)ppdata,
3735 &data_len,
3736 (unsigned char **)pparams,
3737 &param_len);
3739 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3740 !NT_STATUS_IS_OK(status)) {
3741 reply_nterror(req, status);
3742 return;
3745 send_trans2_replies(conn, req,
3746 *pparams,
3747 param_len,
3748 *ppdata,
3749 data_len,
3750 max_data_bytes);
3752 if (NT_STATUS_IS_OK(status)) {
3753 /* Server-side transport
3754 * encryption is now *on*. */
3755 status = srv_encryption_start(conn);
3756 if (!NT_STATUS_IS_OK(status)) {
3757 exit_server_cleanly(
3758 "Failure in setting "
3759 "up encrypted transport");
3762 return;
3765 case SMB_FS_QUOTA_INFORMATION:
3767 files_struct *fsp = NULL;
3768 SMB_NTQUOTA_STRUCT quotas;
3770 ZERO_STRUCT(quotas);
3772 /* access check */
3773 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3774 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3775 lp_servicename(SNUM(conn)),
3776 conn->session_info->unix_name));
3777 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3778 return;
3781 /* note: normaly there're 48 bytes,
3782 * but we didn't use the last 6 bytes for now
3783 * --metze
3785 fsp = file_fsp(req, SVAL(params,0));
3787 if (!check_fsp_ntquota_handle(conn, req,
3788 fsp)) {
3789 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3790 reply_nterror(
3791 req, NT_STATUS_INVALID_HANDLE);
3792 return;
3795 if (total_data < 42) {
3796 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3797 total_data));
3798 reply_nterror(
3799 req,
3800 NT_STATUS_INVALID_PARAMETER);
3801 return;
3804 /* unknown_1 24 NULL bytes in pdata*/
3806 /* the soft quotas 8 bytes (uint64_t)*/
3807 quotas.softlim = BVAL(pdata,24);
3809 /* the hard quotas 8 bytes (uint64_t)*/
3810 quotas.hardlim = BVAL(pdata,32);
3812 /* quota_flags 2 bytes **/
3813 quotas.qflags = SVAL(pdata,40);
3815 /* unknown_2 6 NULL bytes follow*/
3817 /* now set the quotas */
3818 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3819 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3820 reply_nterror(req, map_nt_error_from_unix(errno));
3821 return;
3824 break;
3826 default:
3827 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3828 info_level));
3829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3830 return;
3831 break;
3835 * sending this reply works fine,
3836 * but I'm not sure it's the same
3837 * like windows do...
3838 * --metze
3840 reply_outbuf(req, 10, 0);
3843 #if defined(HAVE_POSIX_ACLS)
3844 /****************************************************************************
3845 Utility function to count the number of entries in a POSIX acl.
3846 ****************************************************************************/
3848 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3850 unsigned int ace_count = 0;
3851 int entry_id = SMB_ACL_FIRST_ENTRY;
3852 SMB_ACL_ENTRY_T entry;
3854 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3855 /* get_next... */
3856 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3857 entry_id = SMB_ACL_NEXT_ENTRY;
3859 ace_count++;
3861 return ace_count;
3864 /****************************************************************************
3865 Utility function to marshall a POSIX acl into wire format.
3866 ****************************************************************************/
3868 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3870 int entry_id = SMB_ACL_FIRST_ENTRY;
3871 SMB_ACL_ENTRY_T entry;
3873 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3874 SMB_ACL_TAG_T tagtype;
3875 SMB_ACL_PERMSET_T permset;
3876 unsigned char perms = 0;
3877 unsigned int own_grp;
3879 /* get_next... */
3880 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3881 entry_id = SMB_ACL_NEXT_ENTRY;
3884 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3885 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3886 return False;
3889 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3891 return False;
3894 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3895 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3896 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3898 SCVAL(pdata,1,perms);
3900 switch (tagtype) {
3901 case SMB_ACL_USER_OBJ:
3902 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3903 own_grp = (unsigned int)pst->st_ex_uid;
3904 SIVAL(pdata,2,own_grp);
3905 SIVAL(pdata,6,0);
3906 break;
3907 case SMB_ACL_USER:
3909 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3910 if (!puid) {
3911 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3912 return False;
3914 own_grp = (unsigned int)*puid;
3915 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3916 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3917 SIVAL(pdata,2,own_grp);
3918 SIVAL(pdata,6,0);
3919 break;
3921 case SMB_ACL_GROUP_OBJ:
3922 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3923 own_grp = (unsigned int)pst->st_ex_gid;
3924 SIVAL(pdata,2,own_grp);
3925 SIVAL(pdata,6,0);
3926 break;
3927 case SMB_ACL_GROUP:
3929 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3930 if (!pgid) {
3931 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3932 return False;
3934 own_grp = (unsigned int)*pgid;
3935 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3936 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3937 SIVAL(pdata,2,own_grp);
3938 SIVAL(pdata,6,0);
3939 break;
3941 case SMB_ACL_MASK:
3942 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3943 SIVAL(pdata,2,0xFFFFFFFF);
3944 SIVAL(pdata,6,0xFFFFFFFF);
3945 break;
3946 case SMB_ACL_OTHER:
3947 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3948 SIVAL(pdata,2,0xFFFFFFFF);
3949 SIVAL(pdata,6,0xFFFFFFFF);
3950 break;
3951 default:
3952 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3953 return False;
3955 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3958 return True;
3960 #endif
3962 /****************************************************************************
3963 Store the FILE_UNIX_BASIC info.
3964 ****************************************************************************/
3966 static char *store_file_unix_basic(connection_struct *conn,
3967 char *pdata,
3968 files_struct *fsp,
3969 const SMB_STRUCT_STAT *psbuf)
3971 uint64_t file_index = get_FileIndex(conn, psbuf);
3973 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3974 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3976 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3977 pdata += 8;
3979 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3980 pdata += 8;
3982 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3983 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3984 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3985 pdata += 24;
3987 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3988 SIVAL(pdata,4,0);
3989 pdata += 8;
3991 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3992 SIVAL(pdata,4,0);
3993 pdata += 8;
3995 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3996 pdata += 4;
3998 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3999 SIVAL(pdata,4,0);
4000 pdata += 8;
4002 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
4003 SIVAL(pdata,4,0);
4004 pdata += 8;
4006 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4007 pdata += 8;
4009 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4010 SIVAL(pdata,4,0);
4011 pdata += 8;
4013 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4014 SIVAL(pdata,4,0);
4015 pdata += 8;
4017 return pdata;
4020 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4021 * the chflags(2) (or equivalent) flags.
4023 * XXX: this really should be behind the VFS interface. To do this, we would
4024 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4025 * Each VFS module could then implement its own mapping as appropriate for the
4026 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4028 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4029 info2_flags_map[] =
4031 #ifdef UF_NODUMP
4032 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4033 #endif
4035 #ifdef UF_IMMUTABLE
4036 { UF_IMMUTABLE, EXT_IMMUTABLE },
4037 #endif
4039 #ifdef UF_APPEND
4040 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4041 #endif
4043 #ifdef UF_HIDDEN
4044 { UF_HIDDEN, EXT_HIDDEN },
4045 #endif
4047 /* Do not remove. We need to guarantee that this array has at least one
4048 * entry to build on HP-UX.
4050 { 0, 0 }
4054 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4055 uint32 *smb_fflags, uint32 *smb_fmask)
4057 int i;
4059 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4060 *smb_fmask |= info2_flags_map[i].smb_fflag;
4061 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4062 *smb_fflags |= info2_flags_map[i].smb_fflag;
4067 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4068 const uint32 smb_fflags,
4069 const uint32 smb_fmask,
4070 int *stat_fflags)
4072 uint32 max_fmask = 0;
4073 int i;
4075 *stat_fflags = psbuf->st_ex_flags;
4077 /* For each flags requested in smb_fmask, check the state of the
4078 * corresponding flag in smb_fflags and set or clear the matching
4079 * stat flag.
4082 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4083 max_fmask |= info2_flags_map[i].smb_fflag;
4084 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4085 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4086 *stat_fflags |= info2_flags_map[i].stat_fflag;
4087 } else {
4088 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4093 /* If smb_fmask is asking to set any bits that are not supported by
4094 * our flag mappings, we should fail.
4096 if ((smb_fmask & max_fmask) != smb_fmask) {
4097 return False;
4100 return True;
4104 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4105 * of file flags and birth (create) time.
4107 static char *store_file_unix_basic_info2(connection_struct *conn,
4108 char *pdata,
4109 files_struct *fsp,
4110 const SMB_STRUCT_STAT *psbuf)
4112 uint32 file_flags = 0;
4113 uint32 flags_mask = 0;
4115 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4117 /* Create (birth) time 64 bit */
4118 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4119 pdata += 8;
4121 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4122 SIVAL(pdata, 0, file_flags); /* flags */
4123 SIVAL(pdata, 4, flags_mask); /* mask */
4124 pdata += 8;
4126 return pdata;
4129 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4130 const struct stream_struct *streams,
4131 char *data,
4132 unsigned int max_data_bytes,
4133 unsigned int *data_size)
4135 unsigned int i;
4136 unsigned int ofs = 0;
4138 for (i = 0; i < num_streams; i++) {
4139 unsigned int next_offset;
4140 size_t namelen;
4141 smb_ucs2_t *namebuf;
4143 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4144 streams[i].name, &namelen) ||
4145 namelen <= 2)
4147 return NT_STATUS_INVALID_PARAMETER;
4151 * name_buf is now null-terminated, we need to marshall as not
4152 * terminated
4155 namelen -= 2;
4158 * We cannot overflow ...
4160 if ((ofs + 24 + namelen) > max_data_bytes) {
4161 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4162 i));
4163 TALLOC_FREE(namebuf);
4164 return STATUS_BUFFER_OVERFLOW;
4167 SIVAL(data, ofs+4, namelen);
4168 SOFF_T(data, ofs+8, streams[i].size);
4169 SOFF_T(data, ofs+16, streams[i].alloc_size);
4170 memcpy(data+ofs+24, namebuf, namelen);
4171 TALLOC_FREE(namebuf);
4173 next_offset = ofs + 24 + namelen;
4175 if (i == num_streams-1) {
4176 SIVAL(data, ofs, 0);
4178 else {
4179 unsigned int align = ndr_align_size(next_offset, 8);
4181 if ((next_offset + align) > max_data_bytes) {
4182 DEBUG(10, ("refusing to overflow align "
4183 "reply at stream %u\n",
4184 i));
4185 TALLOC_FREE(namebuf);
4186 return STATUS_BUFFER_OVERFLOW;
4189 memset(data+next_offset, 0, align);
4190 next_offset += align;
4192 SIVAL(data, ofs, next_offset - ofs);
4193 ofs = next_offset;
4196 ofs = next_offset;
4199 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4201 *data_size = ofs;
4203 return NT_STATUS_OK;
4206 /****************************************************************************
4207 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4208 ****************************************************************************/
4210 static void call_trans2qpipeinfo(connection_struct *conn,
4211 struct smb_request *req,
4212 unsigned int tran_call,
4213 char **pparams, int total_params,
4214 char **ppdata, int total_data,
4215 unsigned int max_data_bytes)
4217 char *params = *pparams;
4218 char *pdata = *ppdata;
4219 unsigned int data_size = 0;
4220 unsigned int param_size = 2;
4221 uint16 info_level;
4222 files_struct *fsp;
4224 if (!params) {
4225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4226 return;
4229 if (total_params < 4) {
4230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4231 return;
4234 fsp = file_fsp(req, SVAL(params,0));
4235 if (!fsp_is_np(fsp)) {
4236 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4237 return;
4240 info_level = SVAL(params,2);
4242 *pparams = (char *)SMB_REALLOC(*pparams,2);
4243 if (*pparams == NULL) {
4244 reply_nterror(req, NT_STATUS_NO_MEMORY);
4245 return;
4247 params = *pparams;
4248 SSVAL(params,0,0);
4249 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4250 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4251 if (*ppdata == NULL ) {
4252 reply_nterror(req, NT_STATUS_NO_MEMORY);
4253 return;
4255 pdata = *ppdata;
4257 switch (info_level) {
4258 case SMB_FILE_STANDARD_INFORMATION:
4259 memset(pdata,0,24);
4260 SOFF_T(pdata,0,4096LL);
4261 SIVAL(pdata,16,1);
4262 SIVAL(pdata,20,1);
4263 data_size = 24;
4264 break;
4266 default:
4267 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4268 return;
4271 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4272 max_data_bytes);
4274 return;
4277 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4278 TALLOC_CTX *mem_ctx,
4279 uint16_t info_level,
4280 files_struct *fsp,
4281 struct smb_filename *smb_fname,
4282 bool delete_pending,
4283 struct timespec write_time_ts,
4284 struct ea_list *ea_list,
4285 int lock_data_count,
4286 char *lock_data,
4287 uint16_t flags2,
4288 unsigned int max_data_bytes,
4289 size_t *fixed_portion,
4290 char **ppdata,
4291 unsigned int *pdata_size)
4293 char *pdata = *ppdata;
4294 char *dstart, *dend;
4295 unsigned int data_size;
4296 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4297 time_t create_time, mtime, atime, c_time;
4298 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4299 char *p;
4300 char *base_name;
4301 char *dos_fname;
4302 int mode;
4303 int nlink;
4304 NTSTATUS status;
4305 uint64_t file_size = 0;
4306 uint64_t pos = 0;
4307 uint64_t allocation_size = 0;
4308 uint64_t file_index = 0;
4309 uint32_t access_mask = 0;
4311 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4312 return NT_STATUS_INVALID_LEVEL;
4315 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4316 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4317 info_level, max_data_bytes));
4319 mode = dos_mode(conn, smb_fname);
4320 nlink = psbuf->st_ex_nlink;
4322 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4323 nlink = 1;
4326 if ((nlink > 0) && delete_pending) {
4327 nlink -= 1;
4330 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4331 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4332 if (*ppdata == NULL) {
4333 return NT_STATUS_NO_MEMORY;
4335 pdata = *ppdata;
4336 dstart = pdata;
4337 dend = dstart + data_size - 1;
4339 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4340 update_stat_ex_mtime(psbuf, write_time_ts);
4343 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4344 mtime_ts = psbuf->st_ex_mtime;
4345 atime_ts = psbuf->st_ex_atime;
4346 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4348 if (lp_dos_filetime_resolution(SNUM(conn))) {
4349 dos_filetime_timespec(&create_time_ts);
4350 dos_filetime_timespec(&mtime_ts);
4351 dos_filetime_timespec(&atime_ts);
4352 dos_filetime_timespec(&ctime_ts);
4355 create_time = convert_timespec_to_time_t(create_time_ts);
4356 mtime = convert_timespec_to_time_t(mtime_ts);
4357 atime = convert_timespec_to_time_t(atime_ts);
4358 c_time = convert_timespec_to_time_t(ctime_ts);
4360 p = strrchr_m(smb_fname->base_name,'/');
4361 if (!p)
4362 base_name = smb_fname->base_name;
4363 else
4364 base_name = p+1;
4366 /* NT expects the name to be in an exact form of the *full*
4367 filename. See the trans2 torture test */
4368 if (ISDOT(base_name)) {
4369 dos_fname = talloc_strdup(mem_ctx, "\\");
4370 if (!dos_fname) {
4371 return NT_STATUS_NO_MEMORY;
4373 } else {
4374 dos_fname = talloc_asprintf(mem_ctx,
4375 "\\%s",
4376 smb_fname->base_name);
4377 if (!dos_fname) {
4378 return NT_STATUS_NO_MEMORY;
4380 if (is_ntfs_stream_smb_fname(smb_fname)) {
4381 dos_fname = talloc_asprintf(dos_fname, "%s",
4382 smb_fname->stream_name);
4383 if (!dos_fname) {
4384 return NT_STATUS_NO_MEMORY;
4388 string_replace(dos_fname, '/', '\\');
4391 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4393 if (!fsp) {
4394 /* Do we have this path open ? */
4395 files_struct *fsp1;
4396 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4397 fsp1 = file_find_di_first(conn->sconn, fileid);
4398 if (fsp1 && fsp1->initial_allocation_size) {
4399 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4403 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4404 file_size = get_file_size_stat(psbuf);
4407 if (fsp) {
4408 pos = fsp->fh->position_information;
4411 if (fsp) {
4412 access_mask = fsp->access_mask;
4413 } else {
4414 /* GENERIC_EXECUTE mapping from Windows */
4415 access_mask = 0x12019F;
4418 /* This should be an index number - looks like
4419 dev/ino to me :-)
4421 I think this causes us to fail the IFSKIT
4422 BasicFileInformationTest. -tpot */
4423 file_index = get_FileIndex(conn, psbuf);
4425 *fixed_portion = 0;
4427 switch (info_level) {
4428 case SMB_INFO_STANDARD:
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4430 data_size = 22;
4431 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4432 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4433 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4434 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4435 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4436 SSVAL(pdata,l1_attrFile,mode);
4437 break;
4439 case SMB_INFO_QUERY_EA_SIZE:
4441 unsigned int ea_size =
4442 estimate_ea_size(conn, fsp,
4443 smb_fname->base_name);
4444 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4445 data_size = 26;
4446 srv_put_dos_date2(pdata,0,create_time);
4447 srv_put_dos_date2(pdata,4,atime);
4448 srv_put_dos_date2(pdata,8,mtime); /* write time */
4449 SIVAL(pdata,12,(uint32)file_size);
4450 SIVAL(pdata,16,(uint32)allocation_size);
4451 SSVAL(pdata,20,mode);
4452 SIVAL(pdata,22,ea_size);
4453 break;
4456 case SMB_INFO_IS_NAME_VALID:
4457 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4458 if (fsp) {
4459 /* os/2 needs this ? really ?*/
4460 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4462 /* This is only reached for qpathinfo */
4463 data_size = 0;
4464 break;
4466 case SMB_INFO_QUERY_EAS_FROM_LIST:
4468 size_t total_ea_len = 0;
4469 struct ea_list *ea_file_list = NULL;
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4473 ea_file_list =
4474 get_ea_list_from_file(mem_ctx, conn, fsp,
4475 smb_fname->base_name,
4476 &total_ea_len);
4477 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4479 if (!ea_list || (total_ea_len > data_size)) {
4480 data_size = 4;
4481 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4482 break;
4485 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4486 break;
4489 case SMB_INFO_QUERY_ALL_EAS:
4491 /* We have data_size bytes to put EA's into. */
4492 size_t total_ea_len = 0;
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4496 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4497 smb_fname->base_name,
4498 &total_ea_len);
4499 if (!ea_list || (total_ea_len > data_size)) {
4500 data_size = 4;
4501 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4502 break;
4505 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4506 break;
4509 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4511 /* This is FileFullEaInformation - 0xF which maps to
4512 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4514 /* We have data_size bytes to put EA's into. */
4515 size_t total_ea_len = 0;
4516 struct ea_list *ea_file_list = NULL;
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4520 /*TODO: add filtering and index handling */
4522 ea_file_list =
4523 get_ea_list_from_file(mem_ctx, conn, fsp,
4524 smb_fname->base_name,
4525 &total_ea_len);
4526 if (!ea_file_list) {
4527 return NT_STATUS_NO_EAS_ON_FILE;
4530 status = fill_ea_chained_buffer(mem_ctx,
4531 pdata,
4532 data_size,
4533 &data_size,
4534 conn, ea_file_list);
4535 if (!NT_STATUS_IS_OK(status)) {
4536 return status;
4538 break;
4541 case SMB_FILE_BASIC_INFORMATION:
4542 case SMB_QUERY_FILE_BASIC_INFO:
4544 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4546 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4547 } else {
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4549 data_size = 40;
4550 SIVAL(pdata,36,0);
4552 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4553 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4554 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4555 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4556 SIVAL(pdata,32,mode);
4558 DEBUG(5,("SMB_QFBI - "));
4559 DEBUG(5,("create: %s ", ctime(&create_time)));
4560 DEBUG(5,("access: %s ", ctime(&atime)));
4561 DEBUG(5,("write: %s ", ctime(&mtime)));
4562 DEBUG(5,("change: %s ", ctime(&c_time)));
4563 DEBUG(5,("mode: %x\n", mode));
4564 *fixed_portion = data_size;
4565 break;
4567 case SMB_FILE_STANDARD_INFORMATION:
4568 case SMB_QUERY_FILE_STANDARD_INFO:
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4571 data_size = 24;
4572 SOFF_T(pdata,0,allocation_size);
4573 SOFF_T(pdata,8,file_size);
4574 SIVAL(pdata,16,nlink);
4575 SCVAL(pdata,20,delete_pending?1:0);
4576 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4577 SSVAL(pdata,22,0); /* Padding. */
4578 *fixed_portion = 24;
4579 break;
4581 case SMB_FILE_EA_INFORMATION:
4582 case SMB_QUERY_FILE_EA_INFO:
4584 unsigned int ea_size =
4585 estimate_ea_size(conn, fsp, smb_fname->base_name);
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4587 data_size = 4;
4588 *fixed_portion = 4;
4589 SIVAL(pdata,0,ea_size);
4590 break;
4593 /* Get the 8.3 name - used if NT SMB was negotiated. */
4594 case SMB_QUERY_FILE_ALT_NAME_INFO:
4595 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4597 int len;
4598 char mangled_name[13];
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4600 if (!name_to_8_3(base_name,mangled_name,
4601 True,conn->params)) {
4602 return NT_STATUS_NO_MEMORY;
4604 len = srvstr_push(dstart, flags2,
4605 pdata+4, mangled_name,
4606 PTR_DIFF(dend, pdata+4),
4607 STR_UNICODE);
4608 data_size = 4 + len;
4609 SIVAL(pdata,0,len);
4610 *fixed_portion = 8;
4611 break;
4614 case SMB_QUERY_FILE_NAME_INFO:
4616 int len;
4618 this must be *exactly* right for ACLs on mapped drives to work
4620 len = srvstr_push(dstart, flags2,
4621 pdata+4, dos_fname,
4622 PTR_DIFF(dend, pdata+4),
4623 STR_UNICODE);
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4625 data_size = 4 + len;
4626 SIVAL(pdata,0,len);
4627 break;
4630 case SMB_FILE_ALLOCATION_INFORMATION:
4631 case SMB_QUERY_FILE_ALLOCATION_INFO:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4633 data_size = 8;
4634 SOFF_T(pdata,0,allocation_size);
4635 break;
4637 case SMB_FILE_END_OF_FILE_INFORMATION:
4638 case SMB_QUERY_FILE_END_OF_FILEINFO:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4640 data_size = 8;
4641 SOFF_T(pdata,0,file_size);
4642 break;
4644 case SMB_QUERY_FILE_ALL_INFO:
4645 case SMB_FILE_ALL_INFORMATION:
4647 int len;
4648 unsigned int ea_size =
4649 estimate_ea_size(conn, fsp, smb_fname->base_name);
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4651 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4652 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4653 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4654 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4655 SIVAL(pdata,32,mode);
4656 SIVAL(pdata,36,0); /* padding. */
4657 pdata += 40;
4658 SOFF_T(pdata,0,allocation_size);
4659 SOFF_T(pdata,8,file_size);
4660 SIVAL(pdata,16,nlink);
4661 SCVAL(pdata,20,delete_pending);
4662 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4663 SSVAL(pdata,22,0);
4664 pdata += 24;
4665 SIVAL(pdata,0,ea_size);
4666 pdata += 4; /* EA info */
4667 len = srvstr_push(dstart, flags2,
4668 pdata+4, dos_fname,
4669 PTR_DIFF(dend, pdata+4),
4670 STR_UNICODE);
4671 SIVAL(pdata,0,len);
4672 pdata += 4 + len;
4673 data_size = PTR_DIFF(pdata,(*ppdata));
4674 *fixed_portion = 10;
4675 break;
4678 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4680 int len;
4681 unsigned int ea_size =
4682 estimate_ea_size(conn, fsp, smb_fname->base_name);
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4684 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4685 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4686 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4687 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4688 SIVAL(pdata, 0x20, mode);
4689 SIVAL(pdata, 0x24, 0); /* padding. */
4690 SBVAL(pdata, 0x28, allocation_size);
4691 SBVAL(pdata, 0x30, file_size);
4692 SIVAL(pdata, 0x38, nlink);
4693 SCVAL(pdata, 0x3C, delete_pending);
4694 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4695 SSVAL(pdata, 0x3E, 0); /* padding */
4696 SBVAL(pdata, 0x40, file_index);
4697 SIVAL(pdata, 0x48, ea_size);
4698 SIVAL(pdata, 0x4C, access_mask);
4699 SBVAL(pdata, 0x50, pos);
4700 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4701 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4703 pdata += 0x60;
4705 len = srvstr_push(dstart, flags2,
4706 pdata+4, dos_fname,
4707 PTR_DIFF(dend, pdata+4),
4708 STR_UNICODE);
4709 SIVAL(pdata,0,len);
4710 pdata += 4 + len;
4711 data_size = PTR_DIFF(pdata,(*ppdata));
4712 *fixed_portion = 104;
4713 break;
4715 case SMB_FILE_INTERNAL_INFORMATION:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4718 SBVAL(pdata, 0, file_index);
4719 data_size = 8;
4720 *fixed_portion = 8;
4721 break;
4723 case SMB_FILE_ACCESS_INFORMATION:
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4725 SIVAL(pdata, 0, access_mask);
4726 data_size = 4;
4727 *fixed_portion = 4;
4728 break;
4730 case SMB_FILE_NAME_INFORMATION:
4731 /* Pathname with leading '\'. */
4733 size_t byte_len;
4734 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4736 SIVAL(pdata,0,byte_len);
4737 data_size = 4 + byte_len;
4738 break;
4741 case SMB_FILE_DISPOSITION_INFORMATION:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4743 data_size = 1;
4744 SCVAL(pdata,0,delete_pending);
4745 *fixed_portion = 1;
4746 break;
4748 case SMB_FILE_POSITION_INFORMATION:
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4750 data_size = 8;
4751 SOFF_T(pdata,0,pos);
4752 *fixed_portion = 8;
4753 break;
4755 case SMB_FILE_MODE_INFORMATION:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4757 SIVAL(pdata,0,mode);
4758 data_size = 4;
4759 *fixed_portion = 4;
4760 break;
4762 case SMB_FILE_ALIGNMENT_INFORMATION:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4764 SIVAL(pdata,0,0); /* No alignment needed. */
4765 data_size = 4;
4766 *fixed_portion = 4;
4767 break;
4770 * NT4 server just returns "invalid query" to this - if we try
4771 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4772 * want this. JRA.
4774 /* The first statement above is false - verified using Thursby
4775 * client against NT4 -- gcolley.
4777 case SMB_QUERY_FILE_STREAM_INFO:
4778 case SMB_FILE_STREAM_INFORMATION: {
4779 unsigned int num_streams = 0;
4780 struct stream_struct *streams = NULL;
4782 DEBUG(10,("smbd_do_qfilepathinfo: "
4783 "SMB_FILE_STREAM_INFORMATION\n"));
4785 if (is_ntfs_stream_smb_fname(smb_fname)) {
4786 return NT_STATUS_INVALID_PARAMETER;
4789 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4790 talloc_tos(), &num_streams, &streams);
4792 if (!NT_STATUS_IS_OK(status)) {
4793 DEBUG(10, ("could not get stream info: %s\n",
4794 nt_errstr(status)));
4795 return status;
4798 status = marshall_stream_info(num_streams, streams,
4799 pdata, max_data_bytes,
4800 &data_size);
4802 if (!NT_STATUS_IS_OK(status)) {
4803 DEBUG(10, ("marshall_stream_info failed: %s\n",
4804 nt_errstr(status)));
4805 TALLOC_FREE(streams);
4806 return status;
4809 TALLOC_FREE(streams);
4811 *fixed_portion = 32;
4813 break;
4815 case SMB_QUERY_COMPRESSION_INFO:
4816 case SMB_FILE_COMPRESSION_INFORMATION:
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4818 SOFF_T(pdata,0,file_size);
4819 SIVAL(pdata,8,0); /* ??? */
4820 SIVAL(pdata,12,0); /* ??? */
4821 data_size = 16;
4822 *fixed_portion = 16;
4823 break;
4825 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4826 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4827 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4828 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4829 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4830 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4831 SOFF_T(pdata,32,allocation_size);
4832 SOFF_T(pdata,40,file_size);
4833 SIVAL(pdata,48,mode);
4834 SIVAL(pdata,52,0); /* ??? */
4835 data_size = 56;
4836 *fixed_portion = 56;
4837 break;
4839 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4841 SIVAL(pdata,0,mode);
4842 SIVAL(pdata,4,0);
4843 data_size = 8;
4844 *fixed_portion = 8;
4845 break;
4848 * CIFS UNIX Extensions.
4851 case SMB_QUERY_FILE_UNIX_BASIC:
4853 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4854 data_size = PTR_DIFF(pdata,(*ppdata));
4856 DEBUG(4,("smbd_do_qfilepathinfo: "
4857 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4858 dump_data(4, (uint8_t *)(*ppdata), data_size);
4860 break;
4862 case SMB_QUERY_FILE_UNIX_INFO2:
4864 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4865 data_size = PTR_DIFF(pdata,(*ppdata));
4868 int i;
4869 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4871 for (i=0; i<100; i++)
4872 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4873 DEBUG(4,("\n"));
4876 break;
4878 case SMB_QUERY_FILE_UNIX_LINK:
4880 int len;
4881 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4883 if (!buffer) {
4884 return NT_STATUS_NO_MEMORY;
4887 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4888 #ifdef S_ISLNK
4889 if(!S_ISLNK(psbuf->st_ex_mode)) {
4890 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4892 #else
4893 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4894 #endif
4895 len = SMB_VFS_READLINK(conn,
4896 smb_fname->base_name,
4897 buffer, PATH_MAX);
4898 if (len == -1) {
4899 return map_nt_error_from_unix(errno);
4901 buffer[len] = 0;
4902 len = srvstr_push(dstart, flags2,
4903 pdata, buffer,
4904 PTR_DIFF(dend, pdata),
4905 STR_TERMINATE);
4906 pdata += len;
4907 data_size = PTR_DIFF(pdata,(*ppdata));
4909 break;
4912 #if defined(HAVE_POSIX_ACLS)
4913 case SMB_QUERY_POSIX_ACL:
4915 SMB_ACL_T file_acl = NULL;
4916 SMB_ACL_T def_acl = NULL;
4917 uint16 num_file_acls = 0;
4918 uint16 num_def_acls = 0;
4920 if (fsp && fsp->fh->fd != -1) {
4921 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4922 } else {
4923 file_acl =
4924 SMB_VFS_SYS_ACL_GET_FILE(conn,
4925 smb_fname->base_name,
4926 SMB_ACL_TYPE_ACCESS);
4929 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4930 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4931 "not implemented on "
4932 "filesystem containing %s\n",
4933 smb_fname->base_name));
4934 return NT_STATUS_NOT_IMPLEMENTED;
4937 if (S_ISDIR(psbuf->st_ex_mode)) {
4938 if (fsp && fsp->is_directory) {
4939 def_acl =
4940 SMB_VFS_SYS_ACL_GET_FILE(
4941 conn,
4942 fsp->fsp_name->base_name,
4943 SMB_ACL_TYPE_DEFAULT);
4944 } else {
4945 def_acl =
4946 SMB_VFS_SYS_ACL_GET_FILE(
4947 conn,
4948 smb_fname->base_name,
4949 SMB_ACL_TYPE_DEFAULT);
4951 def_acl = free_empty_sys_acl(conn, def_acl);
4954 num_file_acls = count_acl_entries(conn, file_acl);
4955 num_def_acls = count_acl_entries(conn, def_acl);
4957 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4958 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4959 data_size,
4960 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4961 SMB_POSIX_ACL_HEADER_SIZE) ));
4962 if (file_acl) {
4963 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4965 if (def_acl) {
4966 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4968 return NT_STATUS_BUFFER_TOO_SMALL;
4971 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4972 SSVAL(pdata,2,num_file_acls);
4973 SSVAL(pdata,4,num_def_acls);
4974 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4975 if (file_acl) {
4976 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4978 if (def_acl) {
4979 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4981 return NT_STATUS_INTERNAL_ERROR;
4983 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4984 if (file_acl) {
4985 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4987 if (def_acl) {
4988 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4990 return NT_STATUS_INTERNAL_ERROR;
4993 if (file_acl) {
4994 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4996 if (def_acl) {
4997 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4999 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5000 break;
5002 #endif
5005 case SMB_QUERY_POSIX_LOCK:
5007 uint64_t count;
5008 uint64_t offset;
5009 uint64_t smblctx;
5010 enum brl_type lock_type;
5012 /* We need an open file with a real fd for this. */
5013 if (!fsp || fsp->fh->fd == -1) {
5014 return NT_STATUS_INVALID_LEVEL;
5017 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5018 return NT_STATUS_INVALID_PARAMETER;
5021 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5022 case POSIX_LOCK_TYPE_READ:
5023 lock_type = READ_LOCK;
5024 break;
5025 case POSIX_LOCK_TYPE_WRITE:
5026 lock_type = WRITE_LOCK;
5027 break;
5028 case POSIX_LOCK_TYPE_UNLOCK:
5029 default:
5030 /* There's no point in asking for an unlock... */
5031 return NT_STATUS_INVALID_PARAMETER;
5034 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5035 #if defined(HAVE_LONGLONG)
5036 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5037 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5038 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5039 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5040 #else /* HAVE_LONGLONG */
5041 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5042 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5043 #endif /* HAVE_LONGLONG */
5045 status = query_lock(fsp,
5046 &smblctx,
5047 &count,
5048 &offset,
5049 &lock_type,
5050 POSIX_LOCK);
5052 if (ERROR_WAS_LOCK_DENIED(status)) {
5053 /* Here we need to report who has it locked... */
5054 data_size = POSIX_LOCK_DATA_SIZE;
5056 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5057 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5058 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5059 #if defined(HAVE_LONGLONG)
5060 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5061 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5062 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5063 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5064 #else /* HAVE_LONGLONG */
5065 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5066 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5067 #endif /* HAVE_LONGLONG */
5069 } else if (NT_STATUS_IS_OK(status)) {
5070 /* For success we just return a copy of what we sent
5071 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5072 data_size = POSIX_LOCK_DATA_SIZE;
5073 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5074 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5075 } else {
5076 return status;
5078 break;
5081 default:
5082 return NT_STATUS_INVALID_LEVEL;
5085 *pdata_size = data_size;
5086 return NT_STATUS_OK;
5089 /****************************************************************************
5090 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5091 file name or file id).
5092 ****************************************************************************/
5094 static void call_trans2qfilepathinfo(connection_struct *conn,
5095 struct smb_request *req,
5096 unsigned int tran_call,
5097 char **pparams, int total_params,
5098 char **ppdata, int total_data,
5099 unsigned int max_data_bytes)
5101 char *params = *pparams;
5102 char *pdata = *ppdata;
5103 uint16 info_level;
5104 unsigned int data_size = 0;
5105 unsigned int param_size = 2;
5106 struct smb_filename *smb_fname = NULL;
5107 bool delete_pending = False;
5108 struct timespec write_time_ts;
5109 files_struct *fsp = NULL;
5110 struct file_id fileid;
5111 struct ea_list *ea_list = NULL;
5112 int lock_data_count = 0;
5113 char *lock_data = NULL;
5114 size_t fixed_portion;
5115 NTSTATUS status = NT_STATUS_OK;
5117 if (!params) {
5118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5119 return;
5122 ZERO_STRUCT(write_time_ts);
5124 if (tran_call == TRANSACT2_QFILEINFO) {
5125 if (total_params < 4) {
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127 return;
5130 if (IS_IPC(conn)) {
5131 call_trans2qpipeinfo(conn, req, tran_call,
5132 pparams, total_params,
5133 ppdata, total_data,
5134 max_data_bytes);
5135 return;
5138 fsp = file_fsp(req, SVAL(params,0));
5139 info_level = SVAL(params,2);
5141 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5143 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5144 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5145 return;
5148 /* Initial check for valid fsp ptr. */
5149 if (!check_fsp_open(conn, req, fsp)) {
5150 return;
5153 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5154 &smb_fname);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 reply_nterror(req, status);
5157 return;
5160 if(fsp->fake_file_handle) {
5162 * This is actually for the QUOTA_FAKE_FILE --metze
5165 /* We know this name is ok, it's already passed the checks. */
5167 } else if(fsp->fh->fd == -1) {
5169 * This is actually a QFILEINFO on a directory
5170 * handle (returned from an NT SMB). NT5.0 seems
5171 * to do this call. JRA.
5174 if (INFO_LEVEL_IS_UNIX(info_level)) {
5175 /* Always do lstat for UNIX calls. */
5176 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5177 DEBUG(3,("call_trans2qfilepathinfo: "
5178 "SMB_VFS_LSTAT of %s failed "
5179 "(%s)\n",
5180 smb_fname_str_dbg(smb_fname),
5181 strerror(errno)));
5182 reply_nterror(req,
5183 map_nt_error_from_unix(errno));
5184 return;
5186 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5187 DEBUG(3,("call_trans2qfilepathinfo: "
5188 "SMB_VFS_STAT of %s failed (%s)\n",
5189 smb_fname_str_dbg(smb_fname),
5190 strerror(errno)));
5191 reply_nterror(req,
5192 map_nt_error_from_unix(errno));
5193 return;
5196 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5197 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5198 } else {
5200 * Original code - this is an open file.
5202 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5203 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5204 fsp->fnum, strerror(errno)));
5205 reply_nterror(req,
5206 map_nt_error_from_unix(errno));
5207 return;
5209 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5210 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5213 } else {
5214 uint32_t name_hash;
5215 char *fname = NULL;
5216 uint32_t ucf_flags = 0;
5218 /* qpathinfo */
5219 if (total_params < 7) {
5220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5221 return;
5224 info_level = SVAL(params,0);
5226 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5228 if (INFO_LEVEL_IS_UNIX(info_level)) {
5229 if (!lp_unix_extensions()) {
5230 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5231 return;
5233 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5234 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5235 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5236 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5240 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5241 total_params - 6,
5242 STR_TERMINATE, &status);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 reply_nterror(req, status);
5245 return;
5248 status = filename_convert(req,
5249 conn,
5250 req->flags2 & FLAGS2_DFS_PATHNAMES,
5251 fname,
5252 ucf_flags,
5253 NULL,
5254 &smb_fname);
5255 if (!NT_STATUS_IS_OK(status)) {
5256 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5257 reply_botherror(req,
5258 NT_STATUS_PATH_NOT_COVERED,
5259 ERRSRV, ERRbadpath);
5260 return;
5262 reply_nterror(req, status);
5263 return;
5266 /* If this is a stream, check if there is a delete_pending. */
5267 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5268 && is_ntfs_stream_smb_fname(smb_fname)) {
5269 struct smb_filename *smb_fname_base = NULL;
5271 /* Create an smb_filename with stream_name == NULL. */
5272 status =
5273 create_synthetic_smb_fname(talloc_tos(),
5274 smb_fname->base_name,
5275 NULL, NULL,
5276 &smb_fname_base);
5277 if (!NT_STATUS_IS_OK(status)) {
5278 reply_nterror(req, status);
5279 return;
5282 if (INFO_LEVEL_IS_UNIX(info_level)) {
5283 /* Always do lstat for UNIX calls. */
5284 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5285 DEBUG(3,("call_trans2qfilepathinfo: "
5286 "SMB_VFS_LSTAT of %s failed "
5287 "(%s)\n",
5288 smb_fname_str_dbg(smb_fname_base),
5289 strerror(errno)));
5290 TALLOC_FREE(smb_fname_base);
5291 reply_nterror(req,
5292 map_nt_error_from_unix(errno));
5293 return;
5295 } else {
5296 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5297 DEBUG(3,("call_trans2qfilepathinfo: "
5298 "fileinfo of %s failed "
5299 "(%s)\n",
5300 smb_fname_str_dbg(smb_fname_base),
5301 strerror(errno)));
5302 TALLOC_FREE(smb_fname_base);
5303 reply_nterror(req,
5304 map_nt_error_from_unix(errno));
5305 return;
5309 status = file_name_hash(conn,
5310 smb_fname_str_dbg(smb_fname_base),
5311 &name_hash);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 TALLOC_FREE(smb_fname_base);
5314 reply_nterror(req, status);
5315 return;
5318 fileid = vfs_file_id_from_sbuf(conn,
5319 &smb_fname_base->st);
5320 TALLOC_FREE(smb_fname_base);
5321 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5322 if (delete_pending) {
5323 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5324 return;
5328 if (INFO_LEVEL_IS_UNIX(info_level)) {
5329 /* Always do lstat for UNIX calls. */
5330 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5331 DEBUG(3,("call_trans2qfilepathinfo: "
5332 "SMB_VFS_LSTAT of %s failed (%s)\n",
5333 smb_fname_str_dbg(smb_fname),
5334 strerror(errno)));
5335 reply_nterror(req,
5336 map_nt_error_from_unix(errno));
5337 return;
5340 } else {
5341 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5342 DEBUG(3,("call_trans2qfilepathinfo: "
5343 "SMB_VFS_STAT of %s failed (%s)\n",
5344 smb_fname_str_dbg(smb_fname),
5345 strerror(errno)));
5346 reply_nterror(req,
5347 map_nt_error_from_unix(errno));
5348 return;
5352 status = file_name_hash(conn,
5353 smb_fname_str_dbg(smb_fname),
5354 &name_hash);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 reply_nterror(req, status);
5357 return;
5360 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5361 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5362 if (delete_pending) {
5363 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5364 return;
5368 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5369 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5370 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5372 /* Pull out any data sent here before we realloc. */
5373 switch (info_level) {
5374 case SMB_INFO_QUERY_EAS_FROM_LIST:
5376 /* Pull any EA list from the data portion. */
5377 uint32 ea_size;
5379 if (total_data < 4) {
5380 reply_nterror(
5381 req, NT_STATUS_INVALID_PARAMETER);
5382 return;
5384 ea_size = IVAL(pdata,0);
5386 if (total_data > 0 && ea_size != total_data) {
5387 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5388 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5389 reply_nterror(
5390 req, NT_STATUS_INVALID_PARAMETER);
5391 return;
5394 if (!lp_ea_support(SNUM(conn))) {
5395 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5396 return;
5399 /* Pull out the list of names. */
5400 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5401 if (!ea_list) {
5402 reply_nterror(
5403 req, NT_STATUS_INVALID_PARAMETER);
5404 return;
5406 break;
5409 case SMB_QUERY_POSIX_LOCK:
5411 if (fsp == NULL || fsp->fh->fd == -1) {
5412 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5413 return;
5416 if (total_data != POSIX_LOCK_DATA_SIZE) {
5417 reply_nterror(
5418 req, NT_STATUS_INVALID_PARAMETER);
5419 return;
5422 /* Copy the lock range data. */
5423 lock_data = (char *)TALLOC_MEMDUP(
5424 req, pdata, total_data);
5425 if (!lock_data) {
5426 reply_nterror(req, NT_STATUS_NO_MEMORY);
5427 return;
5429 lock_data_count = total_data;
5431 default:
5432 break;
5435 *pparams = (char *)SMB_REALLOC(*pparams,2);
5436 if (*pparams == NULL) {
5437 reply_nterror(req, NT_STATUS_NO_MEMORY);
5438 return;
5440 params = *pparams;
5441 SSVAL(params,0,0);
5444 * draft-leach-cifs-v1-spec-02.txt
5445 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5446 * says:
5448 * The requested information is placed in the Data portion of the
5449 * transaction response. For the information levels greater than 0x100,
5450 * the transaction response has 1 parameter word which should be
5451 * ignored by the client.
5453 * However Windows only follows this rule for the IS_NAME_VALID call.
5455 switch (info_level) {
5456 case SMB_INFO_IS_NAME_VALID:
5457 param_size = 0;
5458 break;
5461 if ((info_level & 0xFF00) == 0xFF00) {
5463 * We use levels that start with 0xFF00
5464 * internally to represent SMB2 specific levels
5466 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5467 return;
5470 status = smbd_do_qfilepathinfo(conn, req, info_level,
5471 fsp, smb_fname,
5472 delete_pending, write_time_ts,
5473 ea_list,
5474 lock_data_count, lock_data,
5475 req->flags2, max_data_bytes,
5476 &fixed_portion,
5477 ppdata, &data_size);
5478 if (!NT_STATUS_IS_OK(status)) {
5479 reply_nterror(req, status);
5480 return;
5483 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5484 max_data_bytes);
5486 return;
5489 /****************************************************************************
5490 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5491 code.
5492 ****************************************************************************/
5494 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5495 connection_struct *conn,
5496 struct smb_request *req,
5497 bool overwrite_if_exists,
5498 const struct smb_filename *smb_fname_old,
5499 struct smb_filename *smb_fname_new)
5501 NTSTATUS status = NT_STATUS_OK;
5503 /* source must already exist. */
5504 if (!VALID_STAT(smb_fname_old->st)) {
5505 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5508 if (VALID_STAT(smb_fname_new->st)) {
5509 if (overwrite_if_exists) {
5510 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5511 return NT_STATUS_FILE_IS_A_DIRECTORY;
5513 status = unlink_internals(conn,
5514 req,
5515 FILE_ATTRIBUTE_NORMAL,
5516 smb_fname_new,
5517 false);
5518 if (!NT_STATUS_IS_OK(status)) {
5519 return status;
5521 } else {
5522 /* Disallow if newname already exists. */
5523 return NT_STATUS_OBJECT_NAME_COLLISION;
5527 /* No links from a directory. */
5528 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5529 return NT_STATUS_FILE_IS_A_DIRECTORY;
5532 /* Setting a hardlink to/from a stream isn't currently supported. */
5533 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5534 is_ntfs_stream_smb_fname(smb_fname_new)) {
5535 return NT_STATUS_INVALID_PARAMETER;
5538 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5539 smb_fname_old->base_name, smb_fname_new->base_name));
5541 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5542 smb_fname_new->base_name) != 0) {
5543 status = map_nt_error_from_unix(errno);
5544 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5545 nt_errstr(status), smb_fname_old->base_name,
5546 smb_fname_new->base_name));
5548 return status;
5551 /****************************************************************************
5552 Deal with setting the time from any of the setfilepathinfo functions.
5553 ****************************************************************************/
5555 NTSTATUS smb_set_file_time(connection_struct *conn,
5556 files_struct *fsp,
5557 const struct smb_filename *smb_fname,
5558 struct smb_file_time *ft,
5559 bool setting_write_time)
5561 struct smb_filename smb_fname_base;
5562 uint32 action =
5563 FILE_NOTIFY_CHANGE_LAST_ACCESS
5564 |FILE_NOTIFY_CHANGE_LAST_WRITE
5565 |FILE_NOTIFY_CHANGE_CREATION;
5567 if (!VALID_STAT(smb_fname->st)) {
5568 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5571 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5572 return NT_STATUS_ACCESS_DENIED;
5575 /* get some defaults (no modifications) if any info is zero or -1. */
5576 if (null_timespec(ft->create_time)) {
5577 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5580 if (null_timespec(ft->atime)) {
5581 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5584 if (null_timespec(ft->mtime)) {
5585 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5588 if (!setting_write_time) {
5589 /* ft->mtime comes from change time, not write time. */
5590 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5593 /* Ensure the resolution is the correct for
5594 * what we can store on this filesystem. */
5596 round_timespec(conn->ts_res, &ft->create_time);
5597 round_timespec(conn->ts_res, &ft->ctime);
5598 round_timespec(conn->ts_res, &ft->atime);
5599 round_timespec(conn->ts_res, &ft->mtime);
5601 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5602 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5603 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5604 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5605 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5606 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5607 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5608 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5610 if (setting_write_time) {
5612 * This was a Windows setfileinfo on an open file.
5613 * NT does this a lot. We also need to
5614 * set the time here, as it can be read by
5615 * FindFirst/FindNext and with the patch for bug #2045
5616 * in smbd/fileio.c it ensures that this timestamp is
5617 * kept sticky even after a write. We save the request
5618 * away and will set it on file close and after a write. JRA.
5621 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5622 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5624 if (fsp != NULL) {
5625 if (fsp->base_fsp) {
5626 set_sticky_write_time_fsp(fsp->base_fsp,
5627 ft->mtime);
5628 } else {
5629 set_sticky_write_time_fsp(fsp, ft->mtime);
5631 } else {
5632 set_sticky_write_time_path(
5633 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5634 ft->mtime);
5638 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5640 /* Always call ntimes on the base, even if a stream was passed in. */
5641 smb_fname_base = *smb_fname;
5642 smb_fname_base.stream_name = NULL;
5644 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5645 return map_nt_error_from_unix(errno);
5648 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5649 smb_fname->base_name);
5650 return NT_STATUS_OK;
5653 /****************************************************************************
5654 Deal with setting the dosmode from any of the setfilepathinfo functions.
5655 ****************************************************************************/
5657 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5658 const struct smb_filename *smb_fname,
5659 uint32 dosmode)
5661 struct smb_filename *smb_fname_base = NULL;
5662 NTSTATUS status;
5664 if (!VALID_STAT(smb_fname->st)) {
5665 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5668 /* Always operate on the base_name, even if a stream was passed in. */
5669 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5670 NULL, &smb_fname->st,
5671 &smb_fname_base);
5672 if (!NT_STATUS_IS_OK(status)) {
5673 return status;
5676 if (dosmode) {
5677 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5678 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5679 } else {
5680 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5684 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5686 /* check the mode isn't different, before changing it */
5687 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5688 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5689 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5690 (unsigned int)dosmode));
5692 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5693 false)) {
5694 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5695 "%s failed (%s)\n",
5696 smb_fname_str_dbg(smb_fname_base),
5697 strerror(errno)));
5698 status = map_nt_error_from_unix(errno);
5699 goto out;
5702 status = NT_STATUS_OK;
5703 out:
5704 TALLOC_FREE(smb_fname_base);
5705 return status;
5708 /****************************************************************************
5709 Deal with setting the size from any of the setfilepathinfo functions.
5710 ****************************************************************************/
5712 static NTSTATUS smb_set_file_size(connection_struct *conn,
5713 struct smb_request *req,
5714 files_struct *fsp,
5715 const struct smb_filename *smb_fname,
5716 const SMB_STRUCT_STAT *psbuf,
5717 SMB_OFF_T size,
5718 bool fail_after_createfile)
5720 NTSTATUS status = NT_STATUS_OK;
5721 struct smb_filename *smb_fname_tmp = NULL;
5722 files_struct *new_fsp = NULL;
5724 if (!VALID_STAT(*psbuf)) {
5725 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5728 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5729 return NT_STATUS_ACCESS_DENIED;
5732 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5734 if (size == get_file_size_stat(psbuf)) {
5735 return NT_STATUS_OK;
5738 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5739 smb_fname_str_dbg(smb_fname), (double)size));
5741 if (fsp && fsp->fh->fd != -1) {
5742 /* Handle based call. */
5743 if (vfs_set_filelen(fsp, size) == -1) {
5744 return map_nt_error_from_unix(errno);
5746 trigger_write_time_update_immediate(fsp);
5747 return NT_STATUS_OK;
5750 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5751 if (!NT_STATUS_IS_OK(status)) {
5752 return status;
5755 smb_fname_tmp->st = *psbuf;
5757 status = SMB_VFS_CREATE_FILE(
5758 conn, /* conn */
5759 req, /* req */
5760 0, /* root_dir_fid */
5761 smb_fname_tmp, /* fname */
5762 FILE_WRITE_DATA, /* access_mask */
5763 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5764 FILE_SHARE_DELETE),
5765 FILE_OPEN, /* create_disposition*/
5766 0, /* create_options */
5767 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5768 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5769 0, /* allocation_size */
5770 0, /* private_flags */
5771 NULL, /* sd */
5772 NULL, /* ea_list */
5773 &new_fsp, /* result */
5774 NULL); /* pinfo */
5776 TALLOC_FREE(smb_fname_tmp);
5778 if (!NT_STATUS_IS_OK(status)) {
5779 /* NB. We check for open_was_deferred in the caller. */
5780 return status;
5783 /* See RAW-SFILEINFO-END-OF-FILE */
5784 if (fail_after_createfile) {
5785 close_file(req, new_fsp,NORMAL_CLOSE);
5786 return NT_STATUS_INVALID_LEVEL;
5789 if (vfs_set_filelen(new_fsp, size) == -1) {
5790 status = map_nt_error_from_unix(errno);
5791 close_file(req, new_fsp,NORMAL_CLOSE);
5792 return status;
5795 trigger_write_time_update_immediate(new_fsp);
5796 close_file(req, new_fsp,NORMAL_CLOSE);
5797 return NT_STATUS_OK;
5800 /****************************************************************************
5801 Deal with SMB_INFO_SET_EA.
5802 ****************************************************************************/
5804 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5805 const char *pdata,
5806 int total_data,
5807 files_struct *fsp,
5808 const struct smb_filename *smb_fname)
5810 struct ea_list *ea_list = NULL;
5811 TALLOC_CTX *ctx = NULL;
5812 NTSTATUS status = NT_STATUS_OK;
5814 if (total_data < 10) {
5816 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5817 length. They seem to have no effect. Bug #3212. JRA */
5819 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5820 /* We're done. We only get EA info in this call. */
5821 return NT_STATUS_OK;
5824 return NT_STATUS_INVALID_PARAMETER;
5827 if (IVAL(pdata,0) > total_data) {
5828 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5829 IVAL(pdata,0), (unsigned int)total_data));
5830 return NT_STATUS_INVALID_PARAMETER;
5833 ctx = talloc_tos();
5834 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5835 if (!ea_list) {
5836 return NT_STATUS_INVALID_PARAMETER;
5839 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5840 return NT_STATUS_ACCESS_DENIED;
5843 status = set_ea(conn, fsp, smb_fname, ea_list);
5845 return status;
5848 /****************************************************************************
5849 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5850 ****************************************************************************/
5852 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5853 const char *pdata,
5854 int total_data,
5855 files_struct *fsp)
5857 struct ea_list *ea_list = NULL;
5858 NTSTATUS status;
5860 if (!fsp) {
5861 return NT_STATUS_INVALID_HANDLE;
5864 if (!lp_ea_support(SNUM(conn))) {
5865 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5866 "EA's not supported.\n",
5867 (unsigned int)total_data));
5868 return NT_STATUS_EAS_NOT_SUPPORTED;
5871 if (total_data < 10) {
5872 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5873 "too small.\n",
5874 (unsigned int)total_data));
5875 return NT_STATUS_INVALID_PARAMETER;
5878 ea_list = read_nttrans_ea_list(talloc_tos(),
5879 pdata,
5880 total_data);
5882 if (!ea_list) {
5883 return NT_STATUS_INVALID_PARAMETER;
5886 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5887 return NT_STATUS_ACCESS_DENIED;
5890 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5892 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5893 smb_fname_str_dbg(fsp->fsp_name),
5894 nt_errstr(status) ));
5896 return status;
5900 /****************************************************************************
5901 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5902 ****************************************************************************/
5904 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5905 const char *pdata,
5906 int total_data,
5907 files_struct *fsp,
5908 struct smb_filename *smb_fname)
5910 NTSTATUS status = NT_STATUS_OK;
5911 bool delete_on_close;
5912 uint32 dosmode = 0;
5914 if (total_data < 1) {
5915 return NT_STATUS_INVALID_PARAMETER;
5918 if (fsp == NULL) {
5919 return NT_STATUS_INVALID_HANDLE;
5922 delete_on_close = (CVAL(pdata,0) ? True : False);
5923 dosmode = dos_mode(conn, smb_fname);
5925 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5926 "delete_on_close = %u\n",
5927 smb_fname_str_dbg(smb_fname),
5928 (unsigned int)dosmode,
5929 (unsigned int)delete_on_close ));
5931 if (delete_on_close) {
5932 status = can_set_delete_on_close(fsp, dosmode);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 return status;
5938 /* The set is across all open files on this dev/inode pair. */
5939 if (!set_delete_on_close(fsp, delete_on_close,
5940 conn->session_info->security_token,
5941 &conn->session_info->utok)) {
5942 return NT_STATUS_ACCESS_DENIED;
5944 return NT_STATUS_OK;
5947 /****************************************************************************
5948 Deal with SMB_FILE_POSITION_INFORMATION.
5949 ****************************************************************************/
5951 static NTSTATUS smb_file_position_information(connection_struct *conn,
5952 const char *pdata,
5953 int total_data,
5954 files_struct *fsp)
5956 uint64_t position_information;
5958 if (total_data < 8) {
5959 return NT_STATUS_INVALID_PARAMETER;
5962 if (fsp == NULL) {
5963 /* Ignore on pathname based set. */
5964 return NT_STATUS_OK;
5967 position_information = (uint64_t)IVAL(pdata,0);
5968 #ifdef LARGE_SMB_OFF_T
5969 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5970 #else /* LARGE_SMB_OFF_T */
5971 if (IVAL(pdata,4) != 0) {
5972 /* more than 32 bits? */
5973 return NT_STATUS_INVALID_PARAMETER;
5975 #endif /* LARGE_SMB_OFF_T */
5977 DEBUG(10,("smb_file_position_information: Set file position "
5978 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5979 (double)position_information));
5980 fsp->fh->position_information = position_information;
5981 return NT_STATUS_OK;
5984 /****************************************************************************
5985 Deal with SMB_FILE_MODE_INFORMATION.
5986 ****************************************************************************/
5988 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5989 const char *pdata,
5990 int total_data)
5992 uint32 mode;
5994 if (total_data < 4) {
5995 return NT_STATUS_INVALID_PARAMETER;
5997 mode = IVAL(pdata,0);
5998 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5999 return NT_STATUS_INVALID_PARAMETER;
6001 return NT_STATUS_OK;
6004 /****************************************************************************
6005 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6006 ****************************************************************************/
6008 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6009 struct smb_request *req,
6010 const char *pdata,
6011 int total_data,
6012 const struct smb_filename *smb_fname)
6014 char *link_target = NULL;
6015 const char *newname = smb_fname->base_name;
6016 TALLOC_CTX *ctx = talloc_tos();
6018 /* Set a symbolic link. */
6019 /* Don't allow this if follow links is false. */
6021 if (total_data == 0) {
6022 return NT_STATUS_INVALID_PARAMETER;
6025 if (!lp_symlinks(SNUM(conn))) {
6026 return NT_STATUS_ACCESS_DENIED;
6029 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6030 total_data, STR_TERMINATE);
6032 if (!link_target) {
6033 return NT_STATUS_INVALID_PARAMETER;
6036 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6037 newname, link_target ));
6039 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6040 return map_nt_error_from_unix(errno);
6043 return NT_STATUS_OK;
6046 /****************************************************************************
6047 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6048 ****************************************************************************/
6050 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6051 struct smb_request *req,
6052 const char *pdata, int total_data,
6053 struct smb_filename *smb_fname_new)
6055 char *oldname = NULL;
6056 struct smb_filename *smb_fname_old = NULL;
6057 TALLOC_CTX *ctx = talloc_tos();
6058 NTSTATUS status = NT_STATUS_OK;
6060 /* Set a hard link. */
6061 if (total_data == 0) {
6062 return NT_STATUS_INVALID_PARAMETER;
6065 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6066 total_data, STR_TERMINATE, &status);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 return status;
6071 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6072 smb_fname_str_dbg(smb_fname_new), oldname));
6074 status = filename_convert(ctx,
6075 conn,
6076 req->flags2 & FLAGS2_DFS_PATHNAMES,
6077 oldname,
6079 NULL,
6080 &smb_fname_old);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 return status;
6085 return hardlink_internals(ctx, conn, req, false,
6086 smb_fname_old, smb_fname_new);
6089 /****************************************************************************
6090 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6091 ****************************************************************************/
6093 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6094 struct smb_request *req,
6095 const char *pdata,
6096 int total_data,
6097 files_struct *fsp,
6098 struct smb_filename *smb_fname_src)
6100 bool overwrite;
6101 uint32_t len;
6102 char *newname = NULL;
6103 struct smb_filename *smb_fname_dst = NULL;
6104 NTSTATUS status = NT_STATUS_OK;
6105 TALLOC_CTX *ctx = talloc_tos();
6107 if (!fsp) {
6108 return NT_STATUS_INVALID_HANDLE;
6111 if (total_data < 20) {
6112 return NT_STATUS_INVALID_PARAMETER;
6115 overwrite = (CVAL(pdata,0) ? True : False);
6116 len = IVAL(pdata,16);
6118 if (len > (total_data - 20) || (len == 0)) {
6119 return NT_STATUS_INVALID_PARAMETER;
6122 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6123 &pdata[20], len, STR_TERMINATE,
6124 &status);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 return status;
6129 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6130 newname));
6132 status = filename_convert(ctx,
6133 conn,
6134 req->flags2 & FLAGS2_DFS_PATHNAMES,
6135 newname,
6136 UCF_SAVE_LCOMP,
6137 NULL,
6138 &smb_fname_dst);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 return status;
6143 if (fsp->base_fsp) {
6144 /* newname must be a stream name. */
6145 if (newname[0] != ':') {
6146 return NT_STATUS_NOT_SUPPORTED;
6149 /* Create an smb_fname to call rename_internals_fsp() with. */
6150 status = create_synthetic_smb_fname(talloc_tos(),
6151 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6152 &smb_fname_dst);
6153 if (!NT_STATUS_IS_OK(status)) {
6154 goto out;
6158 * Set the original last component, since
6159 * rename_internals_fsp() requires it.
6161 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6162 newname);
6163 if (smb_fname_dst->original_lcomp == NULL) {
6164 status = NT_STATUS_NO_MEMORY;
6165 goto out;
6170 DEBUG(10,("smb2_file_rename_information: "
6171 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6172 fsp->fnum, fsp_str_dbg(fsp),
6173 smb_fname_str_dbg(smb_fname_dst)));
6174 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6175 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6176 overwrite);
6178 out:
6179 TALLOC_FREE(smb_fname_dst);
6180 return status;
6183 static NTSTATUS smb_file_link_information(connection_struct *conn,
6184 struct smb_request *req,
6185 const char *pdata,
6186 int total_data,
6187 files_struct *fsp,
6188 struct smb_filename *smb_fname_src)
6190 bool overwrite;
6191 uint32_t len;
6192 char *newname = NULL;
6193 struct smb_filename *smb_fname_dst = NULL;
6194 NTSTATUS status = NT_STATUS_OK;
6195 TALLOC_CTX *ctx = talloc_tos();
6197 if (!fsp) {
6198 return NT_STATUS_INVALID_HANDLE;
6201 if (total_data < 20) {
6202 return NT_STATUS_INVALID_PARAMETER;
6205 overwrite = (CVAL(pdata,0) ? true : false);
6206 len = IVAL(pdata,16);
6208 if (len > (total_data - 20) || (len == 0)) {
6209 return NT_STATUS_INVALID_PARAMETER;
6212 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6213 &pdata[20], len, STR_TERMINATE,
6214 &status);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 return status;
6219 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6220 newname));
6222 status = filename_convert(ctx,
6223 conn,
6224 req->flags2 & FLAGS2_DFS_PATHNAMES,
6225 newname,
6226 UCF_SAVE_LCOMP,
6227 NULL,
6228 &smb_fname_dst);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 return status;
6233 if (fsp->base_fsp) {
6234 /* No stream names. */
6235 return NT_STATUS_NOT_SUPPORTED;
6238 DEBUG(10,("smb_file_link_information: "
6239 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6240 fsp->fnum, fsp_str_dbg(fsp),
6241 smb_fname_str_dbg(smb_fname_dst)));
6242 status = hardlink_internals(ctx,
6243 conn,
6244 req,
6245 overwrite,
6246 fsp->fsp_name,
6247 smb_fname_dst);
6249 TALLOC_FREE(smb_fname_dst);
6250 return status;
6253 /****************************************************************************
6254 Deal with SMB_FILE_RENAME_INFORMATION.
6255 ****************************************************************************/
6257 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6258 struct smb_request *req,
6259 const char *pdata,
6260 int total_data,
6261 files_struct *fsp,
6262 struct smb_filename *smb_fname_src)
6264 bool overwrite;
6265 uint32 root_fid;
6266 uint32 len;
6267 char *newname = NULL;
6268 struct smb_filename *smb_fname_dst = NULL;
6269 bool dest_has_wcard = False;
6270 NTSTATUS status = NT_STATUS_OK;
6271 char *p;
6272 TALLOC_CTX *ctx = talloc_tos();
6274 if (total_data < 13) {
6275 return NT_STATUS_INVALID_PARAMETER;
6278 overwrite = (CVAL(pdata,0) ? True : False);
6279 root_fid = IVAL(pdata,4);
6280 len = IVAL(pdata,8);
6282 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6283 return NT_STATUS_INVALID_PARAMETER;
6286 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6287 len, 0, &status,
6288 &dest_has_wcard);
6289 if (!NT_STATUS_IS_OK(status)) {
6290 return status;
6293 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6294 newname));
6296 status = resolve_dfspath_wcard(ctx, conn,
6297 req->flags2 & FLAGS2_DFS_PATHNAMES,
6298 newname,
6299 true,
6300 &newname,
6301 &dest_has_wcard);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 return status;
6306 /* Check the new name has no '/' characters. */
6307 if (strchr_m(newname, '/')) {
6308 return NT_STATUS_NOT_SUPPORTED;
6311 if (fsp && fsp->base_fsp) {
6312 /* newname must be a stream name. */
6313 if (newname[0] != ':') {
6314 return NT_STATUS_NOT_SUPPORTED;
6317 /* Create an smb_fname to call rename_internals_fsp() with. */
6318 status = create_synthetic_smb_fname(talloc_tos(),
6319 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6320 &smb_fname_dst);
6321 if (!NT_STATUS_IS_OK(status)) {
6322 goto out;
6326 * Set the original last component, since
6327 * rename_internals_fsp() requires it.
6329 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6330 newname);
6331 if (smb_fname_dst->original_lcomp == NULL) {
6332 status = NT_STATUS_NO_MEMORY;
6333 goto out;
6336 } else {
6338 * Build up an smb_fname_dst based on the filename passed in.
6339 * We basically just strip off the last component, and put on
6340 * the newname instead.
6342 char *base_name = NULL;
6344 /* newname must *not* be a stream name. */
6345 if (newname[0] == ':') {
6346 return NT_STATUS_NOT_SUPPORTED;
6350 * Strip off the last component (filename) of the path passed
6351 * in.
6353 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6354 if (!base_name) {
6355 return NT_STATUS_NO_MEMORY;
6357 p = strrchr_m(base_name, '/');
6358 if (p) {
6359 p[1] = '\0';
6360 } else {
6361 base_name = talloc_strdup(ctx, "");
6362 if (!base_name) {
6363 return NT_STATUS_NO_MEMORY;
6366 /* Append the new name. */
6367 base_name = talloc_asprintf_append(base_name,
6368 "%s",
6369 newname);
6370 if (!base_name) {
6371 return NT_STATUS_NO_MEMORY;
6374 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6375 (UCF_SAVE_LCOMP |
6376 (dest_has_wcard ?
6377 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6378 0)));
6380 /* If an error we expect this to be
6381 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6383 if (!NT_STATUS_IS_OK(status)) {
6384 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6385 status)) {
6386 goto out;
6388 /* Create an smb_fname to call rename_internals_fsp() */
6389 status = create_synthetic_smb_fname(ctx,
6390 base_name, NULL,
6391 NULL,
6392 &smb_fname_dst);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 goto out;
6399 if (fsp) {
6400 DEBUG(10,("smb_file_rename_information: "
6401 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6402 fsp->fnum, fsp_str_dbg(fsp),
6403 smb_fname_str_dbg(smb_fname_dst)));
6404 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6405 overwrite);
6406 } else {
6407 DEBUG(10,("smb_file_rename_information: "
6408 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6409 smb_fname_str_dbg(smb_fname_src),
6410 smb_fname_str_dbg(smb_fname_dst)));
6411 status = rename_internals(ctx, conn, req, smb_fname_src,
6412 smb_fname_dst, 0, overwrite, false,
6413 dest_has_wcard,
6414 FILE_WRITE_ATTRIBUTES);
6416 out:
6417 TALLOC_FREE(smb_fname_dst);
6418 return status;
6421 /****************************************************************************
6422 Deal with SMB_SET_POSIX_ACL.
6423 ****************************************************************************/
6425 #if defined(HAVE_POSIX_ACLS)
6426 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6427 const char *pdata,
6428 int total_data,
6429 files_struct *fsp,
6430 const struct smb_filename *smb_fname)
6432 uint16 posix_acl_version;
6433 uint16 num_file_acls;
6434 uint16 num_def_acls;
6435 bool valid_file_acls = True;
6436 bool valid_def_acls = True;
6438 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6439 return NT_STATUS_INVALID_PARAMETER;
6441 posix_acl_version = SVAL(pdata,0);
6442 num_file_acls = SVAL(pdata,2);
6443 num_def_acls = SVAL(pdata,4);
6445 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6446 valid_file_acls = False;
6447 num_file_acls = 0;
6450 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6451 valid_def_acls = False;
6452 num_def_acls = 0;
6455 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6456 return NT_STATUS_INVALID_PARAMETER;
6459 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6460 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6461 return NT_STATUS_INVALID_PARAMETER;
6464 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6465 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6466 (unsigned int)num_file_acls,
6467 (unsigned int)num_def_acls));
6469 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6470 smb_fname->base_name, num_file_acls,
6471 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6472 return map_nt_error_from_unix(errno);
6475 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6476 smb_fname->base_name, &smb_fname->st, num_def_acls,
6477 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6478 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6479 return map_nt_error_from_unix(errno);
6481 return NT_STATUS_OK;
6483 #endif
6485 /****************************************************************************
6486 Deal with SMB_SET_POSIX_LOCK.
6487 ****************************************************************************/
6489 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6490 struct smb_request *req,
6491 const char *pdata,
6492 int total_data,
6493 files_struct *fsp)
6495 uint64_t count;
6496 uint64_t offset;
6497 uint64_t smblctx;
6498 bool blocking_lock = False;
6499 enum brl_type lock_type;
6501 NTSTATUS status = NT_STATUS_OK;
6503 if (fsp == NULL || fsp->fh->fd == -1) {
6504 return NT_STATUS_INVALID_HANDLE;
6507 if (total_data != POSIX_LOCK_DATA_SIZE) {
6508 return NT_STATUS_INVALID_PARAMETER;
6511 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6512 case POSIX_LOCK_TYPE_READ:
6513 lock_type = READ_LOCK;
6514 break;
6515 case POSIX_LOCK_TYPE_WRITE:
6516 /* Return the right POSIX-mappable error code for files opened read-only. */
6517 if (!fsp->can_write) {
6518 return NT_STATUS_INVALID_HANDLE;
6520 lock_type = WRITE_LOCK;
6521 break;
6522 case POSIX_LOCK_TYPE_UNLOCK:
6523 lock_type = UNLOCK_LOCK;
6524 break;
6525 default:
6526 return NT_STATUS_INVALID_PARAMETER;
6529 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6530 blocking_lock = False;
6531 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6532 blocking_lock = True;
6533 } else {
6534 return NT_STATUS_INVALID_PARAMETER;
6537 if (!lp_blocking_locks(SNUM(conn))) {
6538 blocking_lock = False;
6541 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6542 #if defined(HAVE_LONGLONG)
6543 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6544 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6545 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6546 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6547 #else /* HAVE_LONGLONG */
6548 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6549 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6550 #endif /* HAVE_LONGLONG */
6552 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6553 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6554 fsp_str_dbg(fsp),
6555 (unsigned int)lock_type,
6556 (unsigned long long)smblctx,
6557 (double)count,
6558 (double)offset ));
6560 if (lock_type == UNLOCK_LOCK) {
6561 status = do_unlock(req->sconn->msg_ctx,
6562 fsp,
6563 smblctx,
6564 count,
6565 offset,
6566 POSIX_LOCK);
6567 } else {
6568 uint64_t block_smblctx;
6570 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6571 fsp,
6572 smblctx,
6573 count,
6574 offset,
6575 lock_type,
6576 POSIX_LOCK,
6577 blocking_lock,
6578 &status,
6579 &block_smblctx,
6580 NULL);
6582 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6584 * A blocking lock was requested. Package up
6585 * this smb into a queued request and push it
6586 * onto the blocking lock queue.
6588 if(push_blocking_lock_request(br_lck,
6589 req,
6590 fsp,
6591 -1, /* infinite timeout. */
6593 smblctx,
6594 lock_type,
6595 POSIX_LOCK,
6596 offset,
6597 count,
6598 block_smblctx)) {
6599 TALLOC_FREE(br_lck);
6600 return status;
6603 TALLOC_FREE(br_lck);
6606 return status;
6609 /****************************************************************************
6610 Deal with SMB_SET_FILE_BASIC_INFO.
6611 ****************************************************************************/
6613 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6614 const char *pdata,
6615 int total_data,
6616 files_struct *fsp,
6617 const struct smb_filename *smb_fname)
6619 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6620 struct smb_file_time ft;
6621 uint32 dosmode = 0;
6622 NTSTATUS status = NT_STATUS_OK;
6624 ZERO_STRUCT(ft);
6626 if (total_data < 36) {
6627 return NT_STATUS_INVALID_PARAMETER;
6630 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6631 return NT_STATUS_ACCESS_DENIED;
6634 /* Set the attributes */
6635 dosmode = IVAL(pdata,32);
6636 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6637 if (!NT_STATUS_IS_OK(status)) {
6638 return status;
6641 /* create time */
6642 ft.create_time = interpret_long_date(pdata);
6644 /* access time */
6645 ft.atime = interpret_long_date(pdata+8);
6647 /* write time. */
6648 ft.mtime = interpret_long_date(pdata+16);
6650 /* change time. */
6651 ft.ctime = interpret_long_date(pdata+24);
6653 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6654 smb_fname_str_dbg(smb_fname)));
6656 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6657 true);
6660 /****************************************************************************
6661 Deal with SMB_INFO_STANDARD.
6662 ****************************************************************************/
6664 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6665 const char *pdata,
6666 int total_data,
6667 files_struct *fsp,
6668 const struct smb_filename *smb_fname)
6670 struct smb_file_time ft;
6672 ZERO_STRUCT(ft);
6674 if (total_data < 12) {
6675 return NT_STATUS_INVALID_PARAMETER;
6678 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6679 return NT_STATUS_ACCESS_DENIED;
6682 /* create time */
6683 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6684 /* access time */
6685 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6686 /* write time */
6687 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6689 DEBUG(10,("smb_set_info_standard: file %s\n",
6690 smb_fname_str_dbg(smb_fname)));
6692 return smb_set_file_time(conn,
6693 fsp,
6694 smb_fname,
6695 &ft,
6696 true);
6699 /****************************************************************************
6700 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6701 ****************************************************************************/
6703 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6704 struct smb_request *req,
6705 const char *pdata,
6706 int total_data,
6707 files_struct *fsp,
6708 struct smb_filename *smb_fname)
6710 uint64_t allocation_size = 0;
6711 NTSTATUS status = NT_STATUS_OK;
6712 files_struct *new_fsp = NULL;
6714 if (!VALID_STAT(smb_fname->st)) {
6715 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6718 if (total_data < 8) {
6719 return NT_STATUS_INVALID_PARAMETER;
6722 allocation_size = (uint64_t)IVAL(pdata,0);
6723 #ifdef LARGE_SMB_OFF_T
6724 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6725 #else /* LARGE_SMB_OFF_T */
6726 if (IVAL(pdata,4) != 0) {
6727 /* more than 32 bits? */
6728 return NT_STATUS_INVALID_PARAMETER;
6730 #endif /* LARGE_SMB_OFF_T */
6732 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6733 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6734 (double)allocation_size));
6736 if (allocation_size) {
6737 allocation_size = smb_roundup(conn, allocation_size);
6740 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6741 return NT_STATUS_ACCESS_DENIED;
6744 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6745 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6746 (double)allocation_size));
6748 if (fsp && fsp->fh->fd != -1) {
6749 /* Open file handle. */
6750 /* Only change if needed. */
6751 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6752 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6753 return map_nt_error_from_unix(errno);
6756 /* But always update the time. */
6758 * This is equivalent to a write. Ensure it's seen immediately
6759 * if there are no pending writes.
6761 trigger_write_time_update_immediate(fsp);
6762 return NT_STATUS_OK;
6765 /* Pathname or stat or directory file. */
6766 status = SMB_VFS_CREATE_FILE(
6767 conn, /* conn */
6768 req, /* req */
6769 0, /* root_dir_fid */
6770 smb_fname, /* fname */
6771 FILE_WRITE_DATA, /* access_mask */
6772 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6773 FILE_SHARE_DELETE),
6774 FILE_OPEN, /* create_disposition*/
6775 0, /* create_options */
6776 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6777 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6778 0, /* allocation_size */
6779 0, /* private_flags */
6780 NULL, /* sd */
6781 NULL, /* ea_list */
6782 &new_fsp, /* result */
6783 NULL); /* pinfo */
6785 if (!NT_STATUS_IS_OK(status)) {
6786 /* NB. We check for open_was_deferred in the caller. */
6787 return status;
6790 /* Only change if needed. */
6791 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6792 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6793 status = map_nt_error_from_unix(errno);
6794 close_file(req, new_fsp, NORMAL_CLOSE);
6795 return status;
6799 /* Changing the allocation size should set the last mod time. */
6801 * This is equivalent to a write. Ensure it's seen immediately
6802 * if there are no pending writes.
6804 trigger_write_time_update_immediate(new_fsp);
6806 close_file(req, new_fsp, NORMAL_CLOSE);
6807 return NT_STATUS_OK;
6810 /****************************************************************************
6811 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6812 ****************************************************************************/
6814 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6815 struct smb_request *req,
6816 const char *pdata,
6817 int total_data,
6818 files_struct *fsp,
6819 const struct smb_filename *smb_fname,
6820 bool fail_after_createfile)
6822 SMB_OFF_T size;
6824 if (total_data < 8) {
6825 return NT_STATUS_INVALID_PARAMETER;
6828 size = IVAL(pdata,0);
6829 #ifdef LARGE_SMB_OFF_T
6830 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6831 #else /* LARGE_SMB_OFF_T */
6832 if (IVAL(pdata,4) != 0) {
6833 /* more than 32 bits? */
6834 return NT_STATUS_INVALID_PARAMETER;
6836 #endif /* LARGE_SMB_OFF_T */
6837 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6838 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6839 (double)size));
6841 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6842 return NT_STATUS_ACCESS_DENIED;
6845 return smb_set_file_size(conn, req,
6846 fsp,
6847 smb_fname,
6848 &smb_fname->st,
6849 size,
6850 fail_after_createfile);
6853 /****************************************************************************
6854 Allow a UNIX info mknod.
6855 ****************************************************************************/
6857 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6858 const char *pdata,
6859 int total_data,
6860 const struct smb_filename *smb_fname)
6862 uint32 file_type = IVAL(pdata,56);
6863 #if defined(HAVE_MAKEDEV)
6864 uint32 dev_major = IVAL(pdata,60);
6865 uint32 dev_minor = IVAL(pdata,68);
6866 #endif
6867 SMB_DEV_T dev = (SMB_DEV_T)0;
6868 uint32 raw_unixmode = IVAL(pdata,84);
6869 NTSTATUS status;
6870 mode_t unixmode;
6872 if (total_data < 100) {
6873 return NT_STATUS_INVALID_PARAMETER;
6876 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6877 PERM_NEW_FILE, &unixmode);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 return status;
6882 #if defined(HAVE_MAKEDEV)
6883 dev = makedev(dev_major, dev_minor);
6884 #endif
6886 switch (file_type) {
6887 #if defined(S_IFIFO)
6888 case UNIX_TYPE_FIFO:
6889 unixmode |= S_IFIFO;
6890 break;
6891 #endif
6892 #if defined(S_IFSOCK)
6893 case UNIX_TYPE_SOCKET:
6894 unixmode |= S_IFSOCK;
6895 break;
6896 #endif
6897 #if defined(S_IFCHR)
6898 case UNIX_TYPE_CHARDEV:
6899 unixmode |= S_IFCHR;
6900 break;
6901 #endif
6902 #if defined(S_IFBLK)
6903 case UNIX_TYPE_BLKDEV:
6904 unixmode |= S_IFBLK;
6905 break;
6906 #endif
6907 default:
6908 return NT_STATUS_INVALID_PARAMETER;
6911 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6912 "%.0f mode 0%o for file %s\n", (double)dev,
6913 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6915 /* Ok - do the mknod. */
6916 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6917 return map_nt_error_from_unix(errno);
6920 /* If any of the other "set" calls fail we
6921 * don't want to end up with a half-constructed mknod.
6924 if (lp_inherit_perms(SNUM(conn))) {
6925 char *parent;
6926 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6927 &parent, NULL)) {
6928 return NT_STATUS_NO_MEMORY;
6930 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6931 unixmode);
6932 TALLOC_FREE(parent);
6935 return NT_STATUS_OK;
6938 /****************************************************************************
6939 Deal with SMB_SET_FILE_UNIX_BASIC.
6940 ****************************************************************************/
6942 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6943 struct smb_request *req,
6944 const char *pdata,
6945 int total_data,
6946 files_struct *fsp,
6947 const struct smb_filename *smb_fname)
6949 struct smb_file_time ft;
6950 uint32 raw_unixmode;
6951 mode_t unixmode;
6952 SMB_OFF_T size = 0;
6953 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6954 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6955 NTSTATUS status = NT_STATUS_OK;
6956 bool delete_on_fail = False;
6957 enum perm_type ptype;
6958 files_struct *all_fsps = NULL;
6959 bool modify_mtime = true;
6960 struct file_id id;
6961 struct smb_filename *smb_fname_tmp = NULL;
6962 SMB_STRUCT_STAT sbuf;
6964 ZERO_STRUCT(ft);
6966 if (total_data < 100) {
6967 return NT_STATUS_INVALID_PARAMETER;
6970 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6971 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6972 size=IVAL(pdata,0); /* first 8 Bytes are size */
6973 #ifdef LARGE_SMB_OFF_T
6974 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6975 #else /* LARGE_SMB_OFF_T */
6976 if (IVAL(pdata,4) != 0) {
6977 /* more than 32 bits? */
6978 return NT_STATUS_INVALID_PARAMETER;
6980 #endif /* LARGE_SMB_OFF_T */
6983 ft.atime = interpret_long_date(pdata+24); /* access_time */
6984 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6985 set_owner = (uid_t)IVAL(pdata,40);
6986 set_grp = (gid_t)IVAL(pdata,48);
6987 raw_unixmode = IVAL(pdata,84);
6989 if (VALID_STAT(smb_fname->st)) {
6990 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6991 ptype = PERM_EXISTING_DIR;
6992 } else {
6993 ptype = PERM_EXISTING_FILE;
6995 } else {
6996 ptype = PERM_NEW_FILE;
6999 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7000 ptype, &unixmode);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 return status;
7005 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7006 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7007 smb_fname_str_dbg(smb_fname), (double)size,
7008 (unsigned int)set_owner, (unsigned int)set_grp,
7009 (int)raw_unixmode));
7011 sbuf = smb_fname->st;
7013 if (!VALID_STAT(sbuf)) {
7015 * The only valid use of this is to create character and block
7016 * devices, and named pipes. This is deprecated (IMHO) and
7017 * a new info level should be used for mknod. JRA.
7020 status = smb_unix_mknod(conn,
7021 pdata,
7022 total_data,
7023 smb_fname);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 return status;
7028 status = copy_smb_filename(talloc_tos(), smb_fname,
7029 &smb_fname_tmp);
7030 if (!NT_STATUS_IS_OK(status)) {
7031 return status;
7034 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7035 status = map_nt_error_from_unix(errno);
7036 TALLOC_FREE(smb_fname_tmp);
7037 SMB_VFS_UNLINK(conn, smb_fname);
7038 return status;
7041 sbuf = smb_fname_tmp->st;
7042 smb_fname = smb_fname_tmp;
7044 /* Ensure we don't try and change anything else. */
7045 raw_unixmode = SMB_MODE_NO_CHANGE;
7046 size = get_file_size_stat(&sbuf);
7047 ft.atime = sbuf.st_ex_atime;
7048 ft.mtime = sbuf.st_ex_mtime;
7050 * We continue here as we might want to change the
7051 * owner uid/gid.
7053 delete_on_fail = True;
7056 #if 1
7057 /* Horrible backwards compatibility hack as an old server bug
7058 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7059 * */
7061 if (!size) {
7062 size = get_file_size_stat(&sbuf);
7064 #endif
7067 * Deal with the UNIX specific mode set.
7070 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7071 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7072 "setting mode 0%o for file %s\n",
7073 (unsigned int)unixmode,
7074 smb_fname_str_dbg(smb_fname)));
7075 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7076 return map_nt_error_from_unix(errno);
7081 * Deal with the UNIX specific uid set.
7084 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7085 (sbuf.st_ex_uid != set_owner)) {
7086 int ret;
7088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7089 "changing owner %u for path %s\n",
7090 (unsigned int)set_owner,
7091 smb_fname_str_dbg(smb_fname)));
7093 if (S_ISLNK(sbuf.st_ex_mode)) {
7094 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7095 set_owner, (gid_t)-1);
7096 } else {
7097 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7098 set_owner, (gid_t)-1);
7101 if (ret != 0) {
7102 status = map_nt_error_from_unix(errno);
7103 if (delete_on_fail) {
7104 SMB_VFS_UNLINK(conn, smb_fname);
7106 return status;
7111 * Deal with the UNIX specific gid set.
7114 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7115 (sbuf.st_ex_gid != set_grp)) {
7116 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7117 "changing group %u for file %s\n",
7118 (unsigned int)set_owner,
7119 smb_fname_str_dbg(smb_fname)));
7120 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7121 set_grp) != 0) {
7122 status = map_nt_error_from_unix(errno);
7123 if (delete_on_fail) {
7124 SMB_VFS_UNLINK(conn, smb_fname);
7126 return status;
7130 /* Deal with any size changes. */
7132 status = smb_set_file_size(conn, req,
7133 fsp,
7134 smb_fname,
7135 &sbuf,
7136 size,
7137 false);
7138 if (!NT_STATUS_IS_OK(status)) {
7139 return status;
7142 /* Deal with any time changes. */
7143 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7144 /* No change, don't cancel anything. */
7145 return status;
7148 id = vfs_file_id_from_sbuf(conn, &sbuf);
7149 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7150 all_fsps = file_find_di_next(all_fsps)) {
7152 * We're setting the time explicitly for UNIX.
7153 * Cancel any pending changes over all handles.
7155 all_fsps->update_write_time_on_close = false;
7156 TALLOC_FREE(all_fsps->update_write_time_event);
7160 * Override the "setting_write_time"
7161 * parameter here as it almost does what
7162 * we need. Just remember if we modified
7163 * mtime and send the notify ourselves.
7165 if (null_timespec(ft.mtime)) {
7166 modify_mtime = false;
7169 status = smb_set_file_time(conn,
7170 fsp,
7171 smb_fname,
7172 &ft,
7173 false);
7174 if (modify_mtime) {
7175 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7176 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7178 return status;
7181 /****************************************************************************
7182 Deal with SMB_SET_FILE_UNIX_INFO2.
7183 ****************************************************************************/
7185 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7186 struct smb_request *req,
7187 const char *pdata,
7188 int total_data,
7189 files_struct *fsp,
7190 const struct smb_filename *smb_fname)
7192 NTSTATUS status;
7193 uint32 smb_fflags;
7194 uint32 smb_fmask;
7196 if (total_data < 116) {
7197 return NT_STATUS_INVALID_PARAMETER;
7200 /* Start by setting all the fields that are common between UNIX_BASIC
7201 * and UNIX_INFO2.
7203 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7204 fsp, smb_fname);
7205 if (!NT_STATUS_IS_OK(status)) {
7206 return status;
7209 smb_fflags = IVAL(pdata, 108);
7210 smb_fmask = IVAL(pdata, 112);
7212 /* NB: We should only attempt to alter the file flags if the client
7213 * sends a non-zero mask.
7215 if (smb_fmask != 0) {
7216 int stat_fflags = 0;
7218 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7219 smb_fmask, &stat_fflags)) {
7220 /* Client asked to alter a flag we don't understand. */
7221 return NT_STATUS_INVALID_PARAMETER;
7224 if (fsp && fsp->fh->fd != -1) {
7225 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7226 return NT_STATUS_NOT_SUPPORTED;
7227 } else {
7228 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7229 stat_fflags) != 0) {
7230 return map_nt_error_from_unix(errno);
7235 /* XXX: need to add support for changing the create_time here. You
7236 * can do this for paths on Darwin with setattrlist(2). The right way
7237 * to hook this up is probably by extending the VFS utimes interface.
7240 return NT_STATUS_OK;
7243 /****************************************************************************
7244 Create a directory with POSIX semantics.
7245 ****************************************************************************/
7247 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7248 struct smb_request *req,
7249 char **ppdata,
7250 int total_data,
7251 struct smb_filename *smb_fname,
7252 int *pdata_return_size)
7254 NTSTATUS status = NT_STATUS_OK;
7255 uint32 raw_unixmode = 0;
7256 uint32 mod_unixmode = 0;
7257 mode_t unixmode = (mode_t)0;
7258 files_struct *fsp = NULL;
7259 uint16 info_level_return = 0;
7260 int info;
7261 char *pdata = *ppdata;
7263 if (total_data < 18) {
7264 return NT_STATUS_INVALID_PARAMETER;
7267 raw_unixmode = IVAL(pdata,8);
7268 /* Next 4 bytes are not yet defined. */
7270 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7271 PERM_NEW_DIR, &unixmode);
7272 if (!NT_STATUS_IS_OK(status)) {
7273 return status;
7276 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7278 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7279 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7281 status = SMB_VFS_CREATE_FILE(
7282 conn, /* conn */
7283 req, /* req */
7284 0, /* root_dir_fid */
7285 smb_fname, /* fname */
7286 FILE_READ_ATTRIBUTES, /* access_mask */
7287 FILE_SHARE_NONE, /* share_access */
7288 FILE_CREATE, /* create_disposition*/
7289 FILE_DIRECTORY_FILE, /* create_options */
7290 mod_unixmode, /* file_attributes */
7291 0, /* oplock_request */
7292 0, /* allocation_size */
7293 0, /* private_flags */
7294 NULL, /* sd */
7295 NULL, /* ea_list */
7296 &fsp, /* result */
7297 &info); /* pinfo */
7299 if (NT_STATUS_IS_OK(status)) {
7300 close_file(req, fsp, NORMAL_CLOSE);
7303 info_level_return = SVAL(pdata,16);
7305 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7306 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7307 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7308 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7309 } else {
7310 *pdata_return_size = 12;
7313 /* Realloc the data size */
7314 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7315 if (*ppdata == NULL) {
7316 *pdata_return_size = 0;
7317 return NT_STATUS_NO_MEMORY;
7319 pdata = *ppdata;
7321 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7322 SSVAL(pdata,2,0); /* No fnum. */
7323 SIVAL(pdata,4,info); /* Was directory created. */
7325 switch (info_level_return) {
7326 case SMB_QUERY_FILE_UNIX_BASIC:
7327 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7328 SSVAL(pdata,10,0); /* Padding. */
7329 store_file_unix_basic(conn, pdata + 12, fsp,
7330 &smb_fname->st);
7331 break;
7332 case SMB_QUERY_FILE_UNIX_INFO2:
7333 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7334 SSVAL(pdata,10,0); /* Padding. */
7335 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7336 &smb_fname->st);
7337 break;
7338 default:
7339 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7340 SSVAL(pdata,10,0); /* Padding. */
7341 break;
7344 return status;
7347 /****************************************************************************
7348 Open/Create a file with POSIX semantics.
7349 ****************************************************************************/
7351 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7352 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7354 static NTSTATUS smb_posix_open(connection_struct *conn,
7355 struct smb_request *req,
7356 char **ppdata,
7357 int total_data,
7358 struct smb_filename *smb_fname,
7359 int *pdata_return_size)
7361 bool extended_oplock_granted = False;
7362 char *pdata = *ppdata;
7363 uint32 flags = 0;
7364 uint32 wire_open_mode = 0;
7365 uint32 raw_unixmode = 0;
7366 uint32 mod_unixmode = 0;
7367 uint32 create_disp = 0;
7368 uint32 access_mask = 0;
7369 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7370 NTSTATUS status = NT_STATUS_OK;
7371 mode_t unixmode = (mode_t)0;
7372 files_struct *fsp = NULL;
7373 int oplock_request = 0;
7374 int info = 0;
7375 uint16 info_level_return = 0;
7377 if (total_data < 18) {
7378 return NT_STATUS_INVALID_PARAMETER;
7381 flags = IVAL(pdata,0);
7382 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7383 if (oplock_request) {
7384 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7387 wire_open_mode = IVAL(pdata,4);
7389 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7390 return smb_posix_mkdir(conn, req,
7391 ppdata,
7392 total_data,
7393 smb_fname,
7394 pdata_return_size);
7397 switch (wire_open_mode & SMB_ACCMODE) {
7398 case SMB_O_RDONLY:
7399 access_mask = SMB_O_RDONLY_MAPPING;
7400 break;
7401 case SMB_O_WRONLY:
7402 access_mask = SMB_O_WRONLY_MAPPING;
7403 break;
7404 case SMB_O_RDWR:
7405 access_mask = (SMB_O_RDONLY_MAPPING|
7406 SMB_O_WRONLY_MAPPING);
7407 break;
7408 default:
7409 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7410 (unsigned int)wire_open_mode ));
7411 return NT_STATUS_INVALID_PARAMETER;
7414 wire_open_mode &= ~SMB_ACCMODE;
7416 /* First take care of O_CREAT|O_EXCL interactions. */
7417 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7418 case (SMB_O_CREAT | SMB_O_EXCL):
7419 /* File exists fail. File not exist create. */
7420 create_disp = FILE_CREATE;
7421 break;
7422 case SMB_O_CREAT:
7423 /* File exists open. File not exist create. */
7424 create_disp = FILE_OPEN_IF;
7425 break;
7426 case SMB_O_EXCL:
7427 /* O_EXCL on its own without O_CREAT is undefined.
7428 We deliberately ignore it as some versions of
7429 Linux CIFSFS can send a bare O_EXCL on the
7430 wire which other filesystems in the kernel
7431 ignore. See bug 9519 for details. */
7433 /* Fallthrough. */
7435 case 0:
7436 /* File exists open. File not exist fail. */
7437 create_disp = FILE_OPEN;
7438 break;
7439 default:
7440 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7441 (unsigned int)wire_open_mode ));
7442 return NT_STATUS_INVALID_PARAMETER;
7445 /* Next factor in the effects of O_TRUNC. */
7446 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7448 if (wire_open_mode & SMB_O_TRUNC) {
7449 switch (create_disp) {
7450 case FILE_CREATE:
7451 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7452 /* Leave create_disp alone as
7453 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7455 /* File exists fail. File not exist create. */
7456 break;
7457 case FILE_OPEN_IF:
7458 /* SMB_O_CREAT | SMB_O_TRUNC */
7459 /* File exists overwrite. File not exist create. */
7460 create_disp = FILE_OVERWRITE_IF;
7461 break;
7462 case FILE_OPEN:
7463 /* SMB_O_TRUNC */
7464 /* File exists overwrite. File not exist fail. */
7465 create_disp = FILE_OVERWRITE;
7466 break;
7467 default:
7468 /* Cannot get here. */
7469 smb_panic("smb_posix_open: logic error");
7470 return NT_STATUS_INVALID_PARAMETER;
7474 raw_unixmode = IVAL(pdata,8);
7475 /* Next 4 bytes are not yet defined. */
7477 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7478 (VALID_STAT(smb_fname->st) ?
7479 PERM_EXISTING_FILE : PERM_NEW_FILE),
7480 &unixmode);
7482 if (!NT_STATUS_IS_OK(status)) {
7483 return status;
7486 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7488 if (wire_open_mode & SMB_O_SYNC) {
7489 create_options |= FILE_WRITE_THROUGH;
7491 if (wire_open_mode & SMB_O_APPEND) {
7492 access_mask |= FILE_APPEND_DATA;
7494 if (wire_open_mode & SMB_O_DIRECT) {
7495 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7498 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7499 VALID_STAT_OF_DIR(smb_fname->st)) {
7500 if (access_mask != SMB_O_RDONLY_MAPPING) {
7501 return NT_STATUS_FILE_IS_A_DIRECTORY;
7503 create_options &= ~FILE_NON_DIRECTORY_FILE;
7504 create_options |= FILE_DIRECTORY_FILE;
7507 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7508 smb_fname_str_dbg(smb_fname),
7509 (unsigned int)wire_open_mode,
7510 (unsigned int)unixmode ));
7512 status = SMB_VFS_CREATE_FILE(
7513 conn, /* conn */
7514 req, /* req */
7515 0, /* root_dir_fid */
7516 smb_fname, /* fname */
7517 access_mask, /* access_mask */
7518 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7519 FILE_SHARE_DELETE),
7520 create_disp, /* create_disposition*/
7521 create_options, /* create_options */
7522 mod_unixmode, /* file_attributes */
7523 oplock_request, /* oplock_request */
7524 0, /* allocation_size */
7525 0, /* private_flags */
7526 NULL, /* sd */
7527 NULL, /* ea_list */
7528 &fsp, /* result */
7529 &info); /* pinfo */
7531 if (!NT_STATUS_IS_OK(status)) {
7532 return status;
7535 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7536 extended_oplock_granted = True;
7539 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7540 extended_oplock_granted = True;
7543 info_level_return = SVAL(pdata,16);
7545 /* Allocate the correct return size. */
7547 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7548 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7549 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7550 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7551 } else {
7552 *pdata_return_size = 12;
7555 /* Realloc the data size */
7556 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7557 if (*ppdata == NULL) {
7558 close_file(req, fsp, ERROR_CLOSE);
7559 *pdata_return_size = 0;
7560 return NT_STATUS_NO_MEMORY;
7562 pdata = *ppdata;
7564 if (extended_oplock_granted) {
7565 if (flags & REQUEST_BATCH_OPLOCK) {
7566 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7567 } else {
7568 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7570 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7571 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7572 } else {
7573 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7576 SSVAL(pdata,2,fsp->fnum);
7577 SIVAL(pdata,4,info); /* Was file created etc. */
7579 switch (info_level_return) {
7580 case SMB_QUERY_FILE_UNIX_BASIC:
7581 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7582 SSVAL(pdata,10,0); /* padding. */
7583 store_file_unix_basic(conn, pdata + 12, fsp,
7584 &smb_fname->st);
7585 break;
7586 case SMB_QUERY_FILE_UNIX_INFO2:
7587 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7588 SSVAL(pdata,10,0); /* padding. */
7589 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7590 &smb_fname->st);
7591 break;
7592 default:
7593 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7594 SSVAL(pdata,10,0); /* padding. */
7595 break;
7597 return NT_STATUS_OK;
7600 /****************************************************************************
7601 Delete a file with POSIX semantics.
7602 ****************************************************************************/
7604 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7605 struct smb_request *req,
7606 const char *pdata,
7607 int total_data,
7608 struct smb_filename *smb_fname)
7610 NTSTATUS status = NT_STATUS_OK;
7611 files_struct *fsp = NULL;
7612 uint16 flags = 0;
7613 char del = 1;
7614 int info = 0;
7615 int create_options = 0;
7616 int i;
7617 struct share_mode_lock *lck = NULL;
7619 if (total_data < 2) {
7620 return NT_STATUS_INVALID_PARAMETER;
7623 flags = SVAL(pdata,0);
7625 if (!VALID_STAT(smb_fname->st)) {
7626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7629 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7630 !VALID_STAT_OF_DIR(smb_fname->st)) {
7631 return NT_STATUS_NOT_A_DIRECTORY;
7634 DEBUG(10,("smb_posix_unlink: %s %s\n",
7635 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7636 smb_fname_str_dbg(smb_fname)));
7638 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7639 create_options |= FILE_DIRECTORY_FILE;
7642 status = SMB_VFS_CREATE_FILE(
7643 conn, /* conn */
7644 req, /* req */
7645 0, /* root_dir_fid */
7646 smb_fname, /* fname */
7647 DELETE_ACCESS, /* access_mask */
7648 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7649 FILE_SHARE_DELETE),
7650 FILE_OPEN, /* create_disposition*/
7651 create_options, /* create_options */
7652 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7653 0, /* oplock_request */
7654 0, /* allocation_size */
7655 0, /* private_flags */
7656 NULL, /* sd */
7657 NULL, /* ea_list */
7658 &fsp, /* result */
7659 &info); /* pinfo */
7661 if (!NT_STATUS_IS_OK(status)) {
7662 return status;
7666 * Don't lie to client. If we can't really delete due to
7667 * non-POSIX opens return SHARING_VIOLATION.
7670 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7671 NULL);
7672 if (lck == NULL) {
7673 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7674 "lock for file %s\n", fsp_str_dbg(fsp)));
7675 close_file(req, fsp, NORMAL_CLOSE);
7676 return NT_STATUS_INVALID_PARAMETER;
7680 * See if others still have the file open. If this is the case, then
7681 * don't delete. If all opens are POSIX delete we can set the delete
7682 * on close disposition.
7684 for (i=0; i<lck->num_share_modes; i++) {
7685 struct share_mode_entry *e = &lck->share_modes[i];
7686 if (is_valid_share_mode_entry(e)) {
7687 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7688 continue;
7690 /* Fail with sharing violation. */
7691 TALLOC_FREE(lck);
7692 close_file(req, fsp, NORMAL_CLOSE);
7693 return NT_STATUS_SHARING_VIOLATION;
7698 * Set the delete on close.
7700 status = smb_set_file_disposition_info(conn,
7701 &del,
7703 fsp,
7704 smb_fname);
7706 TALLOC_FREE(lck);
7708 if (!NT_STATUS_IS_OK(status)) {
7709 close_file(req, fsp, NORMAL_CLOSE);
7710 return status;
7712 return close_file(req, fsp, NORMAL_CLOSE);
7715 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7716 struct smb_request *req,
7717 TALLOC_CTX *mem_ctx,
7718 uint16_t info_level,
7719 files_struct *fsp,
7720 struct smb_filename *smb_fname,
7721 char **ppdata, int total_data,
7722 int *ret_data_size)
7724 char *pdata = *ppdata;
7725 NTSTATUS status = NT_STATUS_OK;
7726 int data_return_size = 0;
7728 *ret_data_size = 0;
7730 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7731 return NT_STATUS_INVALID_LEVEL;
7734 if (!CAN_WRITE(conn)) {
7735 /* Allow POSIX opens. The open path will deny
7736 * any non-readonly opens. */
7737 if (info_level != SMB_POSIX_PATH_OPEN) {
7738 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7742 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7743 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7744 fsp ? fsp->fnum : -1, info_level, total_data));
7746 switch (info_level) {
7748 case SMB_INFO_STANDARD:
7750 status = smb_set_info_standard(conn,
7751 pdata,
7752 total_data,
7753 fsp,
7754 smb_fname);
7755 break;
7758 case SMB_INFO_SET_EA:
7760 status = smb_info_set_ea(conn,
7761 pdata,
7762 total_data,
7763 fsp,
7764 smb_fname);
7765 break;
7768 case SMB_SET_FILE_BASIC_INFO:
7769 case SMB_FILE_BASIC_INFORMATION:
7771 status = smb_set_file_basic_info(conn,
7772 pdata,
7773 total_data,
7774 fsp,
7775 smb_fname);
7776 break;
7779 case SMB_FILE_ALLOCATION_INFORMATION:
7780 case SMB_SET_FILE_ALLOCATION_INFO:
7782 status = smb_set_file_allocation_info(conn, req,
7783 pdata,
7784 total_data,
7785 fsp,
7786 smb_fname);
7787 break;
7790 case SMB_FILE_END_OF_FILE_INFORMATION:
7791 case SMB_SET_FILE_END_OF_FILE_INFO:
7794 * XP/Win7 both fail after the createfile with
7795 * SMB_SET_FILE_END_OF_FILE_INFO but not
7796 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7797 * The level is known here, so pass it down
7798 * appropriately.
7800 bool should_fail =
7801 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7803 status = smb_set_file_end_of_file_info(conn, req,
7804 pdata,
7805 total_data,
7806 fsp,
7807 smb_fname,
7808 should_fail);
7809 break;
7812 case SMB_FILE_DISPOSITION_INFORMATION:
7813 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7815 #if 0
7816 /* JRA - We used to just ignore this on a path ?
7817 * Shouldn't this be invalid level on a pathname
7818 * based call ?
7820 if (tran_call != TRANSACT2_SETFILEINFO) {
7821 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7823 #endif
7824 status = smb_set_file_disposition_info(conn,
7825 pdata,
7826 total_data,
7827 fsp,
7828 smb_fname);
7829 break;
7832 case SMB_FILE_POSITION_INFORMATION:
7834 status = smb_file_position_information(conn,
7835 pdata,
7836 total_data,
7837 fsp);
7838 break;
7841 case SMB_FILE_FULL_EA_INFORMATION:
7843 status = smb_set_file_full_ea_info(conn,
7844 pdata,
7845 total_data,
7846 fsp);
7847 break;
7850 /* From tridge Samba4 :
7851 * MODE_INFORMATION in setfileinfo (I have no
7852 * idea what "mode information" on a file is - it takes a value of 0,
7853 * 2, 4 or 6. What could it be?).
7856 case SMB_FILE_MODE_INFORMATION:
7858 status = smb_file_mode_information(conn,
7859 pdata,
7860 total_data);
7861 break;
7865 * CIFS UNIX extensions.
7868 case SMB_SET_FILE_UNIX_BASIC:
7870 status = smb_set_file_unix_basic(conn, req,
7871 pdata,
7872 total_data,
7873 fsp,
7874 smb_fname);
7875 break;
7878 case SMB_SET_FILE_UNIX_INFO2:
7880 status = smb_set_file_unix_info2(conn, req,
7881 pdata,
7882 total_data,
7883 fsp,
7884 smb_fname);
7885 break;
7888 case SMB_SET_FILE_UNIX_LINK:
7890 if (fsp) {
7891 /* We must have a pathname for this. */
7892 return NT_STATUS_INVALID_LEVEL;
7894 status = smb_set_file_unix_link(conn, req, pdata,
7895 total_data, smb_fname);
7896 break;
7899 case SMB_SET_FILE_UNIX_HLINK:
7901 if (fsp) {
7902 /* We must have a pathname for this. */
7903 return NT_STATUS_INVALID_LEVEL;
7905 status = smb_set_file_unix_hlink(conn, req,
7906 pdata, total_data,
7907 smb_fname);
7908 break;
7911 case SMB_FILE_RENAME_INFORMATION:
7913 status = smb_file_rename_information(conn, req,
7914 pdata, total_data,
7915 fsp, smb_fname);
7916 break;
7919 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7921 /* SMB2 rename information. */
7922 status = smb2_file_rename_information(conn, req,
7923 pdata, total_data,
7924 fsp, smb_fname);
7925 break;
7928 case SMB_FILE_LINK_INFORMATION:
7930 status = smb_file_link_information(conn, req,
7931 pdata, total_data,
7932 fsp, smb_fname);
7933 break;
7936 #if defined(HAVE_POSIX_ACLS)
7937 case SMB_SET_POSIX_ACL:
7939 status = smb_set_posix_acl(conn,
7940 pdata,
7941 total_data,
7942 fsp,
7943 smb_fname);
7944 break;
7946 #endif
7948 case SMB_SET_POSIX_LOCK:
7950 if (!fsp) {
7951 return NT_STATUS_INVALID_LEVEL;
7953 status = smb_set_posix_lock(conn, req,
7954 pdata, total_data, fsp);
7955 break;
7958 case SMB_POSIX_PATH_OPEN:
7960 if (fsp) {
7961 /* We must have a pathname for this. */
7962 return NT_STATUS_INVALID_LEVEL;
7965 status = smb_posix_open(conn, req,
7966 ppdata,
7967 total_data,
7968 smb_fname,
7969 &data_return_size);
7970 break;
7973 case SMB_POSIX_PATH_UNLINK:
7975 if (fsp) {
7976 /* We must have a pathname for this. */
7977 return NT_STATUS_INVALID_LEVEL;
7980 status = smb_posix_unlink(conn, req,
7981 pdata,
7982 total_data,
7983 smb_fname);
7984 break;
7987 default:
7988 return NT_STATUS_INVALID_LEVEL;
7991 if (!NT_STATUS_IS_OK(status)) {
7992 return status;
7995 *ret_data_size = data_return_size;
7996 return NT_STATUS_OK;
7999 /****************************************************************************
8000 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8001 ****************************************************************************/
8003 static void call_trans2setfilepathinfo(connection_struct *conn,
8004 struct smb_request *req,
8005 unsigned int tran_call,
8006 char **pparams, int total_params,
8007 char **ppdata, int total_data,
8008 unsigned int max_data_bytes)
8010 char *params = *pparams;
8011 char *pdata = *ppdata;
8012 uint16 info_level;
8013 struct smb_filename *smb_fname = NULL;
8014 files_struct *fsp = NULL;
8015 NTSTATUS status = NT_STATUS_OK;
8016 int data_return_size = 0;
8018 if (!params) {
8019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8020 return;
8023 if (tran_call == TRANSACT2_SETFILEINFO) {
8024 if (total_params < 4) {
8025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8026 return;
8029 fsp = file_fsp(req, SVAL(params,0));
8030 /* Basic check for non-null fsp. */
8031 if (!check_fsp_open(conn, req, fsp)) {
8032 return;
8034 info_level = SVAL(params,2);
8036 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8037 &smb_fname);
8038 if (!NT_STATUS_IS_OK(status)) {
8039 reply_nterror(req, status);
8040 return;
8043 if(fsp->fh->fd == -1) {
8045 * This is actually a SETFILEINFO on a directory
8046 * handle (returned from an NT SMB). NT5.0 seems
8047 * to do this call. JRA.
8049 if (INFO_LEVEL_IS_UNIX(info_level)) {
8050 /* Always do lstat for UNIX calls. */
8051 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8052 DEBUG(3,("call_trans2setfilepathinfo: "
8053 "SMB_VFS_LSTAT of %s failed "
8054 "(%s)\n",
8055 smb_fname_str_dbg(smb_fname),
8056 strerror(errno)));
8057 reply_nterror(req, map_nt_error_from_unix(errno));
8058 return;
8060 } else {
8061 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8062 DEBUG(3,("call_trans2setfilepathinfo: "
8063 "fileinfo of %s failed (%s)\n",
8064 smb_fname_str_dbg(smb_fname),
8065 strerror(errno)));
8066 reply_nterror(req, map_nt_error_from_unix(errno));
8067 return;
8070 } else if (fsp->print_file) {
8072 * Doing a DELETE_ON_CLOSE should cancel a print job.
8074 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8075 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8077 DEBUG(3,("call_trans2setfilepathinfo: "
8078 "Cancelling print job (%s)\n",
8079 fsp_str_dbg(fsp)));
8081 SSVAL(params,0,0);
8082 send_trans2_replies(conn, req, params, 2,
8083 *ppdata, 0,
8084 max_data_bytes);
8085 return;
8086 } else {
8087 reply_nterror(req,
8088 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8089 return;
8091 } else {
8093 * Original code - this is an open file.
8095 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8096 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8097 "of fnum %d failed (%s)\n", fsp->fnum,
8098 strerror(errno)));
8099 reply_nterror(req, map_nt_error_from_unix(errno));
8100 return;
8103 } else {
8104 char *fname = NULL;
8105 uint32_t ucf_flags = 0;
8107 /* set path info */
8108 if (total_params < 7) {
8109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8110 return;
8113 info_level = SVAL(params,0);
8114 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8115 total_params - 6, STR_TERMINATE,
8116 &status);
8117 if (!NT_STATUS_IS_OK(status)) {
8118 reply_nterror(req, status);
8119 return;
8122 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8123 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8124 info_level == SMB_FILE_RENAME_INFORMATION ||
8125 info_level == SMB_POSIX_PATH_UNLINK) {
8126 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8129 status = filename_convert(req, conn,
8130 req->flags2 & FLAGS2_DFS_PATHNAMES,
8131 fname,
8132 ucf_flags,
8133 NULL,
8134 &smb_fname);
8135 if (!NT_STATUS_IS_OK(status)) {
8136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8137 reply_botherror(req,
8138 NT_STATUS_PATH_NOT_COVERED,
8139 ERRSRV, ERRbadpath);
8140 return;
8142 reply_nterror(req, status);
8143 return;
8146 if (INFO_LEVEL_IS_UNIX(info_level)) {
8148 * For CIFS UNIX extensions the target name may not exist.
8151 /* Always do lstat for UNIX calls. */
8152 SMB_VFS_LSTAT(conn, smb_fname);
8154 } else if (!VALID_STAT(smb_fname->st) &&
8155 SMB_VFS_STAT(conn, smb_fname)) {
8156 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8157 "%s failed (%s)\n",
8158 smb_fname_str_dbg(smb_fname),
8159 strerror(errno)));
8160 reply_nterror(req, map_nt_error_from_unix(errno));
8161 return;
8165 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8166 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8167 fsp ? fsp->fnum : -1, info_level,total_data));
8169 /* Realloc the parameter size */
8170 *pparams = (char *)SMB_REALLOC(*pparams,2);
8171 if (*pparams == NULL) {
8172 reply_nterror(req, NT_STATUS_NO_MEMORY);
8173 return;
8175 params = *pparams;
8177 SSVAL(params,0,0);
8179 status = smbd_do_setfilepathinfo(conn, req, req,
8180 info_level,
8181 fsp,
8182 smb_fname,
8183 ppdata, total_data,
8184 &data_return_size);
8185 if (!NT_STATUS_IS_OK(status)) {
8186 if (open_was_deferred(req->mid)) {
8187 /* We have re-scheduled this call. */
8188 return;
8190 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8191 /* We have re-scheduled this call. */
8192 return;
8194 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8195 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8196 ERRSRV, ERRbadpath);
8197 return;
8199 if (info_level == SMB_POSIX_PATH_OPEN) {
8200 reply_openerror(req, status);
8201 return;
8204 reply_nterror(req, status);
8205 return;
8208 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8209 max_data_bytes);
8211 return;
8214 /****************************************************************************
8215 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8216 ****************************************************************************/
8218 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8219 char **pparams, int total_params,
8220 char **ppdata, int total_data,
8221 unsigned int max_data_bytes)
8223 struct smb_filename *smb_dname = NULL;
8224 char *params = *pparams;
8225 char *pdata = *ppdata;
8226 char *directory = NULL;
8227 NTSTATUS status = NT_STATUS_OK;
8228 struct ea_list *ea_list = NULL;
8229 TALLOC_CTX *ctx = talloc_tos();
8231 if (!CAN_WRITE(conn)) {
8232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8233 return;
8236 if (total_params < 5) {
8237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8238 return;
8241 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8242 total_params - 4, STR_TERMINATE,
8243 &status);
8244 if (!NT_STATUS_IS_OK(status)) {
8245 reply_nterror(req, status);
8246 return;
8249 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8251 status = filename_convert(ctx,
8252 conn,
8253 req->flags2 & FLAGS2_DFS_PATHNAMES,
8254 directory,
8256 NULL,
8257 &smb_dname);
8259 if (!NT_STATUS_IS_OK(status)) {
8260 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8261 reply_botherror(req,
8262 NT_STATUS_PATH_NOT_COVERED,
8263 ERRSRV, ERRbadpath);
8264 return;
8266 reply_nterror(req, status);
8267 return;
8271 * OS/2 workplace shell seems to send SET_EA requests of "null"
8272 * length (4 bytes containing IVAL 4).
8273 * They seem to have no effect. Bug #3212. JRA.
8276 if (total_data && (total_data != 4)) {
8277 /* Any data in this call is an EA list. */
8278 if (total_data < 10) {
8279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8280 goto out;
8283 if (IVAL(pdata,0) > total_data) {
8284 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8285 IVAL(pdata,0), (unsigned int)total_data));
8286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8287 goto out;
8290 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8291 total_data - 4);
8292 if (!ea_list) {
8293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8294 goto out;
8297 if (!lp_ea_support(SNUM(conn))) {
8298 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8299 goto out;
8302 /* If total_data == 4 Windows doesn't care what values
8303 * are placed in that field, it just ignores them.
8304 * The System i QNTC IBM SMB client puts bad values here,
8305 * so ignore them. */
8307 status = create_directory(conn, req, smb_dname);
8309 if (!NT_STATUS_IS_OK(status)) {
8310 reply_nterror(req, status);
8311 goto out;
8314 /* Try and set any given EA. */
8315 if (ea_list) {
8316 status = set_ea(conn, NULL, smb_dname, ea_list);
8317 if (!NT_STATUS_IS_OK(status)) {
8318 reply_nterror(req, status);
8319 goto out;
8323 /* Realloc the parameter and data sizes */
8324 *pparams = (char *)SMB_REALLOC(*pparams,2);
8325 if(*pparams == NULL) {
8326 reply_nterror(req, NT_STATUS_NO_MEMORY);
8327 goto out;
8329 params = *pparams;
8331 SSVAL(params,0,0);
8333 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8335 out:
8336 TALLOC_FREE(smb_dname);
8337 return;
8340 /****************************************************************************
8341 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8342 We don't actually do this - we just send a null response.
8343 ****************************************************************************/
8345 static void call_trans2findnotifyfirst(connection_struct *conn,
8346 struct smb_request *req,
8347 char **pparams, int total_params,
8348 char **ppdata, int total_data,
8349 unsigned int max_data_bytes)
8351 char *params = *pparams;
8352 uint16 info_level;
8354 if (total_params < 6) {
8355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8356 return;
8359 info_level = SVAL(params,4);
8360 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8362 switch (info_level) {
8363 case 1:
8364 case 2:
8365 break;
8366 default:
8367 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8368 return;
8371 /* Realloc the parameter and data sizes */
8372 *pparams = (char *)SMB_REALLOC(*pparams,6);
8373 if (*pparams == NULL) {
8374 reply_nterror(req, NT_STATUS_NO_MEMORY);
8375 return;
8377 params = *pparams;
8379 SSVAL(params,0,fnf_handle);
8380 SSVAL(params,2,0); /* No changes */
8381 SSVAL(params,4,0); /* No EA errors */
8383 fnf_handle++;
8385 if(fnf_handle == 0)
8386 fnf_handle = 257;
8388 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8390 return;
8393 /****************************************************************************
8394 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8395 changes). Currently this does nothing.
8396 ****************************************************************************/
8398 static void call_trans2findnotifynext(connection_struct *conn,
8399 struct smb_request *req,
8400 char **pparams, int total_params,
8401 char **ppdata, int total_data,
8402 unsigned int max_data_bytes)
8404 char *params = *pparams;
8406 DEBUG(3,("call_trans2findnotifynext\n"));
8408 /* Realloc the parameter and data sizes */
8409 *pparams = (char *)SMB_REALLOC(*pparams,4);
8410 if (*pparams == NULL) {
8411 reply_nterror(req, NT_STATUS_NO_MEMORY);
8412 return;
8414 params = *pparams;
8416 SSVAL(params,0,0); /* No changes */
8417 SSVAL(params,2,0); /* No EA errors */
8419 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8421 return;
8424 /****************************************************************************
8425 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8426 ****************************************************************************/
8428 static void call_trans2getdfsreferral(connection_struct *conn,
8429 struct smb_request *req,
8430 char **pparams, int total_params,
8431 char **ppdata, int total_data,
8432 unsigned int max_data_bytes)
8434 char *params = *pparams;
8435 char *pathname = NULL;
8436 int reply_size = 0;
8437 int max_referral_level;
8438 NTSTATUS status = NT_STATUS_OK;
8439 TALLOC_CTX *ctx = talloc_tos();
8441 DEBUG(10,("call_trans2getdfsreferral\n"));
8443 if (total_params < 3) {
8444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445 return;
8448 max_referral_level = SVAL(params,0);
8450 if(!lp_host_msdfs()) {
8451 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8452 return;
8455 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8456 total_params - 2, STR_TERMINATE);
8457 if (!pathname) {
8458 reply_nterror(req, NT_STATUS_NOT_FOUND);
8459 return;
8461 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8462 ppdata,&status)) < 0) {
8463 reply_nterror(req, status);
8464 return;
8467 SSVAL(req->inbuf, smb_flg2,
8468 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8469 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8471 return;
8474 #define LMCAT_SPL 0x53
8475 #define LMFUNC_GETJOBID 0x60
8477 /****************************************************************************
8478 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8479 ****************************************************************************/
8481 static void call_trans2ioctl(connection_struct *conn,
8482 struct smb_request *req,
8483 char **pparams, int total_params,
8484 char **ppdata, int total_data,
8485 unsigned int max_data_bytes)
8487 char *pdata = *ppdata;
8488 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8490 /* check for an invalid fid before proceeding */
8492 if (!fsp) {
8493 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8494 return;
8497 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8498 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8499 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8500 if (*ppdata == NULL) {
8501 reply_nterror(req, NT_STATUS_NO_MEMORY);
8502 return;
8504 pdata = *ppdata;
8506 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8507 CAN ACCEPT THIS IN UNICODE. JRA. */
8509 /* Job number */
8510 if (fsp->print_file) {
8511 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8512 } else {
8513 SSVAL(pdata, 0, 0);
8515 srvstr_push(pdata, req->flags2, pdata + 2,
8516 global_myname(), 15,
8517 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8518 srvstr_push(pdata, req->flags2, pdata+18,
8519 lp_servicename(SNUM(conn)), 13,
8520 STR_ASCII|STR_TERMINATE); /* Service name */
8521 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8522 max_data_bytes);
8523 return;
8526 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8527 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8530 /****************************************************************************
8531 Reply to a SMBfindclose (stop trans2 directory search).
8532 ****************************************************************************/
8534 void reply_findclose(struct smb_request *req)
8536 int dptr_num;
8537 struct smbd_server_connection *sconn = req->sconn;
8539 START_PROFILE(SMBfindclose);
8541 if (req->wct < 1) {
8542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8543 END_PROFILE(SMBfindclose);
8544 return;
8547 dptr_num = SVALS(req->vwv+0, 0);
8549 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8551 dptr_close(sconn, &dptr_num);
8553 reply_outbuf(req, 0, 0);
8555 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8557 END_PROFILE(SMBfindclose);
8558 return;
8561 /****************************************************************************
8562 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8563 ****************************************************************************/
8565 void reply_findnclose(struct smb_request *req)
8567 int dptr_num;
8569 START_PROFILE(SMBfindnclose);
8571 if (req->wct < 1) {
8572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8573 END_PROFILE(SMBfindnclose);
8574 return;
8577 dptr_num = SVAL(req->vwv+0, 0);
8579 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8581 /* We never give out valid handles for a
8582 findnotifyfirst - so any dptr_num is ok here.
8583 Just ignore it. */
8585 reply_outbuf(req, 0, 0);
8587 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8589 END_PROFILE(SMBfindnclose);
8590 return;
8593 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8594 struct trans_state *state)
8596 if (get_Protocol() >= PROTOCOL_NT1) {
8597 req->flags2 |= 0x40; /* IS_LONG_NAME */
8598 SSVAL(req->inbuf,smb_flg2,req->flags2);
8601 if (conn->encrypt_level == Required && !req->encrypted) {
8602 if (state->call != TRANSACT2_QFSINFO &&
8603 state->call != TRANSACT2_SETFSINFO) {
8604 DEBUG(0,("handle_trans2: encryption required "
8605 "with call 0x%x\n",
8606 (unsigned int)state->call));
8607 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8608 return;
8612 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8614 /* Now we must call the relevant TRANS2 function */
8615 switch(state->call) {
8616 case TRANSACT2_OPEN:
8618 START_PROFILE(Trans2_open);
8619 call_trans2open(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_open);
8624 break;
8627 case TRANSACT2_FINDFIRST:
8629 START_PROFILE(Trans2_findfirst);
8630 call_trans2findfirst(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_findfirst);
8635 break;
8638 case TRANSACT2_FINDNEXT:
8640 START_PROFILE(Trans2_findnext);
8641 call_trans2findnext(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_findnext);
8646 break;
8649 case TRANSACT2_QFSINFO:
8651 START_PROFILE(Trans2_qfsinfo);
8652 call_trans2qfsinfo(conn, req,
8653 &state->param, state->total_param,
8654 &state->data, state->total_data,
8655 state->max_data_return);
8656 END_PROFILE(Trans2_qfsinfo);
8657 break;
8660 case TRANSACT2_SETFSINFO:
8662 START_PROFILE(Trans2_setfsinfo);
8663 call_trans2setfsinfo(conn, req,
8664 &state->param, state->total_param,
8665 &state->data, state->total_data,
8666 state->max_data_return);
8667 END_PROFILE(Trans2_setfsinfo);
8668 break;
8671 case TRANSACT2_QPATHINFO:
8672 case TRANSACT2_QFILEINFO:
8674 START_PROFILE(Trans2_qpathinfo);
8675 call_trans2qfilepathinfo(conn, req, state->call,
8676 &state->param, state->total_param,
8677 &state->data, state->total_data,
8678 state->max_data_return);
8679 END_PROFILE(Trans2_qpathinfo);
8680 break;
8683 case TRANSACT2_SETPATHINFO:
8684 case TRANSACT2_SETFILEINFO:
8686 START_PROFILE(Trans2_setpathinfo);
8687 call_trans2setfilepathinfo(conn, req, state->call,
8688 &state->param, state->total_param,
8689 &state->data, state->total_data,
8690 state->max_data_return);
8691 END_PROFILE(Trans2_setpathinfo);
8692 break;
8695 case TRANSACT2_FINDNOTIFYFIRST:
8697 START_PROFILE(Trans2_findnotifyfirst);
8698 call_trans2findnotifyfirst(conn, req,
8699 &state->param, state->total_param,
8700 &state->data, state->total_data,
8701 state->max_data_return);
8702 END_PROFILE(Trans2_findnotifyfirst);
8703 break;
8706 case TRANSACT2_FINDNOTIFYNEXT:
8708 START_PROFILE(Trans2_findnotifynext);
8709 call_trans2findnotifynext(conn, req,
8710 &state->param, state->total_param,
8711 &state->data, state->total_data,
8712 state->max_data_return);
8713 END_PROFILE(Trans2_findnotifynext);
8714 break;
8717 case TRANSACT2_MKDIR:
8719 START_PROFILE(Trans2_mkdir);
8720 call_trans2mkdir(conn, req,
8721 &state->param, state->total_param,
8722 &state->data, state->total_data,
8723 state->max_data_return);
8724 END_PROFILE(Trans2_mkdir);
8725 break;
8728 case TRANSACT2_GET_DFS_REFERRAL:
8730 START_PROFILE(Trans2_get_dfs_referral);
8731 call_trans2getdfsreferral(conn, req,
8732 &state->param, state->total_param,
8733 &state->data, state->total_data,
8734 state->max_data_return);
8735 END_PROFILE(Trans2_get_dfs_referral);
8736 break;
8739 case TRANSACT2_IOCTL:
8741 START_PROFILE(Trans2_ioctl);
8742 call_trans2ioctl(conn, req,
8743 &state->param, state->total_param,
8744 &state->data, state->total_data,
8745 state->max_data_return);
8746 END_PROFILE(Trans2_ioctl);
8747 break;
8750 default:
8751 /* Error in request */
8752 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8753 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8757 /****************************************************************************
8758 Reply to a SMBtrans2.
8759 ****************************************************************************/
8761 void reply_trans2(struct smb_request *req)
8763 connection_struct *conn = req->conn;
8764 unsigned int dsoff;
8765 unsigned int dscnt;
8766 unsigned int psoff;
8767 unsigned int pscnt;
8768 unsigned int tran_call;
8769 struct trans_state *state;
8770 NTSTATUS result;
8772 START_PROFILE(SMBtrans2);
8774 if (req->wct < 14) {
8775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8776 END_PROFILE(SMBtrans2);
8777 return;
8780 dsoff = SVAL(req->vwv+12, 0);
8781 dscnt = SVAL(req->vwv+11, 0);
8782 psoff = SVAL(req->vwv+10, 0);
8783 pscnt = SVAL(req->vwv+9, 0);
8784 tran_call = SVAL(req->vwv+14, 0);
8786 result = allow_new_trans(conn->pending_trans, req->mid);
8787 if (!NT_STATUS_IS_OK(result)) {
8788 DEBUG(2, ("Got invalid trans2 request: %s\n",
8789 nt_errstr(result)));
8790 reply_nterror(req, result);
8791 END_PROFILE(SMBtrans2);
8792 return;
8795 if (IS_IPC(conn)) {
8796 switch (tran_call) {
8797 /* List the allowed trans2 calls on IPC$ */
8798 case TRANSACT2_OPEN:
8799 case TRANSACT2_GET_DFS_REFERRAL:
8800 case TRANSACT2_QFILEINFO:
8801 case TRANSACT2_QFSINFO:
8802 case TRANSACT2_SETFSINFO:
8803 break;
8804 default:
8805 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8806 END_PROFILE(SMBtrans2);
8807 return;
8811 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8812 DEBUG(0, ("talloc failed\n"));
8813 reply_nterror(req, NT_STATUS_NO_MEMORY);
8814 END_PROFILE(SMBtrans2);
8815 return;
8818 state->cmd = SMBtrans2;
8820 state->mid = req->mid;
8821 state->vuid = req->vuid;
8822 state->setup_count = SVAL(req->vwv+13, 0);
8823 state->setup = NULL;
8824 state->total_param = SVAL(req->vwv+0, 0);
8825 state->param = NULL;
8826 state->total_data = SVAL(req->vwv+1, 0);
8827 state->data = NULL;
8828 state->max_param_return = SVAL(req->vwv+2, 0);
8829 state->max_data_return = SVAL(req->vwv+3, 0);
8830 state->max_setup_return = SVAL(req->vwv+4, 0);
8831 state->close_on_completion = BITSETW(req->vwv+5, 0);
8832 state->one_way = BITSETW(req->vwv+5, 1);
8834 state->call = tran_call;
8836 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8837 is so as a sanity check */
8838 if (state->setup_count != 1) {
8840 * Need to have rc=0 for ioctl to get job id for OS/2.
8841 * Network printing will fail if function is not successful.
8842 * Similar function in reply.c will be used if protocol
8843 * is LANMAN1.0 instead of LM1.2X002.
8844 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8845 * outbuf doesn't have to be set(only job id is used).
8847 if ( (state->setup_count == 4)
8848 && (tran_call == TRANSACT2_IOCTL)
8849 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8850 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8851 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8852 } else {
8853 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8854 DEBUG(2,("Transaction is %d\n",tran_call));
8855 TALLOC_FREE(state);
8856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8857 END_PROFILE(SMBtrans2);
8858 return;
8862 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8863 goto bad_param;
8865 if (state->total_data) {
8867 if (trans_oob(state->total_data, 0, dscnt)
8868 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8869 goto bad_param;
8872 /* Can't use talloc here, the core routines do realloc on the
8873 * params and data. */
8874 state->data = (char *)SMB_MALLOC(state->total_data);
8875 if (state->data == NULL) {
8876 DEBUG(0,("reply_trans2: data malloc fail for %u "
8877 "bytes !\n", (unsigned int)state->total_data));
8878 TALLOC_FREE(state);
8879 reply_nterror(req, NT_STATUS_NO_MEMORY);
8880 END_PROFILE(SMBtrans2);
8881 return;
8884 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8887 if (state->total_param) {
8889 if (trans_oob(state->total_param, 0, pscnt)
8890 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8891 goto bad_param;
8894 /* Can't use talloc here, the core routines do realloc on the
8895 * params and data. */
8896 state->param = (char *)SMB_MALLOC(state->total_param);
8897 if (state->param == NULL) {
8898 DEBUG(0,("reply_trans: param malloc fail for %u "
8899 "bytes !\n", (unsigned int)state->total_param));
8900 SAFE_FREE(state->data);
8901 TALLOC_FREE(state);
8902 reply_nterror(req, NT_STATUS_NO_MEMORY);
8903 END_PROFILE(SMBtrans2);
8904 return;
8907 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8910 state->received_data = dscnt;
8911 state->received_param = pscnt;
8913 if ((state->received_param == state->total_param) &&
8914 (state->received_data == state->total_data)) {
8916 handle_trans2(conn, req, state);
8918 SAFE_FREE(state->data);
8919 SAFE_FREE(state->param);
8920 TALLOC_FREE(state);
8921 END_PROFILE(SMBtrans2);
8922 return;
8925 DLIST_ADD(conn->pending_trans, state);
8927 /* We need to send an interim response then receive the rest
8928 of the parameter/data bytes */
8929 reply_outbuf(req, 0, 0);
8930 show_msg((char *)req->outbuf);
8931 END_PROFILE(SMBtrans2);
8932 return;
8934 bad_param:
8936 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8937 SAFE_FREE(state->data);
8938 SAFE_FREE(state->param);
8939 TALLOC_FREE(state);
8940 END_PROFILE(SMBtrans2);
8941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8945 /****************************************************************************
8946 Reply to a SMBtranss2
8947 ****************************************************************************/
8949 void reply_transs2(struct smb_request *req)
8951 connection_struct *conn = req->conn;
8952 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8953 struct trans_state *state;
8955 START_PROFILE(SMBtranss2);
8957 show_msg((char *)req->inbuf);
8959 /* Windows clients expect all replies to
8960 a transact secondary (SMBtranss2 0x33)
8961 to have a command code of transact
8962 (SMBtrans2 0x32). See bug #8989
8963 and also [MS-CIFS] section 2.2.4.47.2
8964 for details.
8966 req->cmd = SMBtrans2;
8968 if (req->wct < 8) {
8969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8970 END_PROFILE(SMBtranss2);
8971 return;
8974 for (state = conn->pending_trans; state != NULL;
8975 state = state->next) {
8976 if (state->mid == req->mid) {
8977 break;
8981 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8983 END_PROFILE(SMBtranss2);
8984 return;
8987 /* Revise state->total_param and state->total_data in case they have
8988 changed downwards */
8990 if (SVAL(req->vwv+0, 0) < state->total_param)
8991 state->total_param = SVAL(req->vwv+0, 0);
8992 if (SVAL(req->vwv+1, 0) < state->total_data)
8993 state->total_data = SVAL(req->vwv+1, 0);
8995 pcnt = SVAL(req->vwv+2, 0);
8996 poff = SVAL(req->vwv+3, 0);
8997 pdisp = SVAL(req->vwv+4, 0);
8999 dcnt = SVAL(req->vwv+5, 0);
9000 doff = SVAL(req->vwv+6, 0);
9001 ddisp = SVAL(req->vwv+7, 0);
9003 state->received_param += pcnt;
9004 state->received_data += dcnt;
9006 if ((state->received_data > state->total_data) ||
9007 (state->received_param > state->total_param))
9008 goto bad_param;
9010 if (pcnt) {
9011 if (trans_oob(state->total_param, pdisp, pcnt)
9012 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9013 goto bad_param;
9015 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9018 if (dcnt) {
9019 if (trans_oob(state->total_data, ddisp, dcnt)
9020 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9021 goto bad_param;
9023 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9026 if ((state->received_param < state->total_param) ||
9027 (state->received_data < state->total_data)) {
9028 END_PROFILE(SMBtranss2);
9029 return;
9032 handle_trans2(conn, req, state);
9034 DLIST_REMOVE(conn->pending_trans, state);
9035 SAFE_FREE(state->data);
9036 SAFE_FREE(state->param);
9037 TALLOC_FREE(state);
9039 END_PROFILE(SMBtranss2);
9040 return;
9042 bad_param:
9044 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9045 DLIST_REMOVE(conn->pending_trans, state);
9046 SAFE_FREE(state->data);
9047 SAFE_FREE(state->param);
9048 TALLOC_FREE(state);
9049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9050 END_PROFILE(SMBtranss2);
9051 return;