s3:smbd: allow info class SMB_QUERY_FS_ATTRIBUTE_INFO to return partial data
[Samba.git] / source3 / smbd / trans2.c
blobfda962c65f5d44e202bb19ce04bedca48e6590f6
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 char **ppdata,
4290 unsigned int *pdata_size)
4292 char *pdata = *ppdata;
4293 char *dstart, *dend;
4294 unsigned int data_size;
4295 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4296 time_t create_time, mtime, atime, c_time;
4297 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4298 char *p;
4299 char *base_name;
4300 char *dos_fname;
4301 int mode;
4302 int nlink;
4303 NTSTATUS status;
4304 uint64_t file_size = 0;
4305 uint64_t pos = 0;
4306 uint64_t allocation_size = 0;
4307 uint64_t file_index = 0;
4308 uint32_t access_mask = 0;
4310 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4311 return NT_STATUS_INVALID_LEVEL;
4314 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4315 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4316 info_level, max_data_bytes));
4318 mode = dos_mode(conn, smb_fname);
4319 nlink = psbuf->st_ex_nlink;
4321 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4322 nlink = 1;
4325 if ((nlink > 0) && delete_pending) {
4326 nlink -= 1;
4329 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4330 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4331 if (*ppdata == NULL) {
4332 return NT_STATUS_NO_MEMORY;
4334 pdata = *ppdata;
4335 dstart = pdata;
4336 dend = dstart + data_size - 1;
4338 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4339 update_stat_ex_mtime(psbuf, write_time_ts);
4342 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4343 mtime_ts = psbuf->st_ex_mtime;
4344 atime_ts = psbuf->st_ex_atime;
4345 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4347 if (lp_dos_filetime_resolution(SNUM(conn))) {
4348 dos_filetime_timespec(&create_time_ts);
4349 dos_filetime_timespec(&mtime_ts);
4350 dos_filetime_timespec(&atime_ts);
4351 dos_filetime_timespec(&ctime_ts);
4354 create_time = convert_timespec_to_time_t(create_time_ts);
4355 mtime = convert_timespec_to_time_t(mtime_ts);
4356 atime = convert_timespec_to_time_t(atime_ts);
4357 c_time = convert_timespec_to_time_t(ctime_ts);
4359 p = strrchr_m(smb_fname->base_name,'/');
4360 if (!p)
4361 base_name = smb_fname->base_name;
4362 else
4363 base_name = p+1;
4365 /* NT expects the name to be in an exact form of the *full*
4366 filename. See the trans2 torture test */
4367 if (ISDOT(base_name)) {
4368 dos_fname = talloc_strdup(mem_ctx, "\\");
4369 if (!dos_fname) {
4370 return NT_STATUS_NO_MEMORY;
4372 } else {
4373 dos_fname = talloc_asprintf(mem_ctx,
4374 "\\%s",
4375 smb_fname->base_name);
4376 if (!dos_fname) {
4377 return NT_STATUS_NO_MEMORY;
4379 if (is_ntfs_stream_smb_fname(smb_fname)) {
4380 dos_fname = talloc_asprintf(dos_fname, "%s",
4381 smb_fname->stream_name);
4382 if (!dos_fname) {
4383 return NT_STATUS_NO_MEMORY;
4387 string_replace(dos_fname, '/', '\\');
4390 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4392 if (!fsp) {
4393 /* Do we have this path open ? */
4394 files_struct *fsp1;
4395 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4396 fsp1 = file_find_di_first(conn->sconn, fileid);
4397 if (fsp1 && fsp1->initial_allocation_size) {
4398 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4402 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4403 file_size = get_file_size_stat(psbuf);
4406 if (fsp) {
4407 pos = fsp->fh->position_information;
4410 if (fsp) {
4411 access_mask = fsp->access_mask;
4412 } else {
4413 /* GENERIC_EXECUTE mapping from Windows */
4414 access_mask = 0x12019F;
4417 /* This should be an index number - looks like
4418 dev/ino to me :-)
4420 I think this causes us to fail the IFSKIT
4421 BasicFileInformationTest. -tpot */
4422 file_index = get_FileIndex(conn, psbuf);
4424 switch (info_level) {
4425 case SMB_INFO_STANDARD:
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4427 data_size = 22;
4428 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4429 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4430 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4431 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4432 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4433 SSVAL(pdata,l1_attrFile,mode);
4434 break;
4436 case SMB_INFO_QUERY_EA_SIZE:
4438 unsigned int ea_size =
4439 estimate_ea_size(conn, fsp,
4440 smb_fname->base_name);
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4442 data_size = 26;
4443 srv_put_dos_date2(pdata,0,create_time);
4444 srv_put_dos_date2(pdata,4,atime);
4445 srv_put_dos_date2(pdata,8,mtime); /* write time */
4446 SIVAL(pdata,12,(uint32)file_size);
4447 SIVAL(pdata,16,(uint32)allocation_size);
4448 SSVAL(pdata,20,mode);
4449 SIVAL(pdata,22,ea_size);
4450 break;
4453 case SMB_INFO_IS_NAME_VALID:
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4455 if (fsp) {
4456 /* os/2 needs this ? really ?*/
4457 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4459 /* This is only reached for qpathinfo */
4460 data_size = 0;
4461 break;
4463 case SMB_INFO_QUERY_EAS_FROM_LIST:
4465 size_t total_ea_len = 0;
4466 struct ea_list *ea_file_list = NULL;
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4470 ea_file_list =
4471 get_ea_list_from_file(mem_ctx, conn, fsp,
4472 smb_fname->base_name,
4473 &total_ea_len);
4474 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4476 if (!ea_list || (total_ea_len > data_size)) {
4477 data_size = 4;
4478 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4479 break;
4482 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4483 break;
4486 case SMB_INFO_QUERY_ALL_EAS:
4488 /* We have data_size bytes to put EA's into. */
4489 size_t total_ea_len = 0;
4491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4493 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4494 smb_fname->base_name,
4495 &total_ea_len);
4496 if (!ea_list || (total_ea_len > data_size)) {
4497 data_size = 4;
4498 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4499 break;
4502 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4503 break;
4506 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4508 /* This is FileFullEaInformation - 0xF which maps to
4509 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4511 /* We have data_size bytes to put EA's into. */
4512 size_t total_ea_len = 0;
4513 struct ea_list *ea_file_list = NULL;
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4517 /*TODO: add filtering and index handling */
4519 ea_file_list =
4520 get_ea_list_from_file(mem_ctx, conn, fsp,
4521 smb_fname->base_name,
4522 &total_ea_len);
4523 if (!ea_file_list) {
4524 return NT_STATUS_NO_EAS_ON_FILE;
4527 status = fill_ea_chained_buffer(mem_ctx,
4528 pdata,
4529 data_size,
4530 &data_size,
4531 conn, ea_file_list);
4532 if (!NT_STATUS_IS_OK(status)) {
4533 return status;
4535 break;
4538 case SMB_FILE_BASIC_INFORMATION:
4539 case SMB_QUERY_FILE_BASIC_INFO:
4541 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4542 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4543 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4544 } else {
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4546 data_size = 40;
4547 SIVAL(pdata,36,0);
4549 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4550 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4551 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4552 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4553 SIVAL(pdata,32,mode);
4555 DEBUG(5,("SMB_QFBI - "));
4556 DEBUG(5,("create: %s ", ctime(&create_time)));
4557 DEBUG(5,("access: %s ", ctime(&atime)));
4558 DEBUG(5,("write: %s ", ctime(&mtime)));
4559 DEBUG(5,("change: %s ", ctime(&c_time)));
4560 DEBUG(5,("mode: %x\n", mode));
4561 break;
4563 case SMB_FILE_STANDARD_INFORMATION:
4564 case SMB_QUERY_FILE_STANDARD_INFO:
4566 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4567 data_size = 24;
4568 SOFF_T(pdata,0,allocation_size);
4569 SOFF_T(pdata,8,file_size);
4570 SIVAL(pdata,16,nlink);
4571 SCVAL(pdata,20,delete_pending?1:0);
4572 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4573 SSVAL(pdata,22,0); /* Padding. */
4574 break;
4576 case SMB_FILE_EA_INFORMATION:
4577 case SMB_QUERY_FILE_EA_INFO:
4579 unsigned int ea_size =
4580 estimate_ea_size(conn, fsp, smb_fname->base_name);
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4582 data_size = 4;
4583 SIVAL(pdata,0,ea_size);
4584 break;
4587 /* Get the 8.3 name - used if NT SMB was negotiated. */
4588 case SMB_QUERY_FILE_ALT_NAME_INFO:
4589 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4591 int len;
4592 char mangled_name[13];
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4594 if (!name_to_8_3(base_name,mangled_name,
4595 True,conn->params)) {
4596 return NT_STATUS_NO_MEMORY;
4598 len = srvstr_push(dstart, flags2,
4599 pdata+4, mangled_name,
4600 PTR_DIFF(dend, pdata+4),
4601 STR_UNICODE);
4602 data_size = 4 + len;
4603 SIVAL(pdata,0,len);
4604 break;
4607 case SMB_QUERY_FILE_NAME_INFO:
4609 int len;
4611 this must be *exactly* right for ACLs on mapped drives to work
4613 len = srvstr_push(dstart, flags2,
4614 pdata+4, dos_fname,
4615 PTR_DIFF(dend, pdata+4),
4616 STR_UNICODE);
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4618 data_size = 4 + len;
4619 SIVAL(pdata,0,len);
4620 break;
4623 case SMB_FILE_ALLOCATION_INFORMATION:
4624 case SMB_QUERY_FILE_ALLOCATION_INFO:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4626 data_size = 8;
4627 SOFF_T(pdata,0,allocation_size);
4628 break;
4630 case SMB_FILE_END_OF_FILE_INFORMATION:
4631 case SMB_QUERY_FILE_END_OF_FILEINFO:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4633 data_size = 8;
4634 SOFF_T(pdata,0,file_size);
4635 break;
4637 case SMB_QUERY_FILE_ALL_INFO:
4638 case SMB_FILE_ALL_INFORMATION:
4640 int len;
4641 unsigned int ea_size =
4642 estimate_ea_size(conn, fsp, smb_fname->base_name);
4643 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4644 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4645 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4646 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4647 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4648 SIVAL(pdata,32,mode);
4649 SIVAL(pdata,36,0); /* padding. */
4650 pdata += 40;
4651 SOFF_T(pdata,0,allocation_size);
4652 SOFF_T(pdata,8,file_size);
4653 SIVAL(pdata,16,nlink);
4654 SCVAL(pdata,20,delete_pending);
4655 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4656 SSVAL(pdata,22,0);
4657 pdata += 24;
4658 SIVAL(pdata,0,ea_size);
4659 pdata += 4; /* EA info */
4660 len = srvstr_push(dstart, flags2,
4661 pdata+4, dos_fname,
4662 PTR_DIFF(dend, pdata+4),
4663 STR_UNICODE);
4664 SIVAL(pdata,0,len);
4665 pdata += 4 + len;
4666 data_size = PTR_DIFF(pdata,(*ppdata));
4667 break;
4670 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4672 int len;
4673 unsigned int ea_size =
4674 estimate_ea_size(conn, fsp, smb_fname->base_name);
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4676 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4677 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4678 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4679 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4680 SIVAL(pdata, 0x20, mode);
4681 SIVAL(pdata, 0x24, 0); /* padding. */
4682 SBVAL(pdata, 0x28, allocation_size);
4683 SBVAL(pdata, 0x30, file_size);
4684 SIVAL(pdata, 0x38, nlink);
4685 SCVAL(pdata, 0x3C, delete_pending);
4686 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4687 SSVAL(pdata, 0x3E, 0); /* padding */
4688 SBVAL(pdata, 0x40, file_index);
4689 SIVAL(pdata, 0x48, ea_size);
4690 SIVAL(pdata, 0x4C, access_mask);
4691 SBVAL(pdata, 0x50, pos);
4692 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4693 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4695 pdata += 0x60;
4697 len = srvstr_push(dstart, flags2,
4698 pdata+4, dos_fname,
4699 PTR_DIFF(dend, pdata+4),
4700 STR_UNICODE);
4701 SIVAL(pdata,0,len);
4702 pdata += 4 + len;
4703 data_size = PTR_DIFF(pdata,(*ppdata));
4704 break;
4706 case SMB_FILE_INTERNAL_INFORMATION:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4709 SBVAL(pdata, 0, file_index);
4710 data_size = 8;
4711 break;
4713 case SMB_FILE_ACCESS_INFORMATION:
4714 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4715 SIVAL(pdata, 0, access_mask);
4716 data_size = 4;
4717 break;
4719 case SMB_FILE_NAME_INFORMATION:
4720 /* Pathname with leading '\'. */
4722 size_t byte_len;
4723 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4725 SIVAL(pdata,0,byte_len);
4726 data_size = 4 + byte_len;
4727 break;
4730 case SMB_FILE_DISPOSITION_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4732 data_size = 1;
4733 SCVAL(pdata,0,delete_pending);
4734 break;
4736 case SMB_FILE_POSITION_INFORMATION:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4738 data_size = 8;
4739 SOFF_T(pdata,0,pos);
4740 break;
4742 case SMB_FILE_MODE_INFORMATION:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4744 SIVAL(pdata,0,mode);
4745 data_size = 4;
4746 break;
4748 case SMB_FILE_ALIGNMENT_INFORMATION:
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4750 SIVAL(pdata,0,0); /* No alignment needed. */
4751 data_size = 4;
4752 break;
4755 * NT4 server just returns "invalid query" to this - if we try
4756 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4757 * want this. JRA.
4759 /* The first statement above is false - verified using Thursby
4760 * client against NT4 -- gcolley.
4762 case SMB_QUERY_FILE_STREAM_INFO:
4763 case SMB_FILE_STREAM_INFORMATION: {
4764 unsigned int num_streams = 0;
4765 struct stream_struct *streams = NULL;
4767 DEBUG(10,("smbd_do_qfilepathinfo: "
4768 "SMB_FILE_STREAM_INFORMATION\n"));
4770 if (is_ntfs_stream_smb_fname(smb_fname)) {
4771 return NT_STATUS_INVALID_PARAMETER;
4774 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4775 talloc_tos(), &num_streams, &streams);
4777 if (!NT_STATUS_IS_OK(status)) {
4778 DEBUG(10, ("could not get stream info: %s\n",
4779 nt_errstr(status)));
4780 return status;
4783 status = marshall_stream_info(num_streams, streams,
4784 pdata, max_data_bytes,
4785 &data_size);
4787 if (!NT_STATUS_IS_OK(status)) {
4788 DEBUG(10, ("marshall_stream_info failed: %s\n",
4789 nt_errstr(status)));
4790 TALLOC_FREE(streams);
4791 return status;
4794 TALLOC_FREE(streams);
4796 break;
4798 case SMB_QUERY_COMPRESSION_INFO:
4799 case SMB_FILE_COMPRESSION_INFORMATION:
4800 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4801 SOFF_T(pdata,0,file_size);
4802 SIVAL(pdata,8,0); /* ??? */
4803 SIVAL(pdata,12,0); /* ??? */
4804 data_size = 16;
4805 break;
4807 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4809 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4810 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4811 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4812 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4813 SOFF_T(pdata,32,allocation_size);
4814 SOFF_T(pdata,40,file_size);
4815 SIVAL(pdata,48,mode);
4816 SIVAL(pdata,52,0); /* ??? */
4817 data_size = 56;
4818 break;
4820 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4821 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4822 SIVAL(pdata,0,mode);
4823 SIVAL(pdata,4,0);
4824 data_size = 8;
4825 break;
4828 * CIFS UNIX Extensions.
4831 case SMB_QUERY_FILE_UNIX_BASIC:
4833 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4834 data_size = PTR_DIFF(pdata,(*ppdata));
4836 DEBUG(4,("smbd_do_qfilepathinfo: "
4837 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4838 dump_data(4, (uint8_t *)(*ppdata), data_size);
4840 break;
4842 case SMB_QUERY_FILE_UNIX_INFO2:
4844 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4845 data_size = PTR_DIFF(pdata,(*ppdata));
4848 int i;
4849 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4851 for (i=0; i<100; i++)
4852 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4853 DEBUG(4,("\n"));
4856 break;
4858 case SMB_QUERY_FILE_UNIX_LINK:
4860 int len;
4861 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4863 if (!buffer) {
4864 return NT_STATUS_NO_MEMORY;
4867 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4868 #ifdef S_ISLNK
4869 if(!S_ISLNK(psbuf->st_ex_mode)) {
4870 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4872 #else
4873 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4874 #endif
4875 len = SMB_VFS_READLINK(conn,
4876 smb_fname->base_name,
4877 buffer, PATH_MAX);
4878 if (len == -1) {
4879 return map_nt_error_from_unix(errno);
4881 buffer[len] = 0;
4882 len = srvstr_push(dstart, flags2,
4883 pdata, buffer,
4884 PTR_DIFF(dend, pdata),
4885 STR_TERMINATE);
4886 pdata += len;
4887 data_size = PTR_DIFF(pdata,(*ppdata));
4889 break;
4892 #if defined(HAVE_POSIX_ACLS)
4893 case SMB_QUERY_POSIX_ACL:
4895 SMB_ACL_T file_acl = NULL;
4896 SMB_ACL_T def_acl = NULL;
4897 uint16 num_file_acls = 0;
4898 uint16 num_def_acls = 0;
4900 if (fsp && fsp->fh->fd != -1) {
4901 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4902 } else {
4903 file_acl =
4904 SMB_VFS_SYS_ACL_GET_FILE(conn,
4905 smb_fname->base_name,
4906 SMB_ACL_TYPE_ACCESS);
4909 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4910 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4911 "not implemented on "
4912 "filesystem containing %s\n",
4913 smb_fname->base_name));
4914 return NT_STATUS_NOT_IMPLEMENTED;
4917 if (S_ISDIR(psbuf->st_ex_mode)) {
4918 if (fsp && fsp->is_directory) {
4919 def_acl =
4920 SMB_VFS_SYS_ACL_GET_FILE(
4921 conn,
4922 fsp->fsp_name->base_name,
4923 SMB_ACL_TYPE_DEFAULT);
4924 } else {
4925 def_acl =
4926 SMB_VFS_SYS_ACL_GET_FILE(
4927 conn,
4928 smb_fname->base_name,
4929 SMB_ACL_TYPE_DEFAULT);
4931 def_acl = free_empty_sys_acl(conn, def_acl);
4934 num_file_acls = count_acl_entries(conn, file_acl);
4935 num_def_acls = count_acl_entries(conn, def_acl);
4937 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4938 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4939 data_size,
4940 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4941 SMB_POSIX_ACL_HEADER_SIZE) ));
4942 if (file_acl) {
4943 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4945 if (def_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4948 return NT_STATUS_BUFFER_TOO_SMALL;
4951 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4952 SSVAL(pdata,2,num_file_acls);
4953 SSVAL(pdata,4,num_def_acls);
4954 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4955 if (file_acl) {
4956 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4958 if (def_acl) {
4959 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4961 return NT_STATUS_INTERNAL_ERROR;
4963 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4964 if (file_acl) {
4965 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4967 if (def_acl) {
4968 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4970 return NT_STATUS_INTERNAL_ERROR;
4973 if (file_acl) {
4974 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4976 if (def_acl) {
4977 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4979 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4980 break;
4982 #endif
4985 case SMB_QUERY_POSIX_LOCK:
4987 uint64_t count;
4988 uint64_t offset;
4989 uint64_t smblctx;
4990 enum brl_type lock_type;
4992 /* We need an open file with a real fd for this. */
4993 if (!fsp || fsp->fh->fd == -1) {
4994 return NT_STATUS_INVALID_LEVEL;
4997 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4998 return NT_STATUS_INVALID_PARAMETER;
5001 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5002 case POSIX_LOCK_TYPE_READ:
5003 lock_type = READ_LOCK;
5004 break;
5005 case POSIX_LOCK_TYPE_WRITE:
5006 lock_type = WRITE_LOCK;
5007 break;
5008 case POSIX_LOCK_TYPE_UNLOCK:
5009 default:
5010 /* There's no point in asking for an unlock... */
5011 return NT_STATUS_INVALID_PARAMETER;
5014 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5015 #if defined(HAVE_LONGLONG)
5016 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5017 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5018 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5019 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5020 #else /* HAVE_LONGLONG */
5021 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5022 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5023 #endif /* HAVE_LONGLONG */
5025 status = query_lock(fsp,
5026 &smblctx,
5027 &count,
5028 &offset,
5029 &lock_type,
5030 POSIX_LOCK);
5032 if (ERROR_WAS_LOCK_DENIED(status)) {
5033 /* Here we need to report who has it locked... */
5034 data_size = POSIX_LOCK_DATA_SIZE;
5036 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5037 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5038 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5039 #if defined(HAVE_LONGLONG)
5040 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5041 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5042 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5043 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5044 #else /* HAVE_LONGLONG */
5045 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5046 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5047 #endif /* HAVE_LONGLONG */
5049 } else if (NT_STATUS_IS_OK(status)) {
5050 /* For success we just return a copy of what we sent
5051 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5052 data_size = POSIX_LOCK_DATA_SIZE;
5053 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5054 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5055 } else {
5056 return status;
5058 break;
5061 default:
5062 return NT_STATUS_INVALID_LEVEL;
5065 *pdata_size = data_size;
5066 return NT_STATUS_OK;
5069 /****************************************************************************
5070 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5071 file name or file id).
5072 ****************************************************************************/
5074 static void call_trans2qfilepathinfo(connection_struct *conn,
5075 struct smb_request *req,
5076 unsigned int tran_call,
5077 char **pparams, int total_params,
5078 char **ppdata, int total_data,
5079 unsigned int max_data_bytes)
5081 char *params = *pparams;
5082 char *pdata = *ppdata;
5083 uint16 info_level;
5084 unsigned int data_size = 0;
5085 unsigned int param_size = 2;
5086 struct smb_filename *smb_fname = NULL;
5087 bool delete_pending = False;
5088 struct timespec write_time_ts;
5089 files_struct *fsp = NULL;
5090 struct file_id fileid;
5091 struct ea_list *ea_list = NULL;
5092 int lock_data_count = 0;
5093 char *lock_data = NULL;
5094 NTSTATUS status = NT_STATUS_OK;
5096 if (!params) {
5097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5098 return;
5101 ZERO_STRUCT(write_time_ts);
5103 if (tran_call == TRANSACT2_QFILEINFO) {
5104 if (total_params < 4) {
5105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5106 return;
5109 if (IS_IPC(conn)) {
5110 call_trans2qpipeinfo(conn, req, tran_call,
5111 pparams, total_params,
5112 ppdata, total_data,
5113 max_data_bytes);
5114 return;
5117 fsp = file_fsp(req, SVAL(params,0));
5118 info_level = SVAL(params,2);
5120 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5122 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5124 return;
5127 /* Initial check for valid fsp ptr. */
5128 if (!check_fsp_open(conn, req, fsp)) {
5129 return;
5132 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5133 &smb_fname);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 reply_nterror(req, status);
5136 return;
5139 if(fsp->fake_file_handle) {
5141 * This is actually for the QUOTA_FAKE_FILE --metze
5144 /* We know this name is ok, it's already passed the checks. */
5146 } else if(fsp->fh->fd == -1) {
5148 * This is actually a QFILEINFO on a directory
5149 * handle (returned from an NT SMB). NT5.0 seems
5150 * to do this call. JRA.
5153 if (INFO_LEVEL_IS_UNIX(info_level)) {
5154 /* Always do lstat for UNIX calls. */
5155 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5156 DEBUG(3,("call_trans2qfilepathinfo: "
5157 "SMB_VFS_LSTAT of %s failed "
5158 "(%s)\n",
5159 smb_fname_str_dbg(smb_fname),
5160 strerror(errno)));
5161 reply_nterror(req,
5162 map_nt_error_from_unix(errno));
5163 return;
5165 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5166 DEBUG(3,("call_trans2qfilepathinfo: "
5167 "SMB_VFS_STAT of %s failed (%s)\n",
5168 smb_fname_str_dbg(smb_fname),
5169 strerror(errno)));
5170 reply_nterror(req,
5171 map_nt_error_from_unix(errno));
5172 return;
5175 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5176 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5177 } else {
5179 * Original code - this is an open file.
5181 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5182 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5183 fsp->fnum, strerror(errno)));
5184 reply_nterror(req,
5185 map_nt_error_from_unix(errno));
5186 return;
5188 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5189 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5192 } else {
5193 uint32_t name_hash;
5194 char *fname = NULL;
5195 uint32_t ucf_flags = 0;
5197 /* qpathinfo */
5198 if (total_params < 7) {
5199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5200 return;
5203 info_level = SVAL(params,0);
5205 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5207 if (INFO_LEVEL_IS_UNIX(info_level)) {
5208 if (!lp_unix_extensions()) {
5209 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5210 return;
5212 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5213 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5214 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5215 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5219 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5220 total_params - 6,
5221 STR_TERMINATE, &status);
5222 if (!NT_STATUS_IS_OK(status)) {
5223 reply_nterror(req, status);
5224 return;
5227 status = filename_convert(req,
5228 conn,
5229 req->flags2 & FLAGS2_DFS_PATHNAMES,
5230 fname,
5231 ucf_flags,
5232 NULL,
5233 &smb_fname);
5234 if (!NT_STATUS_IS_OK(status)) {
5235 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5236 reply_botherror(req,
5237 NT_STATUS_PATH_NOT_COVERED,
5238 ERRSRV, ERRbadpath);
5239 return;
5241 reply_nterror(req, status);
5242 return;
5245 /* If this is a stream, check if there is a delete_pending. */
5246 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5247 && is_ntfs_stream_smb_fname(smb_fname)) {
5248 struct smb_filename *smb_fname_base = NULL;
5250 /* Create an smb_filename with stream_name == NULL. */
5251 status =
5252 create_synthetic_smb_fname(talloc_tos(),
5253 smb_fname->base_name,
5254 NULL, NULL,
5255 &smb_fname_base);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 reply_nterror(req, status);
5258 return;
5261 if (INFO_LEVEL_IS_UNIX(info_level)) {
5262 /* Always do lstat for UNIX calls. */
5263 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5264 DEBUG(3,("call_trans2qfilepathinfo: "
5265 "SMB_VFS_LSTAT of %s failed "
5266 "(%s)\n",
5267 smb_fname_str_dbg(smb_fname_base),
5268 strerror(errno)));
5269 TALLOC_FREE(smb_fname_base);
5270 reply_nterror(req,
5271 map_nt_error_from_unix(errno));
5272 return;
5274 } else {
5275 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5276 DEBUG(3,("call_trans2qfilepathinfo: "
5277 "fileinfo of %s failed "
5278 "(%s)\n",
5279 smb_fname_str_dbg(smb_fname_base),
5280 strerror(errno)));
5281 TALLOC_FREE(smb_fname_base);
5282 reply_nterror(req,
5283 map_nt_error_from_unix(errno));
5284 return;
5288 status = file_name_hash(conn,
5289 smb_fname_str_dbg(smb_fname_base),
5290 &name_hash);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 TALLOC_FREE(smb_fname_base);
5293 reply_nterror(req, status);
5294 return;
5297 fileid = vfs_file_id_from_sbuf(conn,
5298 &smb_fname_base->st);
5299 TALLOC_FREE(smb_fname_base);
5300 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5301 if (delete_pending) {
5302 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5303 return;
5307 if (INFO_LEVEL_IS_UNIX(info_level)) {
5308 /* Always do lstat for UNIX calls. */
5309 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5310 DEBUG(3,("call_trans2qfilepathinfo: "
5311 "SMB_VFS_LSTAT of %s failed (%s)\n",
5312 smb_fname_str_dbg(smb_fname),
5313 strerror(errno)));
5314 reply_nterror(req,
5315 map_nt_error_from_unix(errno));
5316 return;
5319 } else {
5320 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5321 DEBUG(3,("call_trans2qfilepathinfo: "
5322 "SMB_VFS_STAT of %s failed (%s)\n",
5323 smb_fname_str_dbg(smb_fname),
5324 strerror(errno)));
5325 reply_nterror(req,
5326 map_nt_error_from_unix(errno));
5327 return;
5331 status = file_name_hash(conn,
5332 smb_fname_str_dbg(smb_fname),
5333 &name_hash);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 reply_nterror(req, status);
5336 return;
5339 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5340 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5341 if (delete_pending) {
5342 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5343 return;
5347 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5348 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5349 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5351 /* Pull out any data sent here before we realloc. */
5352 switch (info_level) {
5353 case SMB_INFO_QUERY_EAS_FROM_LIST:
5355 /* Pull any EA list from the data portion. */
5356 uint32 ea_size;
5358 if (total_data < 4) {
5359 reply_nterror(
5360 req, NT_STATUS_INVALID_PARAMETER);
5361 return;
5363 ea_size = IVAL(pdata,0);
5365 if (total_data > 0 && ea_size != total_data) {
5366 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5367 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5368 reply_nterror(
5369 req, NT_STATUS_INVALID_PARAMETER);
5370 return;
5373 if (!lp_ea_support(SNUM(conn))) {
5374 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5375 return;
5378 /* Pull out the list of names. */
5379 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5380 if (!ea_list) {
5381 reply_nterror(
5382 req, NT_STATUS_INVALID_PARAMETER);
5383 return;
5385 break;
5388 case SMB_QUERY_POSIX_LOCK:
5390 if (fsp == NULL || fsp->fh->fd == -1) {
5391 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5392 return;
5395 if (total_data != POSIX_LOCK_DATA_SIZE) {
5396 reply_nterror(
5397 req, NT_STATUS_INVALID_PARAMETER);
5398 return;
5401 /* Copy the lock range data. */
5402 lock_data = (char *)TALLOC_MEMDUP(
5403 req, pdata, total_data);
5404 if (!lock_data) {
5405 reply_nterror(req, NT_STATUS_NO_MEMORY);
5406 return;
5408 lock_data_count = total_data;
5410 default:
5411 break;
5414 *pparams = (char *)SMB_REALLOC(*pparams,2);
5415 if (*pparams == NULL) {
5416 reply_nterror(req, NT_STATUS_NO_MEMORY);
5417 return;
5419 params = *pparams;
5420 SSVAL(params,0,0);
5423 * draft-leach-cifs-v1-spec-02.txt
5424 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5425 * says:
5427 * The requested information is placed in the Data portion of the
5428 * transaction response. For the information levels greater than 0x100,
5429 * the transaction response has 1 parameter word which should be
5430 * ignored by the client.
5432 * However Windows only follows this rule for the IS_NAME_VALID call.
5434 switch (info_level) {
5435 case SMB_INFO_IS_NAME_VALID:
5436 param_size = 0;
5437 break;
5440 if ((info_level & 0xFF00) == 0xFF00) {
5442 * We use levels that start with 0xFF00
5443 * internally to represent SMB2 specific levels
5445 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5446 return;
5449 status = smbd_do_qfilepathinfo(conn, req, info_level,
5450 fsp, smb_fname,
5451 delete_pending, write_time_ts,
5452 ea_list,
5453 lock_data_count, lock_data,
5454 req->flags2, max_data_bytes,
5455 ppdata, &data_size);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 reply_nterror(req, status);
5458 return;
5461 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5462 max_data_bytes);
5464 return;
5467 /****************************************************************************
5468 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5469 code.
5470 ****************************************************************************/
5472 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5473 connection_struct *conn,
5474 struct smb_request *req,
5475 bool overwrite_if_exists,
5476 const struct smb_filename *smb_fname_old,
5477 struct smb_filename *smb_fname_new)
5479 NTSTATUS status = NT_STATUS_OK;
5481 /* source must already exist. */
5482 if (!VALID_STAT(smb_fname_old->st)) {
5483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5486 if (VALID_STAT(smb_fname_new->st)) {
5487 if (overwrite_if_exists) {
5488 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5489 return NT_STATUS_FILE_IS_A_DIRECTORY;
5491 status = unlink_internals(conn,
5492 req,
5493 FILE_ATTRIBUTE_NORMAL,
5494 smb_fname_new,
5495 false);
5496 if (!NT_STATUS_IS_OK(status)) {
5497 return status;
5499 } else {
5500 /* Disallow if newname already exists. */
5501 return NT_STATUS_OBJECT_NAME_COLLISION;
5505 /* No links from a directory. */
5506 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5507 return NT_STATUS_FILE_IS_A_DIRECTORY;
5510 /* Setting a hardlink to/from a stream isn't currently supported. */
5511 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5512 is_ntfs_stream_smb_fname(smb_fname_new)) {
5513 return NT_STATUS_INVALID_PARAMETER;
5516 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5517 smb_fname_old->base_name, smb_fname_new->base_name));
5519 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5520 smb_fname_new->base_name) != 0) {
5521 status = map_nt_error_from_unix(errno);
5522 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5523 nt_errstr(status), smb_fname_old->base_name,
5524 smb_fname_new->base_name));
5526 return status;
5529 /****************************************************************************
5530 Deal with setting the time from any of the setfilepathinfo functions.
5531 ****************************************************************************/
5533 NTSTATUS smb_set_file_time(connection_struct *conn,
5534 files_struct *fsp,
5535 const struct smb_filename *smb_fname,
5536 struct smb_file_time *ft,
5537 bool setting_write_time)
5539 struct smb_filename smb_fname_base;
5540 uint32 action =
5541 FILE_NOTIFY_CHANGE_LAST_ACCESS
5542 |FILE_NOTIFY_CHANGE_LAST_WRITE
5543 |FILE_NOTIFY_CHANGE_CREATION;
5545 if (!VALID_STAT(smb_fname->st)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5549 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5550 return NT_STATUS_ACCESS_DENIED;
5553 /* get some defaults (no modifications) if any info is zero or -1. */
5554 if (null_timespec(ft->create_time)) {
5555 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5558 if (null_timespec(ft->atime)) {
5559 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5562 if (null_timespec(ft->mtime)) {
5563 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5566 if (!setting_write_time) {
5567 /* ft->mtime comes from change time, not write time. */
5568 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5571 /* Ensure the resolution is the correct for
5572 * what we can store on this filesystem. */
5574 round_timespec(conn->ts_res, &ft->create_time);
5575 round_timespec(conn->ts_res, &ft->ctime);
5576 round_timespec(conn->ts_res, &ft->atime);
5577 round_timespec(conn->ts_res, &ft->mtime);
5579 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5580 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5581 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5582 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5583 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5584 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5585 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5586 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5588 if (setting_write_time) {
5590 * This was a Windows setfileinfo on an open file.
5591 * NT does this a lot. We also need to
5592 * set the time here, as it can be read by
5593 * FindFirst/FindNext and with the patch for bug #2045
5594 * in smbd/fileio.c it ensures that this timestamp is
5595 * kept sticky even after a write. We save the request
5596 * away and will set it on file close and after a write. JRA.
5599 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5600 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5602 if (fsp != NULL) {
5603 if (fsp->base_fsp) {
5604 set_sticky_write_time_fsp(fsp->base_fsp,
5605 ft->mtime);
5606 } else {
5607 set_sticky_write_time_fsp(fsp, ft->mtime);
5609 } else {
5610 set_sticky_write_time_path(
5611 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5612 ft->mtime);
5616 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5618 /* Always call ntimes on the base, even if a stream was passed in. */
5619 smb_fname_base = *smb_fname;
5620 smb_fname_base.stream_name = NULL;
5622 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5623 return map_nt_error_from_unix(errno);
5626 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5627 smb_fname->base_name);
5628 return NT_STATUS_OK;
5631 /****************************************************************************
5632 Deal with setting the dosmode from any of the setfilepathinfo functions.
5633 ****************************************************************************/
5635 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5636 const struct smb_filename *smb_fname,
5637 uint32 dosmode)
5639 struct smb_filename *smb_fname_base = NULL;
5640 NTSTATUS status;
5642 if (!VALID_STAT(smb_fname->st)) {
5643 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5646 /* Always operate on the base_name, even if a stream was passed in. */
5647 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5648 NULL, &smb_fname->st,
5649 &smb_fname_base);
5650 if (!NT_STATUS_IS_OK(status)) {
5651 return status;
5654 if (dosmode) {
5655 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5656 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5657 } else {
5658 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5662 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5664 /* check the mode isn't different, before changing it */
5665 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5666 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5667 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5668 (unsigned int)dosmode));
5670 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5671 false)) {
5672 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5673 "%s failed (%s)\n",
5674 smb_fname_str_dbg(smb_fname_base),
5675 strerror(errno)));
5676 status = map_nt_error_from_unix(errno);
5677 goto out;
5680 status = NT_STATUS_OK;
5681 out:
5682 TALLOC_FREE(smb_fname_base);
5683 return status;
5686 /****************************************************************************
5687 Deal with setting the size from any of the setfilepathinfo functions.
5688 ****************************************************************************/
5690 static NTSTATUS smb_set_file_size(connection_struct *conn,
5691 struct smb_request *req,
5692 files_struct *fsp,
5693 const struct smb_filename *smb_fname,
5694 const SMB_STRUCT_STAT *psbuf,
5695 SMB_OFF_T size,
5696 bool fail_after_createfile)
5698 NTSTATUS status = NT_STATUS_OK;
5699 struct smb_filename *smb_fname_tmp = NULL;
5700 files_struct *new_fsp = NULL;
5702 if (!VALID_STAT(*psbuf)) {
5703 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5706 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5707 return NT_STATUS_ACCESS_DENIED;
5710 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5712 if (size == get_file_size_stat(psbuf)) {
5713 return NT_STATUS_OK;
5716 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5717 smb_fname_str_dbg(smb_fname), (double)size));
5719 if (fsp && fsp->fh->fd != -1) {
5720 /* Handle based call. */
5721 if (vfs_set_filelen(fsp, size) == -1) {
5722 return map_nt_error_from_unix(errno);
5724 trigger_write_time_update_immediate(fsp);
5725 return NT_STATUS_OK;
5728 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5729 if (!NT_STATUS_IS_OK(status)) {
5730 return status;
5733 smb_fname_tmp->st = *psbuf;
5735 status = SMB_VFS_CREATE_FILE(
5736 conn, /* conn */
5737 req, /* req */
5738 0, /* root_dir_fid */
5739 smb_fname_tmp, /* fname */
5740 FILE_WRITE_DATA, /* access_mask */
5741 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5742 FILE_SHARE_DELETE),
5743 FILE_OPEN, /* create_disposition*/
5744 0, /* create_options */
5745 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5746 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5747 0, /* allocation_size */
5748 0, /* private_flags */
5749 NULL, /* sd */
5750 NULL, /* ea_list */
5751 &new_fsp, /* result */
5752 NULL); /* pinfo */
5754 TALLOC_FREE(smb_fname_tmp);
5756 if (!NT_STATUS_IS_OK(status)) {
5757 /* NB. We check for open_was_deferred in the caller. */
5758 return status;
5761 /* See RAW-SFILEINFO-END-OF-FILE */
5762 if (fail_after_createfile) {
5763 close_file(req, new_fsp,NORMAL_CLOSE);
5764 return NT_STATUS_INVALID_LEVEL;
5767 if (vfs_set_filelen(new_fsp, size) == -1) {
5768 status = map_nt_error_from_unix(errno);
5769 close_file(req, new_fsp,NORMAL_CLOSE);
5770 return status;
5773 trigger_write_time_update_immediate(new_fsp);
5774 close_file(req, new_fsp,NORMAL_CLOSE);
5775 return NT_STATUS_OK;
5778 /****************************************************************************
5779 Deal with SMB_INFO_SET_EA.
5780 ****************************************************************************/
5782 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5783 const char *pdata,
5784 int total_data,
5785 files_struct *fsp,
5786 const struct smb_filename *smb_fname)
5788 struct ea_list *ea_list = NULL;
5789 TALLOC_CTX *ctx = NULL;
5790 NTSTATUS status = NT_STATUS_OK;
5792 if (total_data < 10) {
5794 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5795 length. They seem to have no effect. Bug #3212. JRA */
5797 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5798 /* We're done. We only get EA info in this call. */
5799 return NT_STATUS_OK;
5802 return NT_STATUS_INVALID_PARAMETER;
5805 if (IVAL(pdata,0) > total_data) {
5806 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5807 IVAL(pdata,0), (unsigned int)total_data));
5808 return NT_STATUS_INVALID_PARAMETER;
5811 ctx = talloc_tos();
5812 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5813 if (!ea_list) {
5814 return NT_STATUS_INVALID_PARAMETER;
5817 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5818 return NT_STATUS_ACCESS_DENIED;
5821 status = set_ea(conn, fsp, smb_fname, ea_list);
5823 return status;
5826 /****************************************************************************
5827 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5828 ****************************************************************************/
5830 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5831 const char *pdata,
5832 int total_data,
5833 files_struct *fsp)
5835 struct ea_list *ea_list = NULL;
5836 NTSTATUS status;
5838 if (!fsp) {
5839 return NT_STATUS_INVALID_HANDLE;
5842 if (!lp_ea_support(SNUM(conn))) {
5843 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5844 "EA's not supported.\n",
5845 (unsigned int)total_data));
5846 return NT_STATUS_EAS_NOT_SUPPORTED;
5849 if (total_data < 10) {
5850 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5851 "too small.\n",
5852 (unsigned int)total_data));
5853 return NT_STATUS_INVALID_PARAMETER;
5856 ea_list = read_nttrans_ea_list(talloc_tos(),
5857 pdata,
5858 total_data);
5860 if (!ea_list) {
5861 return NT_STATUS_INVALID_PARAMETER;
5864 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5865 return NT_STATUS_ACCESS_DENIED;
5868 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5870 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5871 smb_fname_str_dbg(fsp->fsp_name),
5872 nt_errstr(status) ));
5874 return status;
5878 /****************************************************************************
5879 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5880 ****************************************************************************/
5882 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5883 const char *pdata,
5884 int total_data,
5885 files_struct *fsp,
5886 struct smb_filename *smb_fname)
5888 NTSTATUS status = NT_STATUS_OK;
5889 bool delete_on_close;
5890 uint32 dosmode = 0;
5892 if (total_data < 1) {
5893 return NT_STATUS_INVALID_PARAMETER;
5896 if (fsp == NULL) {
5897 return NT_STATUS_INVALID_HANDLE;
5900 delete_on_close = (CVAL(pdata,0) ? True : False);
5901 dosmode = dos_mode(conn, smb_fname);
5903 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5904 "delete_on_close = %u\n",
5905 smb_fname_str_dbg(smb_fname),
5906 (unsigned int)dosmode,
5907 (unsigned int)delete_on_close ));
5909 if (delete_on_close) {
5910 status = can_set_delete_on_close(fsp, dosmode);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 return status;
5916 /* The set is across all open files on this dev/inode pair. */
5917 if (!set_delete_on_close(fsp, delete_on_close,
5918 conn->session_info->security_token,
5919 &conn->session_info->utok)) {
5920 return NT_STATUS_ACCESS_DENIED;
5922 return NT_STATUS_OK;
5925 /****************************************************************************
5926 Deal with SMB_FILE_POSITION_INFORMATION.
5927 ****************************************************************************/
5929 static NTSTATUS smb_file_position_information(connection_struct *conn,
5930 const char *pdata,
5931 int total_data,
5932 files_struct *fsp)
5934 uint64_t position_information;
5936 if (total_data < 8) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 if (fsp == NULL) {
5941 /* Ignore on pathname based set. */
5942 return NT_STATUS_OK;
5945 position_information = (uint64_t)IVAL(pdata,0);
5946 #ifdef LARGE_SMB_OFF_T
5947 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5948 #else /* LARGE_SMB_OFF_T */
5949 if (IVAL(pdata,4) != 0) {
5950 /* more than 32 bits? */
5951 return NT_STATUS_INVALID_PARAMETER;
5953 #endif /* LARGE_SMB_OFF_T */
5955 DEBUG(10,("smb_file_position_information: Set file position "
5956 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5957 (double)position_information));
5958 fsp->fh->position_information = position_information;
5959 return NT_STATUS_OK;
5962 /****************************************************************************
5963 Deal with SMB_FILE_MODE_INFORMATION.
5964 ****************************************************************************/
5966 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5967 const char *pdata,
5968 int total_data)
5970 uint32 mode;
5972 if (total_data < 4) {
5973 return NT_STATUS_INVALID_PARAMETER;
5975 mode = IVAL(pdata,0);
5976 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5977 return NT_STATUS_INVALID_PARAMETER;
5979 return NT_STATUS_OK;
5982 /****************************************************************************
5983 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5984 ****************************************************************************/
5986 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5987 struct smb_request *req,
5988 const char *pdata,
5989 int total_data,
5990 const struct smb_filename *smb_fname)
5992 char *link_target = NULL;
5993 const char *newname = smb_fname->base_name;
5994 TALLOC_CTX *ctx = talloc_tos();
5996 /* Set a symbolic link. */
5997 /* Don't allow this if follow links is false. */
5999 if (total_data == 0) {
6000 return NT_STATUS_INVALID_PARAMETER;
6003 if (!lp_symlinks(SNUM(conn))) {
6004 return NT_STATUS_ACCESS_DENIED;
6007 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6008 total_data, STR_TERMINATE);
6010 if (!link_target) {
6011 return NT_STATUS_INVALID_PARAMETER;
6014 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6015 newname, link_target ));
6017 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6018 return map_nt_error_from_unix(errno);
6021 return NT_STATUS_OK;
6024 /****************************************************************************
6025 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6026 ****************************************************************************/
6028 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6029 struct smb_request *req,
6030 const char *pdata, int total_data,
6031 struct smb_filename *smb_fname_new)
6033 char *oldname = NULL;
6034 struct smb_filename *smb_fname_old = NULL;
6035 TALLOC_CTX *ctx = talloc_tos();
6036 NTSTATUS status = NT_STATUS_OK;
6038 /* Set a hard link. */
6039 if (total_data == 0) {
6040 return NT_STATUS_INVALID_PARAMETER;
6043 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6044 total_data, STR_TERMINATE, &status);
6045 if (!NT_STATUS_IS_OK(status)) {
6046 return status;
6049 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6050 smb_fname_str_dbg(smb_fname_new), oldname));
6052 status = filename_convert(ctx,
6053 conn,
6054 req->flags2 & FLAGS2_DFS_PATHNAMES,
6055 oldname,
6057 NULL,
6058 &smb_fname_old);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 return status;
6063 return hardlink_internals(ctx, conn, req, false,
6064 smb_fname_old, smb_fname_new);
6067 /****************************************************************************
6068 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6069 ****************************************************************************/
6071 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6072 struct smb_request *req,
6073 const char *pdata,
6074 int total_data,
6075 files_struct *fsp,
6076 struct smb_filename *smb_fname_src)
6078 bool overwrite;
6079 uint32_t len;
6080 char *newname = NULL;
6081 struct smb_filename *smb_fname_dst = NULL;
6082 NTSTATUS status = NT_STATUS_OK;
6083 TALLOC_CTX *ctx = talloc_tos();
6085 if (!fsp) {
6086 return NT_STATUS_INVALID_HANDLE;
6089 if (total_data < 20) {
6090 return NT_STATUS_INVALID_PARAMETER;
6093 overwrite = (CVAL(pdata,0) ? True : False);
6094 len = IVAL(pdata,16);
6096 if (len > (total_data - 20) || (len == 0)) {
6097 return NT_STATUS_INVALID_PARAMETER;
6100 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6101 &pdata[20], len, STR_TERMINATE,
6102 &status);
6103 if (!NT_STATUS_IS_OK(status)) {
6104 return status;
6107 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6108 newname));
6110 status = filename_convert(ctx,
6111 conn,
6112 req->flags2 & FLAGS2_DFS_PATHNAMES,
6113 newname,
6114 UCF_SAVE_LCOMP,
6115 NULL,
6116 &smb_fname_dst);
6117 if (!NT_STATUS_IS_OK(status)) {
6118 return status;
6121 if (fsp->base_fsp) {
6122 /* newname must be a stream name. */
6123 if (newname[0] != ':') {
6124 return NT_STATUS_NOT_SUPPORTED;
6127 /* Create an smb_fname to call rename_internals_fsp() with. */
6128 status = create_synthetic_smb_fname(talloc_tos(),
6129 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6130 &smb_fname_dst);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 goto out;
6136 * Set the original last component, since
6137 * rename_internals_fsp() requires it.
6139 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6140 newname);
6141 if (smb_fname_dst->original_lcomp == NULL) {
6142 status = NT_STATUS_NO_MEMORY;
6143 goto out;
6148 DEBUG(10,("smb2_file_rename_information: "
6149 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6150 fsp->fnum, fsp_str_dbg(fsp),
6151 smb_fname_str_dbg(smb_fname_dst)));
6152 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6153 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6154 overwrite);
6156 out:
6157 TALLOC_FREE(smb_fname_dst);
6158 return status;
6161 static NTSTATUS smb_file_link_information(connection_struct *conn,
6162 struct smb_request *req,
6163 const char *pdata,
6164 int total_data,
6165 files_struct *fsp,
6166 struct smb_filename *smb_fname_src)
6168 bool overwrite;
6169 uint32_t len;
6170 char *newname = NULL;
6171 struct smb_filename *smb_fname_dst = NULL;
6172 NTSTATUS status = NT_STATUS_OK;
6173 TALLOC_CTX *ctx = talloc_tos();
6175 if (!fsp) {
6176 return NT_STATUS_INVALID_HANDLE;
6179 if (total_data < 20) {
6180 return NT_STATUS_INVALID_PARAMETER;
6183 overwrite = (CVAL(pdata,0) ? true : false);
6184 len = IVAL(pdata,16);
6186 if (len > (total_data - 20) || (len == 0)) {
6187 return NT_STATUS_INVALID_PARAMETER;
6190 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6191 &pdata[20], len, STR_TERMINATE,
6192 &status);
6193 if (!NT_STATUS_IS_OK(status)) {
6194 return status;
6197 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6198 newname));
6200 status = filename_convert(ctx,
6201 conn,
6202 req->flags2 & FLAGS2_DFS_PATHNAMES,
6203 newname,
6204 UCF_SAVE_LCOMP,
6205 NULL,
6206 &smb_fname_dst);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 return status;
6211 if (fsp->base_fsp) {
6212 /* No stream names. */
6213 return NT_STATUS_NOT_SUPPORTED;
6216 DEBUG(10,("smb_file_link_information: "
6217 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6218 fsp->fnum, fsp_str_dbg(fsp),
6219 smb_fname_str_dbg(smb_fname_dst)));
6220 status = hardlink_internals(ctx,
6221 conn,
6222 req,
6223 overwrite,
6224 fsp->fsp_name,
6225 smb_fname_dst);
6227 TALLOC_FREE(smb_fname_dst);
6228 return status;
6231 /****************************************************************************
6232 Deal with SMB_FILE_RENAME_INFORMATION.
6233 ****************************************************************************/
6235 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6236 struct smb_request *req,
6237 const char *pdata,
6238 int total_data,
6239 files_struct *fsp,
6240 struct smb_filename *smb_fname_src)
6242 bool overwrite;
6243 uint32 root_fid;
6244 uint32 len;
6245 char *newname = NULL;
6246 struct smb_filename *smb_fname_dst = NULL;
6247 bool dest_has_wcard = False;
6248 NTSTATUS status = NT_STATUS_OK;
6249 char *p;
6250 TALLOC_CTX *ctx = talloc_tos();
6252 if (total_data < 13) {
6253 return NT_STATUS_INVALID_PARAMETER;
6256 overwrite = (CVAL(pdata,0) ? True : False);
6257 root_fid = IVAL(pdata,4);
6258 len = IVAL(pdata,8);
6260 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6261 return NT_STATUS_INVALID_PARAMETER;
6264 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6265 len, 0, &status,
6266 &dest_has_wcard);
6267 if (!NT_STATUS_IS_OK(status)) {
6268 return status;
6271 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6272 newname));
6274 status = resolve_dfspath_wcard(ctx, conn,
6275 req->flags2 & FLAGS2_DFS_PATHNAMES,
6276 newname,
6277 true,
6278 &newname,
6279 &dest_has_wcard);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 return status;
6284 /* Check the new name has no '/' characters. */
6285 if (strchr_m(newname, '/')) {
6286 return NT_STATUS_NOT_SUPPORTED;
6289 if (fsp && fsp->base_fsp) {
6290 /* newname must be a stream name. */
6291 if (newname[0] != ':') {
6292 return NT_STATUS_NOT_SUPPORTED;
6295 /* Create an smb_fname to call rename_internals_fsp() with. */
6296 status = create_synthetic_smb_fname(talloc_tos(),
6297 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6298 &smb_fname_dst);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 goto out;
6304 * Set the original last component, since
6305 * rename_internals_fsp() requires it.
6307 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6308 newname);
6309 if (smb_fname_dst->original_lcomp == NULL) {
6310 status = NT_STATUS_NO_MEMORY;
6311 goto out;
6314 } else {
6316 * Build up an smb_fname_dst based on the filename passed in.
6317 * We basically just strip off the last component, and put on
6318 * the newname instead.
6320 char *base_name = NULL;
6322 /* newname must *not* be a stream name. */
6323 if (newname[0] == ':') {
6324 return NT_STATUS_NOT_SUPPORTED;
6328 * Strip off the last component (filename) of the path passed
6329 * in.
6331 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6332 if (!base_name) {
6333 return NT_STATUS_NO_MEMORY;
6335 p = strrchr_m(base_name, '/');
6336 if (p) {
6337 p[1] = '\0';
6338 } else {
6339 base_name = talloc_strdup(ctx, "");
6340 if (!base_name) {
6341 return NT_STATUS_NO_MEMORY;
6344 /* Append the new name. */
6345 base_name = talloc_asprintf_append(base_name,
6346 "%s",
6347 newname);
6348 if (!base_name) {
6349 return NT_STATUS_NO_MEMORY;
6352 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6353 (UCF_SAVE_LCOMP |
6354 (dest_has_wcard ?
6355 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6356 0)));
6358 /* If an error we expect this to be
6359 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6361 if (!NT_STATUS_IS_OK(status)) {
6362 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6363 status)) {
6364 goto out;
6366 /* Create an smb_fname to call rename_internals_fsp() */
6367 status = create_synthetic_smb_fname(ctx,
6368 base_name, NULL,
6369 NULL,
6370 &smb_fname_dst);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 goto out;
6377 if (fsp) {
6378 DEBUG(10,("smb_file_rename_information: "
6379 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6380 fsp->fnum, fsp_str_dbg(fsp),
6381 smb_fname_str_dbg(smb_fname_dst)));
6382 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6383 overwrite);
6384 } else {
6385 DEBUG(10,("smb_file_rename_information: "
6386 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6387 smb_fname_str_dbg(smb_fname_src),
6388 smb_fname_str_dbg(smb_fname_dst)));
6389 status = rename_internals(ctx, conn, req, smb_fname_src,
6390 smb_fname_dst, 0, overwrite, false,
6391 dest_has_wcard,
6392 FILE_WRITE_ATTRIBUTES);
6394 out:
6395 TALLOC_FREE(smb_fname_dst);
6396 return status;
6399 /****************************************************************************
6400 Deal with SMB_SET_POSIX_ACL.
6401 ****************************************************************************/
6403 #if defined(HAVE_POSIX_ACLS)
6404 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6405 const char *pdata,
6406 int total_data,
6407 files_struct *fsp,
6408 const struct smb_filename *smb_fname)
6410 uint16 posix_acl_version;
6411 uint16 num_file_acls;
6412 uint16 num_def_acls;
6413 bool valid_file_acls = True;
6414 bool valid_def_acls = True;
6416 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6417 return NT_STATUS_INVALID_PARAMETER;
6419 posix_acl_version = SVAL(pdata,0);
6420 num_file_acls = SVAL(pdata,2);
6421 num_def_acls = SVAL(pdata,4);
6423 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6424 valid_file_acls = False;
6425 num_file_acls = 0;
6428 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6429 valid_def_acls = False;
6430 num_def_acls = 0;
6433 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6434 return NT_STATUS_INVALID_PARAMETER;
6437 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6438 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6439 return NT_STATUS_INVALID_PARAMETER;
6442 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6443 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6444 (unsigned int)num_file_acls,
6445 (unsigned int)num_def_acls));
6447 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6448 smb_fname->base_name, num_file_acls,
6449 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6450 return map_nt_error_from_unix(errno);
6453 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6454 smb_fname->base_name, &smb_fname->st, num_def_acls,
6455 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6456 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6457 return map_nt_error_from_unix(errno);
6459 return NT_STATUS_OK;
6461 #endif
6463 /****************************************************************************
6464 Deal with SMB_SET_POSIX_LOCK.
6465 ****************************************************************************/
6467 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6468 struct smb_request *req,
6469 const char *pdata,
6470 int total_data,
6471 files_struct *fsp)
6473 uint64_t count;
6474 uint64_t offset;
6475 uint64_t smblctx;
6476 bool blocking_lock = False;
6477 enum brl_type lock_type;
6479 NTSTATUS status = NT_STATUS_OK;
6481 if (fsp == NULL || fsp->fh->fd == -1) {
6482 return NT_STATUS_INVALID_HANDLE;
6485 if (total_data != POSIX_LOCK_DATA_SIZE) {
6486 return NT_STATUS_INVALID_PARAMETER;
6489 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6490 case POSIX_LOCK_TYPE_READ:
6491 lock_type = READ_LOCK;
6492 break;
6493 case POSIX_LOCK_TYPE_WRITE:
6494 /* Return the right POSIX-mappable error code for files opened read-only. */
6495 if (!fsp->can_write) {
6496 return NT_STATUS_INVALID_HANDLE;
6498 lock_type = WRITE_LOCK;
6499 break;
6500 case POSIX_LOCK_TYPE_UNLOCK:
6501 lock_type = UNLOCK_LOCK;
6502 break;
6503 default:
6504 return NT_STATUS_INVALID_PARAMETER;
6507 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6508 blocking_lock = False;
6509 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6510 blocking_lock = True;
6511 } else {
6512 return NT_STATUS_INVALID_PARAMETER;
6515 if (!lp_blocking_locks(SNUM(conn))) {
6516 blocking_lock = False;
6519 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6520 #if defined(HAVE_LONGLONG)
6521 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6522 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6523 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6524 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6525 #else /* HAVE_LONGLONG */
6526 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6527 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6528 #endif /* HAVE_LONGLONG */
6530 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6531 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6532 fsp_str_dbg(fsp),
6533 (unsigned int)lock_type,
6534 (unsigned long long)smblctx,
6535 (double)count,
6536 (double)offset ));
6538 if (lock_type == UNLOCK_LOCK) {
6539 status = do_unlock(req->sconn->msg_ctx,
6540 fsp,
6541 smblctx,
6542 count,
6543 offset,
6544 POSIX_LOCK);
6545 } else {
6546 uint64_t block_smblctx;
6548 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6549 fsp,
6550 smblctx,
6551 count,
6552 offset,
6553 lock_type,
6554 POSIX_LOCK,
6555 blocking_lock,
6556 &status,
6557 &block_smblctx,
6558 NULL);
6560 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6562 * A blocking lock was requested. Package up
6563 * this smb into a queued request and push it
6564 * onto the blocking lock queue.
6566 if(push_blocking_lock_request(br_lck,
6567 req,
6568 fsp,
6569 -1, /* infinite timeout. */
6571 smblctx,
6572 lock_type,
6573 POSIX_LOCK,
6574 offset,
6575 count,
6576 block_smblctx)) {
6577 TALLOC_FREE(br_lck);
6578 return status;
6581 TALLOC_FREE(br_lck);
6584 return status;
6587 /****************************************************************************
6588 Deal with SMB_SET_FILE_BASIC_INFO.
6589 ****************************************************************************/
6591 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6592 const char *pdata,
6593 int total_data,
6594 files_struct *fsp,
6595 const struct smb_filename *smb_fname)
6597 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6598 struct smb_file_time ft;
6599 uint32 dosmode = 0;
6600 NTSTATUS status = NT_STATUS_OK;
6602 ZERO_STRUCT(ft);
6604 if (total_data < 36) {
6605 return NT_STATUS_INVALID_PARAMETER;
6608 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6609 return NT_STATUS_ACCESS_DENIED;
6612 /* Set the attributes */
6613 dosmode = IVAL(pdata,32);
6614 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6615 if (!NT_STATUS_IS_OK(status)) {
6616 return status;
6619 /* create time */
6620 ft.create_time = interpret_long_date(pdata);
6622 /* access time */
6623 ft.atime = interpret_long_date(pdata+8);
6625 /* write time. */
6626 ft.mtime = interpret_long_date(pdata+16);
6628 /* change time. */
6629 ft.ctime = interpret_long_date(pdata+24);
6631 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6632 smb_fname_str_dbg(smb_fname)));
6634 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6635 true);
6638 /****************************************************************************
6639 Deal with SMB_INFO_STANDARD.
6640 ****************************************************************************/
6642 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6643 const char *pdata,
6644 int total_data,
6645 files_struct *fsp,
6646 const struct smb_filename *smb_fname)
6648 struct smb_file_time ft;
6650 ZERO_STRUCT(ft);
6652 if (total_data < 12) {
6653 return NT_STATUS_INVALID_PARAMETER;
6656 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6657 return NT_STATUS_ACCESS_DENIED;
6660 /* create time */
6661 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6662 /* access time */
6663 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6664 /* write time */
6665 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6667 DEBUG(10,("smb_set_info_standard: file %s\n",
6668 smb_fname_str_dbg(smb_fname)));
6670 return smb_set_file_time(conn,
6671 fsp,
6672 smb_fname,
6673 &ft,
6674 true);
6677 /****************************************************************************
6678 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6679 ****************************************************************************/
6681 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6682 struct smb_request *req,
6683 const char *pdata,
6684 int total_data,
6685 files_struct *fsp,
6686 struct smb_filename *smb_fname)
6688 uint64_t allocation_size = 0;
6689 NTSTATUS status = NT_STATUS_OK;
6690 files_struct *new_fsp = NULL;
6692 if (!VALID_STAT(smb_fname->st)) {
6693 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6696 if (total_data < 8) {
6697 return NT_STATUS_INVALID_PARAMETER;
6700 allocation_size = (uint64_t)IVAL(pdata,0);
6701 #ifdef LARGE_SMB_OFF_T
6702 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6703 #else /* LARGE_SMB_OFF_T */
6704 if (IVAL(pdata,4) != 0) {
6705 /* more than 32 bits? */
6706 return NT_STATUS_INVALID_PARAMETER;
6708 #endif /* LARGE_SMB_OFF_T */
6710 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6711 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6712 (double)allocation_size));
6714 if (allocation_size) {
6715 allocation_size = smb_roundup(conn, allocation_size);
6718 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6719 return NT_STATUS_ACCESS_DENIED;
6722 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6723 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6724 (double)allocation_size));
6726 if (fsp && fsp->fh->fd != -1) {
6727 /* Open file handle. */
6728 /* Only change if needed. */
6729 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6730 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6731 return map_nt_error_from_unix(errno);
6734 /* But always update the time. */
6736 * This is equivalent to a write. Ensure it's seen immediately
6737 * if there are no pending writes.
6739 trigger_write_time_update_immediate(fsp);
6740 return NT_STATUS_OK;
6743 /* Pathname or stat or directory file. */
6744 status = SMB_VFS_CREATE_FILE(
6745 conn, /* conn */
6746 req, /* req */
6747 0, /* root_dir_fid */
6748 smb_fname, /* fname */
6749 FILE_WRITE_DATA, /* access_mask */
6750 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6751 FILE_SHARE_DELETE),
6752 FILE_OPEN, /* create_disposition*/
6753 0, /* create_options */
6754 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6755 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6756 0, /* allocation_size */
6757 0, /* private_flags */
6758 NULL, /* sd */
6759 NULL, /* ea_list */
6760 &new_fsp, /* result */
6761 NULL); /* pinfo */
6763 if (!NT_STATUS_IS_OK(status)) {
6764 /* NB. We check for open_was_deferred in the caller. */
6765 return status;
6768 /* Only change if needed. */
6769 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6770 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6771 status = map_nt_error_from_unix(errno);
6772 close_file(req, new_fsp, NORMAL_CLOSE);
6773 return status;
6777 /* Changing the allocation size should set the last mod time. */
6779 * This is equivalent to a write. Ensure it's seen immediately
6780 * if there are no pending writes.
6782 trigger_write_time_update_immediate(new_fsp);
6784 close_file(req, new_fsp, NORMAL_CLOSE);
6785 return NT_STATUS_OK;
6788 /****************************************************************************
6789 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6790 ****************************************************************************/
6792 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6793 struct smb_request *req,
6794 const char *pdata,
6795 int total_data,
6796 files_struct *fsp,
6797 const struct smb_filename *smb_fname,
6798 bool fail_after_createfile)
6800 SMB_OFF_T size;
6802 if (total_data < 8) {
6803 return NT_STATUS_INVALID_PARAMETER;
6806 size = IVAL(pdata,0);
6807 #ifdef LARGE_SMB_OFF_T
6808 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6809 #else /* LARGE_SMB_OFF_T */
6810 if (IVAL(pdata,4) != 0) {
6811 /* more than 32 bits? */
6812 return NT_STATUS_INVALID_PARAMETER;
6814 #endif /* LARGE_SMB_OFF_T */
6815 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6816 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6817 (double)size));
6819 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6820 return NT_STATUS_ACCESS_DENIED;
6823 return smb_set_file_size(conn, req,
6824 fsp,
6825 smb_fname,
6826 &smb_fname->st,
6827 size,
6828 fail_after_createfile);
6831 /****************************************************************************
6832 Allow a UNIX info mknod.
6833 ****************************************************************************/
6835 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6836 const char *pdata,
6837 int total_data,
6838 const struct smb_filename *smb_fname)
6840 uint32 file_type = IVAL(pdata,56);
6841 #if defined(HAVE_MAKEDEV)
6842 uint32 dev_major = IVAL(pdata,60);
6843 uint32 dev_minor = IVAL(pdata,68);
6844 #endif
6845 SMB_DEV_T dev = (SMB_DEV_T)0;
6846 uint32 raw_unixmode = IVAL(pdata,84);
6847 NTSTATUS status;
6848 mode_t unixmode;
6850 if (total_data < 100) {
6851 return NT_STATUS_INVALID_PARAMETER;
6854 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6855 PERM_NEW_FILE, &unixmode);
6856 if (!NT_STATUS_IS_OK(status)) {
6857 return status;
6860 #if defined(HAVE_MAKEDEV)
6861 dev = makedev(dev_major, dev_minor);
6862 #endif
6864 switch (file_type) {
6865 #if defined(S_IFIFO)
6866 case UNIX_TYPE_FIFO:
6867 unixmode |= S_IFIFO;
6868 break;
6869 #endif
6870 #if defined(S_IFSOCK)
6871 case UNIX_TYPE_SOCKET:
6872 unixmode |= S_IFSOCK;
6873 break;
6874 #endif
6875 #if defined(S_IFCHR)
6876 case UNIX_TYPE_CHARDEV:
6877 unixmode |= S_IFCHR;
6878 break;
6879 #endif
6880 #if defined(S_IFBLK)
6881 case UNIX_TYPE_BLKDEV:
6882 unixmode |= S_IFBLK;
6883 break;
6884 #endif
6885 default:
6886 return NT_STATUS_INVALID_PARAMETER;
6889 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6890 "%.0f mode 0%o for file %s\n", (double)dev,
6891 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6893 /* Ok - do the mknod. */
6894 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6895 return map_nt_error_from_unix(errno);
6898 /* If any of the other "set" calls fail we
6899 * don't want to end up with a half-constructed mknod.
6902 if (lp_inherit_perms(SNUM(conn))) {
6903 char *parent;
6904 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6905 &parent, NULL)) {
6906 return NT_STATUS_NO_MEMORY;
6908 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6909 unixmode);
6910 TALLOC_FREE(parent);
6913 return NT_STATUS_OK;
6916 /****************************************************************************
6917 Deal with SMB_SET_FILE_UNIX_BASIC.
6918 ****************************************************************************/
6920 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6921 struct smb_request *req,
6922 const char *pdata,
6923 int total_data,
6924 files_struct *fsp,
6925 const struct smb_filename *smb_fname)
6927 struct smb_file_time ft;
6928 uint32 raw_unixmode;
6929 mode_t unixmode;
6930 SMB_OFF_T size = 0;
6931 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6932 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6933 NTSTATUS status = NT_STATUS_OK;
6934 bool delete_on_fail = False;
6935 enum perm_type ptype;
6936 files_struct *all_fsps = NULL;
6937 bool modify_mtime = true;
6938 struct file_id id;
6939 struct smb_filename *smb_fname_tmp = NULL;
6940 SMB_STRUCT_STAT sbuf;
6942 ZERO_STRUCT(ft);
6944 if (total_data < 100) {
6945 return NT_STATUS_INVALID_PARAMETER;
6948 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6949 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6950 size=IVAL(pdata,0); /* first 8 Bytes are size */
6951 #ifdef LARGE_SMB_OFF_T
6952 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6953 #else /* LARGE_SMB_OFF_T */
6954 if (IVAL(pdata,4) != 0) {
6955 /* more than 32 bits? */
6956 return NT_STATUS_INVALID_PARAMETER;
6958 #endif /* LARGE_SMB_OFF_T */
6961 ft.atime = interpret_long_date(pdata+24); /* access_time */
6962 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6963 set_owner = (uid_t)IVAL(pdata,40);
6964 set_grp = (gid_t)IVAL(pdata,48);
6965 raw_unixmode = IVAL(pdata,84);
6967 if (VALID_STAT(smb_fname->st)) {
6968 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6969 ptype = PERM_EXISTING_DIR;
6970 } else {
6971 ptype = PERM_EXISTING_FILE;
6973 } else {
6974 ptype = PERM_NEW_FILE;
6977 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6978 ptype, &unixmode);
6979 if (!NT_STATUS_IS_OK(status)) {
6980 return status;
6983 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6984 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6985 smb_fname_str_dbg(smb_fname), (double)size,
6986 (unsigned int)set_owner, (unsigned int)set_grp,
6987 (int)raw_unixmode));
6989 sbuf = smb_fname->st;
6991 if (!VALID_STAT(sbuf)) {
6993 * The only valid use of this is to create character and block
6994 * devices, and named pipes. This is deprecated (IMHO) and
6995 * a new info level should be used for mknod. JRA.
6998 status = smb_unix_mknod(conn,
6999 pdata,
7000 total_data,
7001 smb_fname);
7002 if (!NT_STATUS_IS_OK(status)) {
7003 return status;
7006 status = copy_smb_filename(talloc_tos(), smb_fname,
7007 &smb_fname_tmp);
7008 if (!NT_STATUS_IS_OK(status)) {
7009 return status;
7012 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7013 status = map_nt_error_from_unix(errno);
7014 TALLOC_FREE(smb_fname_tmp);
7015 SMB_VFS_UNLINK(conn, smb_fname);
7016 return status;
7019 sbuf = smb_fname_tmp->st;
7020 smb_fname = smb_fname_tmp;
7022 /* Ensure we don't try and change anything else. */
7023 raw_unixmode = SMB_MODE_NO_CHANGE;
7024 size = get_file_size_stat(&sbuf);
7025 ft.atime = sbuf.st_ex_atime;
7026 ft.mtime = sbuf.st_ex_mtime;
7028 * We continue here as we might want to change the
7029 * owner uid/gid.
7031 delete_on_fail = True;
7034 #if 1
7035 /* Horrible backwards compatibility hack as an old server bug
7036 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7037 * */
7039 if (!size) {
7040 size = get_file_size_stat(&sbuf);
7042 #endif
7045 * Deal with the UNIX specific mode set.
7048 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7049 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7050 "setting mode 0%o for file %s\n",
7051 (unsigned int)unixmode,
7052 smb_fname_str_dbg(smb_fname)));
7053 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7054 return map_nt_error_from_unix(errno);
7059 * Deal with the UNIX specific uid set.
7062 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7063 (sbuf.st_ex_uid != set_owner)) {
7064 int ret;
7066 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7067 "changing owner %u for path %s\n",
7068 (unsigned int)set_owner,
7069 smb_fname_str_dbg(smb_fname)));
7071 if (S_ISLNK(sbuf.st_ex_mode)) {
7072 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7073 set_owner, (gid_t)-1);
7074 } else {
7075 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7076 set_owner, (gid_t)-1);
7079 if (ret != 0) {
7080 status = map_nt_error_from_unix(errno);
7081 if (delete_on_fail) {
7082 SMB_VFS_UNLINK(conn, smb_fname);
7084 return status;
7089 * Deal with the UNIX specific gid set.
7092 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7093 (sbuf.st_ex_gid != set_grp)) {
7094 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7095 "changing group %u for file %s\n",
7096 (unsigned int)set_owner,
7097 smb_fname_str_dbg(smb_fname)));
7098 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7099 set_grp) != 0) {
7100 status = map_nt_error_from_unix(errno);
7101 if (delete_on_fail) {
7102 SMB_VFS_UNLINK(conn, smb_fname);
7104 return status;
7108 /* Deal with any size changes. */
7110 status = smb_set_file_size(conn, req,
7111 fsp,
7112 smb_fname,
7113 &sbuf,
7114 size,
7115 false);
7116 if (!NT_STATUS_IS_OK(status)) {
7117 return status;
7120 /* Deal with any time changes. */
7121 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7122 /* No change, don't cancel anything. */
7123 return status;
7126 id = vfs_file_id_from_sbuf(conn, &sbuf);
7127 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7128 all_fsps = file_find_di_next(all_fsps)) {
7130 * We're setting the time explicitly for UNIX.
7131 * Cancel any pending changes over all handles.
7133 all_fsps->update_write_time_on_close = false;
7134 TALLOC_FREE(all_fsps->update_write_time_event);
7138 * Override the "setting_write_time"
7139 * parameter here as it almost does what
7140 * we need. Just remember if we modified
7141 * mtime and send the notify ourselves.
7143 if (null_timespec(ft.mtime)) {
7144 modify_mtime = false;
7147 status = smb_set_file_time(conn,
7148 fsp,
7149 smb_fname,
7150 &ft,
7151 false);
7152 if (modify_mtime) {
7153 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7154 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7156 return status;
7159 /****************************************************************************
7160 Deal with SMB_SET_FILE_UNIX_INFO2.
7161 ****************************************************************************/
7163 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7164 struct smb_request *req,
7165 const char *pdata,
7166 int total_data,
7167 files_struct *fsp,
7168 const struct smb_filename *smb_fname)
7170 NTSTATUS status;
7171 uint32 smb_fflags;
7172 uint32 smb_fmask;
7174 if (total_data < 116) {
7175 return NT_STATUS_INVALID_PARAMETER;
7178 /* Start by setting all the fields that are common between UNIX_BASIC
7179 * and UNIX_INFO2.
7181 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7182 fsp, smb_fname);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 return status;
7187 smb_fflags = IVAL(pdata, 108);
7188 smb_fmask = IVAL(pdata, 112);
7190 /* NB: We should only attempt to alter the file flags if the client
7191 * sends a non-zero mask.
7193 if (smb_fmask != 0) {
7194 int stat_fflags = 0;
7196 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7197 smb_fmask, &stat_fflags)) {
7198 /* Client asked to alter a flag we don't understand. */
7199 return NT_STATUS_INVALID_PARAMETER;
7202 if (fsp && fsp->fh->fd != -1) {
7203 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7204 return NT_STATUS_NOT_SUPPORTED;
7205 } else {
7206 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7207 stat_fflags) != 0) {
7208 return map_nt_error_from_unix(errno);
7213 /* XXX: need to add support for changing the create_time here. You
7214 * can do this for paths on Darwin with setattrlist(2). The right way
7215 * to hook this up is probably by extending the VFS utimes interface.
7218 return NT_STATUS_OK;
7221 /****************************************************************************
7222 Create a directory with POSIX semantics.
7223 ****************************************************************************/
7225 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7226 struct smb_request *req,
7227 char **ppdata,
7228 int total_data,
7229 struct smb_filename *smb_fname,
7230 int *pdata_return_size)
7232 NTSTATUS status = NT_STATUS_OK;
7233 uint32 raw_unixmode = 0;
7234 uint32 mod_unixmode = 0;
7235 mode_t unixmode = (mode_t)0;
7236 files_struct *fsp = NULL;
7237 uint16 info_level_return = 0;
7238 int info;
7239 char *pdata = *ppdata;
7241 if (total_data < 18) {
7242 return NT_STATUS_INVALID_PARAMETER;
7245 raw_unixmode = IVAL(pdata,8);
7246 /* Next 4 bytes are not yet defined. */
7248 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7249 PERM_NEW_DIR, &unixmode);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 return status;
7254 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7256 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7257 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7259 status = SMB_VFS_CREATE_FILE(
7260 conn, /* conn */
7261 req, /* req */
7262 0, /* root_dir_fid */
7263 smb_fname, /* fname */
7264 FILE_READ_ATTRIBUTES, /* access_mask */
7265 FILE_SHARE_NONE, /* share_access */
7266 FILE_CREATE, /* create_disposition*/
7267 FILE_DIRECTORY_FILE, /* create_options */
7268 mod_unixmode, /* file_attributes */
7269 0, /* oplock_request */
7270 0, /* allocation_size */
7271 0, /* private_flags */
7272 NULL, /* sd */
7273 NULL, /* ea_list */
7274 &fsp, /* result */
7275 &info); /* pinfo */
7277 if (NT_STATUS_IS_OK(status)) {
7278 close_file(req, fsp, NORMAL_CLOSE);
7281 info_level_return = SVAL(pdata,16);
7283 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7284 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7285 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7286 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7287 } else {
7288 *pdata_return_size = 12;
7291 /* Realloc the data size */
7292 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7293 if (*ppdata == NULL) {
7294 *pdata_return_size = 0;
7295 return NT_STATUS_NO_MEMORY;
7297 pdata = *ppdata;
7299 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7300 SSVAL(pdata,2,0); /* No fnum. */
7301 SIVAL(pdata,4,info); /* Was directory created. */
7303 switch (info_level_return) {
7304 case SMB_QUERY_FILE_UNIX_BASIC:
7305 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7306 SSVAL(pdata,10,0); /* Padding. */
7307 store_file_unix_basic(conn, pdata + 12, fsp,
7308 &smb_fname->st);
7309 break;
7310 case SMB_QUERY_FILE_UNIX_INFO2:
7311 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7312 SSVAL(pdata,10,0); /* Padding. */
7313 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7314 &smb_fname->st);
7315 break;
7316 default:
7317 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7318 SSVAL(pdata,10,0); /* Padding. */
7319 break;
7322 return status;
7325 /****************************************************************************
7326 Open/Create a file with POSIX semantics.
7327 ****************************************************************************/
7329 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7330 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7332 static NTSTATUS smb_posix_open(connection_struct *conn,
7333 struct smb_request *req,
7334 char **ppdata,
7335 int total_data,
7336 struct smb_filename *smb_fname,
7337 int *pdata_return_size)
7339 bool extended_oplock_granted = False;
7340 char *pdata = *ppdata;
7341 uint32 flags = 0;
7342 uint32 wire_open_mode = 0;
7343 uint32 raw_unixmode = 0;
7344 uint32 mod_unixmode = 0;
7345 uint32 create_disp = 0;
7346 uint32 access_mask = 0;
7347 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7348 NTSTATUS status = NT_STATUS_OK;
7349 mode_t unixmode = (mode_t)0;
7350 files_struct *fsp = NULL;
7351 int oplock_request = 0;
7352 int info = 0;
7353 uint16 info_level_return = 0;
7355 if (total_data < 18) {
7356 return NT_STATUS_INVALID_PARAMETER;
7359 flags = IVAL(pdata,0);
7360 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7361 if (oplock_request) {
7362 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7365 wire_open_mode = IVAL(pdata,4);
7367 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7368 return smb_posix_mkdir(conn, req,
7369 ppdata,
7370 total_data,
7371 smb_fname,
7372 pdata_return_size);
7375 switch (wire_open_mode & SMB_ACCMODE) {
7376 case SMB_O_RDONLY:
7377 access_mask = SMB_O_RDONLY_MAPPING;
7378 break;
7379 case SMB_O_WRONLY:
7380 access_mask = SMB_O_WRONLY_MAPPING;
7381 break;
7382 case SMB_O_RDWR:
7383 access_mask = (SMB_O_RDONLY_MAPPING|
7384 SMB_O_WRONLY_MAPPING);
7385 break;
7386 default:
7387 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7388 (unsigned int)wire_open_mode ));
7389 return NT_STATUS_INVALID_PARAMETER;
7392 wire_open_mode &= ~SMB_ACCMODE;
7394 /* First take care of O_CREAT|O_EXCL interactions. */
7395 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7396 case (SMB_O_CREAT | SMB_O_EXCL):
7397 /* File exists fail. File not exist create. */
7398 create_disp = FILE_CREATE;
7399 break;
7400 case SMB_O_CREAT:
7401 /* File exists open. File not exist create. */
7402 create_disp = FILE_OPEN_IF;
7403 break;
7404 case SMB_O_EXCL:
7405 /* O_EXCL on its own without O_CREAT is undefined.
7406 We deliberately ignore it as some versions of
7407 Linux CIFSFS can send a bare O_EXCL on the
7408 wire which other filesystems in the kernel
7409 ignore. See bug 9519 for details. */
7411 /* Fallthrough. */
7413 case 0:
7414 /* File exists open. File not exist fail. */
7415 create_disp = FILE_OPEN;
7416 break;
7417 default:
7418 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7419 (unsigned int)wire_open_mode ));
7420 return NT_STATUS_INVALID_PARAMETER;
7423 /* Next factor in the effects of O_TRUNC. */
7424 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7426 if (wire_open_mode & SMB_O_TRUNC) {
7427 switch (create_disp) {
7428 case FILE_CREATE:
7429 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7430 /* Leave create_disp alone as
7431 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7433 /* File exists fail. File not exist create. */
7434 break;
7435 case FILE_OPEN_IF:
7436 /* SMB_O_CREAT | SMB_O_TRUNC */
7437 /* File exists overwrite. File not exist create. */
7438 create_disp = FILE_OVERWRITE_IF;
7439 break;
7440 case FILE_OPEN:
7441 /* SMB_O_TRUNC */
7442 /* File exists overwrite. File not exist fail. */
7443 create_disp = FILE_OVERWRITE;
7444 break;
7445 default:
7446 /* Cannot get here. */
7447 smb_panic("smb_posix_open: logic error");
7448 return NT_STATUS_INVALID_PARAMETER;
7452 raw_unixmode = IVAL(pdata,8);
7453 /* Next 4 bytes are not yet defined. */
7455 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7456 (VALID_STAT(smb_fname->st) ?
7457 PERM_EXISTING_FILE : PERM_NEW_FILE),
7458 &unixmode);
7460 if (!NT_STATUS_IS_OK(status)) {
7461 return status;
7464 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7466 if (wire_open_mode & SMB_O_SYNC) {
7467 create_options |= FILE_WRITE_THROUGH;
7469 if (wire_open_mode & SMB_O_APPEND) {
7470 access_mask |= FILE_APPEND_DATA;
7472 if (wire_open_mode & SMB_O_DIRECT) {
7473 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7476 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7477 VALID_STAT_OF_DIR(smb_fname->st)) {
7478 if (access_mask != SMB_O_RDONLY_MAPPING) {
7479 return NT_STATUS_FILE_IS_A_DIRECTORY;
7481 create_options &= ~FILE_NON_DIRECTORY_FILE;
7482 create_options |= FILE_DIRECTORY_FILE;
7485 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7486 smb_fname_str_dbg(smb_fname),
7487 (unsigned int)wire_open_mode,
7488 (unsigned int)unixmode ));
7490 status = SMB_VFS_CREATE_FILE(
7491 conn, /* conn */
7492 req, /* req */
7493 0, /* root_dir_fid */
7494 smb_fname, /* fname */
7495 access_mask, /* access_mask */
7496 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7497 FILE_SHARE_DELETE),
7498 create_disp, /* create_disposition*/
7499 create_options, /* create_options */
7500 mod_unixmode, /* file_attributes */
7501 oplock_request, /* oplock_request */
7502 0, /* allocation_size */
7503 0, /* private_flags */
7504 NULL, /* sd */
7505 NULL, /* ea_list */
7506 &fsp, /* result */
7507 &info); /* pinfo */
7509 if (!NT_STATUS_IS_OK(status)) {
7510 return status;
7513 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7514 extended_oplock_granted = True;
7517 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7518 extended_oplock_granted = True;
7521 info_level_return = SVAL(pdata,16);
7523 /* Allocate the correct return size. */
7525 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7526 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7527 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7528 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7529 } else {
7530 *pdata_return_size = 12;
7533 /* Realloc the data size */
7534 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7535 if (*ppdata == NULL) {
7536 close_file(req, fsp, ERROR_CLOSE);
7537 *pdata_return_size = 0;
7538 return NT_STATUS_NO_MEMORY;
7540 pdata = *ppdata;
7542 if (extended_oplock_granted) {
7543 if (flags & REQUEST_BATCH_OPLOCK) {
7544 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7545 } else {
7546 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7548 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7549 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7550 } else {
7551 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7554 SSVAL(pdata,2,fsp->fnum);
7555 SIVAL(pdata,4,info); /* Was file created etc. */
7557 switch (info_level_return) {
7558 case SMB_QUERY_FILE_UNIX_BASIC:
7559 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7560 SSVAL(pdata,10,0); /* padding. */
7561 store_file_unix_basic(conn, pdata + 12, fsp,
7562 &smb_fname->st);
7563 break;
7564 case SMB_QUERY_FILE_UNIX_INFO2:
7565 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7566 SSVAL(pdata,10,0); /* padding. */
7567 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7568 &smb_fname->st);
7569 break;
7570 default:
7571 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7572 SSVAL(pdata,10,0); /* padding. */
7573 break;
7575 return NT_STATUS_OK;
7578 /****************************************************************************
7579 Delete a file with POSIX semantics.
7580 ****************************************************************************/
7582 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7583 struct smb_request *req,
7584 const char *pdata,
7585 int total_data,
7586 struct smb_filename *smb_fname)
7588 NTSTATUS status = NT_STATUS_OK;
7589 files_struct *fsp = NULL;
7590 uint16 flags = 0;
7591 char del = 1;
7592 int info = 0;
7593 int create_options = 0;
7594 int i;
7595 struct share_mode_lock *lck = NULL;
7597 if (total_data < 2) {
7598 return NT_STATUS_INVALID_PARAMETER;
7601 flags = SVAL(pdata,0);
7603 if (!VALID_STAT(smb_fname->st)) {
7604 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7607 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7608 !VALID_STAT_OF_DIR(smb_fname->st)) {
7609 return NT_STATUS_NOT_A_DIRECTORY;
7612 DEBUG(10,("smb_posix_unlink: %s %s\n",
7613 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7614 smb_fname_str_dbg(smb_fname)));
7616 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7617 create_options |= FILE_DIRECTORY_FILE;
7620 status = SMB_VFS_CREATE_FILE(
7621 conn, /* conn */
7622 req, /* req */
7623 0, /* root_dir_fid */
7624 smb_fname, /* fname */
7625 DELETE_ACCESS, /* access_mask */
7626 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7627 FILE_SHARE_DELETE),
7628 FILE_OPEN, /* create_disposition*/
7629 create_options, /* create_options */
7630 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7631 0, /* oplock_request */
7632 0, /* allocation_size */
7633 0, /* private_flags */
7634 NULL, /* sd */
7635 NULL, /* ea_list */
7636 &fsp, /* result */
7637 &info); /* pinfo */
7639 if (!NT_STATUS_IS_OK(status)) {
7640 return status;
7644 * Don't lie to client. If we can't really delete due to
7645 * non-POSIX opens return SHARING_VIOLATION.
7648 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7649 NULL);
7650 if (lck == NULL) {
7651 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7652 "lock for file %s\n", fsp_str_dbg(fsp)));
7653 close_file(req, fsp, NORMAL_CLOSE);
7654 return NT_STATUS_INVALID_PARAMETER;
7658 * See if others still have the file open. If this is the case, then
7659 * don't delete. If all opens are POSIX delete we can set the delete
7660 * on close disposition.
7662 for (i=0; i<lck->num_share_modes; i++) {
7663 struct share_mode_entry *e = &lck->share_modes[i];
7664 if (is_valid_share_mode_entry(e)) {
7665 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7666 continue;
7668 /* Fail with sharing violation. */
7669 TALLOC_FREE(lck);
7670 close_file(req, fsp, NORMAL_CLOSE);
7671 return NT_STATUS_SHARING_VIOLATION;
7676 * Set the delete on close.
7678 status = smb_set_file_disposition_info(conn,
7679 &del,
7681 fsp,
7682 smb_fname);
7684 TALLOC_FREE(lck);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 close_file(req, fsp, NORMAL_CLOSE);
7688 return status;
7690 return close_file(req, fsp, NORMAL_CLOSE);
7693 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7694 struct smb_request *req,
7695 TALLOC_CTX *mem_ctx,
7696 uint16_t info_level,
7697 files_struct *fsp,
7698 struct smb_filename *smb_fname,
7699 char **ppdata, int total_data,
7700 int *ret_data_size)
7702 char *pdata = *ppdata;
7703 NTSTATUS status = NT_STATUS_OK;
7704 int data_return_size = 0;
7706 *ret_data_size = 0;
7708 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7709 return NT_STATUS_INVALID_LEVEL;
7712 if (!CAN_WRITE(conn)) {
7713 /* Allow POSIX opens. The open path will deny
7714 * any non-readonly opens. */
7715 if (info_level != SMB_POSIX_PATH_OPEN) {
7716 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7720 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7721 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7722 fsp ? fsp->fnum : -1, info_level, total_data));
7724 switch (info_level) {
7726 case SMB_INFO_STANDARD:
7728 status = smb_set_info_standard(conn,
7729 pdata,
7730 total_data,
7731 fsp,
7732 smb_fname);
7733 break;
7736 case SMB_INFO_SET_EA:
7738 status = smb_info_set_ea(conn,
7739 pdata,
7740 total_data,
7741 fsp,
7742 smb_fname);
7743 break;
7746 case SMB_SET_FILE_BASIC_INFO:
7747 case SMB_FILE_BASIC_INFORMATION:
7749 status = smb_set_file_basic_info(conn,
7750 pdata,
7751 total_data,
7752 fsp,
7753 smb_fname);
7754 break;
7757 case SMB_FILE_ALLOCATION_INFORMATION:
7758 case SMB_SET_FILE_ALLOCATION_INFO:
7760 status = smb_set_file_allocation_info(conn, req,
7761 pdata,
7762 total_data,
7763 fsp,
7764 smb_fname);
7765 break;
7768 case SMB_FILE_END_OF_FILE_INFORMATION:
7769 case SMB_SET_FILE_END_OF_FILE_INFO:
7772 * XP/Win7 both fail after the createfile with
7773 * SMB_SET_FILE_END_OF_FILE_INFO but not
7774 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7775 * The level is known here, so pass it down
7776 * appropriately.
7778 bool should_fail =
7779 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7781 status = smb_set_file_end_of_file_info(conn, req,
7782 pdata,
7783 total_data,
7784 fsp,
7785 smb_fname,
7786 should_fail);
7787 break;
7790 case SMB_FILE_DISPOSITION_INFORMATION:
7791 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7793 #if 0
7794 /* JRA - We used to just ignore this on a path ?
7795 * Shouldn't this be invalid level on a pathname
7796 * based call ?
7798 if (tran_call != TRANSACT2_SETFILEINFO) {
7799 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7801 #endif
7802 status = smb_set_file_disposition_info(conn,
7803 pdata,
7804 total_data,
7805 fsp,
7806 smb_fname);
7807 break;
7810 case SMB_FILE_POSITION_INFORMATION:
7812 status = smb_file_position_information(conn,
7813 pdata,
7814 total_data,
7815 fsp);
7816 break;
7819 case SMB_FILE_FULL_EA_INFORMATION:
7821 status = smb_set_file_full_ea_info(conn,
7822 pdata,
7823 total_data,
7824 fsp);
7825 break;
7828 /* From tridge Samba4 :
7829 * MODE_INFORMATION in setfileinfo (I have no
7830 * idea what "mode information" on a file is - it takes a value of 0,
7831 * 2, 4 or 6. What could it be?).
7834 case SMB_FILE_MODE_INFORMATION:
7836 status = smb_file_mode_information(conn,
7837 pdata,
7838 total_data);
7839 break;
7843 * CIFS UNIX extensions.
7846 case SMB_SET_FILE_UNIX_BASIC:
7848 status = smb_set_file_unix_basic(conn, req,
7849 pdata,
7850 total_data,
7851 fsp,
7852 smb_fname);
7853 break;
7856 case SMB_SET_FILE_UNIX_INFO2:
7858 status = smb_set_file_unix_info2(conn, req,
7859 pdata,
7860 total_data,
7861 fsp,
7862 smb_fname);
7863 break;
7866 case SMB_SET_FILE_UNIX_LINK:
7868 if (fsp) {
7869 /* We must have a pathname for this. */
7870 return NT_STATUS_INVALID_LEVEL;
7872 status = smb_set_file_unix_link(conn, req, pdata,
7873 total_data, smb_fname);
7874 break;
7877 case SMB_SET_FILE_UNIX_HLINK:
7879 if (fsp) {
7880 /* We must have a pathname for this. */
7881 return NT_STATUS_INVALID_LEVEL;
7883 status = smb_set_file_unix_hlink(conn, req,
7884 pdata, total_data,
7885 smb_fname);
7886 break;
7889 case SMB_FILE_RENAME_INFORMATION:
7891 status = smb_file_rename_information(conn, req,
7892 pdata, total_data,
7893 fsp, smb_fname);
7894 break;
7897 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7899 /* SMB2 rename information. */
7900 status = smb2_file_rename_information(conn, req,
7901 pdata, total_data,
7902 fsp, smb_fname);
7903 break;
7906 case SMB_FILE_LINK_INFORMATION:
7908 status = smb_file_link_information(conn, req,
7909 pdata, total_data,
7910 fsp, smb_fname);
7911 break;
7914 #if defined(HAVE_POSIX_ACLS)
7915 case SMB_SET_POSIX_ACL:
7917 status = smb_set_posix_acl(conn,
7918 pdata,
7919 total_data,
7920 fsp,
7921 smb_fname);
7922 break;
7924 #endif
7926 case SMB_SET_POSIX_LOCK:
7928 if (!fsp) {
7929 return NT_STATUS_INVALID_LEVEL;
7931 status = smb_set_posix_lock(conn, req,
7932 pdata, total_data, fsp);
7933 break;
7936 case SMB_POSIX_PATH_OPEN:
7938 if (fsp) {
7939 /* We must have a pathname for this. */
7940 return NT_STATUS_INVALID_LEVEL;
7943 status = smb_posix_open(conn, req,
7944 ppdata,
7945 total_data,
7946 smb_fname,
7947 &data_return_size);
7948 break;
7951 case SMB_POSIX_PATH_UNLINK:
7953 if (fsp) {
7954 /* We must have a pathname for this. */
7955 return NT_STATUS_INVALID_LEVEL;
7958 status = smb_posix_unlink(conn, req,
7959 pdata,
7960 total_data,
7961 smb_fname);
7962 break;
7965 default:
7966 return NT_STATUS_INVALID_LEVEL;
7969 if (!NT_STATUS_IS_OK(status)) {
7970 return status;
7973 *ret_data_size = data_return_size;
7974 return NT_STATUS_OK;
7977 /****************************************************************************
7978 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7979 ****************************************************************************/
7981 static void call_trans2setfilepathinfo(connection_struct *conn,
7982 struct smb_request *req,
7983 unsigned int tran_call,
7984 char **pparams, int total_params,
7985 char **ppdata, int total_data,
7986 unsigned int max_data_bytes)
7988 char *params = *pparams;
7989 char *pdata = *ppdata;
7990 uint16 info_level;
7991 struct smb_filename *smb_fname = NULL;
7992 files_struct *fsp = NULL;
7993 NTSTATUS status = NT_STATUS_OK;
7994 int data_return_size = 0;
7996 if (!params) {
7997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7998 return;
8001 if (tran_call == TRANSACT2_SETFILEINFO) {
8002 if (total_params < 4) {
8003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8004 return;
8007 fsp = file_fsp(req, SVAL(params,0));
8008 /* Basic check for non-null fsp. */
8009 if (!check_fsp_open(conn, req, fsp)) {
8010 return;
8012 info_level = SVAL(params,2);
8014 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8015 &smb_fname);
8016 if (!NT_STATUS_IS_OK(status)) {
8017 reply_nterror(req, status);
8018 return;
8021 if(fsp->fh->fd == -1) {
8023 * This is actually a SETFILEINFO on a directory
8024 * handle (returned from an NT SMB). NT5.0 seems
8025 * to do this call. JRA.
8027 if (INFO_LEVEL_IS_UNIX(info_level)) {
8028 /* Always do lstat for UNIX calls. */
8029 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8030 DEBUG(3,("call_trans2setfilepathinfo: "
8031 "SMB_VFS_LSTAT of %s failed "
8032 "(%s)\n",
8033 smb_fname_str_dbg(smb_fname),
8034 strerror(errno)));
8035 reply_nterror(req, map_nt_error_from_unix(errno));
8036 return;
8038 } else {
8039 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8040 DEBUG(3,("call_trans2setfilepathinfo: "
8041 "fileinfo of %s failed (%s)\n",
8042 smb_fname_str_dbg(smb_fname),
8043 strerror(errno)));
8044 reply_nterror(req, map_nt_error_from_unix(errno));
8045 return;
8048 } else if (fsp->print_file) {
8050 * Doing a DELETE_ON_CLOSE should cancel a print job.
8052 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8053 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8055 DEBUG(3,("call_trans2setfilepathinfo: "
8056 "Cancelling print job (%s)\n",
8057 fsp_str_dbg(fsp)));
8059 SSVAL(params,0,0);
8060 send_trans2_replies(conn, req, params, 2,
8061 *ppdata, 0,
8062 max_data_bytes);
8063 return;
8064 } else {
8065 reply_nterror(req,
8066 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8067 return;
8069 } else {
8071 * Original code - this is an open file.
8073 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8074 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8075 "of fnum %d failed (%s)\n", fsp->fnum,
8076 strerror(errno)));
8077 reply_nterror(req, map_nt_error_from_unix(errno));
8078 return;
8081 } else {
8082 char *fname = NULL;
8083 uint32_t ucf_flags = 0;
8085 /* set path info */
8086 if (total_params < 7) {
8087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8088 return;
8091 info_level = SVAL(params,0);
8092 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8093 total_params - 6, STR_TERMINATE,
8094 &status);
8095 if (!NT_STATUS_IS_OK(status)) {
8096 reply_nterror(req, status);
8097 return;
8100 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8101 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8102 info_level == SMB_FILE_RENAME_INFORMATION ||
8103 info_level == SMB_POSIX_PATH_UNLINK) {
8104 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8107 status = filename_convert(req, conn,
8108 req->flags2 & FLAGS2_DFS_PATHNAMES,
8109 fname,
8110 ucf_flags,
8111 NULL,
8112 &smb_fname);
8113 if (!NT_STATUS_IS_OK(status)) {
8114 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8115 reply_botherror(req,
8116 NT_STATUS_PATH_NOT_COVERED,
8117 ERRSRV, ERRbadpath);
8118 return;
8120 reply_nterror(req, status);
8121 return;
8124 if (INFO_LEVEL_IS_UNIX(info_level)) {
8126 * For CIFS UNIX extensions the target name may not exist.
8129 /* Always do lstat for UNIX calls. */
8130 SMB_VFS_LSTAT(conn, smb_fname);
8132 } else if (!VALID_STAT(smb_fname->st) &&
8133 SMB_VFS_STAT(conn, smb_fname)) {
8134 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8135 "%s failed (%s)\n",
8136 smb_fname_str_dbg(smb_fname),
8137 strerror(errno)));
8138 reply_nterror(req, map_nt_error_from_unix(errno));
8139 return;
8143 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8144 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8145 fsp ? fsp->fnum : -1, info_level,total_data));
8147 /* Realloc the parameter size */
8148 *pparams = (char *)SMB_REALLOC(*pparams,2);
8149 if (*pparams == NULL) {
8150 reply_nterror(req, NT_STATUS_NO_MEMORY);
8151 return;
8153 params = *pparams;
8155 SSVAL(params,0,0);
8157 status = smbd_do_setfilepathinfo(conn, req, req,
8158 info_level,
8159 fsp,
8160 smb_fname,
8161 ppdata, total_data,
8162 &data_return_size);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 if (open_was_deferred(req->mid)) {
8165 /* We have re-scheduled this call. */
8166 return;
8168 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8169 /* We have re-scheduled this call. */
8170 return;
8172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8173 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8174 ERRSRV, ERRbadpath);
8175 return;
8177 if (info_level == SMB_POSIX_PATH_OPEN) {
8178 reply_openerror(req, status);
8179 return;
8182 reply_nterror(req, status);
8183 return;
8186 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8187 max_data_bytes);
8189 return;
8192 /****************************************************************************
8193 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8194 ****************************************************************************/
8196 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8197 char **pparams, int total_params,
8198 char **ppdata, int total_data,
8199 unsigned int max_data_bytes)
8201 struct smb_filename *smb_dname = NULL;
8202 char *params = *pparams;
8203 char *pdata = *ppdata;
8204 char *directory = NULL;
8205 NTSTATUS status = NT_STATUS_OK;
8206 struct ea_list *ea_list = NULL;
8207 TALLOC_CTX *ctx = talloc_tos();
8209 if (!CAN_WRITE(conn)) {
8210 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8211 return;
8214 if (total_params < 5) {
8215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8216 return;
8219 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8220 total_params - 4, STR_TERMINATE,
8221 &status);
8222 if (!NT_STATUS_IS_OK(status)) {
8223 reply_nterror(req, status);
8224 return;
8227 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8229 status = filename_convert(ctx,
8230 conn,
8231 req->flags2 & FLAGS2_DFS_PATHNAMES,
8232 directory,
8234 NULL,
8235 &smb_dname);
8237 if (!NT_STATUS_IS_OK(status)) {
8238 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8239 reply_botherror(req,
8240 NT_STATUS_PATH_NOT_COVERED,
8241 ERRSRV, ERRbadpath);
8242 return;
8244 reply_nterror(req, status);
8245 return;
8249 * OS/2 workplace shell seems to send SET_EA requests of "null"
8250 * length (4 bytes containing IVAL 4).
8251 * They seem to have no effect. Bug #3212. JRA.
8254 if (total_data && (total_data != 4)) {
8255 /* Any data in this call is an EA list. */
8256 if (total_data < 10) {
8257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8258 goto out;
8261 if (IVAL(pdata,0) > total_data) {
8262 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8263 IVAL(pdata,0), (unsigned int)total_data));
8264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8265 goto out;
8268 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8269 total_data - 4);
8270 if (!ea_list) {
8271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8272 goto out;
8275 if (!lp_ea_support(SNUM(conn))) {
8276 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8277 goto out;
8280 /* If total_data == 4 Windows doesn't care what values
8281 * are placed in that field, it just ignores them.
8282 * The System i QNTC IBM SMB client puts bad values here,
8283 * so ignore them. */
8285 status = create_directory(conn, req, smb_dname);
8287 if (!NT_STATUS_IS_OK(status)) {
8288 reply_nterror(req, status);
8289 goto out;
8292 /* Try and set any given EA. */
8293 if (ea_list) {
8294 status = set_ea(conn, NULL, smb_dname, ea_list);
8295 if (!NT_STATUS_IS_OK(status)) {
8296 reply_nterror(req, status);
8297 goto out;
8301 /* Realloc the parameter and data sizes */
8302 *pparams = (char *)SMB_REALLOC(*pparams,2);
8303 if(*pparams == NULL) {
8304 reply_nterror(req, NT_STATUS_NO_MEMORY);
8305 goto out;
8307 params = *pparams;
8309 SSVAL(params,0,0);
8311 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8313 out:
8314 TALLOC_FREE(smb_dname);
8315 return;
8318 /****************************************************************************
8319 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8320 We don't actually do this - we just send a null response.
8321 ****************************************************************************/
8323 static void call_trans2findnotifyfirst(connection_struct *conn,
8324 struct smb_request *req,
8325 char **pparams, int total_params,
8326 char **ppdata, int total_data,
8327 unsigned int max_data_bytes)
8329 char *params = *pparams;
8330 uint16 info_level;
8332 if (total_params < 6) {
8333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8334 return;
8337 info_level = SVAL(params,4);
8338 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8340 switch (info_level) {
8341 case 1:
8342 case 2:
8343 break;
8344 default:
8345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8346 return;
8349 /* Realloc the parameter and data sizes */
8350 *pparams = (char *)SMB_REALLOC(*pparams,6);
8351 if (*pparams == NULL) {
8352 reply_nterror(req, NT_STATUS_NO_MEMORY);
8353 return;
8355 params = *pparams;
8357 SSVAL(params,0,fnf_handle);
8358 SSVAL(params,2,0); /* No changes */
8359 SSVAL(params,4,0); /* No EA errors */
8361 fnf_handle++;
8363 if(fnf_handle == 0)
8364 fnf_handle = 257;
8366 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8368 return;
8371 /****************************************************************************
8372 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8373 changes). Currently this does nothing.
8374 ****************************************************************************/
8376 static void call_trans2findnotifynext(connection_struct *conn,
8377 struct smb_request *req,
8378 char **pparams, int total_params,
8379 char **ppdata, int total_data,
8380 unsigned int max_data_bytes)
8382 char *params = *pparams;
8384 DEBUG(3,("call_trans2findnotifynext\n"));
8386 /* Realloc the parameter and data sizes */
8387 *pparams = (char *)SMB_REALLOC(*pparams,4);
8388 if (*pparams == NULL) {
8389 reply_nterror(req, NT_STATUS_NO_MEMORY);
8390 return;
8392 params = *pparams;
8394 SSVAL(params,0,0); /* No changes */
8395 SSVAL(params,2,0); /* No EA errors */
8397 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8399 return;
8402 /****************************************************************************
8403 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8404 ****************************************************************************/
8406 static void call_trans2getdfsreferral(connection_struct *conn,
8407 struct smb_request *req,
8408 char **pparams, int total_params,
8409 char **ppdata, int total_data,
8410 unsigned int max_data_bytes)
8412 char *params = *pparams;
8413 char *pathname = NULL;
8414 int reply_size = 0;
8415 int max_referral_level;
8416 NTSTATUS status = NT_STATUS_OK;
8417 TALLOC_CTX *ctx = talloc_tos();
8419 DEBUG(10,("call_trans2getdfsreferral\n"));
8421 if (total_params < 3) {
8422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8423 return;
8426 max_referral_level = SVAL(params,0);
8428 if(!lp_host_msdfs()) {
8429 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8430 return;
8433 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8434 total_params - 2, STR_TERMINATE);
8435 if (!pathname) {
8436 reply_nterror(req, NT_STATUS_NOT_FOUND);
8437 return;
8439 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8440 ppdata,&status)) < 0) {
8441 reply_nterror(req, status);
8442 return;
8445 SSVAL(req->inbuf, smb_flg2,
8446 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8447 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8449 return;
8452 #define LMCAT_SPL 0x53
8453 #define LMFUNC_GETJOBID 0x60
8455 /****************************************************************************
8456 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8457 ****************************************************************************/
8459 static void call_trans2ioctl(connection_struct *conn,
8460 struct smb_request *req,
8461 char **pparams, int total_params,
8462 char **ppdata, int total_data,
8463 unsigned int max_data_bytes)
8465 char *pdata = *ppdata;
8466 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8468 /* check for an invalid fid before proceeding */
8470 if (!fsp) {
8471 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8472 return;
8475 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8476 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8477 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8478 if (*ppdata == NULL) {
8479 reply_nterror(req, NT_STATUS_NO_MEMORY);
8480 return;
8482 pdata = *ppdata;
8484 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8485 CAN ACCEPT THIS IN UNICODE. JRA. */
8487 /* Job number */
8488 if (fsp->print_file) {
8489 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8490 } else {
8491 SSVAL(pdata, 0, 0);
8493 srvstr_push(pdata, req->flags2, pdata + 2,
8494 global_myname(), 15,
8495 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8496 srvstr_push(pdata, req->flags2, pdata+18,
8497 lp_servicename(SNUM(conn)), 13,
8498 STR_ASCII|STR_TERMINATE); /* Service name */
8499 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8500 max_data_bytes);
8501 return;
8504 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8505 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8508 /****************************************************************************
8509 Reply to a SMBfindclose (stop trans2 directory search).
8510 ****************************************************************************/
8512 void reply_findclose(struct smb_request *req)
8514 int dptr_num;
8515 struct smbd_server_connection *sconn = req->sconn;
8517 START_PROFILE(SMBfindclose);
8519 if (req->wct < 1) {
8520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8521 END_PROFILE(SMBfindclose);
8522 return;
8525 dptr_num = SVALS(req->vwv+0, 0);
8527 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8529 dptr_close(sconn, &dptr_num);
8531 reply_outbuf(req, 0, 0);
8533 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8535 END_PROFILE(SMBfindclose);
8536 return;
8539 /****************************************************************************
8540 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8541 ****************************************************************************/
8543 void reply_findnclose(struct smb_request *req)
8545 int dptr_num;
8547 START_PROFILE(SMBfindnclose);
8549 if (req->wct < 1) {
8550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8551 END_PROFILE(SMBfindnclose);
8552 return;
8555 dptr_num = SVAL(req->vwv+0, 0);
8557 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8559 /* We never give out valid handles for a
8560 findnotifyfirst - so any dptr_num is ok here.
8561 Just ignore it. */
8563 reply_outbuf(req, 0, 0);
8565 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8567 END_PROFILE(SMBfindnclose);
8568 return;
8571 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8572 struct trans_state *state)
8574 if (get_Protocol() >= PROTOCOL_NT1) {
8575 req->flags2 |= 0x40; /* IS_LONG_NAME */
8576 SSVAL(req->inbuf,smb_flg2,req->flags2);
8579 if (conn->encrypt_level == Required && !req->encrypted) {
8580 if (state->call != TRANSACT2_QFSINFO &&
8581 state->call != TRANSACT2_SETFSINFO) {
8582 DEBUG(0,("handle_trans2: encryption required "
8583 "with call 0x%x\n",
8584 (unsigned int)state->call));
8585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8586 return;
8590 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8592 /* Now we must call the relevant TRANS2 function */
8593 switch(state->call) {
8594 case TRANSACT2_OPEN:
8596 START_PROFILE(Trans2_open);
8597 call_trans2open(conn, req,
8598 &state->param, state->total_param,
8599 &state->data, state->total_data,
8600 state->max_data_return);
8601 END_PROFILE(Trans2_open);
8602 break;
8605 case TRANSACT2_FINDFIRST:
8607 START_PROFILE(Trans2_findfirst);
8608 call_trans2findfirst(conn, req,
8609 &state->param, state->total_param,
8610 &state->data, state->total_data,
8611 state->max_data_return);
8612 END_PROFILE(Trans2_findfirst);
8613 break;
8616 case TRANSACT2_FINDNEXT:
8618 START_PROFILE(Trans2_findnext);
8619 call_trans2findnext(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_findnext);
8624 break;
8627 case TRANSACT2_QFSINFO:
8629 START_PROFILE(Trans2_qfsinfo);
8630 call_trans2qfsinfo(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_qfsinfo);
8635 break;
8638 case TRANSACT2_SETFSINFO:
8640 START_PROFILE(Trans2_setfsinfo);
8641 call_trans2setfsinfo(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_setfsinfo);
8646 break;
8649 case TRANSACT2_QPATHINFO:
8650 case TRANSACT2_QFILEINFO:
8652 START_PROFILE(Trans2_qpathinfo);
8653 call_trans2qfilepathinfo(conn, req, state->call,
8654 &state->param, state->total_param,
8655 &state->data, state->total_data,
8656 state->max_data_return);
8657 END_PROFILE(Trans2_qpathinfo);
8658 break;
8661 case TRANSACT2_SETPATHINFO:
8662 case TRANSACT2_SETFILEINFO:
8664 START_PROFILE(Trans2_setpathinfo);
8665 call_trans2setfilepathinfo(conn, req, state->call,
8666 &state->param, state->total_param,
8667 &state->data, state->total_data,
8668 state->max_data_return);
8669 END_PROFILE(Trans2_setpathinfo);
8670 break;
8673 case TRANSACT2_FINDNOTIFYFIRST:
8675 START_PROFILE(Trans2_findnotifyfirst);
8676 call_trans2findnotifyfirst(conn, req,
8677 &state->param, state->total_param,
8678 &state->data, state->total_data,
8679 state->max_data_return);
8680 END_PROFILE(Trans2_findnotifyfirst);
8681 break;
8684 case TRANSACT2_FINDNOTIFYNEXT:
8686 START_PROFILE(Trans2_findnotifynext);
8687 call_trans2findnotifynext(conn, req,
8688 &state->param, state->total_param,
8689 &state->data, state->total_data,
8690 state->max_data_return);
8691 END_PROFILE(Trans2_findnotifynext);
8692 break;
8695 case TRANSACT2_MKDIR:
8697 START_PROFILE(Trans2_mkdir);
8698 call_trans2mkdir(conn, req,
8699 &state->param, state->total_param,
8700 &state->data, state->total_data,
8701 state->max_data_return);
8702 END_PROFILE(Trans2_mkdir);
8703 break;
8706 case TRANSACT2_GET_DFS_REFERRAL:
8708 START_PROFILE(Trans2_get_dfs_referral);
8709 call_trans2getdfsreferral(conn, req,
8710 &state->param, state->total_param,
8711 &state->data, state->total_data,
8712 state->max_data_return);
8713 END_PROFILE(Trans2_get_dfs_referral);
8714 break;
8717 case TRANSACT2_IOCTL:
8719 START_PROFILE(Trans2_ioctl);
8720 call_trans2ioctl(conn, req,
8721 &state->param, state->total_param,
8722 &state->data, state->total_data,
8723 state->max_data_return);
8724 END_PROFILE(Trans2_ioctl);
8725 break;
8728 default:
8729 /* Error in request */
8730 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8731 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8735 /****************************************************************************
8736 Reply to a SMBtrans2.
8737 ****************************************************************************/
8739 void reply_trans2(struct smb_request *req)
8741 connection_struct *conn = req->conn;
8742 unsigned int dsoff;
8743 unsigned int dscnt;
8744 unsigned int psoff;
8745 unsigned int pscnt;
8746 unsigned int tran_call;
8747 struct trans_state *state;
8748 NTSTATUS result;
8750 START_PROFILE(SMBtrans2);
8752 if (req->wct < 14) {
8753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8754 END_PROFILE(SMBtrans2);
8755 return;
8758 dsoff = SVAL(req->vwv+12, 0);
8759 dscnt = SVAL(req->vwv+11, 0);
8760 psoff = SVAL(req->vwv+10, 0);
8761 pscnt = SVAL(req->vwv+9, 0);
8762 tran_call = SVAL(req->vwv+14, 0);
8764 result = allow_new_trans(conn->pending_trans, req->mid);
8765 if (!NT_STATUS_IS_OK(result)) {
8766 DEBUG(2, ("Got invalid trans2 request: %s\n",
8767 nt_errstr(result)));
8768 reply_nterror(req, result);
8769 END_PROFILE(SMBtrans2);
8770 return;
8773 if (IS_IPC(conn)) {
8774 switch (tran_call) {
8775 /* List the allowed trans2 calls on IPC$ */
8776 case TRANSACT2_OPEN:
8777 case TRANSACT2_GET_DFS_REFERRAL:
8778 case TRANSACT2_QFILEINFO:
8779 case TRANSACT2_QFSINFO:
8780 case TRANSACT2_SETFSINFO:
8781 break;
8782 default:
8783 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8784 END_PROFILE(SMBtrans2);
8785 return;
8789 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8790 DEBUG(0, ("talloc failed\n"));
8791 reply_nterror(req, NT_STATUS_NO_MEMORY);
8792 END_PROFILE(SMBtrans2);
8793 return;
8796 state->cmd = SMBtrans2;
8798 state->mid = req->mid;
8799 state->vuid = req->vuid;
8800 state->setup_count = SVAL(req->vwv+13, 0);
8801 state->setup = NULL;
8802 state->total_param = SVAL(req->vwv+0, 0);
8803 state->param = NULL;
8804 state->total_data = SVAL(req->vwv+1, 0);
8805 state->data = NULL;
8806 state->max_param_return = SVAL(req->vwv+2, 0);
8807 state->max_data_return = SVAL(req->vwv+3, 0);
8808 state->max_setup_return = SVAL(req->vwv+4, 0);
8809 state->close_on_completion = BITSETW(req->vwv+5, 0);
8810 state->one_way = BITSETW(req->vwv+5, 1);
8812 state->call = tran_call;
8814 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8815 is so as a sanity check */
8816 if (state->setup_count != 1) {
8818 * Need to have rc=0 for ioctl to get job id for OS/2.
8819 * Network printing will fail if function is not successful.
8820 * Similar function in reply.c will be used if protocol
8821 * is LANMAN1.0 instead of LM1.2X002.
8822 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8823 * outbuf doesn't have to be set(only job id is used).
8825 if ( (state->setup_count == 4)
8826 && (tran_call == TRANSACT2_IOCTL)
8827 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8828 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8829 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8830 } else {
8831 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8832 DEBUG(2,("Transaction is %d\n",tran_call));
8833 TALLOC_FREE(state);
8834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8835 END_PROFILE(SMBtrans2);
8836 return;
8840 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8841 goto bad_param;
8843 if (state->total_data) {
8845 if (trans_oob(state->total_data, 0, dscnt)
8846 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8847 goto bad_param;
8850 /* Can't use talloc here, the core routines do realloc on the
8851 * params and data. */
8852 state->data = (char *)SMB_MALLOC(state->total_data);
8853 if (state->data == NULL) {
8854 DEBUG(0,("reply_trans2: data malloc fail for %u "
8855 "bytes !\n", (unsigned int)state->total_data));
8856 TALLOC_FREE(state);
8857 reply_nterror(req, NT_STATUS_NO_MEMORY);
8858 END_PROFILE(SMBtrans2);
8859 return;
8862 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8865 if (state->total_param) {
8867 if (trans_oob(state->total_param, 0, pscnt)
8868 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8869 goto bad_param;
8872 /* Can't use talloc here, the core routines do realloc on the
8873 * params and data. */
8874 state->param = (char *)SMB_MALLOC(state->total_param);
8875 if (state->param == NULL) {
8876 DEBUG(0,("reply_trans: param malloc fail for %u "
8877 "bytes !\n", (unsigned int)state->total_param));
8878 SAFE_FREE(state->data);
8879 TALLOC_FREE(state);
8880 reply_nterror(req, NT_STATUS_NO_MEMORY);
8881 END_PROFILE(SMBtrans2);
8882 return;
8885 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8888 state->received_data = dscnt;
8889 state->received_param = pscnt;
8891 if ((state->received_param == state->total_param) &&
8892 (state->received_data == state->total_data)) {
8894 handle_trans2(conn, req, state);
8896 SAFE_FREE(state->data);
8897 SAFE_FREE(state->param);
8898 TALLOC_FREE(state);
8899 END_PROFILE(SMBtrans2);
8900 return;
8903 DLIST_ADD(conn->pending_trans, state);
8905 /* We need to send an interim response then receive the rest
8906 of the parameter/data bytes */
8907 reply_outbuf(req, 0, 0);
8908 show_msg((char *)req->outbuf);
8909 END_PROFILE(SMBtrans2);
8910 return;
8912 bad_param:
8914 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8915 SAFE_FREE(state->data);
8916 SAFE_FREE(state->param);
8917 TALLOC_FREE(state);
8918 END_PROFILE(SMBtrans2);
8919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8923 /****************************************************************************
8924 Reply to a SMBtranss2
8925 ****************************************************************************/
8927 void reply_transs2(struct smb_request *req)
8929 connection_struct *conn = req->conn;
8930 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8931 struct trans_state *state;
8933 START_PROFILE(SMBtranss2);
8935 show_msg((char *)req->inbuf);
8937 /* Windows clients expect all replies to
8938 a transact secondary (SMBtranss2 0x33)
8939 to have a command code of transact
8940 (SMBtrans2 0x32). See bug #8989
8941 and also [MS-CIFS] section 2.2.4.47.2
8942 for details.
8944 req->cmd = SMBtrans2;
8946 if (req->wct < 8) {
8947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8948 END_PROFILE(SMBtranss2);
8949 return;
8952 for (state = conn->pending_trans; state != NULL;
8953 state = state->next) {
8954 if (state->mid == req->mid) {
8955 break;
8959 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8961 END_PROFILE(SMBtranss2);
8962 return;
8965 /* Revise state->total_param and state->total_data in case they have
8966 changed downwards */
8968 if (SVAL(req->vwv+0, 0) < state->total_param)
8969 state->total_param = SVAL(req->vwv+0, 0);
8970 if (SVAL(req->vwv+1, 0) < state->total_data)
8971 state->total_data = SVAL(req->vwv+1, 0);
8973 pcnt = SVAL(req->vwv+2, 0);
8974 poff = SVAL(req->vwv+3, 0);
8975 pdisp = SVAL(req->vwv+4, 0);
8977 dcnt = SVAL(req->vwv+5, 0);
8978 doff = SVAL(req->vwv+6, 0);
8979 ddisp = SVAL(req->vwv+7, 0);
8981 state->received_param += pcnt;
8982 state->received_data += dcnt;
8984 if ((state->received_data > state->total_data) ||
8985 (state->received_param > state->total_param))
8986 goto bad_param;
8988 if (pcnt) {
8989 if (trans_oob(state->total_param, pdisp, pcnt)
8990 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8991 goto bad_param;
8993 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8996 if (dcnt) {
8997 if (trans_oob(state->total_data, ddisp, dcnt)
8998 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8999 goto bad_param;
9001 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9004 if ((state->received_param < state->total_param) ||
9005 (state->received_data < state->total_data)) {
9006 END_PROFILE(SMBtranss2);
9007 return;
9010 handle_trans2(conn, req, state);
9012 DLIST_REMOVE(conn->pending_trans, state);
9013 SAFE_FREE(state->data);
9014 SAFE_FREE(state->param);
9015 TALLOC_FREE(state);
9017 END_PROFILE(SMBtranss2);
9018 return;
9020 bad_param:
9022 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9023 DLIST_REMOVE(conn->pending_trans, state);
9024 SAFE_FREE(state->data);
9025 SAFE_FREE(state->param);
9026 TALLOC_FREE(state);
9027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9028 END_PROFILE(SMBtranss2);
9029 return;