s3:smbd: allow info class SMB_QUERY_FS_VOLUME_INFO to return partial data
[Samba.git] / source3 / smbd / trans2.c
blob575f96e816dbe5a96e4567e8bc0d9f94c280e318
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 break;
3120 case SMB_QUERY_FS_LABEL_INFO:
3121 case SMB_FS_LABEL_INFORMATION:
3122 len = srvstr_push(pdata, flags2, pdata+4, vname,
3123 PTR_DIFF(end_data, pdata+4), 0);
3124 data_len = 4 + len;
3125 SIVAL(pdata,0,len);
3126 break;
3128 case SMB_QUERY_FS_VOLUME_INFO:
3129 case SMB_FS_VOLUME_INFORMATION:
3132 * Add volume serial number - hash of a combination of
3133 * the called hostname and the service name.
3135 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3136 (str_checksum(get_local_machine_name())<<16));
3138 /* Max label len is 32 characters. */
3139 len = srvstr_push(pdata, flags2, pdata+18, vname,
3140 PTR_DIFF(end_data, pdata+18),
3141 STR_UNICODE);
3142 SIVAL(pdata,12,len);
3143 data_len = 18+len;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3146 (int)strlen(vname),vname, lp_servicename(snum)));
3147 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3148 /* the client only requested a portion of the
3149 volume label */
3150 data_len = max_data_bytes;
3151 status = STATUS_BUFFER_OVERFLOW;
3154 break;
3156 case SMB_QUERY_FS_SIZE_INFO:
3157 case SMB_FS_SIZE_INFORMATION:
3159 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3160 data_len = 24;
3161 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3162 return map_nt_error_from_unix(errno);
3164 block_size = lp_block_size(snum);
3165 if (bsize < block_size) {
3166 uint64_t factor = block_size/bsize;
3167 bsize = block_size;
3168 dsize /= factor;
3169 dfree /= factor;
3171 if (bsize > block_size) {
3172 uint64_t factor = bsize/block_size;
3173 bsize = block_size;
3174 dsize *= factor;
3175 dfree *= factor;
3177 bytes_per_sector = 512;
3178 sectors_per_unit = bsize/bytes_per_sector;
3179 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3180 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3181 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3182 SBIG_UINT(pdata,0,dsize);
3183 SBIG_UINT(pdata,8,dfree);
3184 SIVAL(pdata,16,sectors_per_unit);
3185 SIVAL(pdata,20,bytes_per_sector);
3186 break;
3189 case SMB_FS_FULL_SIZE_INFORMATION:
3191 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3192 data_len = 32;
3193 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3194 return map_nt_error_from_unix(errno);
3196 block_size = lp_block_size(snum);
3197 if (bsize < block_size) {
3198 uint64_t factor = block_size/bsize;
3199 bsize = block_size;
3200 dsize /= factor;
3201 dfree /= factor;
3203 if (bsize > block_size) {
3204 uint64_t factor = bsize/block_size;
3205 bsize = block_size;
3206 dsize *= factor;
3207 dfree *= factor;
3209 bytes_per_sector = 512;
3210 sectors_per_unit = bsize/bytes_per_sector;
3211 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3212 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3213 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3214 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3215 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3216 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3217 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3218 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3219 break;
3222 case SMB_QUERY_FS_DEVICE_INFO:
3223 case SMB_FS_DEVICE_INFORMATION:
3225 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3227 if (!CAN_WRITE(conn)) {
3228 characteristics |= FILE_READ_ONLY_DEVICE;
3230 data_len = 8;
3231 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3232 SIVAL(pdata,4,characteristics);
3233 break;
3236 #ifdef HAVE_SYS_QUOTAS
3237 case SMB_FS_QUOTA_INFORMATION:
3239 * what we have to send --metze:
3241 * Unknown1: 24 NULL bytes
3242 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3243 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3244 * Quota Flags: 2 byte :
3245 * Unknown3: 6 NULL bytes
3247 * 48 bytes total
3249 * details for Quota Flags:
3251 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3252 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3253 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3254 * 0x0001 Enable Quotas: enable quota for this fs
3258 /* we need to fake up a fsp here,
3259 * because its not send in this call
3261 files_struct fsp;
3262 SMB_NTQUOTA_STRUCT quotas;
3264 ZERO_STRUCT(fsp);
3265 ZERO_STRUCT(quotas);
3267 fsp.conn = conn;
3268 fsp.fnum = -1;
3270 /* access check */
3271 if (get_current_uid(conn) != 0) {
3272 DEBUG(0,("set_user_quota: access_denied "
3273 "service [%s] user [%s]\n",
3274 lp_servicename(SNUM(conn)),
3275 conn->session_info->unix_name));
3276 return NT_STATUS_ACCESS_DENIED;
3279 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3280 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3281 return map_nt_error_from_unix(errno);
3284 data_len = 48;
3286 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3287 lp_servicename(SNUM(conn))));
3289 /* Unknown1 24 NULL bytes*/
3290 SBIG_UINT(pdata,0,(uint64_t)0);
3291 SBIG_UINT(pdata,8,(uint64_t)0);
3292 SBIG_UINT(pdata,16,(uint64_t)0);
3294 /* Default Soft Quota 8 bytes */
3295 SBIG_UINT(pdata,24,quotas.softlim);
3297 /* Default Hard Quota 8 bytes */
3298 SBIG_UINT(pdata,32,quotas.hardlim);
3300 /* Quota flag 2 bytes */
3301 SSVAL(pdata,40,quotas.qflags);
3303 /* Unknown3 6 NULL bytes */
3304 SSVAL(pdata,42,0);
3305 SIVAL(pdata,44,0);
3307 break;
3309 #endif /* HAVE_SYS_QUOTAS */
3310 case SMB_FS_OBJECTID_INFORMATION:
3312 unsigned char objid[16];
3313 struct smb_extended_info extended_info;
3314 memcpy(pdata,create_volume_objectid(conn, objid),16);
3315 samba_extended_info_version (&extended_info);
3316 SIVAL(pdata,16,extended_info.samba_magic);
3317 SIVAL(pdata,20,extended_info.samba_version);
3318 SIVAL(pdata,24,extended_info.samba_subversion);
3319 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3320 memcpy(pdata+36,extended_info.samba_version_string,28);
3321 data_len = 64;
3322 break;
3326 * Query the version and capabilities of the CIFS UNIX extensions
3327 * in use.
3330 case SMB_QUERY_CIFS_UNIX_INFO:
3332 bool large_write = lp_min_receive_file_size() &&
3333 !srv_is_signing_active(conn->sconn);
3334 bool large_read = !srv_is_signing_active(conn->sconn);
3335 int encrypt_caps = 0;
3337 if (!lp_unix_extensions()) {
3338 return NT_STATUS_INVALID_LEVEL;
3341 switch (conn->encrypt_level) {
3342 case 0:
3343 encrypt_caps = 0;
3344 break;
3345 case 1:
3346 case Auto:
3347 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3348 break;
3349 case Required:
3350 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3351 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3352 large_write = false;
3353 large_read = false;
3354 break;
3357 data_len = 12;
3358 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3359 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3361 /* We have POSIX ACLs, pathname, encryption,
3362 * large read/write, and locking capability. */
3364 SBIG_UINT(pdata,4,((uint64_t)(
3365 CIFS_UNIX_POSIX_ACLS_CAP|
3366 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3367 CIFS_UNIX_FCNTL_LOCKS_CAP|
3368 CIFS_UNIX_EXTATTR_CAP|
3369 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3370 encrypt_caps|
3371 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3372 (large_write ?
3373 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3374 break;
3377 case SMB_QUERY_POSIX_FS_INFO:
3379 int rc;
3380 vfs_statvfs_struct svfs;
3382 if (!lp_unix_extensions()) {
3383 return NT_STATUS_INVALID_LEVEL;
3386 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3388 if (!rc) {
3389 data_len = 56;
3390 SIVAL(pdata,0,svfs.OptimalTransferSize);
3391 SIVAL(pdata,4,svfs.BlockSize);
3392 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3393 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3394 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3395 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3396 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3397 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3398 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3399 #ifdef EOPNOTSUPP
3400 } else if (rc == EOPNOTSUPP) {
3401 return NT_STATUS_INVALID_LEVEL;
3402 #endif /* EOPNOTSUPP */
3403 } else {
3404 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3405 return NT_STATUS_DOS(ERRSRV, ERRerror);
3407 break;
3410 case SMB_QUERY_POSIX_WHOAMI:
3412 uint32_t flags = 0;
3413 uint32_t sid_bytes;
3414 int i;
3416 if (!lp_unix_extensions()) {
3417 return NT_STATUS_INVALID_LEVEL;
3420 if (max_data_bytes < 40) {
3421 return NT_STATUS_BUFFER_TOO_SMALL;
3424 /* We ARE guest if global_sid_Builtin_Guests is
3425 * in our list of SIDs.
3427 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3428 conn->session_info->security_token)) {
3429 flags |= SMB_WHOAMI_GUEST;
3432 /* We are NOT guest if global_sid_Authenticated_Users
3433 * is in our list of SIDs.
3435 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3436 conn->session_info->security_token)) {
3437 flags &= ~SMB_WHOAMI_GUEST;
3440 /* NOTE: 8 bytes for UID/GID, irrespective of native
3441 * platform size. This matches
3442 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3444 data_len = 4 /* flags */
3445 + 4 /* flag mask */
3446 + 8 /* uid */
3447 + 8 /* gid */
3448 + 4 /* ngroups */
3449 + 4 /* num_sids */
3450 + 4 /* SID bytes */
3451 + 4 /* pad/reserved */
3452 + (conn->session_info->utok.ngroups * 8)
3453 /* groups list */
3454 + (conn->session_info->security_token->num_sids *
3455 SID_MAX_SIZE)
3456 /* SID list */;
3458 SIVAL(pdata, 0, flags);
3459 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3460 SBIG_UINT(pdata, 8,
3461 (uint64_t)conn->session_info->utok.uid);
3462 SBIG_UINT(pdata, 16,
3463 (uint64_t)conn->session_info->utok.gid);
3466 if (data_len >= max_data_bytes) {
3467 /* Potential overflow, skip the GIDs and SIDs. */
3469 SIVAL(pdata, 24, 0); /* num_groups */
3470 SIVAL(pdata, 28, 0); /* num_sids */
3471 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3472 SIVAL(pdata, 36, 0); /* reserved */
3474 data_len = 40;
3475 break;
3478 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3479 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3481 /* We walk the SID list twice, but this call is fairly
3482 * infrequent, and I don't expect that it's performance
3483 * sensitive -- jpeach
3485 for (i = 0, sid_bytes = 0;
3486 i < conn->session_info->security_token->num_sids; ++i) {
3487 sid_bytes += ndr_size_dom_sid(
3488 &conn->session_info->security_token->sids[i],
3492 /* SID list byte count */
3493 SIVAL(pdata, 32, sid_bytes);
3495 /* 4 bytes pad/reserved - must be zero */
3496 SIVAL(pdata, 36, 0);
3497 data_len = 40;
3499 /* GID list */
3500 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3501 SBIG_UINT(pdata, data_len,
3502 (uint64_t)conn->session_info->utok.groups[i]);
3503 data_len += 8;
3506 /* SID list */
3507 for (i = 0;
3508 i < conn->session_info->security_token->num_sids; ++i) {
3509 int sid_len = ndr_size_dom_sid(
3510 &conn->session_info->security_token->sids[i],
3513 sid_linearize(pdata + data_len, sid_len,
3514 &conn->session_info->security_token->sids[i]);
3515 data_len += sid_len;
3518 break;
3521 case SMB_MAC_QUERY_FS_INFO:
3523 * Thursby MAC extension... ONLY on NTFS filesystems
3524 * once we do streams then we don't need this
3526 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3527 data_len = 88;
3528 SIVAL(pdata,84,0x100); /* Don't support mac... */
3529 break;
3531 /* drop through */
3532 default:
3533 return NT_STATUS_INVALID_LEVEL;
3536 *ret_data_len = data_len;
3537 return status;
3540 /****************************************************************************
3541 Reply to a TRANS2_QFSINFO (query filesystem info).
3542 ****************************************************************************/
3544 static void call_trans2qfsinfo(connection_struct *conn,
3545 struct smb_request *req,
3546 char **pparams, int total_params,
3547 char **ppdata, int total_data,
3548 unsigned int max_data_bytes)
3550 char *params = *pparams;
3551 uint16_t info_level;
3552 int data_len = 0;
3553 NTSTATUS status;
3555 if (total_params < 2) {
3556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 return;
3560 info_level = SVAL(params,0);
3562 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3563 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3564 DEBUG(0,("call_trans2qfsinfo: encryption required "
3565 "and info level 0x%x sent.\n",
3566 (unsigned int)info_level));
3567 exit_server_cleanly("encryption required "
3568 "on connection");
3569 return;
3573 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3575 status = smbd_do_qfsinfo(conn, req,
3576 info_level,
3577 req->flags2,
3578 max_data_bytes,
3579 NULL,
3580 ppdata, &data_len);
3581 if (!NT_STATUS_IS_OK(status)) {
3582 reply_nterror(req, status);
3583 return;
3586 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3587 max_data_bytes);
3589 DEBUG( 4, ( "%s info_level = %d\n",
3590 smb_fn_name(req->cmd), info_level) );
3592 return;
3595 /****************************************************************************
3596 Reply to a TRANS2_SETFSINFO (set filesystem info).
3597 ****************************************************************************/
3599 static void call_trans2setfsinfo(connection_struct *conn,
3600 struct smb_request *req,
3601 char **pparams, int total_params,
3602 char **ppdata, int total_data,
3603 unsigned int max_data_bytes)
3605 char *pdata = *ppdata;
3606 char *params = *pparams;
3607 uint16 info_level;
3609 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3611 /* */
3612 if (total_params < 4) {
3613 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3614 total_params));
3615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3616 return;
3619 info_level = SVAL(params,2);
3621 if (IS_IPC(conn)) {
3622 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3623 info_level != SMB_SET_CIFS_UNIX_INFO) {
3624 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3625 "info level (0x%x) on IPC$.\n",
3626 (unsigned int)info_level));
3627 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3628 return;
3632 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3633 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3634 DEBUG(0,("call_trans2setfsinfo: encryption required "
3635 "and info level 0x%x sent.\n",
3636 (unsigned int)info_level));
3637 exit_server_cleanly("encryption required "
3638 "on connection");
3639 return;
3643 switch(info_level) {
3644 case SMB_SET_CIFS_UNIX_INFO:
3646 uint16 client_unix_major;
3647 uint16 client_unix_minor;
3648 uint32 client_unix_cap_low;
3649 uint32 client_unix_cap_high;
3651 if (!lp_unix_extensions()) {
3652 reply_nterror(req,
3653 NT_STATUS_INVALID_LEVEL);
3654 return;
3657 /* There should be 12 bytes of capabilities set. */
3658 if (total_data < 8) {
3659 reply_nterror(
3660 req,
3661 NT_STATUS_INVALID_PARAMETER);
3662 return;
3664 client_unix_major = SVAL(pdata,0);
3665 client_unix_minor = SVAL(pdata,2);
3666 client_unix_cap_low = IVAL(pdata,4);
3667 client_unix_cap_high = IVAL(pdata,8);
3668 /* Just print these values for now. */
3669 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3670 cap_low = 0x%x, cap_high = 0x%x\n",
3671 (unsigned int)client_unix_major,
3672 (unsigned int)client_unix_minor,
3673 (unsigned int)client_unix_cap_low,
3674 (unsigned int)client_unix_cap_high ));
3676 /* Here is where we must switch to posix pathname processing... */
3677 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3678 lp_set_posix_pathnames();
3679 mangle_change_to_posix();
3682 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3683 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3684 /* Client that knows how to do posix locks,
3685 * but not posix open/mkdir operations. Set a
3686 * default type for read/write checks. */
3688 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3691 break;
3694 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3696 NTSTATUS status;
3697 size_t param_len = 0;
3698 size_t data_len = total_data;
3700 if (!lp_unix_extensions()) {
3701 reply_nterror(
3702 req,
3703 NT_STATUS_INVALID_LEVEL);
3704 return;
3707 if (lp_smb_encrypt(SNUM(conn)) == false) {
3708 reply_nterror(
3709 req,
3710 NT_STATUS_NOT_SUPPORTED);
3711 return;
3714 if (req->sconn->smb1.echo_handler.trusted_fde) {
3715 DEBUG( 2,("call_trans2setfsinfo: "
3716 "request transport encryption disabled"
3717 "with 'fork echo handler = yes'\n"));
3718 reply_nterror(
3719 req,
3720 NT_STATUS_NOT_SUPPORTED);
3721 return;
3724 DEBUG( 4,("call_trans2setfsinfo: "
3725 "request transport encryption.\n"));
3727 status = srv_request_encryption_setup(conn,
3728 (unsigned char **)ppdata,
3729 &data_len,
3730 (unsigned char **)pparams,
3731 &param_len);
3733 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3734 !NT_STATUS_IS_OK(status)) {
3735 reply_nterror(req, status);
3736 return;
3739 send_trans2_replies(conn, req,
3740 *pparams,
3741 param_len,
3742 *ppdata,
3743 data_len,
3744 max_data_bytes);
3746 if (NT_STATUS_IS_OK(status)) {
3747 /* Server-side transport
3748 * encryption is now *on*. */
3749 status = srv_encryption_start(conn);
3750 if (!NT_STATUS_IS_OK(status)) {
3751 exit_server_cleanly(
3752 "Failure in setting "
3753 "up encrypted transport");
3756 return;
3759 case SMB_FS_QUOTA_INFORMATION:
3761 files_struct *fsp = NULL;
3762 SMB_NTQUOTA_STRUCT quotas;
3764 ZERO_STRUCT(quotas);
3766 /* access check */
3767 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3768 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3769 lp_servicename(SNUM(conn)),
3770 conn->session_info->unix_name));
3771 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3772 return;
3775 /* note: normaly there're 48 bytes,
3776 * but we didn't use the last 6 bytes for now
3777 * --metze
3779 fsp = file_fsp(req, SVAL(params,0));
3781 if (!check_fsp_ntquota_handle(conn, req,
3782 fsp)) {
3783 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3784 reply_nterror(
3785 req, NT_STATUS_INVALID_HANDLE);
3786 return;
3789 if (total_data < 42) {
3790 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3791 total_data));
3792 reply_nterror(
3793 req,
3794 NT_STATUS_INVALID_PARAMETER);
3795 return;
3798 /* unknown_1 24 NULL bytes in pdata*/
3800 /* the soft quotas 8 bytes (uint64_t)*/
3801 quotas.softlim = BVAL(pdata,24);
3803 /* the hard quotas 8 bytes (uint64_t)*/
3804 quotas.hardlim = BVAL(pdata,32);
3806 /* quota_flags 2 bytes **/
3807 quotas.qflags = SVAL(pdata,40);
3809 /* unknown_2 6 NULL bytes follow*/
3811 /* now set the quotas */
3812 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3813 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3814 reply_nterror(req, map_nt_error_from_unix(errno));
3815 return;
3818 break;
3820 default:
3821 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3822 info_level));
3823 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3824 return;
3825 break;
3829 * sending this reply works fine,
3830 * but I'm not sure it's the same
3831 * like windows do...
3832 * --metze
3834 reply_outbuf(req, 10, 0);
3837 #if defined(HAVE_POSIX_ACLS)
3838 /****************************************************************************
3839 Utility function to count the number of entries in a POSIX acl.
3840 ****************************************************************************/
3842 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3844 unsigned int ace_count = 0;
3845 int entry_id = SMB_ACL_FIRST_ENTRY;
3846 SMB_ACL_ENTRY_T entry;
3848 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3849 /* get_next... */
3850 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3851 entry_id = SMB_ACL_NEXT_ENTRY;
3853 ace_count++;
3855 return ace_count;
3858 /****************************************************************************
3859 Utility function to marshall a POSIX acl into wire format.
3860 ****************************************************************************/
3862 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3864 int entry_id = SMB_ACL_FIRST_ENTRY;
3865 SMB_ACL_ENTRY_T entry;
3867 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3868 SMB_ACL_TAG_T tagtype;
3869 SMB_ACL_PERMSET_T permset;
3870 unsigned char perms = 0;
3871 unsigned int own_grp;
3873 /* get_next... */
3874 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3875 entry_id = SMB_ACL_NEXT_ENTRY;
3878 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3879 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3880 return False;
3883 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3884 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3885 return False;
3888 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3889 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3890 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3892 SCVAL(pdata,1,perms);
3894 switch (tagtype) {
3895 case SMB_ACL_USER_OBJ:
3896 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3897 own_grp = (unsigned int)pst->st_ex_uid;
3898 SIVAL(pdata,2,own_grp);
3899 SIVAL(pdata,6,0);
3900 break;
3901 case SMB_ACL_USER:
3903 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3904 if (!puid) {
3905 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3906 return False;
3908 own_grp = (unsigned int)*puid;
3909 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3910 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3911 SIVAL(pdata,2,own_grp);
3912 SIVAL(pdata,6,0);
3913 break;
3915 case SMB_ACL_GROUP_OBJ:
3916 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3917 own_grp = (unsigned int)pst->st_ex_gid;
3918 SIVAL(pdata,2,own_grp);
3919 SIVAL(pdata,6,0);
3920 break;
3921 case SMB_ACL_GROUP:
3923 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3924 if (!pgid) {
3925 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3926 return False;
3928 own_grp = (unsigned int)*pgid;
3929 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3930 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3931 SIVAL(pdata,2,own_grp);
3932 SIVAL(pdata,6,0);
3933 break;
3935 case SMB_ACL_MASK:
3936 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3937 SIVAL(pdata,2,0xFFFFFFFF);
3938 SIVAL(pdata,6,0xFFFFFFFF);
3939 break;
3940 case SMB_ACL_OTHER:
3941 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3942 SIVAL(pdata,2,0xFFFFFFFF);
3943 SIVAL(pdata,6,0xFFFFFFFF);
3944 break;
3945 default:
3946 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3947 return False;
3949 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3952 return True;
3954 #endif
3956 /****************************************************************************
3957 Store the FILE_UNIX_BASIC info.
3958 ****************************************************************************/
3960 static char *store_file_unix_basic(connection_struct *conn,
3961 char *pdata,
3962 files_struct *fsp,
3963 const SMB_STRUCT_STAT *psbuf)
3965 uint64_t file_index = get_FileIndex(conn, psbuf);
3967 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3968 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3970 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3971 pdata += 8;
3973 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3974 pdata += 8;
3976 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3977 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3978 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3979 pdata += 24;
3981 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3982 SIVAL(pdata,4,0);
3983 pdata += 8;
3985 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3986 SIVAL(pdata,4,0);
3987 pdata += 8;
3989 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3990 pdata += 4;
3992 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3993 SIVAL(pdata,4,0);
3994 pdata += 8;
3996 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3997 SIVAL(pdata,4,0);
3998 pdata += 8;
4000 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4001 pdata += 8;
4003 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4004 SIVAL(pdata,4,0);
4005 pdata += 8;
4007 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4008 SIVAL(pdata,4,0);
4009 pdata += 8;
4011 return pdata;
4014 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4015 * the chflags(2) (or equivalent) flags.
4017 * XXX: this really should be behind the VFS interface. To do this, we would
4018 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4019 * Each VFS module could then implement its own mapping as appropriate for the
4020 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4022 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4023 info2_flags_map[] =
4025 #ifdef UF_NODUMP
4026 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4027 #endif
4029 #ifdef UF_IMMUTABLE
4030 { UF_IMMUTABLE, EXT_IMMUTABLE },
4031 #endif
4033 #ifdef UF_APPEND
4034 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4035 #endif
4037 #ifdef UF_HIDDEN
4038 { UF_HIDDEN, EXT_HIDDEN },
4039 #endif
4041 /* Do not remove. We need to guarantee that this array has at least one
4042 * entry to build on HP-UX.
4044 { 0, 0 }
4048 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4049 uint32 *smb_fflags, uint32 *smb_fmask)
4051 int i;
4053 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4054 *smb_fmask |= info2_flags_map[i].smb_fflag;
4055 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4056 *smb_fflags |= info2_flags_map[i].smb_fflag;
4061 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4062 const uint32 smb_fflags,
4063 const uint32 smb_fmask,
4064 int *stat_fflags)
4066 uint32 max_fmask = 0;
4067 int i;
4069 *stat_fflags = psbuf->st_ex_flags;
4071 /* For each flags requested in smb_fmask, check the state of the
4072 * corresponding flag in smb_fflags and set or clear the matching
4073 * stat flag.
4076 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4077 max_fmask |= info2_flags_map[i].smb_fflag;
4078 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4079 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4080 *stat_fflags |= info2_flags_map[i].stat_fflag;
4081 } else {
4082 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4087 /* If smb_fmask is asking to set any bits that are not supported by
4088 * our flag mappings, we should fail.
4090 if ((smb_fmask & max_fmask) != smb_fmask) {
4091 return False;
4094 return True;
4098 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4099 * of file flags and birth (create) time.
4101 static char *store_file_unix_basic_info2(connection_struct *conn,
4102 char *pdata,
4103 files_struct *fsp,
4104 const SMB_STRUCT_STAT *psbuf)
4106 uint32 file_flags = 0;
4107 uint32 flags_mask = 0;
4109 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4111 /* Create (birth) time 64 bit */
4112 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4113 pdata += 8;
4115 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4116 SIVAL(pdata, 0, file_flags); /* flags */
4117 SIVAL(pdata, 4, flags_mask); /* mask */
4118 pdata += 8;
4120 return pdata;
4123 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4124 const struct stream_struct *streams,
4125 char *data,
4126 unsigned int max_data_bytes,
4127 unsigned int *data_size)
4129 unsigned int i;
4130 unsigned int ofs = 0;
4132 for (i = 0; i < num_streams; i++) {
4133 unsigned int next_offset;
4134 size_t namelen;
4135 smb_ucs2_t *namebuf;
4137 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4138 streams[i].name, &namelen) ||
4139 namelen <= 2)
4141 return NT_STATUS_INVALID_PARAMETER;
4145 * name_buf is now null-terminated, we need to marshall as not
4146 * terminated
4149 namelen -= 2;
4152 * We cannot overflow ...
4154 if ((ofs + 24 + namelen) > max_data_bytes) {
4155 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4156 i));
4157 TALLOC_FREE(namebuf);
4158 return STATUS_BUFFER_OVERFLOW;
4161 SIVAL(data, ofs+4, namelen);
4162 SOFF_T(data, ofs+8, streams[i].size);
4163 SOFF_T(data, ofs+16, streams[i].alloc_size);
4164 memcpy(data+ofs+24, namebuf, namelen);
4165 TALLOC_FREE(namebuf);
4167 next_offset = ofs + 24 + namelen;
4169 if (i == num_streams-1) {
4170 SIVAL(data, ofs, 0);
4172 else {
4173 unsigned int align = ndr_align_size(next_offset, 8);
4175 if ((next_offset + align) > max_data_bytes) {
4176 DEBUG(10, ("refusing to overflow align "
4177 "reply at stream %u\n",
4178 i));
4179 TALLOC_FREE(namebuf);
4180 return STATUS_BUFFER_OVERFLOW;
4183 memset(data+next_offset, 0, align);
4184 next_offset += align;
4186 SIVAL(data, ofs, next_offset - ofs);
4187 ofs = next_offset;
4190 ofs = next_offset;
4193 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4195 *data_size = ofs;
4197 return NT_STATUS_OK;
4200 /****************************************************************************
4201 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4202 ****************************************************************************/
4204 static void call_trans2qpipeinfo(connection_struct *conn,
4205 struct smb_request *req,
4206 unsigned int tran_call,
4207 char **pparams, int total_params,
4208 char **ppdata, int total_data,
4209 unsigned int max_data_bytes)
4211 char *params = *pparams;
4212 char *pdata = *ppdata;
4213 unsigned int data_size = 0;
4214 unsigned int param_size = 2;
4215 uint16 info_level;
4216 files_struct *fsp;
4218 if (!params) {
4219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4220 return;
4223 if (total_params < 4) {
4224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4225 return;
4228 fsp = file_fsp(req, SVAL(params,0));
4229 if (!fsp_is_np(fsp)) {
4230 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4231 return;
4234 info_level = SVAL(params,2);
4236 *pparams = (char *)SMB_REALLOC(*pparams,2);
4237 if (*pparams == NULL) {
4238 reply_nterror(req, NT_STATUS_NO_MEMORY);
4239 return;
4241 params = *pparams;
4242 SSVAL(params,0,0);
4243 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4244 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4245 if (*ppdata == NULL ) {
4246 reply_nterror(req, NT_STATUS_NO_MEMORY);
4247 return;
4249 pdata = *ppdata;
4251 switch (info_level) {
4252 case SMB_FILE_STANDARD_INFORMATION:
4253 memset(pdata,0,24);
4254 SOFF_T(pdata,0,4096LL);
4255 SIVAL(pdata,16,1);
4256 SIVAL(pdata,20,1);
4257 data_size = 24;
4258 break;
4260 default:
4261 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4262 return;
4265 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4266 max_data_bytes);
4268 return;
4271 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4272 TALLOC_CTX *mem_ctx,
4273 uint16_t info_level,
4274 files_struct *fsp,
4275 struct smb_filename *smb_fname,
4276 bool delete_pending,
4277 struct timespec write_time_ts,
4278 struct ea_list *ea_list,
4279 int lock_data_count,
4280 char *lock_data,
4281 uint16_t flags2,
4282 unsigned int max_data_bytes,
4283 char **ppdata,
4284 unsigned int *pdata_size)
4286 char *pdata = *ppdata;
4287 char *dstart, *dend;
4288 unsigned int data_size;
4289 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4290 time_t create_time, mtime, atime, c_time;
4291 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4292 char *p;
4293 char *base_name;
4294 char *dos_fname;
4295 int mode;
4296 int nlink;
4297 NTSTATUS status;
4298 uint64_t file_size = 0;
4299 uint64_t pos = 0;
4300 uint64_t allocation_size = 0;
4301 uint64_t file_index = 0;
4302 uint32_t access_mask = 0;
4304 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4305 return NT_STATUS_INVALID_LEVEL;
4308 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4309 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4310 info_level, max_data_bytes));
4312 mode = dos_mode(conn, smb_fname);
4313 nlink = psbuf->st_ex_nlink;
4315 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4316 nlink = 1;
4319 if ((nlink > 0) && delete_pending) {
4320 nlink -= 1;
4323 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4324 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4325 if (*ppdata == NULL) {
4326 return NT_STATUS_NO_MEMORY;
4328 pdata = *ppdata;
4329 dstart = pdata;
4330 dend = dstart + data_size - 1;
4332 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4333 update_stat_ex_mtime(psbuf, write_time_ts);
4336 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4337 mtime_ts = psbuf->st_ex_mtime;
4338 atime_ts = psbuf->st_ex_atime;
4339 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4341 if (lp_dos_filetime_resolution(SNUM(conn))) {
4342 dos_filetime_timespec(&create_time_ts);
4343 dos_filetime_timespec(&mtime_ts);
4344 dos_filetime_timespec(&atime_ts);
4345 dos_filetime_timespec(&ctime_ts);
4348 create_time = convert_timespec_to_time_t(create_time_ts);
4349 mtime = convert_timespec_to_time_t(mtime_ts);
4350 atime = convert_timespec_to_time_t(atime_ts);
4351 c_time = convert_timespec_to_time_t(ctime_ts);
4353 p = strrchr_m(smb_fname->base_name,'/');
4354 if (!p)
4355 base_name = smb_fname->base_name;
4356 else
4357 base_name = p+1;
4359 /* NT expects the name to be in an exact form of the *full*
4360 filename. See the trans2 torture test */
4361 if (ISDOT(base_name)) {
4362 dos_fname = talloc_strdup(mem_ctx, "\\");
4363 if (!dos_fname) {
4364 return NT_STATUS_NO_MEMORY;
4366 } else {
4367 dos_fname = talloc_asprintf(mem_ctx,
4368 "\\%s",
4369 smb_fname->base_name);
4370 if (!dos_fname) {
4371 return NT_STATUS_NO_MEMORY;
4373 if (is_ntfs_stream_smb_fname(smb_fname)) {
4374 dos_fname = talloc_asprintf(dos_fname, "%s",
4375 smb_fname->stream_name);
4376 if (!dos_fname) {
4377 return NT_STATUS_NO_MEMORY;
4381 string_replace(dos_fname, '/', '\\');
4384 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4386 if (!fsp) {
4387 /* Do we have this path open ? */
4388 files_struct *fsp1;
4389 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4390 fsp1 = file_find_di_first(conn->sconn, fileid);
4391 if (fsp1 && fsp1->initial_allocation_size) {
4392 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4396 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4397 file_size = get_file_size_stat(psbuf);
4400 if (fsp) {
4401 pos = fsp->fh->position_information;
4404 if (fsp) {
4405 access_mask = fsp->access_mask;
4406 } else {
4407 /* GENERIC_EXECUTE mapping from Windows */
4408 access_mask = 0x12019F;
4411 /* This should be an index number - looks like
4412 dev/ino to me :-)
4414 I think this causes us to fail the IFSKIT
4415 BasicFileInformationTest. -tpot */
4416 file_index = get_FileIndex(conn, psbuf);
4418 switch (info_level) {
4419 case SMB_INFO_STANDARD:
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4421 data_size = 22;
4422 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4423 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4424 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4425 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4426 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4427 SSVAL(pdata,l1_attrFile,mode);
4428 break;
4430 case SMB_INFO_QUERY_EA_SIZE:
4432 unsigned int ea_size =
4433 estimate_ea_size(conn, fsp,
4434 smb_fname->base_name);
4435 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4436 data_size = 26;
4437 srv_put_dos_date2(pdata,0,create_time);
4438 srv_put_dos_date2(pdata,4,atime);
4439 srv_put_dos_date2(pdata,8,mtime); /* write time */
4440 SIVAL(pdata,12,(uint32)file_size);
4441 SIVAL(pdata,16,(uint32)allocation_size);
4442 SSVAL(pdata,20,mode);
4443 SIVAL(pdata,22,ea_size);
4444 break;
4447 case SMB_INFO_IS_NAME_VALID:
4448 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4449 if (fsp) {
4450 /* os/2 needs this ? really ?*/
4451 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4453 /* This is only reached for qpathinfo */
4454 data_size = 0;
4455 break;
4457 case SMB_INFO_QUERY_EAS_FROM_LIST:
4459 size_t total_ea_len = 0;
4460 struct ea_list *ea_file_list = NULL;
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4464 ea_file_list =
4465 get_ea_list_from_file(mem_ctx, conn, fsp,
4466 smb_fname->base_name,
4467 &total_ea_len);
4468 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4470 if (!ea_list || (total_ea_len > data_size)) {
4471 data_size = 4;
4472 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4473 break;
4476 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4477 break;
4480 case SMB_INFO_QUERY_ALL_EAS:
4482 /* We have data_size bytes to put EA's into. */
4483 size_t total_ea_len = 0;
4485 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4487 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4488 smb_fname->base_name,
4489 &total_ea_len);
4490 if (!ea_list || (total_ea_len > data_size)) {
4491 data_size = 4;
4492 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4493 break;
4496 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4497 break;
4500 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4502 /* This is FileFullEaInformation - 0xF which maps to
4503 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4505 /* We have data_size bytes to put EA's into. */
4506 size_t total_ea_len = 0;
4507 struct ea_list *ea_file_list = NULL;
4509 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4511 /*TODO: add filtering and index handling */
4513 ea_file_list =
4514 get_ea_list_from_file(mem_ctx, conn, fsp,
4515 smb_fname->base_name,
4516 &total_ea_len);
4517 if (!ea_file_list) {
4518 return NT_STATUS_NO_EAS_ON_FILE;
4521 status = fill_ea_chained_buffer(mem_ctx,
4522 pdata,
4523 data_size,
4524 &data_size,
4525 conn, ea_file_list);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 return status;
4529 break;
4532 case SMB_FILE_BASIC_INFORMATION:
4533 case SMB_QUERY_FILE_BASIC_INFO:
4535 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4537 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4538 } else {
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4540 data_size = 40;
4541 SIVAL(pdata,36,0);
4543 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4544 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4545 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4546 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4547 SIVAL(pdata,32,mode);
4549 DEBUG(5,("SMB_QFBI - "));
4550 DEBUG(5,("create: %s ", ctime(&create_time)));
4551 DEBUG(5,("access: %s ", ctime(&atime)));
4552 DEBUG(5,("write: %s ", ctime(&mtime)));
4553 DEBUG(5,("change: %s ", ctime(&c_time)));
4554 DEBUG(5,("mode: %x\n", mode));
4555 break;
4557 case SMB_FILE_STANDARD_INFORMATION:
4558 case SMB_QUERY_FILE_STANDARD_INFO:
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4561 data_size = 24;
4562 SOFF_T(pdata,0,allocation_size);
4563 SOFF_T(pdata,8,file_size);
4564 SIVAL(pdata,16,nlink);
4565 SCVAL(pdata,20,delete_pending?1:0);
4566 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4567 SSVAL(pdata,22,0); /* Padding. */
4568 break;
4570 case SMB_FILE_EA_INFORMATION:
4571 case SMB_QUERY_FILE_EA_INFO:
4573 unsigned int ea_size =
4574 estimate_ea_size(conn, fsp, smb_fname->base_name);
4575 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4576 data_size = 4;
4577 SIVAL(pdata,0,ea_size);
4578 break;
4581 /* Get the 8.3 name - used if NT SMB was negotiated. */
4582 case SMB_QUERY_FILE_ALT_NAME_INFO:
4583 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4585 int len;
4586 char mangled_name[13];
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4588 if (!name_to_8_3(base_name,mangled_name,
4589 True,conn->params)) {
4590 return NT_STATUS_NO_MEMORY;
4592 len = srvstr_push(dstart, flags2,
4593 pdata+4, mangled_name,
4594 PTR_DIFF(dend, pdata+4),
4595 STR_UNICODE);
4596 data_size = 4 + len;
4597 SIVAL(pdata,0,len);
4598 break;
4601 case SMB_QUERY_FILE_NAME_INFO:
4603 int len;
4605 this must be *exactly* right for ACLs on mapped drives to work
4607 len = srvstr_push(dstart, flags2,
4608 pdata+4, dos_fname,
4609 PTR_DIFF(dend, pdata+4),
4610 STR_UNICODE);
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4612 data_size = 4 + len;
4613 SIVAL(pdata,0,len);
4614 break;
4617 case SMB_FILE_ALLOCATION_INFORMATION:
4618 case SMB_QUERY_FILE_ALLOCATION_INFO:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4620 data_size = 8;
4621 SOFF_T(pdata,0,allocation_size);
4622 break;
4624 case SMB_FILE_END_OF_FILE_INFORMATION:
4625 case SMB_QUERY_FILE_END_OF_FILEINFO:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4627 data_size = 8;
4628 SOFF_T(pdata,0,file_size);
4629 break;
4631 case SMB_QUERY_FILE_ALL_INFO:
4632 case SMB_FILE_ALL_INFORMATION:
4634 int len;
4635 unsigned int ea_size =
4636 estimate_ea_size(conn, fsp, smb_fname->base_name);
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4638 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4639 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4640 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4641 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4642 SIVAL(pdata,32,mode);
4643 SIVAL(pdata,36,0); /* padding. */
4644 pdata += 40;
4645 SOFF_T(pdata,0,allocation_size);
4646 SOFF_T(pdata,8,file_size);
4647 SIVAL(pdata,16,nlink);
4648 SCVAL(pdata,20,delete_pending);
4649 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4650 SSVAL(pdata,22,0);
4651 pdata += 24;
4652 SIVAL(pdata,0,ea_size);
4653 pdata += 4; /* EA info */
4654 len = srvstr_push(dstart, flags2,
4655 pdata+4, dos_fname,
4656 PTR_DIFF(dend, pdata+4),
4657 STR_UNICODE);
4658 SIVAL(pdata,0,len);
4659 pdata += 4 + len;
4660 data_size = PTR_DIFF(pdata,(*ppdata));
4661 break;
4664 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4666 int len;
4667 unsigned int ea_size =
4668 estimate_ea_size(conn, fsp, smb_fname->base_name);
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4670 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4671 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4672 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4673 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4674 SIVAL(pdata, 0x20, mode);
4675 SIVAL(pdata, 0x24, 0); /* padding. */
4676 SBVAL(pdata, 0x28, allocation_size);
4677 SBVAL(pdata, 0x30, file_size);
4678 SIVAL(pdata, 0x38, nlink);
4679 SCVAL(pdata, 0x3C, delete_pending);
4680 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4681 SSVAL(pdata, 0x3E, 0); /* padding */
4682 SBVAL(pdata, 0x40, file_index);
4683 SIVAL(pdata, 0x48, ea_size);
4684 SIVAL(pdata, 0x4C, access_mask);
4685 SBVAL(pdata, 0x50, pos);
4686 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4687 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4689 pdata += 0x60;
4691 len = srvstr_push(dstart, flags2,
4692 pdata+4, dos_fname,
4693 PTR_DIFF(dend, pdata+4),
4694 STR_UNICODE);
4695 SIVAL(pdata,0,len);
4696 pdata += 4 + len;
4697 data_size = PTR_DIFF(pdata,(*ppdata));
4698 break;
4700 case SMB_FILE_INTERNAL_INFORMATION:
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4703 SBVAL(pdata, 0, file_index);
4704 data_size = 8;
4705 break;
4707 case SMB_FILE_ACCESS_INFORMATION:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4709 SIVAL(pdata, 0, access_mask);
4710 data_size = 4;
4711 break;
4713 case SMB_FILE_NAME_INFORMATION:
4714 /* Pathname with leading '\'. */
4716 size_t byte_len;
4717 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4719 SIVAL(pdata,0,byte_len);
4720 data_size = 4 + byte_len;
4721 break;
4724 case SMB_FILE_DISPOSITION_INFORMATION:
4725 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4726 data_size = 1;
4727 SCVAL(pdata,0,delete_pending);
4728 break;
4730 case SMB_FILE_POSITION_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4732 data_size = 8;
4733 SOFF_T(pdata,0,pos);
4734 break;
4736 case SMB_FILE_MODE_INFORMATION:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4738 SIVAL(pdata,0,mode);
4739 data_size = 4;
4740 break;
4742 case SMB_FILE_ALIGNMENT_INFORMATION:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4744 SIVAL(pdata,0,0); /* No alignment needed. */
4745 data_size = 4;
4746 break;
4749 * NT4 server just returns "invalid query" to this - if we try
4750 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4751 * want this. JRA.
4753 /* The first statement above is false - verified using Thursby
4754 * client against NT4 -- gcolley.
4756 case SMB_QUERY_FILE_STREAM_INFO:
4757 case SMB_FILE_STREAM_INFORMATION: {
4758 unsigned int num_streams = 0;
4759 struct stream_struct *streams = NULL;
4761 DEBUG(10,("smbd_do_qfilepathinfo: "
4762 "SMB_FILE_STREAM_INFORMATION\n"));
4764 if (is_ntfs_stream_smb_fname(smb_fname)) {
4765 return NT_STATUS_INVALID_PARAMETER;
4768 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4769 talloc_tos(), &num_streams, &streams);
4771 if (!NT_STATUS_IS_OK(status)) {
4772 DEBUG(10, ("could not get stream info: %s\n",
4773 nt_errstr(status)));
4774 return status;
4777 status = marshall_stream_info(num_streams, streams,
4778 pdata, max_data_bytes,
4779 &data_size);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 DEBUG(10, ("marshall_stream_info failed: %s\n",
4783 nt_errstr(status)));
4784 TALLOC_FREE(streams);
4785 return status;
4788 TALLOC_FREE(streams);
4790 break;
4792 case SMB_QUERY_COMPRESSION_INFO:
4793 case SMB_FILE_COMPRESSION_INFORMATION:
4794 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4795 SOFF_T(pdata,0,file_size);
4796 SIVAL(pdata,8,0); /* ??? */
4797 SIVAL(pdata,12,0); /* ??? */
4798 data_size = 16;
4799 break;
4801 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4803 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4804 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4805 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4806 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4807 SOFF_T(pdata,32,allocation_size);
4808 SOFF_T(pdata,40,file_size);
4809 SIVAL(pdata,48,mode);
4810 SIVAL(pdata,52,0); /* ??? */
4811 data_size = 56;
4812 break;
4814 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4815 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4816 SIVAL(pdata,0,mode);
4817 SIVAL(pdata,4,0);
4818 data_size = 8;
4819 break;
4822 * CIFS UNIX Extensions.
4825 case SMB_QUERY_FILE_UNIX_BASIC:
4827 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4828 data_size = PTR_DIFF(pdata,(*ppdata));
4830 DEBUG(4,("smbd_do_qfilepathinfo: "
4831 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4832 dump_data(4, (uint8_t *)(*ppdata), data_size);
4834 break;
4836 case SMB_QUERY_FILE_UNIX_INFO2:
4838 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4839 data_size = PTR_DIFF(pdata,(*ppdata));
4842 int i;
4843 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4845 for (i=0; i<100; i++)
4846 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4847 DEBUG(4,("\n"));
4850 break;
4852 case SMB_QUERY_FILE_UNIX_LINK:
4854 int len;
4855 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4857 if (!buffer) {
4858 return NT_STATUS_NO_MEMORY;
4861 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4862 #ifdef S_ISLNK
4863 if(!S_ISLNK(psbuf->st_ex_mode)) {
4864 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4866 #else
4867 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4868 #endif
4869 len = SMB_VFS_READLINK(conn,
4870 smb_fname->base_name,
4871 buffer, PATH_MAX);
4872 if (len == -1) {
4873 return map_nt_error_from_unix(errno);
4875 buffer[len] = 0;
4876 len = srvstr_push(dstart, flags2,
4877 pdata, buffer,
4878 PTR_DIFF(dend, pdata),
4879 STR_TERMINATE);
4880 pdata += len;
4881 data_size = PTR_DIFF(pdata,(*ppdata));
4883 break;
4886 #if defined(HAVE_POSIX_ACLS)
4887 case SMB_QUERY_POSIX_ACL:
4889 SMB_ACL_T file_acl = NULL;
4890 SMB_ACL_T def_acl = NULL;
4891 uint16 num_file_acls = 0;
4892 uint16 num_def_acls = 0;
4894 if (fsp && fsp->fh->fd != -1) {
4895 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4896 } else {
4897 file_acl =
4898 SMB_VFS_SYS_ACL_GET_FILE(conn,
4899 smb_fname->base_name,
4900 SMB_ACL_TYPE_ACCESS);
4903 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4904 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4905 "not implemented on "
4906 "filesystem containing %s\n",
4907 smb_fname->base_name));
4908 return NT_STATUS_NOT_IMPLEMENTED;
4911 if (S_ISDIR(psbuf->st_ex_mode)) {
4912 if (fsp && fsp->is_directory) {
4913 def_acl =
4914 SMB_VFS_SYS_ACL_GET_FILE(
4915 conn,
4916 fsp->fsp_name->base_name,
4917 SMB_ACL_TYPE_DEFAULT);
4918 } else {
4919 def_acl =
4920 SMB_VFS_SYS_ACL_GET_FILE(
4921 conn,
4922 smb_fname->base_name,
4923 SMB_ACL_TYPE_DEFAULT);
4925 def_acl = free_empty_sys_acl(conn, def_acl);
4928 num_file_acls = count_acl_entries(conn, file_acl);
4929 num_def_acls = count_acl_entries(conn, def_acl);
4931 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4932 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4933 data_size,
4934 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4935 SMB_POSIX_ACL_HEADER_SIZE) ));
4936 if (file_acl) {
4937 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4939 if (def_acl) {
4940 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4942 return NT_STATUS_BUFFER_TOO_SMALL;
4945 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4946 SSVAL(pdata,2,num_file_acls);
4947 SSVAL(pdata,4,num_def_acls);
4948 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4949 if (file_acl) {
4950 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4952 if (def_acl) {
4953 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4955 return NT_STATUS_INTERNAL_ERROR;
4957 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4958 if (file_acl) {
4959 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4961 if (def_acl) {
4962 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4964 return NT_STATUS_INTERNAL_ERROR;
4967 if (file_acl) {
4968 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4970 if (def_acl) {
4971 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4973 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4974 break;
4976 #endif
4979 case SMB_QUERY_POSIX_LOCK:
4981 uint64_t count;
4982 uint64_t offset;
4983 uint64_t smblctx;
4984 enum brl_type lock_type;
4986 /* We need an open file with a real fd for this. */
4987 if (!fsp || fsp->fh->fd == -1) {
4988 return NT_STATUS_INVALID_LEVEL;
4991 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4992 return NT_STATUS_INVALID_PARAMETER;
4995 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4996 case POSIX_LOCK_TYPE_READ:
4997 lock_type = READ_LOCK;
4998 break;
4999 case POSIX_LOCK_TYPE_WRITE:
5000 lock_type = WRITE_LOCK;
5001 break;
5002 case POSIX_LOCK_TYPE_UNLOCK:
5003 default:
5004 /* There's no point in asking for an unlock... */
5005 return NT_STATUS_INVALID_PARAMETER;
5008 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5009 #if defined(HAVE_LONGLONG)
5010 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5011 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5012 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5013 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5014 #else /* HAVE_LONGLONG */
5015 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5016 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5017 #endif /* HAVE_LONGLONG */
5019 status = query_lock(fsp,
5020 &smblctx,
5021 &count,
5022 &offset,
5023 &lock_type,
5024 POSIX_LOCK);
5026 if (ERROR_WAS_LOCK_DENIED(status)) {
5027 /* Here we need to report who has it locked... */
5028 data_size = POSIX_LOCK_DATA_SIZE;
5030 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5031 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5032 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5033 #if defined(HAVE_LONGLONG)
5034 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5035 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5036 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5037 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5038 #else /* HAVE_LONGLONG */
5039 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5040 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5041 #endif /* HAVE_LONGLONG */
5043 } else if (NT_STATUS_IS_OK(status)) {
5044 /* For success we just return a copy of what we sent
5045 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5046 data_size = POSIX_LOCK_DATA_SIZE;
5047 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5048 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5049 } else {
5050 return status;
5052 break;
5055 default:
5056 return NT_STATUS_INVALID_LEVEL;
5059 *pdata_size = data_size;
5060 return NT_STATUS_OK;
5063 /****************************************************************************
5064 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5065 file name or file id).
5066 ****************************************************************************/
5068 static void call_trans2qfilepathinfo(connection_struct *conn,
5069 struct smb_request *req,
5070 unsigned int tran_call,
5071 char **pparams, int total_params,
5072 char **ppdata, int total_data,
5073 unsigned int max_data_bytes)
5075 char *params = *pparams;
5076 char *pdata = *ppdata;
5077 uint16 info_level;
5078 unsigned int data_size = 0;
5079 unsigned int param_size = 2;
5080 struct smb_filename *smb_fname = NULL;
5081 bool delete_pending = False;
5082 struct timespec write_time_ts;
5083 files_struct *fsp = NULL;
5084 struct file_id fileid;
5085 struct ea_list *ea_list = NULL;
5086 int lock_data_count = 0;
5087 char *lock_data = NULL;
5088 NTSTATUS status = NT_STATUS_OK;
5090 if (!params) {
5091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5092 return;
5095 ZERO_STRUCT(write_time_ts);
5097 if (tran_call == TRANSACT2_QFILEINFO) {
5098 if (total_params < 4) {
5099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5100 return;
5103 if (IS_IPC(conn)) {
5104 call_trans2qpipeinfo(conn, req, tran_call,
5105 pparams, total_params,
5106 ppdata, total_data,
5107 max_data_bytes);
5108 return;
5111 fsp = file_fsp(req, SVAL(params,0));
5112 info_level = SVAL(params,2);
5114 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5116 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5117 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5118 return;
5121 /* Initial check for valid fsp ptr. */
5122 if (!check_fsp_open(conn, req, fsp)) {
5123 return;
5126 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5127 &smb_fname);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 reply_nterror(req, status);
5130 return;
5133 if(fsp->fake_file_handle) {
5135 * This is actually for the QUOTA_FAKE_FILE --metze
5138 /* We know this name is ok, it's already passed the checks. */
5140 } else if(fsp->fh->fd == -1) {
5142 * This is actually a QFILEINFO on a directory
5143 * handle (returned from an NT SMB). NT5.0 seems
5144 * to do this call. JRA.
5147 if (INFO_LEVEL_IS_UNIX(info_level)) {
5148 /* Always do lstat for UNIX calls. */
5149 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5150 DEBUG(3,("call_trans2qfilepathinfo: "
5151 "SMB_VFS_LSTAT of %s failed "
5152 "(%s)\n",
5153 smb_fname_str_dbg(smb_fname),
5154 strerror(errno)));
5155 reply_nterror(req,
5156 map_nt_error_from_unix(errno));
5157 return;
5159 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5160 DEBUG(3,("call_trans2qfilepathinfo: "
5161 "SMB_VFS_STAT of %s failed (%s)\n",
5162 smb_fname_str_dbg(smb_fname),
5163 strerror(errno)));
5164 reply_nterror(req,
5165 map_nt_error_from_unix(errno));
5166 return;
5169 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5170 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5171 } else {
5173 * Original code - this is an open file.
5175 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5176 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5177 fsp->fnum, strerror(errno)));
5178 reply_nterror(req,
5179 map_nt_error_from_unix(errno));
5180 return;
5182 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5183 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5186 } else {
5187 uint32_t name_hash;
5188 char *fname = NULL;
5189 uint32_t ucf_flags = 0;
5191 /* qpathinfo */
5192 if (total_params < 7) {
5193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5194 return;
5197 info_level = SVAL(params,0);
5199 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5201 if (INFO_LEVEL_IS_UNIX(info_level)) {
5202 if (!lp_unix_extensions()) {
5203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5204 return;
5206 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5207 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5208 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5209 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5213 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5214 total_params - 6,
5215 STR_TERMINATE, &status);
5216 if (!NT_STATUS_IS_OK(status)) {
5217 reply_nterror(req, status);
5218 return;
5221 status = filename_convert(req,
5222 conn,
5223 req->flags2 & FLAGS2_DFS_PATHNAMES,
5224 fname,
5225 ucf_flags,
5226 NULL,
5227 &smb_fname);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5230 reply_botherror(req,
5231 NT_STATUS_PATH_NOT_COVERED,
5232 ERRSRV, ERRbadpath);
5233 return;
5235 reply_nterror(req, status);
5236 return;
5239 /* If this is a stream, check if there is a delete_pending. */
5240 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5241 && is_ntfs_stream_smb_fname(smb_fname)) {
5242 struct smb_filename *smb_fname_base = NULL;
5244 /* Create an smb_filename with stream_name == NULL. */
5245 status =
5246 create_synthetic_smb_fname(talloc_tos(),
5247 smb_fname->base_name,
5248 NULL, NULL,
5249 &smb_fname_base);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 reply_nterror(req, status);
5252 return;
5255 if (INFO_LEVEL_IS_UNIX(info_level)) {
5256 /* Always do lstat for UNIX calls. */
5257 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5258 DEBUG(3,("call_trans2qfilepathinfo: "
5259 "SMB_VFS_LSTAT of %s failed "
5260 "(%s)\n",
5261 smb_fname_str_dbg(smb_fname_base),
5262 strerror(errno)));
5263 TALLOC_FREE(smb_fname_base);
5264 reply_nterror(req,
5265 map_nt_error_from_unix(errno));
5266 return;
5268 } else {
5269 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5270 DEBUG(3,("call_trans2qfilepathinfo: "
5271 "fileinfo of %s failed "
5272 "(%s)\n",
5273 smb_fname_str_dbg(smb_fname_base),
5274 strerror(errno)));
5275 TALLOC_FREE(smb_fname_base);
5276 reply_nterror(req,
5277 map_nt_error_from_unix(errno));
5278 return;
5282 status = file_name_hash(conn,
5283 smb_fname_str_dbg(smb_fname_base),
5284 &name_hash);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 TALLOC_FREE(smb_fname_base);
5287 reply_nterror(req, status);
5288 return;
5291 fileid = vfs_file_id_from_sbuf(conn,
5292 &smb_fname_base->st);
5293 TALLOC_FREE(smb_fname_base);
5294 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5295 if (delete_pending) {
5296 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5297 return;
5301 if (INFO_LEVEL_IS_UNIX(info_level)) {
5302 /* Always do lstat for UNIX calls. */
5303 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5304 DEBUG(3,("call_trans2qfilepathinfo: "
5305 "SMB_VFS_LSTAT of %s failed (%s)\n",
5306 smb_fname_str_dbg(smb_fname),
5307 strerror(errno)));
5308 reply_nterror(req,
5309 map_nt_error_from_unix(errno));
5310 return;
5313 } else {
5314 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5315 DEBUG(3,("call_trans2qfilepathinfo: "
5316 "SMB_VFS_STAT of %s failed (%s)\n",
5317 smb_fname_str_dbg(smb_fname),
5318 strerror(errno)));
5319 reply_nterror(req,
5320 map_nt_error_from_unix(errno));
5321 return;
5325 status = file_name_hash(conn,
5326 smb_fname_str_dbg(smb_fname),
5327 &name_hash);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 reply_nterror(req, status);
5330 return;
5333 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5334 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5335 if (delete_pending) {
5336 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5337 return;
5341 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5342 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5343 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5345 /* Pull out any data sent here before we realloc. */
5346 switch (info_level) {
5347 case SMB_INFO_QUERY_EAS_FROM_LIST:
5349 /* Pull any EA list from the data portion. */
5350 uint32 ea_size;
5352 if (total_data < 4) {
5353 reply_nterror(
5354 req, NT_STATUS_INVALID_PARAMETER);
5355 return;
5357 ea_size = IVAL(pdata,0);
5359 if (total_data > 0 && ea_size != total_data) {
5360 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5361 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5362 reply_nterror(
5363 req, NT_STATUS_INVALID_PARAMETER);
5364 return;
5367 if (!lp_ea_support(SNUM(conn))) {
5368 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5369 return;
5372 /* Pull out the list of names. */
5373 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5374 if (!ea_list) {
5375 reply_nterror(
5376 req, NT_STATUS_INVALID_PARAMETER);
5377 return;
5379 break;
5382 case SMB_QUERY_POSIX_LOCK:
5384 if (fsp == NULL || fsp->fh->fd == -1) {
5385 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5386 return;
5389 if (total_data != POSIX_LOCK_DATA_SIZE) {
5390 reply_nterror(
5391 req, NT_STATUS_INVALID_PARAMETER);
5392 return;
5395 /* Copy the lock range data. */
5396 lock_data = (char *)TALLOC_MEMDUP(
5397 req, pdata, total_data);
5398 if (!lock_data) {
5399 reply_nterror(req, NT_STATUS_NO_MEMORY);
5400 return;
5402 lock_data_count = total_data;
5404 default:
5405 break;
5408 *pparams = (char *)SMB_REALLOC(*pparams,2);
5409 if (*pparams == NULL) {
5410 reply_nterror(req, NT_STATUS_NO_MEMORY);
5411 return;
5413 params = *pparams;
5414 SSVAL(params,0,0);
5417 * draft-leach-cifs-v1-spec-02.txt
5418 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5419 * says:
5421 * The requested information is placed in the Data portion of the
5422 * transaction response. For the information levels greater than 0x100,
5423 * the transaction response has 1 parameter word which should be
5424 * ignored by the client.
5426 * However Windows only follows this rule for the IS_NAME_VALID call.
5428 switch (info_level) {
5429 case SMB_INFO_IS_NAME_VALID:
5430 param_size = 0;
5431 break;
5434 if ((info_level & 0xFF00) == 0xFF00) {
5436 * We use levels that start with 0xFF00
5437 * internally to represent SMB2 specific levels
5439 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5440 return;
5443 status = smbd_do_qfilepathinfo(conn, req, info_level,
5444 fsp, smb_fname,
5445 delete_pending, write_time_ts,
5446 ea_list,
5447 lock_data_count, lock_data,
5448 req->flags2, max_data_bytes,
5449 ppdata, &data_size);
5450 if (!NT_STATUS_IS_OK(status)) {
5451 reply_nterror(req, status);
5452 return;
5455 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5456 max_data_bytes);
5458 return;
5461 /****************************************************************************
5462 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5463 code.
5464 ****************************************************************************/
5466 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5467 connection_struct *conn,
5468 struct smb_request *req,
5469 bool overwrite_if_exists,
5470 const struct smb_filename *smb_fname_old,
5471 struct smb_filename *smb_fname_new)
5473 NTSTATUS status = NT_STATUS_OK;
5475 /* source must already exist. */
5476 if (!VALID_STAT(smb_fname_old->st)) {
5477 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5480 if (VALID_STAT(smb_fname_new->st)) {
5481 if (overwrite_if_exists) {
5482 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5483 return NT_STATUS_FILE_IS_A_DIRECTORY;
5485 status = unlink_internals(conn,
5486 req,
5487 FILE_ATTRIBUTE_NORMAL,
5488 smb_fname_new,
5489 false);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 return status;
5493 } else {
5494 /* Disallow if newname already exists. */
5495 return NT_STATUS_OBJECT_NAME_COLLISION;
5499 /* No links from a directory. */
5500 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5501 return NT_STATUS_FILE_IS_A_DIRECTORY;
5504 /* Setting a hardlink to/from a stream isn't currently supported. */
5505 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5506 is_ntfs_stream_smb_fname(smb_fname_new)) {
5507 return NT_STATUS_INVALID_PARAMETER;
5510 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5511 smb_fname_old->base_name, smb_fname_new->base_name));
5513 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5514 smb_fname_new->base_name) != 0) {
5515 status = map_nt_error_from_unix(errno);
5516 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5517 nt_errstr(status), smb_fname_old->base_name,
5518 smb_fname_new->base_name));
5520 return status;
5523 /****************************************************************************
5524 Deal with setting the time from any of the setfilepathinfo functions.
5525 ****************************************************************************/
5527 NTSTATUS smb_set_file_time(connection_struct *conn,
5528 files_struct *fsp,
5529 const struct smb_filename *smb_fname,
5530 struct smb_file_time *ft,
5531 bool setting_write_time)
5533 struct smb_filename smb_fname_base;
5534 uint32 action =
5535 FILE_NOTIFY_CHANGE_LAST_ACCESS
5536 |FILE_NOTIFY_CHANGE_LAST_WRITE
5537 |FILE_NOTIFY_CHANGE_CREATION;
5539 if (!VALID_STAT(smb_fname->st)) {
5540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5543 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5544 return NT_STATUS_ACCESS_DENIED;
5547 /* get some defaults (no modifications) if any info is zero or -1. */
5548 if (null_timespec(ft->create_time)) {
5549 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5552 if (null_timespec(ft->atime)) {
5553 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5556 if (null_timespec(ft->mtime)) {
5557 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5560 if (!setting_write_time) {
5561 /* ft->mtime comes from change time, not write time. */
5562 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5565 /* Ensure the resolution is the correct for
5566 * what we can store on this filesystem. */
5568 round_timespec(conn->ts_res, &ft->create_time);
5569 round_timespec(conn->ts_res, &ft->ctime);
5570 round_timespec(conn->ts_res, &ft->atime);
5571 round_timespec(conn->ts_res, &ft->mtime);
5573 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5574 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5575 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5576 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5577 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5578 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5579 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5580 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5582 if (setting_write_time) {
5584 * This was a Windows setfileinfo on an open file.
5585 * NT does this a lot. We also need to
5586 * set the time here, as it can be read by
5587 * FindFirst/FindNext and with the patch for bug #2045
5588 * in smbd/fileio.c it ensures that this timestamp is
5589 * kept sticky even after a write. We save the request
5590 * away and will set it on file close and after a write. JRA.
5593 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5594 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5596 if (fsp != NULL) {
5597 if (fsp->base_fsp) {
5598 set_sticky_write_time_fsp(fsp->base_fsp,
5599 ft->mtime);
5600 } else {
5601 set_sticky_write_time_fsp(fsp, ft->mtime);
5603 } else {
5604 set_sticky_write_time_path(
5605 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5606 ft->mtime);
5610 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5612 /* Always call ntimes on the base, even if a stream was passed in. */
5613 smb_fname_base = *smb_fname;
5614 smb_fname_base.stream_name = NULL;
5616 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5617 return map_nt_error_from_unix(errno);
5620 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5621 smb_fname->base_name);
5622 return NT_STATUS_OK;
5625 /****************************************************************************
5626 Deal with setting the dosmode from any of the setfilepathinfo functions.
5627 ****************************************************************************/
5629 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5630 const struct smb_filename *smb_fname,
5631 uint32 dosmode)
5633 struct smb_filename *smb_fname_base = NULL;
5634 NTSTATUS status;
5636 if (!VALID_STAT(smb_fname->st)) {
5637 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5640 /* Always operate on the base_name, even if a stream was passed in. */
5641 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5642 NULL, &smb_fname->st,
5643 &smb_fname_base);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 return status;
5648 if (dosmode) {
5649 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5650 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5651 } else {
5652 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5656 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5658 /* check the mode isn't different, before changing it */
5659 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5660 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5661 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5662 (unsigned int)dosmode));
5664 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5665 false)) {
5666 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5667 "%s failed (%s)\n",
5668 smb_fname_str_dbg(smb_fname_base),
5669 strerror(errno)));
5670 status = map_nt_error_from_unix(errno);
5671 goto out;
5674 status = NT_STATUS_OK;
5675 out:
5676 TALLOC_FREE(smb_fname_base);
5677 return status;
5680 /****************************************************************************
5681 Deal with setting the size from any of the setfilepathinfo functions.
5682 ****************************************************************************/
5684 static NTSTATUS smb_set_file_size(connection_struct *conn,
5685 struct smb_request *req,
5686 files_struct *fsp,
5687 const struct smb_filename *smb_fname,
5688 const SMB_STRUCT_STAT *psbuf,
5689 SMB_OFF_T size,
5690 bool fail_after_createfile)
5692 NTSTATUS status = NT_STATUS_OK;
5693 struct smb_filename *smb_fname_tmp = NULL;
5694 files_struct *new_fsp = NULL;
5696 if (!VALID_STAT(*psbuf)) {
5697 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5700 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5701 return NT_STATUS_ACCESS_DENIED;
5704 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5706 if (size == get_file_size_stat(psbuf)) {
5707 return NT_STATUS_OK;
5710 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5711 smb_fname_str_dbg(smb_fname), (double)size));
5713 if (fsp && fsp->fh->fd != -1) {
5714 /* Handle based call. */
5715 if (vfs_set_filelen(fsp, size) == -1) {
5716 return map_nt_error_from_unix(errno);
5718 trigger_write_time_update_immediate(fsp);
5719 return NT_STATUS_OK;
5722 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5723 if (!NT_STATUS_IS_OK(status)) {
5724 return status;
5727 smb_fname_tmp->st = *psbuf;
5729 status = SMB_VFS_CREATE_FILE(
5730 conn, /* conn */
5731 req, /* req */
5732 0, /* root_dir_fid */
5733 smb_fname_tmp, /* fname */
5734 FILE_WRITE_DATA, /* access_mask */
5735 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5736 FILE_SHARE_DELETE),
5737 FILE_OPEN, /* create_disposition*/
5738 0, /* create_options */
5739 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5740 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5741 0, /* allocation_size */
5742 0, /* private_flags */
5743 NULL, /* sd */
5744 NULL, /* ea_list */
5745 &new_fsp, /* result */
5746 NULL); /* pinfo */
5748 TALLOC_FREE(smb_fname_tmp);
5750 if (!NT_STATUS_IS_OK(status)) {
5751 /* NB. We check for open_was_deferred in the caller. */
5752 return status;
5755 /* See RAW-SFILEINFO-END-OF-FILE */
5756 if (fail_after_createfile) {
5757 close_file(req, new_fsp,NORMAL_CLOSE);
5758 return NT_STATUS_INVALID_LEVEL;
5761 if (vfs_set_filelen(new_fsp, size) == -1) {
5762 status = map_nt_error_from_unix(errno);
5763 close_file(req, new_fsp,NORMAL_CLOSE);
5764 return status;
5767 trigger_write_time_update_immediate(new_fsp);
5768 close_file(req, new_fsp,NORMAL_CLOSE);
5769 return NT_STATUS_OK;
5772 /****************************************************************************
5773 Deal with SMB_INFO_SET_EA.
5774 ****************************************************************************/
5776 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5777 const char *pdata,
5778 int total_data,
5779 files_struct *fsp,
5780 const struct smb_filename *smb_fname)
5782 struct ea_list *ea_list = NULL;
5783 TALLOC_CTX *ctx = NULL;
5784 NTSTATUS status = NT_STATUS_OK;
5786 if (total_data < 10) {
5788 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5789 length. They seem to have no effect. Bug #3212. JRA */
5791 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5792 /* We're done. We only get EA info in this call. */
5793 return NT_STATUS_OK;
5796 return NT_STATUS_INVALID_PARAMETER;
5799 if (IVAL(pdata,0) > total_data) {
5800 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5801 IVAL(pdata,0), (unsigned int)total_data));
5802 return NT_STATUS_INVALID_PARAMETER;
5805 ctx = talloc_tos();
5806 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5807 if (!ea_list) {
5808 return NT_STATUS_INVALID_PARAMETER;
5811 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5812 return NT_STATUS_ACCESS_DENIED;
5815 status = set_ea(conn, fsp, smb_fname, ea_list);
5817 return status;
5820 /****************************************************************************
5821 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5822 ****************************************************************************/
5824 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5825 const char *pdata,
5826 int total_data,
5827 files_struct *fsp)
5829 struct ea_list *ea_list = NULL;
5830 NTSTATUS status;
5832 if (!fsp) {
5833 return NT_STATUS_INVALID_HANDLE;
5836 if (!lp_ea_support(SNUM(conn))) {
5837 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5838 "EA's not supported.\n",
5839 (unsigned int)total_data));
5840 return NT_STATUS_EAS_NOT_SUPPORTED;
5843 if (total_data < 10) {
5844 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5845 "too small.\n",
5846 (unsigned int)total_data));
5847 return NT_STATUS_INVALID_PARAMETER;
5850 ea_list = read_nttrans_ea_list(talloc_tos(),
5851 pdata,
5852 total_data);
5854 if (!ea_list) {
5855 return NT_STATUS_INVALID_PARAMETER;
5858 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5859 return NT_STATUS_ACCESS_DENIED;
5862 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5864 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5865 smb_fname_str_dbg(fsp->fsp_name),
5866 nt_errstr(status) ));
5868 return status;
5872 /****************************************************************************
5873 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5874 ****************************************************************************/
5876 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5877 const char *pdata,
5878 int total_data,
5879 files_struct *fsp,
5880 struct smb_filename *smb_fname)
5882 NTSTATUS status = NT_STATUS_OK;
5883 bool delete_on_close;
5884 uint32 dosmode = 0;
5886 if (total_data < 1) {
5887 return NT_STATUS_INVALID_PARAMETER;
5890 if (fsp == NULL) {
5891 return NT_STATUS_INVALID_HANDLE;
5894 delete_on_close = (CVAL(pdata,0) ? True : False);
5895 dosmode = dos_mode(conn, smb_fname);
5897 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5898 "delete_on_close = %u\n",
5899 smb_fname_str_dbg(smb_fname),
5900 (unsigned int)dosmode,
5901 (unsigned int)delete_on_close ));
5903 if (delete_on_close) {
5904 status = can_set_delete_on_close(fsp, dosmode);
5905 if (!NT_STATUS_IS_OK(status)) {
5906 return status;
5910 /* The set is across all open files on this dev/inode pair. */
5911 if (!set_delete_on_close(fsp, delete_on_close,
5912 conn->session_info->security_token,
5913 &conn->session_info->utok)) {
5914 return NT_STATUS_ACCESS_DENIED;
5916 return NT_STATUS_OK;
5919 /****************************************************************************
5920 Deal with SMB_FILE_POSITION_INFORMATION.
5921 ****************************************************************************/
5923 static NTSTATUS smb_file_position_information(connection_struct *conn,
5924 const char *pdata,
5925 int total_data,
5926 files_struct *fsp)
5928 uint64_t position_information;
5930 if (total_data < 8) {
5931 return NT_STATUS_INVALID_PARAMETER;
5934 if (fsp == NULL) {
5935 /* Ignore on pathname based set. */
5936 return NT_STATUS_OK;
5939 position_information = (uint64_t)IVAL(pdata,0);
5940 #ifdef LARGE_SMB_OFF_T
5941 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5942 #else /* LARGE_SMB_OFF_T */
5943 if (IVAL(pdata,4) != 0) {
5944 /* more than 32 bits? */
5945 return NT_STATUS_INVALID_PARAMETER;
5947 #endif /* LARGE_SMB_OFF_T */
5949 DEBUG(10,("smb_file_position_information: Set file position "
5950 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5951 (double)position_information));
5952 fsp->fh->position_information = position_information;
5953 return NT_STATUS_OK;
5956 /****************************************************************************
5957 Deal with SMB_FILE_MODE_INFORMATION.
5958 ****************************************************************************/
5960 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5961 const char *pdata,
5962 int total_data)
5964 uint32 mode;
5966 if (total_data < 4) {
5967 return NT_STATUS_INVALID_PARAMETER;
5969 mode = IVAL(pdata,0);
5970 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5971 return NT_STATUS_INVALID_PARAMETER;
5973 return NT_STATUS_OK;
5976 /****************************************************************************
5977 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5978 ****************************************************************************/
5980 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5981 struct smb_request *req,
5982 const char *pdata,
5983 int total_data,
5984 const struct smb_filename *smb_fname)
5986 char *link_target = NULL;
5987 const char *newname = smb_fname->base_name;
5988 TALLOC_CTX *ctx = talloc_tos();
5990 /* Set a symbolic link. */
5991 /* Don't allow this if follow links is false. */
5993 if (total_data == 0) {
5994 return NT_STATUS_INVALID_PARAMETER;
5997 if (!lp_symlinks(SNUM(conn))) {
5998 return NT_STATUS_ACCESS_DENIED;
6001 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6002 total_data, STR_TERMINATE);
6004 if (!link_target) {
6005 return NT_STATUS_INVALID_PARAMETER;
6008 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6009 newname, link_target ));
6011 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6012 return map_nt_error_from_unix(errno);
6015 return NT_STATUS_OK;
6018 /****************************************************************************
6019 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6020 ****************************************************************************/
6022 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6023 struct smb_request *req,
6024 const char *pdata, int total_data,
6025 struct smb_filename *smb_fname_new)
6027 char *oldname = NULL;
6028 struct smb_filename *smb_fname_old = NULL;
6029 TALLOC_CTX *ctx = talloc_tos();
6030 NTSTATUS status = NT_STATUS_OK;
6032 /* Set a hard link. */
6033 if (total_data == 0) {
6034 return NT_STATUS_INVALID_PARAMETER;
6037 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6038 total_data, STR_TERMINATE, &status);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 return status;
6043 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6044 smb_fname_str_dbg(smb_fname_new), oldname));
6046 status = filename_convert(ctx,
6047 conn,
6048 req->flags2 & FLAGS2_DFS_PATHNAMES,
6049 oldname,
6051 NULL,
6052 &smb_fname_old);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 return status;
6057 return hardlink_internals(ctx, conn, req, false,
6058 smb_fname_old, smb_fname_new);
6061 /****************************************************************************
6062 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6063 ****************************************************************************/
6065 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6066 struct smb_request *req,
6067 const char *pdata,
6068 int total_data,
6069 files_struct *fsp,
6070 struct smb_filename *smb_fname_src)
6072 bool overwrite;
6073 uint32_t len;
6074 char *newname = NULL;
6075 struct smb_filename *smb_fname_dst = NULL;
6076 NTSTATUS status = NT_STATUS_OK;
6077 TALLOC_CTX *ctx = talloc_tos();
6079 if (!fsp) {
6080 return NT_STATUS_INVALID_HANDLE;
6083 if (total_data < 20) {
6084 return NT_STATUS_INVALID_PARAMETER;
6087 overwrite = (CVAL(pdata,0) ? True : False);
6088 len = IVAL(pdata,16);
6090 if (len > (total_data - 20) || (len == 0)) {
6091 return NT_STATUS_INVALID_PARAMETER;
6094 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6095 &pdata[20], len, STR_TERMINATE,
6096 &status);
6097 if (!NT_STATUS_IS_OK(status)) {
6098 return status;
6101 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6102 newname));
6104 status = filename_convert(ctx,
6105 conn,
6106 req->flags2 & FLAGS2_DFS_PATHNAMES,
6107 newname,
6108 UCF_SAVE_LCOMP,
6109 NULL,
6110 &smb_fname_dst);
6111 if (!NT_STATUS_IS_OK(status)) {
6112 return status;
6115 if (fsp->base_fsp) {
6116 /* newname must be a stream name. */
6117 if (newname[0] != ':') {
6118 return NT_STATUS_NOT_SUPPORTED;
6121 /* Create an smb_fname to call rename_internals_fsp() with. */
6122 status = create_synthetic_smb_fname(talloc_tos(),
6123 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6124 &smb_fname_dst);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 goto out;
6130 * Set the original last component, since
6131 * rename_internals_fsp() requires it.
6133 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6134 newname);
6135 if (smb_fname_dst->original_lcomp == NULL) {
6136 status = NT_STATUS_NO_MEMORY;
6137 goto out;
6142 DEBUG(10,("smb2_file_rename_information: "
6143 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6144 fsp->fnum, fsp_str_dbg(fsp),
6145 smb_fname_str_dbg(smb_fname_dst)));
6146 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6147 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6148 overwrite);
6150 out:
6151 TALLOC_FREE(smb_fname_dst);
6152 return status;
6155 static NTSTATUS smb_file_link_information(connection_struct *conn,
6156 struct smb_request *req,
6157 const char *pdata,
6158 int total_data,
6159 files_struct *fsp,
6160 struct smb_filename *smb_fname_src)
6162 bool overwrite;
6163 uint32_t len;
6164 char *newname = NULL;
6165 struct smb_filename *smb_fname_dst = NULL;
6166 NTSTATUS status = NT_STATUS_OK;
6167 TALLOC_CTX *ctx = talloc_tos();
6169 if (!fsp) {
6170 return NT_STATUS_INVALID_HANDLE;
6173 if (total_data < 20) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 overwrite = (CVAL(pdata,0) ? true : false);
6178 len = IVAL(pdata,16);
6180 if (len > (total_data - 20) || (len == 0)) {
6181 return NT_STATUS_INVALID_PARAMETER;
6184 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6185 &pdata[20], len, STR_TERMINATE,
6186 &status);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 return status;
6191 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6192 newname));
6194 status = filename_convert(ctx,
6195 conn,
6196 req->flags2 & FLAGS2_DFS_PATHNAMES,
6197 newname,
6198 UCF_SAVE_LCOMP,
6199 NULL,
6200 &smb_fname_dst);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 return status;
6205 if (fsp->base_fsp) {
6206 /* No stream names. */
6207 return NT_STATUS_NOT_SUPPORTED;
6210 DEBUG(10,("smb_file_link_information: "
6211 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6212 fsp->fnum, fsp_str_dbg(fsp),
6213 smb_fname_str_dbg(smb_fname_dst)));
6214 status = hardlink_internals(ctx,
6215 conn,
6216 req,
6217 overwrite,
6218 fsp->fsp_name,
6219 smb_fname_dst);
6221 TALLOC_FREE(smb_fname_dst);
6222 return status;
6225 /****************************************************************************
6226 Deal with SMB_FILE_RENAME_INFORMATION.
6227 ****************************************************************************/
6229 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6230 struct smb_request *req,
6231 const char *pdata,
6232 int total_data,
6233 files_struct *fsp,
6234 struct smb_filename *smb_fname_src)
6236 bool overwrite;
6237 uint32 root_fid;
6238 uint32 len;
6239 char *newname = NULL;
6240 struct smb_filename *smb_fname_dst = NULL;
6241 bool dest_has_wcard = False;
6242 NTSTATUS status = NT_STATUS_OK;
6243 char *p;
6244 TALLOC_CTX *ctx = talloc_tos();
6246 if (total_data < 13) {
6247 return NT_STATUS_INVALID_PARAMETER;
6250 overwrite = (CVAL(pdata,0) ? True : False);
6251 root_fid = IVAL(pdata,4);
6252 len = IVAL(pdata,8);
6254 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6255 return NT_STATUS_INVALID_PARAMETER;
6258 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6259 len, 0, &status,
6260 &dest_has_wcard);
6261 if (!NT_STATUS_IS_OK(status)) {
6262 return status;
6265 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6266 newname));
6268 status = resolve_dfspath_wcard(ctx, conn,
6269 req->flags2 & FLAGS2_DFS_PATHNAMES,
6270 newname,
6271 true,
6272 &newname,
6273 &dest_has_wcard);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 return status;
6278 /* Check the new name has no '/' characters. */
6279 if (strchr_m(newname, '/')) {
6280 return NT_STATUS_NOT_SUPPORTED;
6283 if (fsp && fsp->base_fsp) {
6284 /* newname must be a stream name. */
6285 if (newname[0] != ':') {
6286 return NT_STATUS_NOT_SUPPORTED;
6289 /* Create an smb_fname to call rename_internals_fsp() with. */
6290 status = create_synthetic_smb_fname(talloc_tos(),
6291 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6292 &smb_fname_dst);
6293 if (!NT_STATUS_IS_OK(status)) {
6294 goto out;
6298 * Set the original last component, since
6299 * rename_internals_fsp() requires it.
6301 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6302 newname);
6303 if (smb_fname_dst->original_lcomp == NULL) {
6304 status = NT_STATUS_NO_MEMORY;
6305 goto out;
6308 } else {
6310 * Build up an smb_fname_dst based on the filename passed in.
6311 * We basically just strip off the last component, and put on
6312 * the newname instead.
6314 char *base_name = NULL;
6316 /* newname must *not* be a stream name. */
6317 if (newname[0] == ':') {
6318 return NT_STATUS_NOT_SUPPORTED;
6322 * Strip off the last component (filename) of the path passed
6323 * in.
6325 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6326 if (!base_name) {
6327 return NT_STATUS_NO_MEMORY;
6329 p = strrchr_m(base_name, '/');
6330 if (p) {
6331 p[1] = '\0';
6332 } else {
6333 base_name = talloc_strdup(ctx, "");
6334 if (!base_name) {
6335 return NT_STATUS_NO_MEMORY;
6338 /* Append the new name. */
6339 base_name = talloc_asprintf_append(base_name,
6340 "%s",
6341 newname);
6342 if (!base_name) {
6343 return NT_STATUS_NO_MEMORY;
6346 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6347 (UCF_SAVE_LCOMP |
6348 (dest_has_wcard ?
6349 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6350 0)));
6352 /* If an error we expect this to be
6353 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6355 if (!NT_STATUS_IS_OK(status)) {
6356 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6357 status)) {
6358 goto out;
6360 /* Create an smb_fname to call rename_internals_fsp() */
6361 status = create_synthetic_smb_fname(ctx,
6362 base_name, NULL,
6363 NULL,
6364 &smb_fname_dst);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 goto out;
6371 if (fsp) {
6372 DEBUG(10,("smb_file_rename_information: "
6373 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6374 fsp->fnum, fsp_str_dbg(fsp),
6375 smb_fname_str_dbg(smb_fname_dst)));
6376 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6377 overwrite);
6378 } else {
6379 DEBUG(10,("smb_file_rename_information: "
6380 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6381 smb_fname_str_dbg(smb_fname_src),
6382 smb_fname_str_dbg(smb_fname_dst)));
6383 status = rename_internals(ctx, conn, req, smb_fname_src,
6384 smb_fname_dst, 0, overwrite, false,
6385 dest_has_wcard,
6386 FILE_WRITE_ATTRIBUTES);
6388 out:
6389 TALLOC_FREE(smb_fname_dst);
6390 return status;
6393 /****************************************************************************
6394 Deal with SMB_SET_POSIX_ACL.
6395 ****************************************************************************/
6397 #if defined(HAVE_POSIX_ACLS)
6398 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6399 const char *pdata,
6400 int total_data,
6401 files_struct *fsp,
6402 const struct smb_filename *smb_fname)
6404 uint16 posix_acl_version;
6405 uint16 num_file_acls;
6406 uint16 num_def_acls;
6407 bool valid_file_acls = True;
6408 bool valid_def_acls = True;
6410 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6411 return NT_STATUS_INVALID_PARAMETER;
6413 posix_acl_version = SVAL(pdata,0);
6414 num_file_acls = SVAL(pdata,2);
6415 num_def_acls = SVAL(pdata,4);
6417 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6418 valid_file_acls = False;
6419 num_file_acls = 0;
6422 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6423 valid_def_acls = False;
6424 num_def_acls = 0;
6427 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6428 return NT_STATUS_INVALID_PARAMETER;
6431 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6432 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6433 return NT_STATUS_INVALID_PARAMETER;
6436 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6437 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6438 (unsigned int)num_file_acls,
6439 (unsigned int)num_def_acls));
6441 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6442 smb_fname->base_name, num_file_acls,
6443 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6444 return map_nt_error_from_unix(errno);
6447 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6448 smb_fname->base_name, &smb_fname->st, num_def_acls,
6449 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6450 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6451 return map_nt_error_from_unix(errno);
6453 return NT_STATUS_OK;
6455 #endif
6457 /****************************************************************************
6458 Deal with SMB_SET_POSIX_LOCK.
6459 ****************************************************************************/
6461 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6462 struct smb_request *req,
6463 const char *pdata,
6464 int total_data,
6465 files_struct *fsp)
6467 uint64_t count;
6468 uint64_t offset;
6469 uint64_t smblctx;
6470 bool blocking_lock = False;
6471 enum brl_type lock_type;
6473 NTSTATUS status = NT_STATUS_OK;
6475 if (fsp == NULL || fsp->fh->fd == -1) {
6476 return NT_STATUS_INVALID_HANDLE;
6479 if (total_data != POSIX_LOCK_DATA_SIZE) {
6480 return NT_STATUS_INVALID_PARAMETER;
6483 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6484 case POSIX_LOCK_TYPE_READ:
6485 lock_type = READ_LOCK;
6486 break;
6487 case POSIX_LOCK_TYPE_WRITE:
6488 /* Return the right POSIX-mappable error code for files opened read-only. */
6489 if (!fsp->can_write) {
6490 return NT_STATUS_INVALID_HANDLE;
6492 lock_type = WRITE_LOCK;
6493 break;
6494 case POSIX_LOCK_TYPE_UNLOCK:
6495 lock_type = UNLOCK_LOCK;
6496 break;
6497 default:
6498 return NT_STATUS_INVALID_PARAMETER;
6501 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6502 blocking_lock = False;
6503 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6504 blocking_lock = True;
6505 } else {
6506 return NT_STATUS_INVALID_PARAMETER;
6509 if (!lp_blocking_locks(SNUM(conn))) {
6510 blocking_lock = False;
6513 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6514 #if defined(HAVE_LONGLONG)
6515 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6516 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6517 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6518 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6519 #else /* HAVE_LONGLONG */
6520 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6521 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6522 #endif /* HAVE_LONGLONG */
6524 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6525 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6526 fsp_str_dbg(fsp),
6527 (unsigned int)lock_type,
6528 (unsigned long long)smblctx,
6529 (double)count,
6530 (double)offset ));
6532 if (lock_type == UNLOCK_LOCK) {
6533 status = do_unlock(req->sconn->msg_ctx,
6534 fsp,
6535 smblctx,
6536 count,
6537 offset,
6538 POSIX_LOCK);
6539 } else {
6540 uint64_t block_smblctx;
6542 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6543 fsp,
6544 smblctx,
6545 count,
6546 offset,
6547 lock_type,
6548 POSIX_LOCK,
6549 blocking_lock,
6550 &status,
6551 &block_smblctx,
6552 NULL);
6554 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6556 * A blocking lock was requested. Package up
6557 * this smb into a queued request and push it
6558 * onto the blocking lock queue.
6560 if(push_blocking_lock_request(br_lck,
6561 req,
6562 fsp,
6563 -1, /* infinite timeout. */
6565 smblctx,
6566 lock_type,
6567 POSIX_LOCK,
6568 offset,
6569 count,
6570 block_smblctx)) {
6571 TALLOC_FREE(br_lck);
6572 return status;
6575 TALLOC_FREE(br_lck);
6578 return status;
6581 /****************************************************************************
6582 Deal with SMB_SET_FILE_BASIC_INFO.
6583 ****************************************************************************/
6585 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6586 const char *pdata,
6587 int total_data,
6588 files_struct *fsp,
6589 const struct smb_filename *smb_fname)
6591 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6592 struct smb_file_time ft;
6593 uint32 dosmode = 0;
6594 NTSTATUS status = NT_STATUS_OK;
6596 ZERO_STRUCT(ft);
6598 if (total_data < 36) {
6599 return NT_STATUS_INVALID_PARAMETER;
6602 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6603 return NT_STATUS_ACCESS_DENIED;
6606 /* Set the attributes */
6607 dosmode = IVAL(pdata,32);
6608 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6609 if (!NT_STATUS_IS_OK(status)) {
6610 return status;
6613 /* create time */
6614 ft.create_time = interpret_long_date(pdata);
6616 /* access time */
6617 ft.atime = interpret_long_date(pdata+8);
6619 /* write time. */
6620 ft.mtime = interpret_long_date(pdata+16);
6622 /* change time. */
6623 ft.ctime = interpret_long_date(pdata+24);
6625 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6626 smb_fname_str_dbg(smb_fname)));
6628 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6629 true);
6632 /****************************************************************************
6633 Deal with SMB_INFO_STANDARD.
6634 ****************************************************************************/
6636 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6637 const char *pdata,
6638 int total_data,
6639 files_struct *fsp,
6640 const struct smb_filename *smb_fname)
6642 struct smb_file_time ft;
6644 ZERO_STRUCT(ft);
6646 if (total_data < 12) {
6647 return NT_STATUS_INVALID_PARAMETER;
6650 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6651 return NT_STATUS_ACCESS_DENIED;
6654 /* create time */
6655 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6656 /* access time */
6657 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6658 /* write time */
6659 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6661 DEBUG(10,("smb_set_info_standard: file %s\n",
6662 smb_fname_str_dbg(smb_fname)));
6664 return smb_set_file_time(conn,
6665 fsp,
6666 smb_fname,
6667 &ft,
6668 true);
6671 /****************************************************************************
6672 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6673 ****************************************************************************/
6675 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6676 struct smb_request *req,
6677 const char *pdata,
6678 int total_data,
6679 files_struct *fsp,
6680 struct smb_filename *smb_fname)
6682 uint64_t allocation_size = 0;
6683 NTSTATUS status = NT_STATUS_OK;
6684 files_struct *new_fsp = NULL;
6686 if (!VALID_STAT(smb_fname->st)) {
6687 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6690 if (total_data < 8) {
6691 return NT_STATUS_INVALID_PARAMETER;
6694 allocation_size = (uint64_t)IVAL(pdata,0);
6695 #ifdef LARGE_SMB_OFF_T
6696 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6697 #else /* LARGE_SMB_OFF_T */
6698 if (IVAL(pdata,4) != 0) {
6699 /* more than 32 bits? */
6700 return NT_STATUS_INVALID_PARAMETER;
6702 #endif /* LARGE_SMB_OFF_T */
6704 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6705 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6706 (double)allocation_size));
6708 if (allocation_size) {
6709 allocation_size = smb_roundup(conn, allocation_size);
6712 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6713 return NT_STATUS_ACCESS_DENIED;
6716 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6717 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6718 (double)allocation_size));
6720 if (fsp && fsp->fh->fd != -1) {
6721 /* Open file handle. */
6722 /* Only change if needed. */
6723 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6724 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6725 return map_nt_error_from_unix(errno);
6728 /* But always update the time. */
6730 * This is equivalent to a write. Ensure it's seen immediately
6731 * if there are no pending writes.
6733 trigger_write_time_update_immediate(fsp);
6734 return NT_STATUS_OK;
6737 /* Pathname or stat or directory file. */
6738 status = SMB_VFS_CREATE_FILE(
6739 conn, /* conn */
6740 req, /* req */
6741 0, /* root_dir_fid */
6742 smb_fname, /* fname */
6743 FILE_WRITE_DATA, /* access_mask */
6744 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6745 FILE_SHARE_DELETE),
6746 FILE_OPEN, /* create_disposition*/
6747 0, /* create_options */
6748 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6749 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6750 0, /* allocation_size */
6751 0, /* private_flags */
6752 NULL, /* sd */
6753 NULL, /* ea_list */
6754 &new_fsp, /* result */
6755 NULL); /* pinfo */
6757 if (!NT_STATUS_IS_OK(status)) {
6758 /* NB. We check for open_was_deferred in the caller. */
6759 return status;
6762 /* Only change if needed. */
6763 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6764 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6765 status = map_nt_error_from_unix(errno);
6766 close_file(req, new_fsp, NORMAL_CLOSE);
6767 return status;
6771 /* Changing the allocation size should set the last mod time. */
6773 * This is equivalent to a write. Ensure it's seen immediately
6774 * if there are no pending writes.
6776 trigger_write_time_update_immediate(new_fsp);
6778 close_file(req, new_fsp, NORMAL_CLOSE);
6779 return NT_STATUS_OK;
6782 /****************************************************************************
6783 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6784 ****************************************************************************/
6786 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6787 struct smb_request *req,
6788 const char *pdata,
6789 int total_data,
6790 files_struct *fsp,
6791 const struct smb_filename *smb_fname,
6792 bool fail_after_createfile)
6794 SMB_OFF_T size;
6796 if (total_data < 8) {
6797 return NT_STATUS_INVALID_PARAMETER;
6800 size = IVAL(pdata,0);
6801 #ifdef LARGE_SMB_OFF_T
6802 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6803 #else /* LARGE_SMB_OFF_T */
6804 if (IVAL(pdata,4) != 0) {
6805 /* more than 32 bits? */
6806 return NT_STATUS_INVALID_PARAMETER;
6808 #endif /* LARGE_SMB_OFF_T */
6809 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6810 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6811 (double)size));
6813 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6814 return NT_STATUS_ACCESS_DENIED;
6817 return smb_set_file_size(conn, req,
6818 fsp,
6819 smb_fname,
6820 &smb_fname->st,
6821 size,
6822 fail_after_createfile);
6825 /****************************************************************************
6826 Allow a UNIX info mknod.
6827 ****************************************************************************/
6829 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6830 const char *pdata,
6831 int total_data,
6832 const struct smb_filename *smb_fname)
6834 uint32 file_type = IVAL(pdata,56);
6835 #if defined(HAVE_MAKEDEV)
6836 uint32 dev_major = IVAL(pdata,60);
6837 uint32 dev_minor = IVAL(pdata,68);
6838 #endif
6839 SMB_DEV_T dev = (SMB_DEV_T)0;
6840 uint32 raw_unixmode = IVAL(pdata,84);
6841 NTSTATUS status;
6842 mode_t unixmode;
6844 if (total_data < 100) {
6845 return NT_STATUS_INVALID_PARAMETER;
6848 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6849 PERM_NEW_FILE, &unixmode);
6850 if (!NT_STATUS_IS_OK(status)) {
6851 return status;
6854 #if defined(HAVE_MAKEDEV)
6855 dev = makedev(dev_major, dev_minor);
6856 #endif
6858 switch (file_type) {
6859 #if defined(S_IFIFO)
6860 case UNIX_TYPE_FIFO:
6861 unixmode |= S_IFIFO;
6862 break;
6863 #endif
6864 #if defined(S_IFSOCK)
6865 case UNIX_TYPE_SOCKET:
6866 unixmode |= S_IFSOCK;
6867 break;
6868 #endif
6869 #if defined(S_IFCHR)
6870 case UNIX_TYPE_CHARDEV:
6871 unixmode |= S_IFCHR;
6872 break;
6873 #endif
6874 #if defined(S_IFBLK)
6875 case UNIX_TYPE_BLKDEV:
6876 unixmode |= S_IFBLK;
6877 break;
6878 #endif
6879 default:
6880 return NT_STATUS_INVALID_PARAMETER;
6883 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6884 "%.0f mode 0%o for file %s\n", (double)dev,
6885 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6887 /* Ok - do the mknod. */
6888 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6889 return map_nt_error_from_unix(errno);
6892 /* If any of the other "set" calls fail we
6893 * don't want to end up with a half-constructed mknod.
6896 if (lp_inherit_perms(SNUM(conn))) {
6897 char *parent;
6898 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6899 &parent, NULL)) {
6900 return NT_STATUS_NO_MEMORY;
6902 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6903 unixmode);
6904 TALLOC_FREE(parent);
6907 return NT_STATUS_OK;
6910 /****************************************************************************
6911 Deal with SMB_SET_FILE_UNIX_BASIC.
6912 ****************************************************************************/
6914 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6915 struct smb_request *req,
6916 const char *pdata,
6917 int total_data,
6918 files_struct *fsp,
6919 const struct smb_filename *smb_fname)
6921 struct smb_file_time ft;
6922 uint32 raw_unixmode;
6923 mode_t unixmode;
6924 SMB_OFF_T size = 0;
6925 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6926 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6927 NTSTATUS status = NT_STATUS_OK;
6928 bool delete_on_fail = False;
6929 enum perm_type ptype;
6930 files_struct *all_fsps = NULL;
6931 bool modify_mtime = true;
6932 struct file_id id;
6933 struct smb_filename *smb_fname_tmp = NULL;
6934 SMB_STRUCT_STAT sbuf;
6936 ZERO_STRUCT(ft);
6938 if (total_data < 100) {
6939 return NT_STATUS_INVALID_PARAMETER;
6942 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6943 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6944 size=IVAL(pdata,0); /* first 8 Bytes are size */
6945 #ifdef LARGE_SMB_OFF_T
6946 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6947 #else /* LARGE_SMB_OFF_T */
6948 if (IVAL(pdata,4) != 0) {
6949 /* more than 32 bits? */
6950 return NT_STATUS_INVALID_PARAMETER;
6952 #endif /* LARGE_SMB_OFF_T */
6955 ft.atime = interpret_long_date(pdata+24); /* access_time */
6956 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6957 set_owner = (uid_t)IVAL(pdata,40);
6958 set_grp = (gid_t)IVAL(pdata,48);
6959 raw_unixmode = IVAL(pdata,84);
6961 if (VALID_STAT(smb_fname->st)) {
6962 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6963 ptype = PERM_EXISTING_DIR;
6964 } else {
6965 ptype = PERM_EXISTING_FILE;
6967 } else {
6968 ptype = PERM_NEW_FILE;
6971 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6972 ptype, &unixmode);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 return status;
6977 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6978 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6979 smb_fname_str_dbg(smb_fname), (double)size,
6980 (unsigned int)set_owner, (unsigned int)set_grp,
6981 (int)raw_unixmode));
6983 sbuf = smb_fname->st;
6985 if (!VALID_STAT(sbuf)) {
6987 * The only valid use of this is to create character and block
6988 * devices, and named pipes. This is deprecated (IMHO) and
6989 * a new info level should be used for mknod. JRA.
6992 status = smb_unix_mknod(conn,
6993 pdata,
6994 total_data,
6995 smb_fname);
6996 if (!NT_STATUS_IS_OK(status)) {
6997 return status;
7000 status = copy_smb_filename(talloc_tos(), smb_fname,
7001 &smb_fname_tmp);
7002 if (!NT_STATUS_IS_OK(status)) {
7003 return status;
7006 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7007 status = map_nt_error_from_unix(errno);
7008 TALLOC_FREE(smb_fname_tmp);
7009 SMB_VFS_UNLINK(conn, smb_fname);
7010 return status;
7013 sbuf = smb_fname_tmp->st;
7014 smb_fname = smb_fname_tmp;
7016 /* Ensure we don't try and change anything else. */
7017 raw_unixmode = SMB_MODE_NO_CHANGE;
7018 size = get_file_size_stat(&sbuf);
7019 ft.atime = sbuf.st_ex_atime;
7020 ft.mtime = sbuf.st_ex_mtime;
7022 * We continue here as we might want to change the
7023 * owner uid/gid.
7025 delete_on_fail = True;
7028 #if 1
7029 /* Horrible backwards compatibility hack as an old server bug
7030 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7031 * */
7033 if (!size) {
7034 size = get_file_size_stat(&sbuf);
7036 #endif
7039 * Deal with the UNIX specific mode set.
7042 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7043 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7044 "setting mode 0%o for file %s\n",
7045 (unsigned int)unixmode,
7046 smb_fname_str_dbg(smb_fname)));
7047 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7048 return map_nt_error_from_unix(errno);
7053 * Deal with the UNIX specific uid set.
7056 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7057 (sbuf.st_ex_uid != set_owner)) {
7058 int ret;
7060 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7061 "changing owner %u for path %s\n",
7062 (unsigned int)set_owner,
7063 smb_fname_str_dbg(smb_fname)));
7065 if (S_ISLNK(sbuf.st_ex_mode)) {
7066 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7067 set_owner, (gid_t)-1);
7068 } else {
7069 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7070 set_owner, (gid_t)-1);
7073 if (ret != 0) {
7074 status = map_nt_error_from_unix(errno);
7075 if (delete_on_fail) {
7076 SMB_VFS_UNLINK(conn, smb_fname);
7078 return status;
7083 * Deal with the UNIX specific gid set.
7086 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7087 (sbuf.st_ex_gid != set_grp)) {
7088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7089 "changing group %u for file %s\n",
7090 (unsigned int)set_owner,
7091 smb_fname_str_dbg(smb_fname)));
7092 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7093 set_grp) != 0) {
7094 status = map_nt_error_from_unix(errno);
7095 if (delete_on_fail) {
7096 SMB_VFS_UNLINK(conn, smb_fname);
7098 return status;
7102 /* Deal with any size changes. */
7104 status = smb_set_file_size(conn, req,
7105 fsp,
7106 smb_fname,
7107 &sbuf,
7108 size,
7109 false);
7110 if (!NT_STATUS_IS_OK(status)) {
7111 return status;
7114 /* Deal with any time changes. */
7115 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7116 /* No change, don't cancel anything. */
7117 return status;
7120 id = vfs_file_id_from_sbuf(conn, &sbuf);
7121 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7122 all_fsps = file_find_di_next(all_fsps)) {
7124 * We're setting the time explicitly for UNIX.
7125 * Cancel any pending changes over all handles.
7127 all_fsps->update_write_time_on_close = false;
7128 TALLOC_FREE(all_fsps->update_write_time_event);
7132 * Override the "setting_write_time"
7133 * parameter here as it almost does what
7134 * we need. Just remember if we modified
7135 * mtime and send the notify ourselves.
7137 if (null_timespec(ft.mtime)) {
7138 modify_mtime = false;
7141 status = smb_set_file_time(conn,
7142 fsp,
7143 smb_fname,
7144 &ft,
7145 false);
7146 if (modify_mtime) {
7147 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7148 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7150 return status;
7153 /****************************************************************************
7154 Deal with SMB_SET_FILE_UNIX_INFO2.
7155 ****************************************************************************/
7157 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7158 struct smb_request *req,
7159 const char *pdata,
7160 int total_data,
7161 files_struct *fsp,
7162 const struct smb_filename *smb_fname)
7164 NTSTATUS status;
7165 uint32 smb_fflags;
7166 uint32 smb_fmask;
7168 if (total_data < 116) {
7169 return NT_STATUS_INVALID_PARAMETER;
7172 /* Start by setting all the fields that are common between UNIX_BASIC
7173 * and UNIX_INFO2.
7175 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7176 fsp, smb_fname);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 return status;
7181 smb_fflags = IVAL(pdata, 108);
7182 smb_fmask = IVAL(pdata, 112);
7184 /* NB: We should only attempt to alter the file flags if the client
7185 * sends a non-zero mask.
7187 if (smb_fmask != 0) {
7188 int stat_fflags = 0;
7190 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7191 smb_fmask, &stat_fflags)) {
7192 /* Client asked to alter a flag we don't understand. */
7193 return NT_STATUS_INVALID_PARAMETER;
7196 if (fsp && fsp->fh->fd != -1) {
7197 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7198 return NT_STATUS_NOT_SUPPORTED;
7199 } else {
7200 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7201 stat_fflags) != 0) {
7202 return map_nt_error_from_unix(errno);
7207 /* XXX: need to add support for changing the create_time here. You
7208 * can do this for paths on Darwin with setattrlist(2). The right way
7209 * to hook this up is probably by extending the VFS utimes interface.
7212 return NT_STATUS_OK;
7215 /****************************************************************************
7216 Create a directory with POSIX semantics.
7217 ****************************************************************************/
7219 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7220 struct smb_request *req,
7221 char **ppdata,
7222 int total_data,
7223 struct smb_filename *smb_fname,
7224 int *pdata_return_size)
7226 NTSTATUS status = NT_STATUS_OK;
7227 uint32 raw_unixmode = 0;
7228 uint32 mod_unixmode = 0;
7229 mode_t unixmode = (mode_t)0;
7230 files_struct *fsp = NULL;
7231 uint16 info_level_return = 0;
7232 int info;
7233 char *pdata = *ppdata;
7235 if (total_data < 18) {
7236 return NT_STATUS_INVALID_PARAMETER;
7239 raw_unixmode = IVAL(pdata,8);
7240 /* Next 4 bytes are not yet defined. */
7242 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7243 PERM_NEW_DIR, &unixmode);
7244 if (!NT_STATUS_IS_OK(status)) {
7245 return status;
7248 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7250 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7251 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7253 status = SMB_VFS_CREATE_FILE(
7254 conn, /* conn */
7255 req, /* req */
7256 0, /* root_dir_fid */
7257 smb_fname, /* fname */
7258 FILE_READ_ATTRIBUTES, /* access_mask */
7259 FILE_SHARE_NONE, /* share_access */
7260 FILE_CREATE, /* create_disposition*/
7261 FILE_DIRECTORY_FILE, /* create_options */
7262 mod_unixmode, /* file_attributes */
7263 0, /* oplock_request */
7264 0, /* allocation_size */
7265 0, /* private_flags */
7266 NULL, /* sd */
7267 NULL, /* ea_list */
7268 &fsp, /* result */
7269 &info); /* pinfo */
7271 if (NT_STATUS_IS_OK(status)) {
7272 close_file(req, fsp, NORMAL_CLOSE);
7275 info_level_return = SVAL(pdata,16);
7277 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7278 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7279 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7280 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7281 } else {
7282 *pdata_return_size = 12;
7285 /* Realloc the data size */
7286 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7287 if (*ppdata == NULL) {
7288 *pdata_return_size = 0;
7289 return NT_STATUS_NO_MEMORY;
7291 pdata = *ppdata;
7293 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7294 SSVAL(pdata,2,0); /* No fnum. */
7295 SIVAL(pdata,4,info); /* Was directory created. */
7297 switch (info_level_return) {
7298 case SMB_QUERY_FILE_UNIX_BASIC:
7299 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7300 SSVAL(pdata,10,0); /* Padding. */
7301 store_file_unix_basic(conn, pdata + 12, fsp,
7302 &smb_fname->st);
7303 break;
7304 case SMB_QUERY_FILE_UNIX_INFO2:
7305 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7306 SSVAL(pdata,10,0); /* Padding. */
7307 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7308 &smb_fname->st);
7309 break;
7310 default:
7311 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7312 SSVAL(pdata,10,0); /* Padding. */
7313 break;
7316 return status;
7319 /****************************************************************************
7320 Open/Create a file with POSIX semantics.
7321 ****************************************************************************/
7323 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7324 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7326 static NTSTATUS smb_posix_open(connection_struct *conn,
7327 struct smb_request *req,
7328 char **ppdata,
7329 int total_data,
7330 struct smb_filename *smb_fname,
7331 int *pdata_return_size)
7333 bool extended_oplock_granted = False;
7334 char *pdata = *ppdata;
7335 uint32 flags = 0;
7336 uint32 wire_open_mode = 0;
7337 uint32 raw_unixmode = 0;
7338 uint32 mod_unixmode = 0;
7339 uint32 create_disp = 0;
7340 uint32 access_mask = 0;
7341 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7342 NTSTATUS status = NT_STATUS_OK;
7343 mode_t unixmode = (mode_t)0;
7344 files_struct *fsp = NULL;
7345 int oplock_request = 0;
7346 int info = 0;
7347 uint16 info_level_return = 0;
7349 if (total_data < 18) {
7350 return NT_STATUS_INVALID_PARAMETER;
7353 flags = IVAL(pdata,0);
7354 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7355 if (oplock_request) {
7356 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7359 wire_open_mode = IVAL(pdata,4);
7361 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7362 return smb_posix_mkdir(conn, req,
7363 ppdata,
7364 total_data,
7365 smb_fname,
7366 pdata_return_size);
7369 switch (wire_open_mode & SMB_ACCMODE) {
7370 case SMB_O_RDONLY:
7371 access_mask = SMB_O_RDONLY_MAPPING;
7372 break;
7373 case SMB_O_WRONLY:
7374 access_mask = SMB_O_WRONLY_MAPPING;
7375 break;
7376 case SMB_O_RDWR:
7377 access_mask = (SMB_O_RDONLY_MAPPING|
7378 SMB_O_WRONLY_MAPPING);
7379 break;
7380 default:
7381 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7382 (unsigned int)wire_open_mode ));
7383 return NT_STATUS_INVALID_PARAMETER;
7386 wire_open_mode &= ~SMB_ACCMODE;
7388 /* First take care of O_CREAT|O_EXCL interactions. */
7389 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7390 case (SMB_O_CREAT | SMB_O_EXCL):
7391 /* File exists fail. File not exist create. */
7392 create_disp = FILE_CREATE;
7393 break;
7394 case SMB_O_CREAT:
7395 /* File exists open. File not exist create. */
7396 create_disp = FILE_OPEN_IF;
7397 break;
7398 case SMB_O_EXCL:
7399 /* O_EXCL on its own without O_CREAT is undefined.
7400 We deliberately ignore it as some versions of
7401 Linux CIFSFS can send a bare O_EXCL on the
7402 wire which other filesystems in the kernel
7403 ignore. See bug 9519 for details. */
7405 /* Fallthrough. */
7407 case 0:
7408 /* File exists open. File not exist fail. */
7409 create_disp = FILE_OPEN;
7410 break;
7411 default:
7412 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7413 (unsigned int)wire_open_mode ));
7414 return NT_STATUS_INVALID_PARAMETER;
7417 /* Next factor in the effects of O_TRUNC. */
7418 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7420 if (wire_open_mode & SMB_O_TRUNC) {
7421 switch (create_disp) {
7422 case FILE_CREATE:
7423 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7424 /* Leave create_disp alone as
7425 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7427 /* File exists fail. File not exist create. */
7428 break;
7429 case FILE_OPEN_IF:
7430 /* SMB_O_CREAT | SMB_O_TRUNC */
7431 /* File exists overwrite. File not exist create. */
7432 create_disp = FILE_OVERWRITE_IF;
7433 break;
7434 case FILE_OPEN:
7435 /* SMB_O_TRUNC */
7436 /* File exists overwrite. File not exist fail. */
7437 create_disp = FILE_OVERWRITE;
7438 break;
7439 default:
7440 /* Cannot get here. */
7441 smb_panic("smb_posix_open: logic error");
7442 return NT_STATUS_INVALID_PARAMETER;
7446 raw_unixmode = IVAL(pdata,8);
7447 /* Next 4 bytes are not yet defined. */
7449 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7450 (VALID_STAT(smb_fname->st) ?
7451 PERM_EXISTING_FILE : PERM_NEW_FILE),
7452 &unixmode);
7454 if (!NT_STATUS_IS_OK(status)) {
7455 return status;
7458 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7460 if (wire_open_mode & SMB_O_SYNC) {
7461 create_options |= FILE_WRITE_THROUGH;
7463 if (wire_open_mode & SMB_O_APPEND) {
7464 access_mask |= FILE_APPEND_DATA;
7466 if (wire_open_mode & SMB_O_DIRECT) {
7467 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7470 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7471 VALID_STAT_OF_DIR(smb_fname->st)) {
7472 if (access_mask != SMB_O_RDONLY_MAPPING) {
7473 return NT_STATUS_FILE_IS_A_DIRECTORY;
7475 create_options &= ~FILE_NON_DIRECTORY_FILE;
7476 create_options |= FILE_DIRECTORY_FILE;
7479 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7480 smb_fname_str_dbg(smb_fname),
7481 (unsigned int)wire_open_mode,
7482 (unsigned int)unixmode ));
7484 status = SMB_VFS_CREATE_FILE(
7485 conn, /* conn */
7486 req, /* req */
7487 0, /* root_dir_fid */
7488 smb_fname, /* fname */
7489 access_mask, /* access_mask */
7490 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7491 FILE_SHARE_DELETE),
7492 create_disp, /* create_disposition*/
7493 create_options, /* create_options */
7494 mod_unixmode, /* file_attributes */
7495 oplock_request, /* oplock_request */
7496 0, /* allocation_size */
7497 0, /* private_flags */
7498 NULL, /* sd */
7499 NULL, /* ea_list */
7500 &fsp, /* result */
7501 &info); /* pinfo */
7503 if (!NT_STATUS_IS_OK(status)) {
7504 return status;
7507 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7508 extended_oplock_granted = True;
7511 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7512 extended_oplock_granted = True;
7515 info_level_return = SVAL(pdata,16);
7517 /* Allocate the correct return size. */
7519 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7520 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7521 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7522 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7523 } else {
7524 *pdata_return_size = 12;
7527 /* Realloc the data size */
7528 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7529 if (*ppdata == NULL) {
7530 close_file(req, fsp, ERROR_CLOSE);
7531 *pdata_return_size = 0;
7532 return NT_STATUS_NO_MEMORY;
7534 pdata = *ppdata;
7536 if (extended_oplock_granted) {
7537 if (flags & REQUEST_BATCH_OPLOCK) {
7538 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7539 } else {
7540 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7542 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7543 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7544 } else {
7545 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7548 SSVAL(pdata,2,fsp->fnum);
7549 SIVAL(pdata,4,info); /* Was file created etc. */
7551 switch (info_level_return) {
7552 case SMB_QUERY_FILE_UNIX_BASIC:
7553 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7554 SSVAL(pdata,10,0); /* padding. */
7555 store_file_unix_basic(conn, pdata + 12, fsp,
7556 &smb_fname->st);
7557 break;
7558 case SMB_QUERY_FILE_UNIX_INFO2:
7559 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7560 SSVAL(pdata,10,0); /* padding. */
7561 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7562 &smb_fname->st);
7563 break;
7564 default:
7565 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7566 SSVAL(pdata,10,0); /* padding. */
7567 break;
7569 return NT_STATUS_OK;
7572 /****************************************************************************
7573 Delete a file with POSIX semantics.
7574 ****************************************************************************/
7576 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7577 struct smb_request *req,
7578 const char *pdata,
7579 int total_data,
7580 struct smb_filename *smb_fname)
7582 NTSTATUS status = NT_STATUS_OK;
7583 files_struct *fsp = NULL;
7584 uint16 flags = 0;
7585 char del = 1;
7586 int info = 0;
7587 int create_options = 0;
7588 int i;
7589 struct share_mode_lock *lck = NULL;
7591 if (total_data < 2) {
7592 return NT_STATUS_INVALID_PARAMETER;
7595 flags = SVAL(pdata,0);
7597 if (!VALID_STAT(smb_fname->st)) {
7598 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7601 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7602 !VALID_STAT_OF_DIR(smb_fname->st)) {
7603 return NT_STATUS_NOT_A_DIRECTORY;
7606 DEBUG(10,("smb_posix_unlink: %s %s\n",
7607 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7608 smb_fname_str_dbg(smb_fname)));
7610 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7611 create_options |= FILE_DIRECTORY_FILE;
7614 status = SMB_VFS_CREATE_FILE(
7615 conn, /* conn */
7616 req, /* req */
7617 0, /* root_dir_fid */
7618 smb_fname, /* fname */
7619 DELETE_ACCESS, /* access_mask */
7620 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7621 FILE_SHARE_DELETE),
7622 FILE_OPEN, /* create_disposition*/
7623 create_options, /* create_options */
7624 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7625 0, /* oplock_request */
7626 0, /* allocation_size */
7627 0, /* private_flags */
7628 NULL, /* sd */
7629 NULL, /* ea_list */
7630 &fsp, /* result */
7631 &info); /* pinfo */
7633 if (!NT_STATUS_IS_OK(status)) {
7634 return status;
7638 * Don't lie to client. If we can't really delete due to
7639 * non-POSIX opens return SHARING_VIOLATION.
7642 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7643 NULL);
7644 if (lck == NULL) {
7645 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7646 "lock for file %s\n", fsp_str_dbg(fsp)));
7647 close_file(req, fsp, NORMAL_CLOSE);
7648 return NT_STATUS_INVALID_PARAMETER;
7652 * See if others still have the file open. If this is the case, then
7653 * don't delete. If all opens are POSIX delete we can set the delete
7654 * on close disposition.
7656 for (i=0; i<lck->num_share_modes; i++) {
7657 struct share_mode_entry *e = &lck->share_modes[i];
7658 if (is_valid_share_mode_entry(e)) {
7659 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7660 continue;
7662 /* Fail with sharing violation. */
7663 TALLOC_FREE(lck);
7664 close_file(req, fsp, NORMAL_CLOSE);
7665 return NT_STATUS_SHARING_VIOLATION;
7670 * Set the delete on close.
7672 status = smb_set_file_disposition_info(conn,
7673 &del,
7675 fsp,
7676 smb_fname);
7678 TALLOC_FREE(lck);
7680 if (!NT_STATUS_IS_OK(status)) {
7681 close_file(req, fsp, NORMAL_CLOSE);
7682 return status;
7684 return close_file(req, fsp, NORMAL_CLOSE);
7687 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7688 struct smb_request *req,
7689 TALLOC_CTX *mem_ctx,
7690 uint16_t info_level,
7691 files_struct *fsp,
7692 struct smb_filename *smb_fname,
7693 char **ppdata, int total_data,
7694 int *ret_data_size)
7696 char *pdata = *ppdata;
7697 NTSTATUS status = NT_STATUS_OK;
7698 int data_return_size = 0;
7700 *ret_data_size = 0;
7702 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7703 return NT_STATUS_INVALID_LEVEL;
7706 if (!CAN_WRITE(conn)) {
7707 /* Allow POSIX opens. The open path will deny
7708 * any non-readonly opens. */
7709 if (info_level != SMB_POSIX_PATH_OPEN) {
7710 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7714 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7715 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7716 fsp ? fsp->fnum : -1, info_level, total_data));
7718 switch (info_level) {
7720 case SMB_INFO_STANDARD:
7722 status = smb_set_info_standard(conn,
7723 pdata,
7724 total_data,
7725 fsp,
7726 smb_fname);
7727 break;
7730 case SMB_INFO_SET_EA:
7732 status = smb_info_set_ea(conn,
7733 pdata,
7734 total_data,
7735 fsp,
7736 smb_fname);
7737 break;
7740 case SMB_SET_FILE_BASIC_INFO:
7741 case SMB_FILE_BASIC_INFORMATION:
7743 status = smb_set_file_basic_info(conn,
7744 pdata,
7745 total_data,
7746 fsp,
7747 smb_fname);
7748 break;
7751 case SMB_FILE_ALLOCATION_INFORMATION:
7752 case SMB_SET_FILE_ALLOCATION_INFO:
7754 status = smb_set_file_allocation_info(conn, req,
7755 pdata,
7756 total_data,
7757 fsp,
7758 smb_fname);
7759 break;
7762 case SMB_FILE_END_OF_FILE_INFORMATION:
7763 case SMB_SET_FILE_END_OF_FILE_INFO:
7766 * XP/Win7 both fail after the createfile with
7767 * SMB_SET_FILE_END_OF_FILE_INFO but not
7768 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7769 * The level is known here, so pass it down
7770 * appropriately.
7772 bool should_fail =
7773 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7775 status = smb_set_file_end_of_file_info(conn, req,
7776 pdata,
7777 total_data,
7778 fsp,
7779 smb_fname,
7780 should_fail);
7781 break;
7784 case SMB_FILE_DISPOSITION_INFORMATION:
7785 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7787 #if 0
7788 /* JRA - We used to just ignore this on a path ?
7789 * Shouldn't this be invalid level on a pathname
7790 * based call ?
7792 if (tran_call != TRANSACT2_SETFILEINFO) {
7793 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7795 #endif
7796 status = smb_set_file_disposition_info(conn,
7797 pdata,
7798 total_data,
7799 fsp,
7800 smb_fname);
7801 break;
7804 case SMB_FILE_POSITION_INFORMATION:
7806 status = smb_file_position_information(conn,
7807 pdata,
7808 total_data,
7809 fsp);
7810 break;
7813 case SMB_FILE_FULL_EA_INFORMATION:
7815 status = smb_set_file_full_ea_info(conn,
7816 pdata,
7817 total_data,
7818 fsp);
7819 break;
7822 /* From tridge Samba4 :
7823 * MODE_INFORMATION in setfileinfo (I have no
7824 * idea what "mode information" on a file is - it takes a value of 0,
7825 * 2, 4 or 6. What could it be?).
7828 case SMB_FILE_MODE_INFORMATION:
7830 status = smb_file_mode_information(conn,
7831 pdata,
7832 total_data);
7833 break;
7837 * CIFS UNIX extensions.
7840 case SMB_SET_FILE_UNIX_BASIC:
7842 status = smb_set_file_unix_basic(conn, req,
7843 pdata,
7844 total_data,
7845 fsp,
7846 smb_fname);
7847 break;
7850 case SMB_SET_FILE_UNIX_INFO2:
7852 status = smb_set_file_unix_info2(conn, req,
7853 pdata,
7854 total_data,
7855 fsp,
7856 smb_fname);
7857 break;
7860 case SMB_SET_FILE_UNIX_LINK:
7862 if (fsp) {
7863 /* We must have a pathname for this. */
7864 return NT_STATUS_INVALID_LEVEL;
7866 status = smb_set_file_unix_link(conn, req, pdata,
7867 total_data, smb_fname);
7868 break;
7871 case SMB_SET_FILE_UNIX_HLINK:
7873 if (fsp) {
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL;
7877 status = smb_set_file_unix_hlink(conn, req,
7878 pdata, total_data,
7879 smb_fname);
7880 break;
7883 case SMB_FILE_RENAME_INFORMATION:
7885 status = smb_file_rename_information(conn, req,
7886 pdata, total_data,
7887 fsp, smb_fname);
7888 break;
7891 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7893 /* SMB2 rename information. */
7894 status = smb2_file_rename_information(conn, req,
7895 pdata, total_data,
7896 fsp, smb_fname);
7897 break;
7900 case SMB_FILE_LINK_INFORMATION:
7902 status = smb_file_link_information(conn, req,
7903 pdata, total_data,
7904 fsp, smb_fname);
7905 break;
7908 #if defined(HAVE_POSIX_ACLS)
7909 case SMB_SET_POSIX_ACL:
7911 status = smb_set_posix_acl(conn,
7912 pdata,
7913 total_data,
7914 fsp,
7915 smb_fname);
7916 break;
7918 #endif
7920 case SMB_SET_POSIX_LOCK:
7922 if (!fsp) {
7923 return NT_STATUS_INVALID_LEVEL;
7925 status = smb_set_posix_lock(conn, req,
7926 pdata, total_data, fsp);
7927 break;
7930 case SMB_POSIX_PATH_OPEN:
7932 if (fsp) {
7933 /* We must have a pathname for this. */
7934 return NT_STATUS_INVALID_LEVEL;
7937 status = smb_posix_open(conn, req,
7938 ppdata,
7939 total_data,
7940 smb_fname,
7941 &data_return_size);
7942 break;
7945 case SMB_POSIX_PATH_UNLINK:
7947 if (fsp) {
7948 /* We must have a pathname for this. */
7949 return NT_STATUS_INVALID_LEVEL;
7952 status = smb_posix_unlink(conn, req,
7953 pdata,
7954 total_data,
7955 smb_fname);
7956 break;
7959 default:
7960 return NT_STATUS_INVALID_LEVEL;
7963 if (!NT_STATUS_IS_OK(status)) {
7964 return status;
7967 *ret_data_size = data_return_size;
7968 return NT_STATUS_OK;
7971 /****************************************************************************
7972 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7973 ****************************************************************************/
7975 static void call_trans2setfilepathinfo(connection_struct *conn,
7976 struct smb_request *req,
7977 unsigned int tran_call,
7978 char **pparams, int total_params,
7979 char **ppdata, int total_data,
7980 unsigned int max_data_bytes)
7982 char *params = *pparams;
7983 char *pdata = *ppdata;
7984 uint16 info_level;
7985 struct smb_filename *smb_fname = NULL;
7986 files_struct *fsp = NULL;
7987 NTSTATUS status = NT_STATUS_OK;
7988 int data_return_size = 0;
7990 if (!params) {
7991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7992 return;
7995 if (tran_call == TRANSACT2_SETFILEINFO) {
7996 if (total_params < 4) {
7997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7998 return;
8001 fsp = file_fsp(req, SVAL(params,0));
8002 /* Basic check for non-null fsp. */
8003 if (!check_fsp_open(conn, req, fsp)) {
8004 return;
8006 info_level = SVAL(params,2);
8008 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8009 &smb_fname);
8010 if (!NT_STATUS_IS_OK(status)) {
8011 reply_nterror(req, status);
8012 return;
8015 if(fsp->fh->fd == -1) {
8017 * This is actually a SETFILEINFO on a directory
8018 * handle (returned from an NT SMB). NT5.0 seems
8019 * to do this call. JRA.
8021 if (INFO_LEVEL_IS_UNIX(info_level)) {
8022 /* Always do lstat for UNIX calls. */
8023 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8024 DEBUG(3,("call_trans2setfilepathinfo: "
8025 "SMB_VFS_LSTAT of %s failed "
8026 "(%s)\n",
8027 smb_fname_str_dbg(smb_fname),
8028 strerror(errno)));
8029 reply_nterror(req, map_nt_error_from_unix(errno));
8030 return;
8032 } else {
8033 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8034 DEBUG(3,("call_trans2setfilepathinfo: "
8035 "fileinfo of %s failed (%s)\n",
8036 smb_fname_str_dbg(smb_fname),
8037 strerror(errno)));
8038 reply_nterror(req, map_nt_error_from_unix(errno));
8039 return;
8042 } else if (fsp->print_file) {
8044 * Doing a DELETE_ON_CLOSE should cancel a print job.
8046 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8047 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8049 DEBUG(3,("call_trans2setfilepathinfo: "
8050 "Cancelling print job (%s)\n",
8051 fsp_str_dbg(fsp)));
8053 SSVAL(params,0,0);
8054 send_trans2_replies(conn, req, params, 2,
8055 *ppdata, 0,
8056 max_data_bytes);
8057 return;
8058 } else {
8059 reply_nterror(req,
8060 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8061 return;
8063 } else {
8065 * Original code - this is an open file.
8067 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8068 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8069 "of fnum %d failed (%s)\n", fsp->fnum,
8070 strerror(errno)));
8071 reply_nterror(req, map_nt_error_from_unix(errno));
8072 return;
8075 } else {
8076 char *fname = NULL;
8077 uint32_t ucf_flags = 0;
8079 /* set path info */
8080 if (total_params < 7) {
8081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8082 return;
8085 info_level = SVAL(params,0);
8086 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8087 total_params - 6, STR_TERMINATE,
8088 &status);
8089 if (!NT_STATUS_IS_OK(status)) {
8090 reply_nterror(req, status);
8091 return;
8094 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8095 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8096 info_level == SMB_FILE_RENAME_INFORMATION ||
8097 info_level == SMB_POSIX_PATH_UNLINK) {
8098 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8101 status = filename_convert(req, conn,
8102 req->flags2 & FLAGS2_DFS_PATHNAMES,
8103 fname,
8104 ucf_flags,
8105 NULL,
8106 &smb_fname);
8107 if (!NT_STATUS_IS_OK(status)) {
8108 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8109 reply_botherror(req,
8110 NT_STATUS_PATH_NOT_COVERED,
8111 ERRSRV, ERRbadpath);
8112 return;
8114 reply_nterror(req, status);
8115 return;
8118 if (INFO_LEVEL_IS_UNIX(info_level)) {
8120 * For CIFS UNIX extensions the target name may not exist.
8123 /* Always do lstat for UNIX calls. */
8124 SMB_VFS_LSTAT(conn, smb_fname);
8126 } else if (!VALID_STAT(smb_fname->st) &&
8127 SMB_VFS_STAT(conn, smb_fname)) {
8128 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8129 "%s failed (%s)\n",
8130 smb_fname_str_dbg(smb_fname),
8131 strerror(errno)));
8132 reply_nterror(req, map_nt_error_from_unix(errno));
8133 return;
8137 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8138 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8139 fsp ? fsp->fnum : -1, info_level,total_data));
8141 /* Realloc the parameter size */
8142 *pparams = (char *)SMB_REALLOC(*pparams,2);
8143 if (*pparams == NULL) {
8144 reply_nterror(req, NT_STATUS_NO_MEMORY);
8145 return;
8147 params = *pparams;
8149 SSVAL(params,0,0);
8151 status = smbd_do_setfilepathinfo(conn, req, req,
8152 info_level,
8153 fsp,
8154 smb_fname,
8155 ppdata, total_data,
8156 &data_return_size);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 if (open_was_deferred(req->mid)) {
8159 /* We have re-scheduled this call. */
8160 return;
8162 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8163 /* We have re-scheduled this call. */
8164 return;
8166 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8167 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8168 ERRSRV, ERRbadpath);
8169 return;
8171 if (info_level == SMB_POSIX_PATH_OPEN) {
8172 reply_openerror(req, status);
8173 return;
8176 reply_nterror(req, status);
8177 return;
8180 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8181 max_data_bytes);
8183 return;
8186 /****************************************************************************
8187 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8188 ****************************************************************************/
8190 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8191 char **pparams, int total_params,
8192 char **ppdata, int total_data,
8193 unsigned int max_data_bytes)
8195 struct smb_filename *smb_dname = NULL;
8196 char *params = *pparams;
8197 char *pdata = *ppdata;
8198 char *directory = NULL;
8199 NTSTATUS status = NT_STATUS_OK;
8200 struct ea_list *ea_list = NULL;
8201 TALLOC_CTX *ctx = talloc_tos();
8203 if (!CAN_WRITE(conn)) {
8204 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8205 return;
8208 if (total_params < 5) {
8209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8210 return;
8213 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8214 total_params - 4, STR_TERMINATE,
8215 &status);
8216 if (!NT_STATUS_IS_OK(status)) {
8217 reply_nterror(req, status);
8218 return;
8221 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8223 status = filename_convert(ctx,
8224 conn,
8225 req->flags2 & FLAGS2_DFS_PATHNAMES,
8226 directory,
8228 NULL,
8229 &smb_dname);
8231 if (!NT_STATUS_IS_OK(status)) {
8232 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8233 reply_botherror(req,
8234 NT_STATUS_PATH_NOT_COVERED,
8235 ERRSRV, ERRbadpath);
8236 return;
8238 reply_nterror(req, status);
8239 return;
8243 * OS/2 workplace shell seems to send SET_EA requests of "null"
8244 * length (4 bytes containing IVAL 4).
8245 * They seem to have no effect. Bug #3212. JRA.
8248 if (total_data && (total_data != 4)) {
8249 /* Any data in this call is an EA list. */
8250 if (total_data < 10) {
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8252 goto out;
8255 if (IVAL(pdata,0) > total_data) {
8256 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8257 IVAL(pdata,0), (unsigned int)total_data));
8258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8259 goto out;
8262 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8263 total_data - 4);
8264 if (!ea_list) {
8265 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8266 goto out;
8269 if (!lp_ea_support(SNUM(conn))) {
8270 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8271 goto out;
8274 /* If total_data == 4 Windows doesn't care what values
8275 * are placed in that field, it just ignores them.
8276 * The System i QNTC IBM SMB client puts bad values here,
8277 * so ignore them. */
8279 status = create_directory(conn, req, smb_dname);
8281 if (!NT_STATUS_IS_OK(status)) {
8282 reply_nterror(req, status);
8283 goto out;
8286 /* Try and set any given EA. */
8287 if (ea_list) {
8288 status = set_ea(conn, NULL, smb_dname, ea_list);
8289 if (!NT_STATUS_IS_OK(status)) {
8290 reply_nterror(req, status);
8291 goto out;
8295 /* Realloc the parameter and data sizes */
8296 *pparams = (char *)SMB_REALLOC(*pparams,2);
8297 if(*pparams == NULL) {
8298 reply_nterror(req, NT_STATUS_NO_MEMORY);
8299 goto out;
8301 params = *pparams;
8303 SSVAL(params,0,0);
8305 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8307 out:
8308 TALLOC_FREE(smb_dname);
8309 return;
8312 /****************************************************************************
8313 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8314 We don't actually do this - we just send a null response.
8315 ****************************************************************************/
8317 static void call_trans2findnotifyfirst(connection_struct *conn,
8318 struct smb_request *req,
8319 char **pparams, int total_params,
8320 char **ppdata, int total_data,
8321 unsigned int max_data_bytes)
8323 char *params = *pparams;
8324 uint16 info_level;
8326 if (total_params < 6) {
8327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8328 return;
8331 info_level = SVAL(params,4);
8332 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8334 switch (info_level) {
8335 case 1:
8336 case 2:
8337 break;
8338 default:
8339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8340 return;
8343 /* Realloc the parameter and data sizes */
8344 *pparams = (char *)SMB_REALLOC(*pparams,6);
8345 if (*pparams == NULL) {
8346 reply_nterror(req, NT_STATUS_NO_MEMORY);
8347 return;
8349 params = *pparams;
8351 SSVAL(params,0,fnf_handle);
8352 SSVAL(params,2,0); /* No changes */
8353 SSVAL(params,4,0); /* No EA errors */
8355 fnf_handle++;
8357 if(fnf_handle == 0)
8358 fnf_handle = 257;
8360 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8362 return;
8365 /****************************************************************************
8366 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8367 changes). Currently this does nothing.
8368 ****************************************************************************/
8370 static void call_trans2findnotifynext(connection_struct *conn,
8371 struct smb_request *req,
8372 char **pparams, int total_params,
8373 char **ppdata, int total_data,
8374 unsigned int max_data_bytes)
8376 char *params = *pparams;
8378 DEBUG(3,("call_trans2findnotifynext\n"));
8380 /* Realloc the parameter and data sizes */
8381 *pparams = (char *)SMB_REALLOC(*pparams,4);
8382 if (*pparams == NULL) {
8383 reply_nterror(req, NT_STATUS_NO_MEMORY);
8384 return;
8386 params = *pparams;
8388 SSVAL(params,0,0); /* No changes */
8389 SSVAL(params,2,0); /* No EA errors */
8391 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8393 return;
8396 /****************************************************************************
8397 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8398 ****************************************************************************/
8400 static void call_trans2getdfsreferral(connection_struct *conn,
8401 struct smb_request *req,
8402 char **pparams, int total_params,
8403 char **ppdata, int total_data,
8404 unsigned int max_data_bytes)
8406 char *params = *pparams;
8407 char *pathname = NULL;
8408 int reply_size = 0;
8409 int max_referral_level;
8410 NTSTATUS status = NT_STATUS_OK;
8411 TALLOC_CTX *ctx = talloc_tos();
8413 DEBUG(10,("call_trans2getdfsreferral\n"));
8415 if (total_params < 3) {
8416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8417 return;
8420 max_referral_level = SVAL(params,0);
8422 if(!lp_host_msdfs()) {
8423 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8424 return;
8427 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8428 total_params - 2, STR_TERMINATE);
8429 if (!pathname) {
8430 reply_nterror(req, NT_STATUS_NOT_FOUND);
8431 return;
8433 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8434 ppdata,&status)) < 0) {
8435 reply_nterror(req, status);
8436 return;
8439 SSVAL(req->inbuf, smb_flg2,
8440 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8441 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8443 return;
8446 #define LMCAT_SPL 0x53
8447 #define LMFUNC_GETJOBID 0x60
8449 /****************************************************************************
8450 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8451 ****************************************************************************/
8453 static void call_trans2ioctl(connection_struct *conn,
8454 struct smb_request *req,
8455 char **pparams, int total_params,
8456 char **ppdata, int total_data,
8457 unsigned int max_data_bytes)
8459 char *pdata = *ppdata;
8460 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8462 /* check for an invalid fid before proceeding */
8464 if (!fsp) {
8465 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8466 return;
8469 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8470 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8471 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8472 if (*ppdata == NULL) {
8473 reply_nterror(req, NT_STATUS_NO_MEMORY);
8474 return;
8476 pdata = *ppdata;
8478 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8479 CAN ACCEPT THIS IN UNICODE. JRA. */
8481 /* Job number */
8482 if (fsp->print_file) {
8483 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8484 } else {
8485 SSVAL(pdata, 0, 0);
8487 srvstr_push(pdata, req->flags2, pdata + 2,
8488 global_myname(), 15,
8489 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8490 srvstr_push(pdata, req->flags2, pdata+18,
8491 lp_servicename(SNUM(conn)), 13,
8492 STR_ASCII|STR_TERMINATE); /* Service name */
8493 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8494 max_data_bytes);
8495 return;
8498 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8499 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8502 /****************************************************************************
8503 Reply to a SMBfindclose (stop trans2 directory search).
8504 ****************************************************************************/
8506 void reply_findclose(struct smb_request *req)
8508 int dptr_num;
8509 struct smbd_server_connection *sconn = req->sconn;
8511 START_PROFILE(SMBfindclose);
8513 if (req->wct < 1) {
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8515 END_PROFILE(SMBfindclose);
8516 return;
8519 dptr_num = SVALS(req->vwv+0, 0);
8521 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8523 dptr_close(sconn, &dptr_num);
8525 reply_outbuf(req, 0, 0);
8527 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8529 END_PROFILE(SMBfindclose);
8530 return;
8533 /****************************************************************************
8534 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8535 ****************************************************************************/
8537 void reply_findnclose(struct smb_request *req)
8539 int dptr_num;
8541 START_PROFILE(SMBfindnclose);
8543 if (req->wct < 1) {
8544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8545 END_PROFILE(SMBfindnclose);
8546 return;
8549 dptr_num = SVAL(req->vwv+0, 0);
8551 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8553 /* We never give out valid handles for a
8554 findnotifyfirst - so any dptr_num is ok here.
8555 Just ignore it. */
8557 reply_outbuf(req, 0, 0);
8559 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8561 END_PROFILE(SMBfindnclose);
8562 return;
8565 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8566 struct trans_state *state)
8568 if (get_Protocol() >= PROTOCOL_NT1) {
8569 req->flags2 |= 0x40; /* IS_LONG_NAME */
8570 SSVAL(req->inbuf,smb_flg2,req->flags2);
8573 if (conn->encrypt_level == Required && !req->encrypted) {
8574 if (state->call != TRANSACT2_QFSINFO &&
8575 state->call != TRANSACT2_SETFSINFO) {
8576 DEBUG(0,("handle_trans2: encryption required "
8577 "with call 0x%x\n",
8578 (unsigned int)state->call));
8579 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8580 return;
8584 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8586 /* Now we must call the relevant TRANS2 function */
8587 switch(state->call) {
8588 case TRANSACT2_OPEN:
8590 START_PROFILE(Trans2_open);
8591 call_trans2open(conn, req,
8592 &state->param, state->total_param,
8593 &state->data, state->total_data,
8594 state->max_data_return);
8595 END_PROFILE(Trans2_open);
8596 break;
8599 case TRANSACT2_FINDFIRST:
8601 START_PROFILE(Trans2_findfirst);
8602 call_trans2findfirst(conn, req,
8603 &state->param, state->total_param,
8604 &state->data, state->total_data,
8605 state->max_data_return);
8606 END_PROFILE(Trans2_findfirst);
8607 break;
8610 case TRANSACT2_FINDNEXT:
8612 START_PROFILE(Trans2_findnext);
8613 call_trans2findnext(conn, req,
8614 &state->param, state->total_param,
8615 &state->data, state->total_data,
8616 state->max_data_return);
8617 END_PROFILE(Trans2_findnext);
8618 break;
8621 case TRANSACT2_QFSINFO:
8623 START_PROFILE(Trans2_qfsinfo);
8624 call_trans2qfsinfo(conn, req,
8625 &state->param, state->total_param,
8626 &state->data, state->total_data,
8627 state->max_data_return);
8628 END_PROFILE(Trans2_qfsinfo);
8629 break;
8632 case TRANSACT2_SETFSINFO:
8634 START_PROFILE(Trans2_setfsinfo);
8635 call_trans2setfsinfo(conn, req,
8636 &state->param, state->total_param,
8637 &state->data, state->total_data,
8638 state->max_data_return);
8639 END_PROFILE(Trans2_setfsinfo);
8640 break;
8643 case TRANSACT2_QPATHINFO:
8644 case TRANSACT2_QFILEINFO:
8646 START_PROFILE(Trans2_qpathinfo);
8647 call_trans2qfilepathinfo(conn, req, state->call,
8648 &state->param, state->total_param,
8649 &state->data, state->total_data,
8650 state->max_data_return);
8651 END_PROFILE(Trans2_qpathinfo);
8652 break;
8655 case TRANSACT2_SETPATHINFO:
8656 case TRANSACT2_SETFILEINFO:
8658 START_PROFILE(Trans2_setpathinfo);
8659 call_trans2setfilepathinfo(conn, req, state->call,
8660 &state->param, state->total_param,
8661 &state->data, state->total_data,
8662 state->max_data_return);
8663 END_PROFILE(Trans2_setpathinfo);
8664 break;
8667 case TRANSACT2_FINDNOTIFYFIRST:
8669 START_PROFILE(Trans2_findnotifyfirst);
8670 call_trans2findnotifyfirst(conn, req,
8671 &state->param, state->total_param,
8672 &state->data, state->total_data,
8673 state->max_data_return);
8674 END_PROFILE(Trans2_findnotifyfirst);
8675 break;
8678 case TRANSACT2_FINDNOTIFYNEXT:
8680 START_PROFILE(Trans2_findnotifynext);
8681 call_trans2findnotifynext(conn, req,
8682 &state->param, state->total_param,
8683 &state->data, state->total_data,
8684 state->max_data_return);
8685 END_PROFILE(Trans2_findnotifynext);
8686 break;
8689 case TRANSACT2_MKDIR:
8691 START_PROFILE(Trans2_mkdir);
8692 call_trans2mkdir(conn, req,
8693 &state->param, state->total_param,
8694 &state->data, state->total_data,
8695 state->max_data_return);
8696 END_PROFILE(Trans2_mkdir);
8697 break;
8700 case TRANSACT2_GET_DFS_REFERRAL:
8702 START_PROFILE(Trans2_get_dfs_referral);
8703 call_trans2getdfsreferral(conn, req,
8704 &state->param, state->total_param,
8705 &state->data, state->total_data,
8706 state->max_data_return);
8707 END_PROFILE(Trans2_get_dfs_referral);
8708 break;
8711 case TRANSACT2_IOCTL:
8713 START_PROFILE(Trans2_ioctl);
8714 call_trans2ioctl(conn, req,
8715 &state->param, state->total_param,
8716 &state->data, state->total_data,
8717 state->max_data_return);
8718 END_PROFILE(Trans2_ioctl);
8719 break;
8722 default:
8723 /* Error in request */
8724 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8725 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8729 /****************************************************************************
8730 Reply to a SMBtrans2.
8731 ****************************************************************************/
8733 void reply_trans2(struct smb_request *req)
8735 connection_struct *conn = req->conn;
8736 unsigned int dsoff;
8737 unsigned int dscnt;
8738 unsigned int psoff;
8739 unsigned int pscnt;
8740 unsigned int tran_call;
8741 struct trans_state *state;
8742 NTSTATUS result;
8744 START_PROFILE(SMBtrans2);
8746 if (req->wct < 14) {
8747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8748 END_PROFILE(SMBtrans2);
8749 return;
8752 dsoff = SVAL(req->vwv+12, 0);
8753 dscnt = SVAL(req->vwv+11, 0);
8754 psoff = SVAL(req->vwv+10, 0);
8755 pscnt = SVAL(req->vwv+9, 0);
8756 tran_call = SVAL(req->vwv+14, 0);
8758 result = allow_new_trans(conn->pending_trans, req->mid);
8759 if (!NT_STATUS_IS_OK(result)) {
8760 DEBUG(2, ("Got invalid trans2 request: %s\n",
8761 nt_errstr(result)));
8762 reply_nterror(req, result);
8763 END_PROFILE(SMBtrans2);
8764 return;
8767 if (IS_IPC(conn)) {
8768 switch (tran_call) {
8769 /* List the allowed trans2 calls on IPC$ */
8770 case TRANSACT2_OPEN:
8771 case TRANSACT2_GET_DFS_REFERRAL:
8772 case TRANSACT2_QFILEINFO:
8773 case TRANSACT2_QFSINFO:
8774 case TRANSACT2_SETFSINFO:
8775 break;
8776 default:
8777 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8778 END_PROFILE(SMBtrans2);
8779 return;
8783 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8784 DEBUG(0, ("talloc failed\n"));
8785 reply_nterror(req, NT_STATUS_NO_MEMORY);
8786 END_PROFILE(SMBtrans2);
8787 return;
8790 state->cmd = SMBtrans2;
8792 state->mid = req->mid;
8793 state->vuid = req->vuid;
8794 state->setup_count = SVAL(req->vwv+13, 0);
8795 state->setup = NULL;
8796 state->total_param = SVAL(req->vwv+0, 0);
8797 state->param = NULL;
8798 state->total_data = SVAL(req->vwv+1, 0);
8799 state->data = NULL;
8800 state->max_param_return = SVAL(req->vwv+2, 0);
8801 state->max_data_return = SVAL(req->vwv+3, 0);
8802 state->max_setup_return = SVAL(req->vwv+4, 0);
8803 state->close_on_completion = BITSETW(req->vwv+5, 0);
8804 state->one_way = BITSETW(req->vwv+5, 1);
8806 state->call = tran_call;
8808 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8809 is so as a sanity check */
8810 if (state->setup_count != 1) {
8812 * Need to have rc=0 for ioctl to get job id for OS/2.
8813 * Network printing will fail if function is not successful.
8814 * Similar function in reply.c will be used if protocol
8815 * is LANMAN1.0 instead of LM1.2X002.
8816 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8817 * outbuf doesn't have to be set(only job id is used).
8819 if ( (state->setup_count == 4)
8820 && (tran_call == TRANSACT2_IOCTL)
8821 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8822 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8823 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8824 } else {
8825 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8826 DEBUG(2,("Transaction is %d\n",tran_call));
8827 TALLOC_FREE(state);
8828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8829 END_PROFILE(SMBtrans2);
8830 return;
8834 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8835 goto bad_param;
8837 if (state->total_data) {
8839 if (trans_oob(state->total_data, 0, dscnt)
8840 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8841 goto bad_param;
8844 /* Can't use talloc here, the core routines do realloc on the
8845 * params and data. */
8846 state->data = (char *)SMB_MALLOC(state->total_data);
8847 if (state->data == NULL) {
8848 DEBUG(0,("reply_trans2: data malloc fail for %u "
8849 "bytes !\n", (unsigned int)state->total_data));
8850 TALLOC_FREE(state);
8851 reply_nterror(req, NT_STATUS_NO_MEMORY);
8852 END_PROFILE(SMBtrans2);
8853 return;
8856 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8859 if (state->total_param) {
8861 if (trans_oob(state->total_param, 0, pscnt)
8862 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8863 goto bad_param;
8866 /* Can't use talloc here, the core routines do realloc on the
8867 * params and data. */
8868 state->param = (char *)SMB_MALLOC(state->total_param);
8869 if (state->param == NULL) {
8870 DEBUG(0,("reply_trans: param malloc fail for %u "
8871 "bytes !\n", (unsigned int)state->total_param));
8872 SAFE_FREE(state->data);
8873 TALLOC_FREE(state);
8874 reply_nterror(req, NT_STATUS_NO_MEMORY);
8875 END_PROFILE(SMBtrans2);
8876 return;
8879 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8882 state->received_data = dscnt;
8883 state->received_param = pscnt;
8885 if ((state->received_param == state->total_param) &&
8886 (state->received_data == state->total_data)) {
8888 handle_trans2(conn, req, state);
8890 SAFE_FREE(state->data);
8891 SAFE_FREE(state->param);
8892 TALLOC_FREE(state);
8893 END_PROFILE(SMBtrans2);
8894 return;
8897 DLIST_ADD(conn->pending_trans, state);
8899 /* We need to send an interim response then receive the rest
8900 of the parameter/data bytes */
8901 reply_outbuf(req, 0, 0);
8902 show_msg((char *)req->outbuf);
8903 END_PROFILE(SMBtrans2);
8904 return;
8906 bad_param:
8908 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8909 SAFE_FREE(state->data);
8910 SAFE_FREE(state->param);
8911 TALLOC_FREE(state);
8912 END_PROFILE(SMBtrans2);
8913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8917 /****************************************************************************
8918 Reply to a SMBtranss2
8919 ****************************************************************************/
8921 void reply_transs2(struct smb_request *req)
8923 connection_struct *conn = req->conn;
8924 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8925 struct trans_state *state;
8927 START_PROFILE(SMBtranss2);
8929 show_msg((char *)req->inbuf);
8931 /* Windows clients expect all replies to
8932 a transact secondary (SMBtranss2 0x33)
8933 to have a command code of transact
8934 (SMBtrans2 0x32). See bug #8989
8935 and also [MS-CIFS] section 2.2.4.47.2
8936 for details.
8938 req->cmd = SMBtrans2;
8940 if (req->wct < 8) {
8941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8942 END_PROFILE(SMBtranss2);
8943 return;
8946 for (state = conn->pending_trans; state != NULL;
8947 state = state->next) {
8948 if (state->mid == req->mid) {
8949 break;
8953 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8955 END_PROFILE(SMBtranss2);
8956 return;
8959 /* Revise state->total_param and state->total_data in case they have
8960 changed downwards */
8962 if (SVAL(req->vwv+0, 0) < state->total_param)
8963 state->total_param = SVAL(req->vwv+0, 0);
8964 if (SVAL(req->vwv+1, 0) < state->total_data)
8965 state->total_data = SVAL(req->vwv+1, 0);
8967 pcnt = SVAL(req->vwv+2, 0);
8968 poff = SVAL(req->vwv+3, 0);
8969 pdisp = SVAL(req->vwv+4, 0);
8971 dcnt = SVAL(req->vwv+5, 0);
8972 doff = SVAL(req->vwv+6, 0);
8973 ddisp = SVAL(req->vwv+7, 0);
8975 state->received_param += pcnt;
8976 state->received_data += dcnt;
8978 if ((state->received_data > state->total_data) ||
8979 (state->received_param > state->total_param))
8980 goto bad_param;
8982 if (pcnt) {
8983 if (trans_oob(state->total_param, pdisp, pcnt)
8984 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8985 goto bad_param;
8987 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8990 if (dcnt) {
8991 if (trans_oob(state->total_data, ddisp, dcnt)
8992 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8993 goto bad_param;
8995 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8998 if ((state->received_param < state->total_param) ||
8999 (state->received_data < state->total_data)) {
9000 END_PROFILE(SMBtranss2);
9001 return;
9004 handle_trans2(conn, req, state);
9006 DLIST_REMOVE(conn->pending_trans, state);
9007 SAFE_FREE(state->data);
9008 SAFE_FREE(state->param);
9009 TALLOC_FREE(state);
9011 END_PROFILE(SMBtranss2);
9012 return;
9014 bad_param:
9016 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9017 DLIST_REMOVE(conn->pending_trans, state);
9018 SAFE_FREE(state->data);
9019 SAFE_FREE(state->param);
9020 TALLOC_FREE(state);
9021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9022 END_PROFILE(SMBtranss2);
9023 return;