s3:smbd: allow status code in smbd_do_qfsinfo() to be set by information class handler
[Samba.git] / source3 / smbd / trans2.c
blob20d42f7ea254abee0c03dd01528be76de6db24d5
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 break;
3149 case SMB_QUERY_FS_SIZE_INFO:
3150 case SMB_FS_SIZE_INFORMATION:
3152 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3153 data_len = 24;
3154 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3155 return map_nt_error_from_unix(errno);
3157 block_size = lp_block_size(snum);
3158 if (bsize < block_size) {
3159 uint64_t factor = block_size/bsize;
3160 bsize = block_size;
3161 dsize /= factor;
3162 dfree /= factor;
3164 if (bsize > block_size) {
3165 uint64_t factor = bsize/block_size;
3166 bsize = block_size;
3167 dsize *= factor;
3168 dfree *= factor;
3170 bytes_per_sector = 512;
3171 sectors_per_unit = bsize/bytes_per_sector;
3172 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3173 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3174 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3175 SBIG_UINT(pdata,0,dsize);
3176 SBIG_UINT(pdata,8,dfree);
3177 SIVAL(pdata,16,sectors_per_unit);
3178 SIVAL(pdata,20,bytes_per_sector);
3179 break;
3182 case SMB_FS_FULL_SIZE_INFORMATION:
3184 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3185 data_len = 32;
3186 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3187 return map_nt_error_from_unix(errno);
3189 block_size = lp_block_size(snum);
3190 if (bsize < block_size) {
3191 uint64_t factor = block_size/bsize;
3192 bsize = block_size;
3193 dsize /= factor;
3194 dfree /= factor;
3196 if (bsize > block_size) {
3197 uint64_t factor = bsize/block_size;
3198 bsize = block_size;
3199 dsize *= factor;
3200 dfree *= factor;
3202 bytes_per_sector = 512;
3203 sectors_per_unit = bsize/bytes_per_sector;
3204 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3205 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3206 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3207 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3208 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3209 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3210 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3211 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3212 break;
3215 case SMB_QUERY_FS_DEVICE_INFO:
3216 case SMB_FS_DEVICE_INFORMATION:
3218 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3220 if (!CAN_WRITE(conn)) {
3221 characteristics |= FILE_READ_ONLY_DEVICE;
3223 data_len = 8;
3224 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3225 SIVAL(pdata,4,characteristics);
3226 break;
3229 #ifdef HAVE_SYS_QUOTAS
3230 case SMB_FS_QUOTA_INFORMATION:
3232 * what we have to send --metze:
3234 * Unknown1: 24 NULL bytes
3235 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3236 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3237 * Quota Flags: 2 byte :
3238 * Unknown3: 6 NULL bytes
3240 * 48 bytes total
3242 * details for Quota Flags:
3244 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3245 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3246 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3247 * 0x0001 Enable Quotas: enable quota for this fs
3251 /* we need to fake up a fsp here,
3252 * because its not send in this call
3254 files_struct fsp;
3255 SMB_NTQUOTA_STRUCT quotas;
3257 ZERO_STRUCT(fsp);
3258 ZERO_STRUCT(quotas);
3260 fsp.conn = conn;
3261 fsp.fnum = -1;
3263 /* access check */
3264 if (get_current_uid(conn) != 0) {
3265 DEBUG(0,("set_user_quota: access_denied "
3266 "service [%s] user [%s]\n",
3267 lp_servicename(SNUM(conn)),
3268 conn->session_info->unix_name));
3269 return NT_STATUS_ACCESS_DENIED;
3272 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3273 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3274 return map_nt_error_from_unix(errno);
3277 data_len = 48;
3279 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3280 lp_servicename(SNUM(conn))));
3282 /* Unknown1 24 NULL bytes*/
3283 SBIG_UINT(pdata,0,(uint64_t)0);
3284 SBIG_UINT(pdata,8,(uint64_t)0);
3285 SBIG_UINT(pdata,16,(uint64_t)0);
3287 /* Default Soft Quota 8 bytes */
3288 SBIG_UINT(pdata,24,quotas.softlim);
3290 /* Default Hard Quota 8 bytes */
3291 SBIG_UINT(pdata,32,quotas.hardlim);
3293 /* Quota flag 2 bytes */
3294 SSVAL(pdata,40,quotas.qflags);
3296 /* Unknown3 6 NULL bytes */
3297 SSVAL(pdata,42,0);
3298 SIVAL(pdata,44,0);
3300 break;
3302 #endif /* HAVE_SYS_QUOTAS */
3303 case SMB_FS_OBJECTID_INFORMATION:
3305 unsigned char objid[16];
3306 struct smb_extended_info extended_info;
3307 memcpy(pdata,create_volume_objectid(conn, objid),16);
3308 samba_extended_info_version (&extended_info);
3309 SIVAL(pdata,16,extended_info.samba_magic);
3310 SIVAL(pdata,20,extended_info.samba_version);
3311 SIVAL(pdata,24,extended_info.samba_subversion);
3312 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3313 memcpy(pdata+36,extended_info.samba_version_string,28);
3314 data_len = 64;
3315 break;
3319 * Query the version and capabilities of the CIFS UNIX extensions
3320 * in use.
3323 case SMB_QUERY_CIFS_UNIX_INFO:
3325 bool large_write = lp_min_receive_file_size() &&
3326 !srv_is_signing_active(conn->sconn);
3327 bool large_read = !srv_is_signing_active(conn->sconn);
3328 int encrypt_caps = 0;
3330 if (!lp_unix_extensions()) {
3331 return NT_STATUS_INVALID_LEVEL;
3334 switch (conn->encrypt_level) {
3335 case 0:
3336 encrypt_caps = 0;
3337 break;
3338 case 1:
3339 case Auto:
3340 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3341 break;
3342 case Required:
3343 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3344 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3345 large_write = false;
3346 large_read = false;
3347 break;
3350 data_len = 12;
3351 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3352 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3354 /* We have POSIX ACLs, pathname, encryption,
3355 * large read/write, and locking capability. */
3357 SBIG_UINT(pdata,4,((uint64_t)(
3358 CIFS_UNIX_POSIX_ACLS_CAP|
3359 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3360 CIFS_UNIX_FCNTL_LOCKS_CAP|
3361 CIFS_UNIX_EXTATTR_CAP|
3362 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3363 encrypt_caps|
3364 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3365 (large_write ?
3366 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3367 break;
3370 case SMB_QUERY_POSIX_FS_INFO:
3372 int rc;
3373 vfs_statvfs_struct svfs;
3375 if (!lp_unix_extensions()) {
3376 return NT_STATUS_INVALID_LEVEL;
3379 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3381 if (!rc) {
3382 data_len = 56;
3383 SIVAL(pdata,0,svfs.OptimalTransferSize);
3384 SIVAL(pdata,4,svfs.BlockSize);
3385 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3386 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3387 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3388 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3389 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3390 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3391 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3392 #ifdef EOPNOTSUPP
3393 } else if (rc == EOPNOTSUPP) {
3394 return NT_STATUS_INVALID_LEVEL;
3395 #endif /* EOPNOTSUPP */
3396 } else {
3397 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3398 return NT_STATUS_DOS(ERRSRV, ERRerror);
3400 break;
3403 case SMB_QUERY_POSIX_WHOAMI:
3405 uint32_t flags = 0;
3406 uint32_t sid_bytes;
3407 int i;
3409 if (!lp_unix_extensions()) {
3410 return NT_STATUS_INVALID_LEVEL;
3413 if (max_data_bytes < 40) {
3414 return NT_STATUS_BUFFER_TOO_SMALL;
3417 /* We ARE guest if global_sid_Builtin_Guests is
3418 * in our list of SIDs.
3420 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3421 conn->session_info->security_token)) {
3422 flags |= SMB_WHOAMI_GUEST;
3425 /* We are NOT guest if global_sid_Authenticated_Users
3426 * is in our list of SIDs.
3428 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3429 conn->session_info->security_token)) {
3430 flags &= ~SMB_WHOAMI_GUEST;
3433 /* NOTE: 8 bytes for UID/GID, irrespective of native
3434 * platform size. This matches
3435 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3437 data_len = 4 /* flags */
3438 + 4 /* flag mask */
3439 + 8 /* uid */
3440 + 8 /* gid */
3441 + 4 /* ngroups */
3442 + 4 /* num_sids */
3443 + 4 /* SID bytes */
3444 + 4 /* pad/reserved */
3445 + (conn->session_info->utok.ngroups * 8)
3446 /* groups list */
3447 + (conn->session_info->security_token->num_sids *
3448 SID_MAX_SIZE)
3449 /* SID list */;
3451 SIVAL(pdata, 0, flags);
3452 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3453 SBIG_UINT(pdata, 8,
3454 (uint64_t)conn->session_info->utok.uid);
3455 SBIG_UINT(pdata, 16,
3456 (uint64_t)conn->session_info->utok.gid);
3459 if (data_len >= max_data_bytes) {
3460 /* Potential overflow, skip the GIDs and SIDs. */
3462 SIVAL(pdata, 24, 0); /* num_groups */
3463 SIVAL(pdata, 28, 0); /* num_sids */
3464 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3465 SIVAL(pdata, 36, 0); /* reserved */
3467 data_len = 40;
3468 break;
3471 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3472 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3474 /* We walk the SID list twice, but this call is fairly
3475 * infrequent, and I don't expect that it's performance
3476 * sensitive -- jpeach
3478 for (i = 0, sid_bytes = 0;
3479 i < conn->session_info->security_token->num_sids; ++i) {
3480 sid_bytes += ndr_size_dom_sid(
3481 &conn->session_info->security_token->sids[i],
3485 /* SID list byte count */
3486 SIVAL(pdata, 32, sid_bytes);
3488 /* 4 bytes pad/reserved - must be zero */
3489 SIVAL(pdata, 36, 0);
3490 data_len = 40;
3492 /* GID list */
3493 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3494 SBIG_UINT(pdata, data_len,
3495 (uint64_t)conn->session_info->utok.groups[i]);
3496 data_len += 8;
3499 /* SID list */
3500 for (i = 0;
3501 i < conn->session_info->security_token->num_sids; ++i) {
3502 int sid_len = ndr_size_dom_sid(
3503 &conn->session_info->security_token->sids[i],
3506 sid_linearize(pdata + data_len, sid_len,
3507 &conn->session_info->security_token->sids[i]);
3508 data_len += sid_len;
3511 break;
3514 case SMB_MAC_QUERY_FS_INFO:
3516 * Thursby MAC extension... ONLY on NTFS filesystems
3517 * once we do streams then we don't need this
3519 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3520 data_len = 88;
3521 SIVAL(pdata,84,0x100); /* Don't support mac... */
3522 break;
3524 /* drop through */
3525 default:
3526 return NT_STATUS_INVALID_LEVEL;
3529 *ret_data_len = data_len;
3530 return status;
3533 /****************************************************************************
3534 Reply to a TRANS2_QFSINFO (query filesystem info).
3535 ****************************************************************************/
3537 static void call_trans2qfsinfo(connection_struct *conn,
3538 struct smb_request *req,
3539 char **pparams, int total_params,
3540 char **ppdata, int total_data,
3541 unsigned int max_data_bytes)
3543 char *params = *pparams;
3544 uint16_t info_level;
3545 int data_len = 0;
3546 NTSTATUS status;
3548 if (total_params < 2) {
3549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550 return;
3553 info_level = SVAL(params,0);
3555 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3556 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3557 DEBUG(0,("call_trans2qfsinfo: encryption required "
3558 "and info level 0x%x sent.\n",
3559 (unsigned int)info_level));
3560 exit_server_cleanly("encryption required "
3561 "on connection");
3562 return;
3566 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3568 status = smbd_do_qfsinfo(conn, req,
3569 info_level,
3570 req->flags2,
3571 max_data_bytes,
3572 NULL,
3573 ppdata, &data_len);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 reply_nterror(req, status);
3576 return;
3579 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3580 max_data_bytes);
3582 DEBUG( 4, ( "%s info_level = %d\n",
3583 smb_fn_name(req->cmd), info_level) );
3585 return;
3588 /****************************************************************************
3589 Reply to a TRANS2_SETFSINFO (set filesystem info).
3590 ****************************************************************************/
3592 static void call_trans2setfsinfo(connection_struct *conn,
3593 struct smb_request *req,
3594 char **pparams, int total_params,
3595 char **ppdata, int total_data,
3596 unsigned int max_data_bytes)
3598 char *pdata = *ppdata;
3599 char *params = *pparams;
3600 uint16 info_level;
3602 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3604 /* */
3605 if (total_params < 4) {
3606 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3607 total_params));
3608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3609 return;
3612 info_level = SVAL(params,2);
3614 if (IS_IPC(conn)) {
3615 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3616 info_level != SMB_SET_CIFS_UNIX_INFO) {
3617 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3618 "info level (0x%x) on IPC$.\n",
3619 (unsigned int)info_level));
3620 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3621 return;
3625 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3626 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3627 DEBUG(0,("call_trans2setfsinfo: encryption required "
3628 "and info level 0x%x sent.\n",
3629 (unsigned int)info_level));
3630 exit_server_cleanly("encryption required "
3631 "on connection");
3632 return;
3636 switch(info_level) {
3637 case SMB_SET_CIFS_UNIX_INFO:
3639 uint16 client_unix_major;
3640 uint16 client_unix_minor;
3641 uint32 client_unix_cap_low;
3642 uint32 client_unix_cap_high;
3644 if (!lp_unix_extensions()) {
3645 reply_nterror(req,
3646 NT_STATUS_INVALID_LEVEL);
3647 return;
3650 /* There should be 12 bytes of capabilities set. */
3651 if (total_data < 8) {
3652 reply_nterror(
3653 req,
3654 NT_STATUS_INVALID_PARAMETER);
3655 return;
3657 client_unix_major = SVAL(pdata,0);
3658 client_unix_minor = SVAL(pdata,2);
3659 client_unix_cap_low = IVAL(pdata,4);
3660 client_unix_cap_high = IVAL(pdata,8);
3661 /* Just print these values for now. */
3662 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3663 cap_low = 0x%x, cap_high = 0x%x\n",
3664 (unsigned int)client_unix_major,
3665 (unsigned int)client_unix_minor,
3666 (unsigned int)client_unix_cap_low,
3667 (unsigned int)client_unix_cap_high ));
3669 /* Here is where we must switch to posix pathname processing... */
3670 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3671 lp_set_posix_pathnames();
3672 mangle_change_to_posix();
3675 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3676 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3677 /* Client that knows how to do posix locks,
3678 * but not posix open/mkdir operations. Set a
3679 * default type for read/write checks. */
3681 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3684 break;
3687 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3689 NTSTATUS status;
3690 size_t param_len = 0;
3691 size_t data_len = total_data;
3693 if (!lp_unix_extensions()) {
3694 reply_nterror(
3695 req,
3696 NT_STATUS_INVALID_LEVEL);
3697 return;
3700 if (lp_smb_encrypt(SNUM(conn)) == false) {
3701 reply_nterror(
3702 req,
3703 NT_STATUS_NOT_SUPPORTED);
3704 return;
3707 if (req->sconn->smb1.echo_handler.trusted_fde) {
3708 DEBUG( 2,("call_trans2setfsinfo: "
3709 "request transport encryption disabled"
3710 "with 'fork echo handler = yes'\n"));
3711 reply_nterror(
3712 req,
3713 NT_STATUS_NOT_SUPPORTED);
3714 return;
3717 DEBUG( 4,("call_trans2setfsinfo: "
3718 "request transport encryption.\n"));
3720 status = srv_request_encryption_setup(conn,
3721 (unsigned char **)ppdata,
3722 &data_len,
3723 (unsigned char **)pparams,
3724 &param_len);
3726 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3727 !NT_STATUS_IS_OK(status)) {
3728 reply_nterror(req, status);
3729 return;
3732 send_trans2_replies(conn, req,
3733 *pparams,
3734 param_len,
3735 *ppdata,
3736 data_len,
3737 max_data_bytes);
3739 if (NT_STATUS_IS_OK(status)) {
3740 /* Server-side transport
3741 * encryption is now *on*. */
3742 status = srv_encryption_start(conn);
3743 if (!NT_STATUS_IS_OK(status)) {
3744 exit_server_cleanly(
3745 "Failure in setting "
3746 "up encrypted transport");
3749 return;
3752 case SMB_FS_QUOTA_INFORMATION:
3754 files_struct *fsp = NULL;
3755 SMB_NTQUOTA_STRUCT quotas;
3757 ZERO_STRUCT(quotas);
3759 /* access check */
3760 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3761 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3762 lp_servicename(SNUM(conn)),
3763 conn->session_info->unix_name));
3764 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3765 return;
3768 /* note: normaly there're 48 bytes,
3769 * but we didn't use the last 6 bytes for now
3770 * --metze
3772 fsp = file_fsp(req, SVAL(params,0));
3774 if (!check_fsp_ntquota_handle(conn, req,
3775 fsp)) {
3776 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3777 reply_nterror(
3778 req, NT_STATUS_INVALID_HANDLE);
3779 return;
3782 if (total_data < 42) {
3783 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3784 total_data));
3785 reply_nterror(
3786 req,
3787 NT_STATUS_INVALID_PARAMETER);
3788 return;
3791 /* unknown_1 24 NULL bytes in pdata*/
3793 /* the soft quotas 8 bytes (uint64_t)*/
3794 quotas.softlim = BVAL(pdata,24);
3796 /* the hard quotas 8 bytes (uint64_t)*/
3797 quotas.hardlim = BVAL(pdata,32);
3799 /* quota_flags 2 bytes **/
3800 quotas.qflags = SVAL(pdata,40);
3802 /* unknown_2 6 NULL bytes follow*/
3804 /* now set the quotas */
3805 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3806 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3807 reply_nterror(req, map_nt_error_from_unix(errno));
3808 return;
3811 break;
3813 default:
3814 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3815 info_level));
3816 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3817 return;
3818 break;
3822 * sending this reply works fine,
3823 * but I'm not sure it's the same
3824 * like windows do...
3825 * --metze
3827 reply_outbuf(req, 10, 0);
3830 #if defined(HAVE_POSIX_ACLS)
3831 /****************************************************************************
3832 Utility function to count the number of entries in a POSIX acl.
3833 ****************************************************************************/
3835 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3837 unsigned int ace_count = 0;
3838 int entry_id = SMB_ACL_FIRST_ENTRY;
3839 SMB_ACL_ENTRY_T entry;
3841 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3842 /* get_next... */
3843 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3844 entry_id = SMB_ACL_NEXT_ENTRY;
3846 ace_count++;
3848 return ace_count;
3851 /****************************************************************************
3852 Utility function to marshall a POSIX acl into wire format.
3853 ****************************************************************************/
3855 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3857 int entry_id = SMB_ACL_FIRST_ENTRY;
3858 SMB_ACL_ENTRY_T entry;
3860 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3861 SMB_ACL_TAG_T tagtype;
3862 SMB_ACL_PERMSET_T permset;
3863 unsigned char perms = 0;
3864 unsigned int own_grp;
3866 /* get_next... */
3867 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3868 entry_id = SMB_ACL_NEXT_ENTRY;
3871 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3873 return False;
3876 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3877 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3878 return False;
3881 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3882 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3883 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3885 SCVAL(pdata,1,perms);
3887 switch (tagtype) {
3888 case SMB_ACL_USER_OBJ:
3889 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3890 own_grp = (unsigned int)pst->st_ex_uid;
3891 SIVAL(pdata,2,own_grp);
3892 SIVAL(pdata,6,0);
3893 break;
3894 case SMB_ACL_USER:
3896 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3897 if (!puid) {
3898 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3899 return False;
3901 own_grp = (unsigned int)*puid;
3902 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3903 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3904 SIVAL(pdata,2,own_grp);
3905 SIVAL(pdata,6,0);
3906 break;
3908 case SMB_ACL_GROUP_OBJ:
3909 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3910 own_grp = (unsigned int)pst->st_ex_gid;
3911 SIVAL(pdata,2,own_grp);
3912 SIVAL(pdata,6,0);
3913 break;
3914 case SMB_ACL_GROUP:
3916 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3917 if (!pgid) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3919 return False;
3921 own_grp = (unsigned int)*pgid;
3922 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3923 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3924 SIVAL(pdata,2,own_grp);
3925 SIVAL(pdata,6,0);
3926 break;
3928 case SMB_ACL_MASK:
3929 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3930 SIVAL(pdata,2,0xFFFFFFFF);
3931 SIVAL(pdata,6,0xFFFFFFFF);
3932 break;
3933 case SMB_ACL_OTHER:
3934 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3935 SIVAL(pdata,2,0xFFFFFFFF);
3936 SIVAL(pdata,6,0xFFFFFFFF);
3937 break;
3938 default:
3939 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3940 return False;
3942 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3945 return True;
3947 #endif
3949 /****************************************************************************
3950 Store the FILE_UNIX_BASIC info.
3951 ****************************************************************************/
3953 static char *store_file_unix_basic(connection_struct *conn,
3954 char *pdata,
3955 files_struct *fsp,
3956 const SMB_STRUCT_STAT *psbuf)
3958 uint64_t file_index = get_FileIndex(conn, psbuf);
3960 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3961 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3963 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3964 pdata += 8;
3966 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3967 pdata += 8;
3969 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3970 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3971 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3972 pdata += 24;
3974 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3975 SIVAL(pdata,4,0);
3976 pdata += 8;
3978 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3979 SIVAL(pdata,4,0);
3980 pdata += 8;
3982 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3983 pdata += 4;
3985 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3986 SIVAL(pdata,4,0);
3987 pdata += 8;
3989 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3990 SIVAL(pdata,4,0);
3991 pdata += 8;
3993 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3994 pdata += 8;
3996 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3997 SIVAL(pdata,4,0);
3998 pdata += 8;
4000 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4001 SIVAL(pdata,4,0);
4002 pdata += 8;
4004 return pdata;
4007 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4008 * the chflags(2) (or equivalent) flags.
4010 * XXX: this really should be behind the VFS interface. To do this, we would
4011 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4012 * Each VFS module could then implement its own mapping as appropriate for the
4013 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4015 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4016 info2_flags_map[] =
4018 #ifdef UF_NODUMP
4019 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4020 #endif
4022 #ifdef UF_IMMUTABLE
4023 { UF_IMMUTABLE, EXT_IMMUTABLE },
4024 #endif
4026 #ifdef UF_APPEND
4027 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4028 #endif
4030 #ifdef UF_HIDDEN
4031 { UF_HIDDEN, EXT_HIDDEN },
4032 #endif
4034 /* Do not remove. We need to guarantee that this array has at least one
4035 * entry to build on HP-UX.
4037 { 0, 0 }
4041 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4042 uint32 *smb_fflags, uint32 *smb_fmask)
4044 int i;
4046 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4047 *smb_fmask |= info2_flags_map[i].smb_fflag;
4048 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4049 *smb_fflags |= info2_flags_map[i].smb_fflag;
4054 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4055 const uint32 smb_fflags,
4056 const uint32 smb_fmask,
4057 int *stat_fflags)
4059 uint32 max_fmask = 0;
4060 int i;
4062 *stat_fflags = psbuf->st_ex_flags;
4064 /* For each flags requested in smb_fmask, check the state of the
4065 * corresponding flag in smb_fflags and set or clear the matching
4066 * stat flag.
4069 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4070 max_fmask |= info2_flags_map[i].smb_fflag;
4071 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4072 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4073 *stat_fflags |= info2_flags_map[i].stat_fflag;
4074 } else {
4075 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4080 /* If smb_fmask is asking to set any bits that are not supported by
4081 * our flag mappings, we should fail.
4083 if ((smb_fmask & max_fmask) != smb_fmask) {
4084 return False;
4087 return True;
4091 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4092 * of file flags and birth (create) time.
4094 static char *store_file_unix_basic_info2(connection_struct *conn,
4095 char *pdata,
4096 files_struct *fsp,
4097 const SMB_STRUCT_STAT *psbuf)
4099 uint32 file_flags = 0;
4100 uint32 flags_mask = 0;
4102 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4104 /* Create (birth) time 64 bit */
4105 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4106 pdata += 8;
4108 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4109 SIVAL(pdata, 0, file_flags); /* flags */
4110 SIVAL(pdata, 4, flags_mask); /* mask */
4111 pdata += 8;
4113 return pdata;
4116 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4117 const struct stream_struct *streams,
4118 char *data,
4119 unsigned int max_data_bytes,
4120 unsigned int *data_size)
4122 unsigned int i;
4123 unsigned int ofs = 0;
4125 for (i = 0; i < num_streams; i++) {
4126 unsigned int next_offset;
4127 size_t namelen;
4128 smb_ucs2_t *namebuf;
4130 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4131 streams[i].name, &namelen) ||
4132 namelen <= 2)
4134 return NT_STATUS_INVALID_PARAMETER;
4138 * name_buf is now null-terminated, we need to marshall as not
4139 * terminated
4142 namelen -= 2;
4145 * We cannot overflow ...
4147 if ((ofs + 24 + namelen) > max_data_bytes) {
4148 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4149 i));
4150 TALLOC_FREE(namebuf);
4151 return STATUS_BUFFER_OVERFLOW;
4154 SIVAL(data, ofs+4, namelen);
4155 SOFF_T(data, ofs+8, streams[i].size);
4156 SOFF_T(data, ofs+16, streams[i].alloc_size);
4157 memcpy(data+ofs+24, namebuf, namelen);
4158 TALLOC_FREE(namebuf);
4160 next_offset = ofs + 24 + namelen;
4162 if (i == num_streams-1) {
4163 SIVAL(data, ofs, 0);
4165 else {
4166 unsigned int align = ndr_align_size(next_offset, 8);
4168 if ((next_offset + align) > max_data_bytes) {
4169 DEBUG(10, ("refusing to overflow align "
4170 "reply at stream %u\n",
4171 i));
4172 TALLOC_FREE(namebuf);
4173 return STATUS_BUFFER_OVERFLOW;
4176 memset(data+next_offset, 0, align);
4177 next_offset += align;
4179 SIVAL(data, ofs, next_offset - ofs);
4180 ofs = next_offset;
4183 ofs = next_offset;
4186 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4188 *data_size = ofs;
4190 return NT_STATUS_OK;
4193 /****************************************************************************
4194 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4195 ****************************************************************************/
4197 static void call_trans2qpipeinfo(connection_struct *conn,
4198 struct smb_request *req,
4199 unsigned int tran_call,
4200 char **pparams, int total_params,
4201 char **ppdata, int total_data,
4202 unsigned int max_data_bytes)
4204 char *params = *pparams;
4205 char *pdata = *ppdata;
4206 unsigned int data_size = 0;
4207 unsigned int param_size = 2;
4208 uint16 info_level;
4209 files_struct *fsp;
4211 if (!params) {
4212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4213 return;
4216 if (total_params < 4) {
4217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4218 return;
4221 fsp = file_fsp(req, SVAL(params,0));
4222 if (!fsp_is_np(fsp)) {
4223 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4224 return;
4227 info_level = SVAL(params,2);
4229 *pparams = (char *)SMB_REALLOC(*pparams,2);
4230 if (*pparams == NULL) {
4231 reply_nterror(req, NT_STATUS_NO_MEMORY);
4232 return;
4234 params = *pparams;
4235 SSVAL(params,0,0);
4236 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4237 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4238 if (*ppdata == NULL ) {
4239 reply_nterror(req, NT_STATUS_NO_MEMORY);
4240 return;
4242 pdata = *ppdata;
4244 switch (info_level) {
4245 case SMB_FILE_STANDARD_INFORMATION:
4246 memset(pdata,0,24);
4247 SOFF_T(pdata,0,4096LL);
4248 SIVAL(pdata,16,1);
4249 SIVAL(pdata,20,1);
4250 data_size = 24;
4251 break;
4253 default:
4254 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4255 return;
4258 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4259 max_data_bytes);
4261 return;
4264 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4265 TALLOC_CTX *mem_ctx,
4266 uint16_t info_level,
4267 files_struct *fsp,
4268 struct smb_filename *smb_fname,
4269 bool delete_pending,
4270 struct timespec write_time_ts,
4271 struct ea_list *ea_list,
4272 int lock_data_count,
4273 char *lock_data,
4274 uint16_t flags2,
4275 unsigned int max_data_bytes,
4276 char **ppdata,
4277 unsigned int *pdata_size)
4279 char *pdata = *ppdata;
4280 char *dstart, *dend;
4281 unsigned int data_size;
4282 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4283 time_t create_time, mtime, atime, c_time;
4284 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4285 char *p;
4286 char *base_name;
4287 char *dos_fname;
4288 int mode;
4289 int nlink;
4290 NTSTATUS status;
4291 uint64_t file_size = 0;
4292 uint64_t pos = 0;
4293 uint64_t allocation_size = 0;
4294 uint64_t file_index = 0;
4295 uint32_t access_mask = 0;
4297 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4298 return NT_STATUS_INVALID_LEVEL;
4301 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4302 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4303 info_level, max_data_bytes));
4305 mode = dos_mode(conn, smb_fname);
4306 nlink = psbuf->st_ex_nlink;
4308 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4309 nlink = 1;
4312 if ((nlink > 0) && delete_pending) {
4313 nlink -= 1;
4316 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4317 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4318 if (*ppdata == NULL) {
4319 return NT_STATUS_NO_MEMORY;
4321 pdata = *ppdata;
4322 dstart = pdata;
4323 dend = dstart + data_size - 1;
4325 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4326 update_stat_ex_mtime(psbuf, write_time_ts);
4329 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4330 mtime_ts = psbuf->st_ex_mtime;
4331 atime_ts = psbuf->st_ex_atime;
4332 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4334 if (lp_dos_filetime_resolution(SNUM(conn))) {
4335 dos_filetime_timespec(&create_time_ts);
4336 dos_filetime_timespec(&mtime_ts);
4337 dos_filetime_timespec(&atime_ts);
4338 dos_filetime_timespec(&ctime_ts);
4341 create_time = convert_timespec_to_time_t(create_time_ts);
4342 mtime = convert_timespec_to_time_t(mtime_ts);
4343 atime = convert_timespec_to_time_t(atime_ts);
4344 c_time = convert_timespec_to_time_t(ctime_ts);
4346 p = strrchr_m(smb_fname->base_name,'/');
4347 if (!p)
4348 base_name = smb_fname->base_name;
4349 else
4350 base_name = p+1;
4352 /* NT expects the name to be in an exact form of the *full*
4353 filename. See the trans2 torture test */
4354 if (ISDOT(base_name)) {
4355 dos_fname = talloc_strdup(mem_ctx, "\\");
4356 if (!dos_fname) {
4357 return NT_STATUS_NO_MEMORY;
4359 } else {
4360 dos_fname = talloc_asprintf(mem_ctx,
4361 "\\%s",
4362 smb_fname->base_name);
4363 if (!dos_fname) {
4364 return NT_STATUS_NO_MEMORY;
4366 if (is_ntfs_stream_smb_fname(smb_fname)) {
4367 dos_fname = talloc_asprintf(dos_fname, "%s",
4368 smb_fname->stream_name);
4369 if (!dos_fname) {
4370 return NT_STATUS_NO_MEMORY;
4374 string_replace(dos_fname, '/', '\\');
4377 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4379 if (!fsp) {
4380 /* Do we have this path open ? */
4381 files_struct *fsp1;
4382 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4383 fsp1 = file_find_di_first(conn->sconn, fileid);
4384 if (fsp1 && fsp1->initial_allocation_size) {
4385 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4389 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4390 file_size = get_file_size_stat(psbuf);
4393 if (fsp) {
4394 pos = fsp->fh->position_information;
4397 if (fsp) {
4398 access_mask = fsp->access_mask;
4399 } else {
4400 /* GENERIC_EXECUTE mapping from Windows */
4401 access_mask = 0x12019F;
4404 /* This should be an index number - looks like
4405 dev/ino to me :-)
4407 I think this causes us to fail the IFSKIT
4408 BasicFileInformationTest. -tpot */
4409 file_index = get_FileIndex(conn, psbuf);
4411 switch (info_level) {
4412 case SMB_INFO_STANDARD:
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4414 data_size = 22;
4415 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4416 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4417 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4418 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4419 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4420 SSVAL(pdata,l1_attrFile,mode);
4421 break;
4423 case SMB_INFO_QUERY_EA_SIZE:
4425 unsigned int ea_size =
4426 estimate_ea_size(conn, fsp,
4427 smb_fname->base_name);
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4429 data_size = 26;
4430 srv_put_dos_date2(pdata,0,create_time);
4431 srv_put_dos_date2(pdata,4,atime);
4432 srv_put_dos_date2(pdata,8,mtime); /* write time */
4433 SIVAL(pdata,12,(uint32)file_size);
4434 SIVAL(pdata,16,(uint32)allocation_size);
4435 SSVAL(pdata,20,mode);
4436 SIVAL(pdata,22,ea_size);
4437 break;
4440 case SMB_INFO_IS_NAME_VALID:
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4442 if (fsp) {
4443 /* os/2 needs this ? really ?*/
4444 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4446 /* This is only reached for qpathinfo */
4447 data_size = 0;
4448 break;
4450 case SMB_INFO_QUERY_EAS_FROM_LIST:
4452 size_t total_ea_len = 0;
4453 struct ea_list *ea_file_list = NULL;
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4457 ea_file_list =
4458 get_ea_list_from_file(mem_ctx, conn, fsp,
4459 smb_fname->base_name,
4460 &total_ea_len);
4461 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4463 if (!ea_list || (total_ea_len > data_size)) {
4464 data_size = 4;
4465 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4466 break;
4469 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4470 break;
4473 case SMB_INFO_QUERY_ALL_EAS:
4475 /* We have data_size bytes to put EA's into. */
4476 size_t total_ea_len = 0;
4478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4480 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4481 smb_fname->base_name,
4482 &total_ea_len);
4483 if (!ea_list || (total_ea_len > data_size)) {
4484 data_size = 4;
4485 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4486 break;
4489 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4490 break;
4493 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4495 /* This is FileFullEaInformation - 0xF which maps to
4496 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4498 /* We have data_size bytes to put EA's into. */
4499 size_t total_ea_len = 0;
4500 struct ea_list *ea_file_list = NULL;
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4504 /*TODO: add filtering and index handling */
4506 ea_file_list =
4507 get_ea_list_from_file(mem_ctx, conn, fsp,
4508 smb_fname->base_name,
4509 &total_ea_len);
4510 if (!ea_file_list) {
4511 return NT_STATUS_NO_EAS_ON_FILE;
4514 status = fill_ea_chained_buffer(mem_ctx,
4515 pdata,
4516 data_size,
4517 &data_size,
4518 conn, ea_file_list);
4519 if (!NT_STATUS_IS_OK(status)) {
4520 return status;
4522 break;
4525 case SMB_FILE_BASIC_INFORMATION:
4526 case SMB_QUERY_FILE_BASIC_INFO:
4528 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4530 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4531 } else {
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4533 data_size = 40;
4534 SIVAL(pdata,36,0);
4536 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4537 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4538 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4539 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4540 SIVAL(pdata,32,mode);
4542 DEBUG(5,("SMB_QFBI - "));
4543 DEBUG(5,("create: %s ", ctime(&create_time)));
4544 DEBUG(5,("access: %s ", ctime(&atime)));
4545 DEBUG(5,("write: %s ", ctime(&mtime)));
4546 DEBUG(5,("change: %s ", ctime(&c_time)));
4547 DEBUG(5,("mode: %x\n", mode));
4548 break;
4550 case SMB_FILE_STANDARD_INFORMATION:
4551 case SMB_QUERY_FILE_STANDARD_INFO:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4554 data_size = 24;
4555 SOFF_T(pdata,0,allocation_size);
4556 SOFF_T(pdata,8,file_size);
4557 SIVAL(pdata,16,nlink);
4558 SCVAL(pdata,20,delete_pending?1:0);
4559 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4560 SSVAL(pdata,22,0); /* Padding. */
4561 break;
4563 case SMB_FILE_EA_INFORMATION:
4564 case SMB_QUERY_FILE_EA_INFO:
4566 unsigned int ea_size =
4567 estimate_ea_size(conn, fsp, smb_fname->base_name);
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4569 data_size = 4;
4570 SIVAL(pdata,0,ea_size);
4571 break;
4574 /* Get the 8.3 name - used if NT SMB was negotiated. */
4575 case SMB_QUERY_FILE_ALT_NAME_INFO:
4576 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4578 int len;
4579 char mangled_name[13];
4580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4581 if (!name_to_8_3(base_name,mangled_name,
4582 True,conn->params)) {
4583 return NT_STATUS_NO_MEMORY;
4585 len = srvstr_push(dstart, flags2,
4586 pdata+4, mangled_name,
4587 PTR_DIFF(dend, pdata+4),
4588 STR_UNICODE);
4589 data_size = 4 + len;
4590 SIVAL(pdata,0,len);
4591 break;
4594 case SMB_QUERY_FILE_NAME_INFO:
4596 int len;
4598 this must be *exactly* right for ACLs on mapped drives to work
4600 len = srvstr_push(dstart, flags2,
4601 pdata+4, dos_fname,
4602 PTR_DIFF(dend, pdata+4),
4603 STR_UNICODE);
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4605 data_size = 4 + len;
4606 SIVAL(pdata,0,len);
4607 break;
4610 case SMB_FILE_ALLOCATION_INFORMATION:
4611 case SMB_QUERY_FILE_ALLOCATION_INFO:
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4613 data_size = 8;
4614 SOFF_T(pdata,0,allocation_size);
4615 break;
4617 case SMB_FILE_END_OF_FILE_INFORMATION:
4618 case SMB_QUERY_FILE_END_OF_FILEINFO:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4620 data_size = 8;
4621 SOFF_T(pdata,0,file_size);
4622 break;
4624 case SMB_QUERY_FILE_ALL_INFO:
4625 case SMB_FILE_ALL_INFORMATION:
4627 int len;
4628 unsigned int ea_size =
4629 estimate_ea_size(conn, fsp, smb_fname->base_name);
4630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4631 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4632 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4633 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4634 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4635 SIVAL(pdata,32,mode);
4636 SIVAL(pdata,36,0); /* padding. */
4637 pdata += 40;
4638 SOFF_T(pdata,0,allocation_size);
4639 SOFF_T(pdata,8,file_size);
4640 SIVAL(pdata,16,nlink);
4641 SCVAL(pdata,20,delete_pending);
4642 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4643 SSVAL(pdata,22,0);
4644 pdata += 24;
4645 SIVAL(pdata,0,ea_size);
4646 pdata += 4; /* EA info */
4647 len = srvstr_push(dstart, flags2,
4648 pdata+4, dos_fname,
4649 PTR_DIFF(dend, pdata+4),
4650 STR_UNICODE);
4651 SIVAL(pdata,0,len);
4652 pdata += 4 + len;
4653 data_size = PTR_DIFF(pdata,(*ppdata));
4654 break;
4657 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4659 int len;
4660 unsigned int ea_size =
4661 estimate_ea_size(conn, fsp, smb_fname->base_name);
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4663 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4664 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4665 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4666 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4667 SIVAL(pdata, 0x20, mode);
4668 SIVAL(pdata, 0x24, 0); /* padding. */
4669 SBVAL(pdata, 0x28, allocation_size);
4670 SBVAL(pdata, 0x30, file_size);
4671 SIVAL(pdata, 0x38, nlink);
4672 SCVAL(pdata, 0x3C, delete_pending);
4673 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4674 SSVAL(pdata, 0x3E, 0); /* padding */
4675 SBVAL(pdata, 0x40, file_index);
4676 SIVAL(pdata, 0x48, ea_size);
4677 SIVAL(pdata, 0x4C, access_mask);
4678 SBVAL(pdata, 0x50, pos);
4679 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4680 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4682 pdata += 0x60;
4684 len = srvstr_push(dstart, flags2,
4685 pdata+4, dos_fname,
4686 PTR_DIFF(dend, pdata+4),
4687 STR_UNICODE);
4688 SIVAL(pdata,0,len);
4689 pdata += 4 + len;
4690 data_size = PTR_DIFF(pdata,(*ppdata));
4691 break;
4693 case SMB_FILE_INTERNAL_INFORMATION:
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4696 SBVAL(pdata, 0, file_index);
4697 data_size = 8;
4698 break;
4700 case SMB_FILE_ACCESS_INFORMATION:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4702 SIVAL(pdata, 0, access_mask);
4703 data_size = 4;
4704 break;
4706 case SMB_FILE_NAME_INFORMATION:
4707 /* Pathname with leading '\'. */
4709 size_t byte_len;
4710 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4711 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4712 SIVAL(pdata,0,byte_len);
4713 data_size = 4 + byte_len;
4714 break;
4717 case SMB_FILE_DISPOSITION_INFORMATION:
4718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4719 data_size = 1;
4720 SCVAL(pdata,0,delete_pending);
4721 break;
4723 case SMB_FILE_POSITION_INFORMATION:
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4725 data_size = 8;
4726 SOFF_T(pdata,0,pos);
4727 break;
4729 case SMB_FILE_MODE_INFORMATION:
4730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4731 SIVAL(pdata,0,mode);
4732 data_size = 4;
4733 break;
4735 case SMB_FILE_ALIGNMENT_INFORMATION:
4736 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4737 SIVAL(pdata,0,0); /* No alignment needed. */
4738 data_size = 4;
4739 break;
4742 * NT4 server just returns "invalid query" to this - if we try
4743 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4744 * want this. JRA.
4746 /* The first statement above is false - verified using Thursby
4747 * client against NT4 -- gcolley.
4749 case SMB_QUERY_FILE_STREAM_INFO:
4750 case SMB_FILE_STREAM_INFORMATION: {
4751 unsigned int num_streams = 0;
4752 struct stream_struct *streams = NULL;
4754 DEBUG(10,("smbd_do_qfilepathinfo: "
4755 "SMB_FILE_STREAM_INFORMATION\n"));
4757 if (is_ntfs_stream_smb_fname(smb_fname)) {
4758 return NT_STATUS_INVALID_PARAMETER;
4761 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4762 talloc_tos(), &num_streams, &streams);
4764 if (!NT_STATUS_IS_OK(status)) {
4765 DEBUG(10, ("could not get stream info: %s\n",
4766 nt_errstr(status)));
4767 return status;
4770 status = marshall_stream_info(num_streams, streams,
4771 pdata, max_data_bytes,
4772 &data_size);
4774 if (!NT_STATUS_IS_OK(status)) {
4775 DEBUG(10, ("marshall_stream_info failed: %s\n",
4776 nt_errstr(status)));
4777 TALLOC_FREE(streams);
4778 return status;
4781 TALLOC_FREE(streams);
4783 break;
4785 case SMB_QUERY_COMPRESSION_INFO:
4786 case SMB_FILE_COMPRESSION_INFORMATION:
4787 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4788 SOFF_T(pdata,0,file_size);
4789 SIVAL(pdata,8,0); /* ??? */
4790 SIVAL(pdata,12,0); /* ??? */
4791 data_size = 16;
4792 break;
4794 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4795 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4796 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4797 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4798 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4799 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4800 SOFF_T(pdata,32,allocation_size);
4801 SOFF_T(pdata,40,file_size);
4802 SIVAL(pdata,48,mode);
4803 SIVAL(pdata,52,0); /* ??? */
4804 data_size = 56;
4805 break;
4807 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4808 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4809 SIVAL(pdata,0,mode);
4810 SIVAL(pdata,4,0);
4811 data_size = 8;
4812 break;
4815 * CIFS UNIX Extensions.
4818 case SMB_QUERY_FILE_UNIX_BASIC:
4820 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4821 data_size = PTR_DIFF(pdata,(*ppdata));
4823 DEBUG(4,("smbd_do_qfilepathinfo: "
4824 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4825 dump_data(4, (uint8_t *)(*ppdata), data_size);
4827 break;
4829 case SMB_QUERY_FILE_UNIX_INFO2:
4831 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4832 data_size = PTR_DIFF(pdata,(*ppdata));
4835 int i;
4836 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4838 for (i=0; i<100; i++)
4839 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4840 DEBUG(4,("\n"));
4843 break;
4845 case SMB_QUERY_FILE_UNIX_LINK:
4847 int len;
4848 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4850 if (!buffer) {
4851 return NT_STATUS_NO_MEMORY;
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4855 #ifdef S_ISLNK
4856 if(!S_ISLNK(psbuf->st_ex_mode)) {
4857 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4859 #else
4860 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4861 #endif
4862 len = SMB_VFS_READLINK(conn,
4863 smb_fname->base_name,
4864 buffer, PATH_MAX);
4865 if (len == -1) {
4866 return map_nt_error_from_unix(errno);
4868 buffer[len] = 0;
4869 len = srvstr_push(dstart, flags2,
4870 pdata, buffer,
4871 PTR_DIFF(dend, pdata),
4872 STR_TERMINATE);
4873 pdata += len;
4874 data_size = PTR_DIFF(pdata,(*ppdata));
4876 break;
4879 #if defined(HAVE_POSIX_ACLS)
4880 case SMB_QUERY_POSIX_ACL:
4882 SMB_ACL_T file_acl = NULL;
4883 SMB_ACL_T def_acl = NULL;
4884 uint16 num_file_acls = 0;
4885 uint16 num_def_acls = 0;
4887 if (fsp && fsp->fh->fd != -1) {
4888 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4889 } else {
4890 file_acl =
4891 SMB_VFS_SYS_ACL_GET_FILE(conn,
4892 smb_fname->base_name,
4893 SMB_ACL_TYPE_ACCESS);
4896 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4897 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4898 "not implemented on "
4899 "filesystem containing %s\n",
4900 smb_fname->base_name));
4901 return NT_STATUS_NOT_IMPLEMENTED;
4904 if (S_ISDIR(psbuf->st_ex_mode)) {
4905 if (fsp && fsp->is_directory) {
4906 def_acl =
4907 SMB_VFS_SYS_ACL_GET_FILE(
4908 conn,
4909 fsp->fsp_name->base_name,
4910 SMB_ACL_TYPE_DEFAULT);
4911 } else {
4912 def_acl =
4913 SMB_VFS_SYS_ACL_GET_FILE(
4914 conn,
4915 smb_fname->base_name,
4916 SMB_ACL_TYPE_DEFAULT);
4918 def_acl = free_empty_sys_acl(conn, def_acl);
4921 num_file_acls = count_acl_entries(conn, file_acl);
4922 num_def_acls = count_acl_entries(conn, def_acl);
4924 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4925 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4926 data_size,
4927 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4928 SMB_POSIX_ACL_HEADER_SIZE) ));
4929 if (file_acl) {
4930 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4932 if (def_acl) {
4933 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4935 return NT_STATUS_BUFFER_TOO_SMALL;
4938 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4939 SSVAL(pdata,2,num_file_acls);
4940 SSVAL(pdata,4,num_def_acls);
4941 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4942 if (file_acl) {
4943 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4945 if (def_acl) {
4946 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4948 return NT_STATUS_INTERNAL_ERROR;
4950 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4951 if (file_acl) {
4952 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4954 if (def_acl) {
4955 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4957 return NT_STATUS_INTERNAL_ERROR;
4960 if (file_acl) {
4961 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4963 if (def_acl) {
4964 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4966 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4967 break;
4969 #endif
4972 case SMB_QUERY_POSIX_LOCK:
4974 uint64_t count;
4975 uint64_t offset;
4976 uint64_t smblctx;
4977 enum brl_type lock_type;
4979 /* We need an open file with a real fd for this. */
4980 if (!fsp || fsp->fh->fd == -1) {
4981 return NT_STATUS_INVALID_LEVEL;
4984 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4985 return NT_STATUS_INVALID_PARAMETER;
4988 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4989 case POSIX_LOCK_TYPE_READ:
4990 lock_type = READ_LOCK;
4991 break;
4992 case POSIX_LOCK_TYPE_WRITE:
4993 lock_type = WRITE_LOCK;
4994 break;
4995 case POSIX_LOCK_TYPE_UNLOCK:
4996 default:
4997 /* There's no point in asking for an unlock... */
4998 return NT_STATUS_INVALID_PARAMETER;
5001 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5002 #if defined(HAVE_LONGLONG)
5003 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5004 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5005 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5006 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5007 #else /* HAVE_LONGLONG */
5008 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5009 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5010 #endif /* HAVE_LONGLONG */
5012 status = query_lock(fsp,
5013 &smblctx,
5014 &count,
5015 &offset,
5016 &lock_type,
5017 POSIX_LOCK);
5019 if (ERROR_WAS_LOCK_DENIED(status)) {
5020 /* Here we need to report who has it locked... */
5021 data_size = POSIX_LOCK_DATA_SIZE;
5023 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5024 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5025 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5026 #if defined(HAVE_LONGLONG)
5027 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5028 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5029 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5030 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5031 #else /* HAVE_LONGLONG */
5032 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5033 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5034 #endif /* HAVE_LONGLONG */
5036 } else if (NT_STATUS_IS_OK(status)) {
5037 /* For success we just return a copy of what we sent
5038 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5039 data_size = POSIX_LOCK_DATA_SIZE;
5040 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5041 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5042 } else {
5043 return status;
5045 break;
5048 default:
5049 return NT_STATUS_INVALID_LEVEL;
5052 *pdata_size = data_size;
5053 return NT_STATUS_OK;
5056 /****************************************************************************
5057 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5058 file name or file id).
5059 ****************************************************************************/
5061 static void call_trans2qfilepathinfo(connection_struct *conn,
5062 struct smb_request *req,
5063 unsigned int tran_call,
5064 char **pparams, int total_params,
5065 char **ppdata, int total_data,
5066 unsigned int max_data_bytes)
5068 char *params = *pparams;
5069 char *pdata = *ppdata;
5070 uint16 info_level;
5071 unsigned int data_size = 0;
5072 unsigned int param_size = 2;
5073 struct smb_filename *smb_fname = NULL;
5074 bool delete_pending = False;
5075 struct timespec write_time_ts;
5076 files_struct *fsp = NULL;
5077 struct file_id fileid;
5078 struct ea_list *ea_list = NULL;
5079 int lock_data_count = 0;
5080 char *lock_data = NULL;
5081 NTSTATUS status = NT_STATUS_OK;
5083 if (!params) {
5084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5085 return;
5088 ZERO_STRUCT(write_time_ts);
5090 if (tran_call == TRANSACT2_QFILEINFO) {
5091 if (total_params < 4) {
5092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5093 return;
5096 if (IS_IPC(conn)) {
5097 call_trans2qpipeinfo(conn, req, tran_call,
5098 pparams, total_params,
5099 ppdata, total_data,
5100 max_data_bytes);
5101 return;
5104 fsp = file_fsp(req, SVAL(params,0));
5105 info_level = SVAL(params,2);
5107 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5109 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5110 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5111 return;
5114 /* Initial check for valid fsp ptr. */
5115 if (!check_fsp_open(conn, req, fsp)) {
5116 return;
5119 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5120 &smb_fname);
5121 if (!NT_STATUS_IS_OK(status)) {
5122 reply_nterror(req, status);
5123 return;
5126 if(fsp->fake_file_handle) {
5128 * This is actually for the QUOTA_FAKE_FILE --metze
5131 /* We know this name is ok, it's already passed the checks. */
5133 } else if(fsp->fh->fd == -1) {
5135 * This is actually a QFILEINFO on a directory
5136 * handle (returned from an NT SMB). NT5.0 seems
5137 * to do this call. JRA.
5140 if (INFO_LEVEL_IS_UNIX(info_level)) {
5141 /* Always do lstat for UNIX calls. */
5142 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5143 DEBUG(3,("call_trans2qfilepathinfo: "
5144 "SMB_VFS_LSTAT of %s failed "
5145 "(%s)\n",
5146 smb_fname_str_dbg(smb_fname),
5147 strerror(errno)));
5148 reply_nterror(req,
5149 map_nt_error_from_unix(errno));
5150 return;
5152 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5153 DEBUG(3,("call_trans2qfilepathinfo: "
5154 "SMB_VFS_STAT of %s failed (%s)\n",
5155 smb_fname_str_dbg(smb_fname),
5156 strerror(errno)));
5157 reply_nterror(req,
5158 map_nt_error_from_unix(errno));
5159 return;
5162 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5163 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5164 } else {
5166 * Original code - this is an open file.
5168 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5169 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5170 fsp->fnum, strerror(errno)));
5171 reply_nterror(req,
5172 map_nt_error_from_unix(errno));
5173 return;
5175 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5176 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5179 } else {
5180 uint32_t name_hash;
5181 char *fname = NULL;
5182 uint32_t ucf_flags = 0;
5184 /* qpathinfo */
5185 if (total_params < 7) {
5186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5187 return;
5190 info_level = SVAL(params,0);
5192 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5194 if (INFO_LEVEL_IS_UNIX(info_level)) {
5195 if (!lp_unix_extensions()) {
5196 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5197 return;
5199 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5200 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5201 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5202 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5206 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5207 total_params - 6,
5208 STR_TERMINATE, &status);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 reply_nterror(req, status);
5211 return;
5214 status = filename_convert(req,
5215 conn,
5216 req->flags2 & FLAGS2_DFS_PATHNAMES,
5217 fname,
5218 ucf_flags,
5219 NULL,
5220 &smb_fname);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5223 reply_botherror(req,
5224 NT_STATUS_PATH_NOT_COVERED,
5225 ERRSRV, ERRbadpath);
5226 return;
5228 reply_nterror(req, status);
5229 return;
5232 /* If this is a stream, check if there is a delete_pending. */
5233 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5234 && is_ntfs_stream_smb_fname(smb_fname)) {
5235 struct smb_filename *smb_fname_base = NULL;
5237 /* Create an smb_filename with stream_name == NULL. */
5238 status =
5239 create_synthetic_smb_fname(talloc_tos(),
5240 smb_fname->base_name,
5241 NULL, NULL,
5242 &smb_fname_base);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 reply_nterror(req, status);
5245 return;
5248 if (INFO_LEVEL_IS_UNIX(info_level)) {
5249 /* Always do lstat for UNIX calls. */
5250 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5251 DEBUG(3,("call_trans2qfilepathinfo: "
5252 "SMB_VFS_LSTAT of %s failed "
5253 "(%s)\n",
5254 smb_fname_str_dbg(smb_fname_base),
5255 strerror(errno)));
5256 TALLOC_FREE(smb_fname_base);
5257 reply_nterror(req,
5258 map_nt_error_from_unix(errno));
5259 return;
5261 } else {
5262 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5263 DEBUG(3,("call_trans2qfilepathinfo: "
5264 "fileinfo of %s failed "
5265 "(%s)\n",
5266 smb_fname_str_dbg(smb_fname_base),
5267 strerror(errno)));
5268 TALLOC_FREE(smb_fname_base);
5269 reply_nterror(req,
5270 map_nt_error_from_unix(errno));
5271 return;
5275 status = file_name_hash(conn,
5276 smb_fname_str_dbg(smb_fname_base),
5277 &name_hash);
5278 if (!NT_STATUS_IS_OK(status)) {
5279 TALLOC_FREE(smb_fname_base);
5280 reply_nterror(req, status);
5281 return;
5284 fileid = vfs_file_id_from_sbuf(conn,
5285 &smb_fname_base->st);
5286 TALLOC_FREE(smb_fname_base);
5287 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5288 if (delete_pending) {
5289 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5290 return;
5294 if (INFO_LEVEL_IS_UNIX(info_level)) {
5295 /* Always do lstat for UNIX calls. */
5296 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5297 DEBUG(3,("call_trans2qfilepathinfo: "
5298 "SMB_VFS_LSTAT of %s failed (%s)\n",
5299 smb_fname_str_dbg(smb_fname),
5300 strerror(errno)));
5301 reply_nterror(req,
5302 map_nt_error_from_unix(errno));
5303 return;
5306 } else {
5307 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5308 DEBUG(3,("call_trans2qfilepathinfo: "
5309 "SMB_VFS_STAT of %s failed (%s)\n",
5310 smb_fname_str_dbg(smb_fname),
5311 strerror(errno)));
5312 reply_nterror(req,
5313 map_nt_error_from_unix(errno));
5314 return;
5318 status = file_name_hash(conn,
5319 smb_fname_str_dbg(smb_fname),
5320 &name_hash);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 reply_nterror(req, status);
5323 return;
5326 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5327 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5328 if (delete_pending) {
5329 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5330 return;
5334 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5335 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5336 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5338 /* Pull out any data sent here before we realloc. */
5339 switch (info_level) {
5340 case SMB_INFO_QUERY_EAS_FROM_LIST:
5342 /* Pull any EA list from the data portion. */
5343 uint32 ea_size;
5345 if (total_data < 4) {
5346 reply_nterror(
5347 req, NT_STATUS_INVALID_PARAMETER);
5348 return;
5350 ea_size = IVAL(pdata,0);
5352 if (total_data > 0 && ea_size != total_data) {
5353 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5354 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5355 reply_nterror(
5356 req, NT_STATUS_INVALID_PARAMETER);
5357 return;
5360 if (!lp_ea_support(SNUM(conn))) {
5361 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5362 return;
5365 /* Pull out the list of names. */
5366 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5367 if (!ea_list) {
5368 reply_nterror(
5369 req, NT_STATUS_INVALID_PARAMETER);
5370 return;
5372 break;
5375 case SMB_QUERY_POSIX_LOCK:
5377 if (fsp == NULL || fsp->fh->fd == -1) {
5378 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5379 return;
5382 if (total_data != POSIX_LOCK_DATA_SIZE) {
5383 reply_nterror(
5384 req, NT_STATUS_INVALID_PARAMETER);
5385 return;
5388 /* Copy the lock range data. */
5389 lock_data = (char *)TALLOC_MEMDUP(
5390 req, pdata, total_data);
5391 if (!lock_data) {
5392 reply_nterror(req, NT_STATUS_NO_MEMORY);
5393 return;
5395 lock_data_count = total_data;
5397 default:
5398 break;
5401 *pparams = (char *)SMB_REALLOC(*pparams,2);
5402 if (*pparams == NULL) {
5403 reply_nterror(req, NT_STATUS_NO_MEMORY);
5404 return;
5406 params = *pparams;
5407 SSVAL(params,0,0);
5410 * draft-leach-cifs-v1-spec-02.txt
5411 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5412 * says:
5414 * The requested information is placed in the Data portion of the
5415 * transaction response. For the information levels greater than 0x100,
5416 * the transaction response has 1 parameter word which should be
5417 * ignored by the client.
5419 * However Windows only follows this rule for the IS_NAME_VALID call.
5421 switch (info_level) {
5422 case SMB_INFO_IS_NAME_VALID:
5423 param_size = 0;
5424 break;
5427 if ((info_level & 0xFF00) == 0xFF00) {
5429 * We use levels that start with 0xFF00
5430 * internally to represent SMB2 specific levels
5432 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5433 return;
5436 status = smbd_do_qfilepathinfo(conn, req, info_level,
5437 fsp, smb_fname,
5438 delete_pending, write_time_ts,
5439 ea_list,
5440 lock_data_count, lock_data,
5441 req->flags2, max_data_bytes,
5442 ppdata, &data_size);
5443 if (!NT_STATUS_IS_OK(status)) {
5444 reply_nterror(req, status);
5445 return;
5448 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5449 max_data_bytes);
5451 return;
5454 /****************************************************************************
5455 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5456 code.
5457 ****************************************************************************/
5459 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5460 connection_struct *conn,
5461 struct smb_request *req,
5462 bool overwrite_if_exists,
5463 const struct smb_filename *smb_fname_old,
5464 struct smb_filename *smb_fname_new)
5466 NTSTATUS status = NT_STATUS_OK;
5468 /* source must already exist. */
5469 if (!VALID_STAT(smb_fname_old->st)) {
5470 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5473 if (VALID_STAT(smb_fname_new->st)) {
5474 if (overwrite_if_exists) {
5475 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5476 return NT_STATUS_FILE_IS_A_DIRECTORY;
5478 status = unlink_internals(conn,
5479 req,
5480 FILE_ATTRIBUTE_NORMAL,
5481 smb_fname_new,
5482 false);
5483 if (!NT_STATUS_IS_OK(status)) {
5484 return status;
5486 } else {
5487 /* Disallow if newname already exists. */
5488 return NT_STATUS_OBJECT_NAME_COLLISION;
5492 /* No links from a directory. */
5493 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5494 return NT_STATUS_FILE_IS_A_DIRECTORY;
5497 /* Setting a hardlink to/from a stream isn't currently supported. */
5498 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5499 is_ntfs_stream_smb_fname(smb_fname_new)) {
5500 return NT_STATUS_INVALID_PARAMETER;
5503 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5504 smb_fname_old->base_name, smb_fname_new->base_name));
5506 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5507 smb_fname_new->base_name) != 0) {
5508 status = map_nt_error_from_unix(errno);
5509 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5510 nt_errstr(status), smb_fname_old->base_name,
5511 smb_fname_new->base_name));
5513 return status;
5516 /****************************************************************************
5517 Deal with setting the time from any of the setfilepathinfo functions.
5518 ****************************************************************************/
5520 NTSTATUS smb_set_file_time(connection_struct *conn,
5521 files_struct *fsp,
5522 const struct smb_filename *smb_fname,
5523 struct smb_file_time *ft,
5524 bool setting_write_time)
5526 struct smb_filename smb_fname_base;
5527 uint32 action =
5528 FILE_NOTIFY_CHANGE_LAST_ACCESS
5529 |FILE_NOTIFY_CHANGE_LAST_WRITE
5530 |FILE_NOTIFY_CHANGE_CREATION;
5532 if (!VALID_STAT(smb_fname->st)) {
5533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5536 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5537 return NT_STATUS_ACCESS_DENIED;
5540 /* get some defaults (no modifications) if any info is zero or -1. */
5541 if (null_timespec(ft->create_time)) {
5542 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5545 if (null_timespec(ft->atime)) {
5546 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5549 if (null_timespec(ft->mtime)) {
5550 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5553 if (!setting_write_time) {
5554 /* ft->mtime comes from change time, not write time. */
5555 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5558 /* Ensure the resolution is the correct for
5559 * what we can store on this filesystem. */
5561 round_timespec(conn->ts_res, &ft->create_time);
5562 round_timespec(conn->ts_res, &ft->ctime);
5563 round_timespec(conn->ts_res, &ft->atime);
5564 round_timespec(conn->ts_res, &ft->mtime);
5566 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5567 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5568 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5569 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5570 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5571 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5572 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5573 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5575 if (setting_write_time) {
5577 * This was a Windows setfileinfo on an open file.
5578 * NT does this a lot. We also need to
5579 * set the time here, as it can be read by
5580 * FindFirst/FindNext and with the patch for bug #2045
5581 * in smbd/fileio.c it ensures that this timestamp is
5582 * kept sticky even after a write. We save the request
5583 * away and will set it on file close and after a write. JRA.
5586 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5587 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5589 if (fsp != NULL) {
5590 if (fsp->base_fsp) {
5591 set_sticky_write_time_fsp(fsp->base_fsp,
5592 ft->mtime);
5593 } else {
5594 set_sticky_write_time_fsp(fsp, ft->mtime);
5596 } else {
5597 set_sticky_write_time_path(
5598 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5599 ft->mtime);
5603 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5605 /* Always call ntimes on the base, even if a stream was passed in. */
5606 smb_fname_base = *smb_fname;
5607 smb_fname_base.stream_name = NULL;
5609 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5610 return map_nt_error_from_unix(errno);
5613 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5614 smb_fname->base_name);
5615 return NT_STATUS_OK;
5618 /****************************************************************************
5619 Deal with setting the dosmode from any of the setfilepathinfo functions.
5620 ****************************************************************************/
5622 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5623 const struct smb_filename *smb_fname,
5624 uint32 dosmode)
5626 struct smb_filename *smb_fname_base = NULL;
5627 NTSTATUS status;
5629 if (!VALID_STAT(smb_fname->st)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5633 /* Always operate on the base_name, even if a stream was passed in. */
5634 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5635 NULL, &smb_fname->st,
5636 &smb_fname_base);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 return status;
5641 if (dosmode) {
5642 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5643 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5644 } else {
5645 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5649 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5651 /* check the mode isn't different, before changing it */
5652 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5653 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5654 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5655 (unsigned int)dosmode));
5657 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5658 false)) {
5659 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5660 "%s failed (%s)\n",
5661 smb_fname_str_dbg(smb_fname_base),
5662 strerror(errno)));
5663 status = map_nt_error_from_unix(errno);
5664 goto out;
5667 status = NT_STATUS_OK;
5668 out:
5669 TALLOC_FREE(smb_fname_base);
5670 return status;
5673 /****************************************************************************
5674 Deal with setting the size from any of the setfilepathinfo functions.
5675 ****************************************************************************/
5677 static NTSTATUS smb_set_file_size(connection_struct *conn,
5678 struct smb_request *req,
5679 files_struct *fsp,
5680 const struct smb_filename *smb_fname,
5681 const SMB_STRUCT_STAT *psbuf,
5682 SMB_OFF_T size,
5683 bool fail_after_createfile)
5685 NTSTATUS status = NT_STATUS_OK;
5686 struct smb_filename *smb_fname_tmp = NULL;
5687 files_struct *new_fsp = NULL;
5689 if (!VALID_STAT(*psbuf)) {
5690 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5693 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5694 return NT_STATUS_ACCESS_DENIED;
5697 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5699 if (size == get_file_size_stat(psbuf)) {
5700 return NT_STATUS_OK;
5703 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5704 smb_fname_str_dbg(smb_fname), (double)size));
5706 if (fsp && fsp->fh->fd != -1) {
5707 /* Handle based call. */
5708 if (vfs_set_filelen(fsp, size) == -1) {
5709 return map_nt_error_from_unix(errno);
5711 trigger_write_time_update_immediate(fsp);
5712 return NT_STATUS_OK;
5715 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5716 if (!NT_STATUS_IS_OK(status)) {
5717 return status;
5720 smb_fname_tmp->st = *psbuf;
5722 status = SMB_VFS_CREATE_FILE(
5723 conn, /* conn */
5724 req, /* req */
5725 0, /* root_dir_fid */
5726 smb_fname_tmp, /* fname */
5727 FILE_WRITE_DATA, /* access_mask */
5728 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5729 FILE_SHARE_DELETE),
5730 FILE_OPEN, /* create_disposition*/
5731 0, /* create_options */
5732 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5733 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5734 0, /* allocation_size */
5735 0, /* private_flags */
5736 NULL, /* sd */
5737 NULL, /* ea_list */
5738 &new_fsp, /* result */
5739 NULL); /* pinfo */
5741 TALLOC_FREE(smb_fname_tmp);
5743 if (!NT_STATUS_IS_OK(status)) {
5744 /* NB. We check for open_was_deferred in the caller. */
5745 return status;
5748 /* See RAW-SFILEINFO-END-OF-FILE */
5749 if (fail_after_createfile) {
5750 close_file(req, new_fsp,NORMAL_CLOSE);
5751 return NT_STATUS_INVALID_LEVEL;
5754 if (vfs_set_filelen(new_fsp, size) == -1) {
5755 status = map_nt_error_from_unix(errno);
5756 close_file(req, new_fsp,NORMAL_CLOSE);
5757 return status;
5760 trigger_write_time_update_immediate(new_fsp);
5761 close_file(req, new_fsp,NORMAL_CLOSE);
5762 return NT_STATUS_OK;
5765 /****************************************************************************
5766 Deal with SMB_INFO_SET_EA.
5767 ****************************************************************************/
5769 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5770 const char *pdata,
5771 int total_data,
5772 files_struct *fsp,
5773 const struct smb_filename *smb_fname)
5775 struct ea_list *ea_list = NULL;
5776 TALLOC_CTX *ctx = NULL;
5777 NTSTATUS status = NT_STATUS_OK;
5779 if (total_data < 10) {
5781 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5782 length. They seem to have no effect. Bug #3212. JRA */
5784 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5785 /* We're done. We only get EA info in this call. */
5786 return NT_STATUS_OK;
5789 return NT_STATUS_INVALID_PARAMETER;
5792 if (IVAL(pdata,0) > total_data) {
5793 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5794 IVAL(pdata,0), (unsigned int)total_data));
5795 return NT_STATUS_INVALID_PARAMETER;
5798 ctx = talloc_tos();
5799 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5800 if (!ea_list) {
5801 return NT_STATUS_INVALID_PARAMETER;
5804 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5805 return NT_STATUS_ACCESS_DENIED;
5808 status = set_ea(conn, fsp, smb_fname, ea_list);
5810 return status;
5813 /****************************************************************************
5814 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5815 ****************************************************************************/
5817 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5818 const char *pdata,
5819 int total_data,
5820 files_struct *fsp)
5822 struct ea_list *ea_list = NULL;
5823 NTSTATUS status;
5825 if (!fsp) {
5826 return NT_STATUS_INVALID_HANDLE;
5829 if (!lp_ea_support(SNUM(conn))) {
5830 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5831 "EA's not supported.\n",
5832 (unsigned int)total_data));
5833 return NT_STATUS_EAS_NOT_SUPPORTED;
5836 if (total_data < 10) {
5837 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5838 "too small.\n",
5839 (unsigned int)total_data));
5840 return NT_STATUS_INVALID_PARAMETER;
5843 ea_list = read_nttrans_ea_list(talloc_tos(),
5844 pdata,
5845 total_data);
5847 if (!ea_list) {
5848 return NT_STATUS_INVALID_PARAMETER;
5851 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5852 return NT_STATUS_ACCESS_DENIED;
5855 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5857 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5858 smb_fname_str_dbg(fsp->fsp_name),
5859 nt_errstr(status) ));
5861 return status;
5865 /****************************************************************************
5866 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5867 ****************************************************************************/
5869 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5870 const char *pdata,
5871 int total_data,
5872 files_struct *fsp,
5873 struct smb_filename *smb_fname)
5875 NTSTATUS status = NT_STATUS_OK;
5876 bool delete_on_close;
5877 uint32 dosmode = 0;
5879 if (total_data < 1) {
5880 return NT_STATUS_INVALID_PARAMETER;
5883 if (fsp == NULL) {
5884 return NT_STATUS_INVALID_HANDLE;
5887 delete_on_close = (CVAL(pdata,0) ? True : False);
5888 dosmode = dos_mode(conn, smb_fname);
5890 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5891 "delete_on_close = %u\n",
5892 smb_fname_str_dbg(smb_fname),
5893 (unsigned int)dosmode,
5894 (unsigned int)delete_on_close ));
5896 if (delete_on_close) {
5897 status = can_set_delete_on_close(fsp, dosmode);
5898 if (!NT_STATUS_IS_OK(status)) {
5899 return status;
5903 /* The set is across all open files on this dev/inode pair. */
5904 if (!set_delete_on_close(fsp, delete_on_close,
5905 conn->session_info->security_token,
5906 &conn->session_info->utok)) {
5907 return NT_STATUS_ACCESS_DENIED;
5909 return NT_STATUS_OK;
5912 /****************************************************************************
5913 Deal with SMB_FILE_POSITION_INFORMATION.
5914 ****************************************************************************/
5916 static NTSTATUS smb_file_position_information(connection_struct *conn,
5917 const char *pdata,
5918 int total_data,
5919 files_struct *fsp)
5921 uint64_t position_information;
5923 if (total_data < 8) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 if (fsp == NULL) {
5928 /* Ignore on pathname based set. */
5929 return NT_STATUS_OK;
5932 position_information = (uint64_t)IVAL(pdata,0);
5933 #ifdef LARGE_SMB_OFF_T
5934 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5935 #else /* LARGE_SMB_OFF_T */
5936 if (IVAL(pdata,4) != 0) {
5937 /* more than 32 bits? */
5938 return NT_STATUS_INVALID_PARAMETER;
5940 #endif /* LARGE_SMB_OFF_T */
5942 DEBUG(10,("smb_file_position_information: Set file position "
5943 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5944 (double)position_information));
5945 fsp->fh->position_information = position_information;
5946 return NT_STATUS_OK;
5949 /****************************************************************************
5950 Deal with SMB_FILE_MODE_INFORMATION.
5951 ****************************************************************************/
5953 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5954 const char *pdata,
5955 int total_data)
5957 uint32 mode;
5959 if (total_data < 4) {
5960 return NT_STATUS_INVALID_PARAMETER;
5962 mode = IVAL(pdata,0);
5963 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5964 return NT_STATUS_INVALID_PARAMETER;
5966 return NT_STATUS_OK;
5969 /****************************************************************************
5970 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5971 ****************************************************************************/
5973 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5974 struct smb_request *req,
5975 const char *pdata,
5976 int total_data,
5977 const struct smb_filename *smb_fname)
5979 char *link_target = NULL;
5980 const char *newname = smb_fname->base_name;
5981 TALLOC_CTX *ctx = talloc_tos();
5983 /* Set a symbolic link. */
5984 /* Don't allow this if follow links is false. */
5986 if (total_data == 0) {
5987 return NT_STATUS_INVALID_PARAMETER;
5990 if (!lp_symlinks(SNUM(conn))) {
5991 return NT_STATUS_ACCESS_DENIED;
5994 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5995 total_data, STR_TERMINATE);
5997 if (!link_target) {
5998 return NT_STATUS_INVALID_PARAMETER;
6001 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6002 newname, link_target ));
6004 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6005 return map_nt_error_from_unix(errno);
6008 return NT_STATUS_OK;
6011 /****************************************************************************
6012 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6013 ****************************************************************************/
6015 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6016 struct smb_request *req,
6017 const char *pdata, int total_data,
6018 struct smb_filename *smb_fname_new)
6020 char *oldname = NULL;
6021 struct smb_filename *smb_fname_old = NULL;
6022 TALLOC_CTX *ctx = talloc_tos();
6023 NTSTATUS status = NT_STATUS_OK;
6025 /* Set a hard link. */
6026 if (total_data == 0) {
6027 return NT_STATUS_INVALID_PARAMETER;
6030 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6031 total_data, STR_TERMINATE, &status);
6032 if (!NT_STATUS_IS_OK(status)) {
6033 return status;
6036 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6037 smb_fname_str_dbg(smb_fname_new), oldname));
6039 status = filename_convert(ctx,
6040 conn,
6041 req->flags2 & FLAGS2_DFS_PATHNAMES,
6042 oldname,
6044 NULL,
6045 &smb_fname_old);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 return status;
6050 return hardlink_internals(ctx, conn, req, false,
6051 smb_fname_old, smb_fname_new);
6054 /****************************************************************************
6055 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6056 ****************************************************************************/
6058 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6059 struct smb_request *req,
6060 const char *pdata,
6061 int total_data,
6062 files_struct *fsp,
6063 struct smb_filename *smb_fname_src)
6065 bool overwrite;
6066 uint32_t len;
6067 char *newname = NULL;
6068 struct smb_filename *smb_fname_dst = NULL;
6069 NTSTATUS status = NT_STATUS_OK;
6070 TALLOC_CTX *ctx = talloc_tos();
6072 if (!fsp) {
6073 return NT_STATUS_INVALID_HANDLE;
6076 if (total_data < 20) {
6077 return NT_STATUS_INVALID_PARAMETER;
6080 overwrite = (CVAL(pdata,0) ? True : False);
6081 len = IVAL(pdata,16);
6083 if (len > (total_data - 20) || (len == 0)) {
6084 return NT_STATUS_INVALID_PARAMETER;
6087 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6088 &pdata[20], len, STR_TERMINATE,
6089 &status);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 return status;
6094 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6095 newname));
6097 status = filename_convert(ctx,
6098 conn,
6099 req->flags2 & FLAGS2_DFS_PATHNAMES,
6100 newname,
6101 UCF_SAVE_LCOMP,
6102 NULL,
6103 &smb_fname_dst);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 return status;
6108 if (fsp->base_fsp) {
6109 /* newname must be a stream name. */
6110 if (newname[0] != ':') {
6111 return NT_STATUS_NOT_SUPPORTED;
6114 /* Create an smb_fname to call rename_internals_fsp() with. */
6115 status = create_synthetic_smb_fname(talloc_tos(),
6116 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6117 &smb_fname_dst);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 goto out;
6123 * Set the original last component, since
6124 * rename_internals_fsp() requires it.
6126 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6127 newname);
6128 if (smb_fname_dst->original_lcomp == NULL) {
6129 status = NT_STATUS_NO_MEMORY;
6130 goto out;
6135 DEBUG(10,("smb2_file_rename_information: "
6136 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6137 fsp->fnum, fsp_str_dbg(fsp),
6138 smb_fname_str_dbg(smb_fname_dst)));
6139 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6140 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6141 overwrite);
6143 out:
6144 TALLOC_FREE(smb_fname_dst);
6145 return status;
6148 static NTSTATUS smb_file_link_information(connection_struct *conn,
6149 struct smb_request *req,
6150 const char *pdata,
6151 int total_data,
6152 files_struct *fsp,
6153 struct smb_filename *smb_fname_src)
6155 bool overwrite;
6156 uint32_t len;
6157 char *newname = NULL;
6158 struct smb_filename *smb_fname_dst = NULL;
6159 NTSTATUS status = NT_STATUS_OK;
6160 TALLOC_CTX *ctx = talloc_tos();
6162 if (!fsp) {
6163 return NT_STATUS_INVALID_HANDLE;
6166 if (total_data < 20) {
6167 return NT_STATUS_INVALID_PARAMETER;
6170 overwrite = (CVAL(pdata,0) ? true : false);
6171 len = IVAL(pdata,16);
6173 if (len > (total_data - 20) || (len == 0)) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6178 &pdata[20], len, STR_TERMINATE,
6179 &status);
6180 if (!NT_STATUS_IS_OK(status)) {
6181 return status;
6184 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6185 newname));
6187 status = filename_convert(ctx,
6188 conn,
6189 req->flags2 & FLAGS2_DFS_PATHNAMES,
6190 newname,
6191 UCF_SAVE_LCOMP,
6192 NULL,
6193 &smb_fname_dst);
6194 if (!NT_STATUS_IS_OK(status)) {
6195 return status;
6198 if (fsp->base_fsp) {
6199 /* No stream names. */
6200 return NT_STATUS_NOT_SUPPORTED;
6203 DEBUG(10,("smb_file_link_information: "
6204 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6205 fsp->fnum, fsp_str_dbg(fsp),
6206 smb_fname_str_dbg(smb_fname_dst)));
6207 status = hardlink_internals(ctx,
6208 conn,
6209 req,
6210 overwrite,
6211 fsp->fsp_name,
6212 smb_fname_dst);
6214 TALLOC_FREE(smb_fname_dst);
6215 return status;
6218 /****************************************************************************
6219 Deal with SMB_FILE_RENAME_INFORMATION.
6220 ****************************************************************************/
6222 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6223 struct smb_request *req,
6224 const char *pdata,
6225 int total_data,
6226 files_struct *fsp,
6227 struct smb_filename *smb_fname_src)
6229 bool overwrite;
6230 uint32 root_fid;
6231 uint32 len;
6232 char *newname = NULL;
6233 struct smb_filename *smb_fname_dst = NULL;
6234 bool dest_has_wcard = False;
6235 NTSTATUS status = NT_STATUS_OK;
6236 char *p;
6237 TALLOC_CTX *ctx = talloc_tos();
6239 if (total_data < 13) {
6240 return NT_STATUS_INVALID_PARAMETER;
6243 overwrite = (CVAL(pdata,0) ? True : False);
6244 root_fid = IVAL(pdata,4);
6245 len = IVAL(pdata,8);
6247 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6248 return NT_STATUS_INVALID_PARAMETER;
6251 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6252 len, 0, &status,
6253 &dest_has_wcard);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 return status;
6258 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6259 newname));
6261 status = resolve_dfspath_wcard(ctx, conn,
6262 req->flags2 & FLAGS2_DFS_PATHNAMES,
6263 newname,
6264 true,
6265 &newname,
6266 &dest_has_wcard);
6267 if (!NT_STATUS_IS_OK(status)) {
6268 return status;
6271 /* Check the new name has no '/' characters. */
6272 if (strchr_m(newname, '/')) {
6273 return NT_STATUS_NOT_SUPPORTED;
6276 if (fsp && fsp->base_fsp) {
6277 /* newname must be a stream name. */
6278 if (newname[0] != ':') {
6279 return NT_STATUS_NOT_SUPPORTED;
6282 /* Create an smb_fname to call rename_internals_fsp() with. */
6283 status = create_synthetic_smb_fname(talloc_tos(),
6284 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6285 &smb_fname_dst);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 goto out;
6291 * Set the original last component, since
6292 * rename_internals_fsp() requires it.
6294 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6295 newname);
6296 if (smb_fname_dst->original_lcomp == NULL) {
6297 status = NT_STATUS_NO_MEMORY;
6298 goto out;
6301 } else {
6303 * Build up an smb_fname_dst based on the filename passed in.
6304 * We basically just strip off the last component, and put on
6305 * the newname instead.
6307 char *base_name = NULL;
6309 /* newname must *not* be a stream name. */
6310 if (newname[0] == ':') {
6311 return NT_STATUS_NOT_SUPPORTED;
6315 * Strip off the last component (filename) of the path passed
6316 * in.
6318 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6319 if (!base_name) {
6320 return NT_STATUS_NO_MEMORY;
6322 p = strrchr_m(base_name, '/');
6323 if (p) {
6324 p[1] = '\0';
6325 } else {
6326 base_name = talloc_strdup(ctx, "");
6327 if (!base_name) {
6328 return NT_STATUS_NO_MEMORY;
6331 /* Append the new name. */
6332 base_name = talloc_asprintf_append(base_name,
6333 "%s",
6334 newname);
6335 if (!base_name) {
6336 return NT_STATUS_NO_MEMORY;
6339 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6340 (UCF_SAVE_LCOMP |
6341 (dest_has_wcard ?
6342 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6343 0)));
6345 /* If an error we expect this to be
6346 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6348 if (!NT_STATUS_IS_OK(status)) {
6349 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6350 status)) {
6351 goto out;
6353 /* Create an smb_fname to call rename_internals_fsp() */
6354 status = create_synthetic_smb_fname(ctx,
6355 base_name, NULL,
6356 NULL,
6357 &smb_fname_dst);
6358 if (!NT_STATUS_IS_OK(status)) {
6359 goto out;
6364 if (fsp) {
6365 DEBUG(10,("smb_file_rename_information: "
6366 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6367 fsp->fnum, fsp_str_dbg(fsp),
6368 smb_fname_str_dbg(smb_fname_dst)));
6369 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6370 overwrite);
6371 } else {
6372 DEBUG(10,("smb_file_rename_information: "
6373 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6374 smb_fname_str_dbg(smb_fname_src),
6375 smb_fname_str_dbg(smb_fname_dst)));
6376 status = rename_internals(ctx, conn, req, smb_fname_src,
6377 smb_fname_dst, 0, overwrite, false,
6378 dest_has_wcard,
6379 FILE_WRITE_ATTRIBUTES);
6381 out:
6382 TALLOC_FREE(smb_fname_dst);
6383 return status;
6386 /****************************************************************************
6387 Deal with SMB_SET_POSIX_ACL.
6388 ****************************************************************************/
6390 #if defined(HAVE_POSIX_ACLS)
6391 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6392 const char *pdata,
6393 int total_data,
6394 files_struct *fsp,
6395 const struct smb_filename *smb_fname)
6397 uint16 posix_acl_version;
6398 uint16 num_file_acls;
6399 uint16 num_def_acls;
6400 bool valid_file_acls = True;
6401 bool valid_def_acls = True;
6403 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6404 return NT_STATUS_INVALID_PARAMETER;
6406 posix_acl_version = SVAL(pdata,0);
6407 num_file_acls = SVAL(pdata,2);
6408 num_def_acls = SVAL(pdata,4);
6410 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6411 valid_file_acls = False;
6412 num_file_acls = 0;
6415 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6416 valid_def_acls = False;
6417 num_def_acls = 0;
6420 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6421 return NT_STATUS_INVALID_PARAMETER;
6424 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6425 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6426 return NT_STATUS_INVALID_PARAMETER;
6429 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6430 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6431 (unsigned int)num_file_acls,
6432 (unsigned int)num_def_acls));
6434 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6435 smb_fname->base_name, num_file_acls,
6436 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6437 return map_nt_error_from_unix(errno);
6440 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6441 smb_fname->base_name, &smb_fname->st, num_def_acls,
6442 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6443 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6444 return map_nt_error_from_unix(errno);
6446 return NT_STATUS_OK;
6448 #endif
6450 /****************************************************************************
6451 Deal with SMB_SET_POSIX_LOCK.
6452 ****************************************************************************/
6454 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6455 struct smb_request *req,
6456 const char *pdata,
6457 int total_data,
6458 files_struct *fsp)
6460 uint64_t count;
6461 uint64_t offset;
6462 uint64_t smblctx;
6463 bool blocking_lock = False;
6464 enum brl_type lock_type;
6466 NTSTATUS status = NT_STATUS_OK;
6468 if (fsp == NULL || fsp->fh->fd == -1) {
6469 return NT_STATUS_INVALID_HANDLE;
6472 if (total_data != POSIX_LOCK_DATA_SIZE) {
6473 return NT_STATUS_INVALID_PARAMETER;
6476 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6477 case POSIX_LOCK_TYPE_READ:
6478 lock_type = READ_LOCK;
6479 break;
6480 case POSIX_LOCK_TYPE_WRITE:
6481 /* Return the right POSIX-mappable error code for files opened read-only. */
6482 if (!fsp->can_write) {
6483 return NT_STATUS_INVALID_HANDLE;
6485 lock_type = WRITE_LOCK;
6486 break;
6487 case POSIX_LOCK_TYPE_UNLOCK:
6488 lock_type = UNLOCK_LOCK;
6489 break;
6490 default:
6491 return NT_STATUS_INVALID_PARAMETER;
6494 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6495 blocking_lock = False;
6496 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6497 blocking_lock = True;
6498 } else {
6499 return NT_STATUS_INVALID_PARAMETER;
6502 if (!lp_blocking_locks(SNUM(conn))) {
6503 blocking_lock = False;
6506 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6507 #if defined(HAVE_LONGLONG)
6508 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6509 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6510 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6511 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6512 #else /* HAVE_LONGLONG */
6513 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6514 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6515 #endif /* HAVE_LONGLONG */
6517 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6518 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6519 fsp_str_dbg(fsp),
6520 (unsigned int)lock_type,
6521 (unsigned long long)smblctx,
6522 (double)count,
6523 (double)offset ));
6525 if (lock_type == UNLOCK_LOCK) {
6526 status = do_unlock(req->sconn->msg_ctx,
6527 fsp,
6528 smblctx,
6529 count,
6530 offset,
6531 POSIX_LOCK);
6532 } else {
6533 uint64_t block_smblctx;
6535 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6536 fsp,
6537 smblctx,
6538 count,
6539 offset,
6540 lock_type,
6541 POSIX_LOCK,
6542 blocking_lock,
6543 &status,
6544 &block_smblctx,
6545 NULL);
6547 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6549 * A blocking lock was requested. Package up
6550 * this smb into a queued request and push it
6551 * onto the blocking lock queue.
6553 if(push_blocking_lock_request(br_lck,
6554 req,
6555 fsp,
6556 -1, /* infinite timeout. */
6558 smblctx,
6559 lock_type,
6560 POSIX_LOCK,
6561 offset,
6562 count,
6563 block_smblctx)) {
6564 TALLOC_FREE(br_lck);
6565 return status;
6568 TALLOC_FREE(br_lck);
6571 return status;
6574 /****************************************************************************
6575 Deal with SMB_SET_FILE_BASIC_INFO.
6576 ****************************************************************************/
6578 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6579 const char *pdata,
6580 int total_data,
6581 files_struct *fsp,
6582 const struct smb_filename *smb_fname)
6584 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6585 struct smb_file_time ft;
6586 uint32 dosmode = 0;
6587 NTSTATUS status = NT_STATUS_OK;
6589 ZERO_STRUCT(ft);
6591 if (total_data < 36) {
6592 return NT_STATUS_INVALID_PARAMETER;
6595 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6596 return NT_STATUS_ACCESS_DENIED;
6599 /* Set the attributes */
6600 dosmode = IVAL(pdata,32);
6601 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 return status;
6606 /* create time */
6607 ft.create_time = interpret_long_date(pdata);
6609 /* access time */
6610 ft.atime = interpret_long_date(pdata+8);
6612 /* write time. */
6613 ft.mtime = interpret_long_date(pdata+16);
6615 /* change time. */
6616 ft.ctime = interpret_long_date(pdata+24);
6618 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6619 smb_fname_str_dbg(smb_fname)));
6621 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6622 true);
6625 /****************************************************************************
6626 Deal with SMB_INFO_STANDARD.
6627 ****************************************************************************/
6629 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6630 const char *pdata,
6631 int total_data,
6632 files_struct *fsp,
6633 const struct smb_filename *smb_fname)
6635 struct smb_file_time ft;
6637 ZERO_STRUCT(ft);
6639 if (total_data < 12) {
6640 return NT_STATUS_INVALID_PARAMETER;
6643 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6644 return NT_STATUS_ACCESS_DENIED;
6647 /* create time */
6648 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6649 /* access time */
6650 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6651 /* write time */
6652 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6654 DEBUG(10,("smb_set_info_standard: file %s\n",
6655 smb_fname_str_dbg(smb_fname)));
6657 return smb_set_file_time(conn,
6658 fsp,
6659 smb_fname,
6660 &ft,
6661 true);
6664 /****************************************************************************
6665 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6666 ****************************************************************************/
6668 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6669 struct smb_request *req,
6670 const char *pdata,
6671 int total_data,
6672 files_struct *fsp,
6673 struct smb_filename *smb_fname)
6675 uint64_t allocation_size = 0;
6676 NTSTATUS status = NT_STATUS_OK;
6677 files_struct *new_fsp = NULL;
6679 if (!VALID_STAT(smb_fname->st)) {
6680 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6683 if (total_data < 8) {
6684 return NT_STATUS_INVALID_PARAMETER;
6687 allocation_size = (uint64_t)IVAL(pdata,0);
6688 #ifdef LARGE_SMB_OFF_T
6689 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6690 #else /* LARGE_SMB_OFF_T */
6691 if (IVAL(pdata,4) != 0) {
6692 /* more than 32 bits? */
6693 return NT_STATUS_INVALID_PARAMETER;
6695 #endif /* LARGE_SMB_OFF_T */
6697 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6698 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6699 (double)allocation_size));
6701 if (allocation_size) {
6702 allocation_size = smb_roundup(conn, allocation_size);
6705 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6706 return NT_STATUS_ACCESS_DENIED;
6709 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6710 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6711 (double)allocation_size));
6713 if (fsp && fsp->fh->fd != -1) {
6714 /* Open file handle. */
6715 /* Only change if needed. */
6716 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6717 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6718 return map_nt_error_from_unix(errno);
6721 /* But always update the time. */
6723 * This is equivalent to a write. Ensure it's seen immediately
6724 * if there are no pending writes.
6726 trigger_write_time_update_immediate(fsp);
6727 return NT_STATUS_OK;
6730 /* Pathname or stat or directory file. */
6731 status = SMB_VFS_CREATE_FILE(
6732 conn, /* conn */
6733 req, /* req */
6734 0, /* root_dir_fid */
6735 smb_fname, /* fname */
6736 FILE_WRITE_DATA, /* access_mask */
6737 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6738 FILE_SHARE_DELETE),
6739 FILE_OPEN, /* create_disposition*/
6740 0, /* create_options */
6741 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6742 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6743 0, /* allocation_size */
6744 0, /* private_flags */
6745 NULL, /* sd */
6746 NULL, /* ea_list */
6747 &new_fsp, /* result */
6748 NULL); /* pinfo */
6750 if (!NT_STATUS_IS_OK(status)) {
6751 /* NB. We check for open_was_deferred in the caller. */
6752 return status;
6755 /* Only change if needed. */
6756 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6757 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6758 status = map_nt_error_from_unix(errno);
6759 close_file(req, new_fsp, NORMAL_CLOSE);
6760 return status;
6764 /* Changing the allocation size should set the last mod time. */
6766 * This is equivalent to a write. Ensure it's seen immediately
6767 * if there are no pending writes.
6769 trigger_write_time_update_immediate(new_fsp);
6771 close_file(req, new_fsp, NORMAL_CLOSE);
6772 return NT_STATUS_OK;
6775 /****************************************************************************
6776 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6777 ****************************************************************************/
6779 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6780 struct smb_request *req,
6781 const char *pdata,
6782 int total_data,
6783 files_struct *fsp,
6784 const struct smb_filename *smb_fname,
6785 bool fail_after_createfile)
6787 SMB_OFF_T size;
6789 if (total_data < 8) {
6790 return NT_STATUS_INVALID_PARAMETER;
6793 size = IVAL(pdata,0);
6794 #ifdef LARGE_SMB_OFF_T
6795 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6796 #else /* LARGE_SMB_OFF_T */
6797 if (IVAL(pdata,4) != 0) {
6798 /* more than 32 bits? */
6799 return NT_STATUS_INVALID_PARAMETER;
6801 #endif /* LARGE_SMB_OFF_T */
6802 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6803 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6804 (double)size));
6806 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6807 return NT_STATUS_ACCESS_DENIED;
6810 return smb_set_file_size(conn, req,
6811 fsp,
6812 smb_fname,
6813 &smb_fname->st,
6814 size,
6815 fail_after_createfile);
6818 /****************************************************************************
6819 Allow a UNIX info mknod.
6820 ****************************************************************************/
6822 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6823 const char *pdata,
6824 int total_data,
6825 const struct smb_filename *smb_fname)
6827 uint32 file_type = IVAL(pdata,56);
6828 #if defined(HAVE_MAKEDEV)
6829 uint32 dev_major = IVAL(pdata,60);
6830 uint32 dev_minor = IVAL(pdata,68);
6831 #endif
6832 SMB_DEV_T dev = (SMB_DEV_T)0;
6833 uint32 raw_unixmode = IVAL(pdata,84);
6834 NTSTATUS status;
6835 mode_t unixmode;
6837 if (total_data < 100) {
6838 return NT_STATUS_INVALID_PARAMETER;
6841 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6842 PERM_NEW_FILE, &unixmode);
6843 if (!NT_STATUS_IS_OK(status)) {
6844 return status;
6847 #if defined(HAVE_MAKEDEV)
6848 dev = makedev(dev_major, dev_minor);
6849 #endif
6851 switch (file_type) {
6852 #if defined(S_IFIFO)
6853 case UNIX_TYPE_FIFO:
6854 unixmode |= S_IFIFO;
6855 break;
6856 #endif
6857 #if defined(S_IFSOCK)
6858 case UNIX_TYPE_SOCKET:
6859 unixmode |= S_IFSOCK;
6860 break;
6861 #endif
6862 #if defined(S_IFCHR)
6863 case UNIX_TYPE_CHARDEV:
6864 unixmode |= S_IFCHR;
6865 break;
6866 #endif
6867 #if defined(S_IFBLK)
6868 case UNIX_TYPE_BLKDEV:
6869 unixmode |= S_IFBLK;
6870 break;
6871 #endif
6872 default:
6873 return NT_STATUS_INVALID_PARAMETER;
6876 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6877 "%.0f mode 0%o for file %s\n", (double)dev,
6878 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6880 /* Ok - do the mknod. */
6881 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6882 return map_nt_error_from_unix(errno);
6885 /* If any of the other "set" calls fail we
6886 * don't want to end up with a half-constructed mknod.
6889 if (lp_inherit_perms(SNUM(conn))) {
6890 char *parent;
6891 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6892 &parent, NULL)) {
6893 return NT_STATUS_NO_MEMORY;
6895 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6896 unixmode);
6897 TALLOC_FREE(parent);
6900 return NT_STATUS_OK;
6903 /****************************************************************************
6904 Deal with SMB_SET_FILE_UNIX_BASIC.
6905 ****************************************************************************/
6907 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6908 struct smb_request *req,
6909 const char *pdata,
6910 int total_data,
6911 files_struct *fsp,
6912 const struct smb_filename *smb_fname)
6914 struct smb_file_time ft;
6915 uint32 raw_unixmode;
6916 mode_t unixmode;
6917 SMB_OFF_T size = 0;
6918 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6919 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6920 NTSTATUS status = NT_STATUS_OK;
6921 bool delete_on_fail = False;
6922 enum perm_type ptype;
6923 files_struct *all_fsps = NULL;
6924 bool modify_mtime = true;
6925 struct file_id id;
6926 struct smb_filename *smb_fname_tmp = NULL;
6927 SMB_STRUCT_STAT sbuf;
6929 ZERO_STRUCT(ft);
6931 if (total_data < 100) {
6932 return NT_STATUS_INVALID_PARAMETER;
6935 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6936 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6937 size=IVAL(pdata,0); /* first 8 Bytes are size */
6938 #ifdef LARGE_SMB_OFF_T
6939 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6940 #else /* LARGE_SMB_OFF_T */
6941 if (IVAL(pdata,4) != 0) {
6942 /* more than 32 bits? */
6943 return NT_STATUS_INVALID_PARAMETER;
6945 #endif /* LARGE_SMB_OFF_T */
6948 ft.atime = interpret_long_date(pdata+24); /* access_time */
6949 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6950 set_owner = (uid_t)IVAL(pdata,40);
6951 set_grp = (gid_t)IVAL(pdata,48);
6952 raw_unixmode = IVAL(pdata,84);
6954 if (VALID_STAT(smb_fname->st)) {
6955 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6956 ptype = PERM_EXISTING_DIR;
6957 } else {
6958 ptype = PERM_EXISTING_FILE;
6960 } else {
6961 ptype = PERM_NEW_FILE;
6964 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6965 ptype, &unixmode);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 return status;
6970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6971 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6972 smb_fname_str_dbg(smb_fname), (double)size,
6973 (unsigned int)set_owner, (unsigned int)set_grp,
6974 (int)raw_unixmode));
6976 sbuf = smb_fname->st;
6978 if (!VALID_STAT(sbuf)) {
6980 * The only valid use of this is to create character and block
6981 * devices, and named pipes. This is deprecated (IMHO) and
6982 * a new info level should be used for mknod. JRA.
6985 status = smb_unix_mknod(conn,
6986 pdata,
6987 total_data,
6988 smb_fname);
6989 if (!NT_STATUS_IS_OK(status)) {
6990 return status;
6993 status = copy_smb_filename(talloc_tos(), smb_fname,
6994 &smb_fname_tmp);
6995 if (!NT_STATUS_IS_OK(status)) {
6996 return status;
6999 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7000 status = map_nt_error_from_unix(errno);
7001 TALLOC_FREE(smb_fname_tmp);
7002 SMB_VFS_UNLINK(conn, smb_fname);
7003 return status;
7006 sbuf = smb_fname_tmp->st;
7007 smb_fname = smb_fname_tmp;
7009 /* Ensure we don't try and change anything else. */
7010 raw_unixmode = SMB_MODE_NO_CHANGE;
7011 size = get_file_size_stat(&sbuf);
7012 ft.atime = sbuf.st_ex_atime;
7013 ft.mtime = sbuf.st_ex_mtime;
7015 * We continue here as we might want to change the
7016 * owner uid/gid.
7018 delete_on_fail = True;
7021 #if 1
7022 /* Horrible backwards compatibility hack as an old server bug
7023 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7024 * */
7026 if (!size) {
7027 size = get_file_size_stat(&sbuf);
7029 #endif
7032 * Deal with the UNIX specific mode set.
7035 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7036 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7037 "setting mode 0%o for file %s\n",
7038 (unsigned int)unixmode,
7039 smb_fname_str_dbg(smb_fname)));
7040 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7041 return map_nt_error_from_unix(errno);
7046 * Deal with the UNIX specific uid set.
7049 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7050 (sbuf.st_ex_uid != set_owner)) {
7051 int ret;
7053 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7054 "changing owner %u for path %s\n",
7055 (unsigned int)set_owner,
7056 smb_fname_str_dbg(smb_fname)));
7058 if (S_ISLNK(sbuf.st_ex_mode)) {
7059 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7060 set_owner, (gid_t)-1);
7061 } else {
7062 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7063 set_owner, (gid_t)-1);
7066 if (ret != 0) {
7067 status = map_nt_error_from_unix(errno);
7068 if (delete_on_fail) {
7069 SMB_VFS_UNLINK(conn, smb_fname);
7071 return status;
7076 * Deal with the UNIX specific gid set.
7079 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7080 (sbuf.st_ex_gid != set_grp)) {
7081 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7082 "changing group %u for file %s\n",
7083 (unsigned int)set_owner,
7084 smb_fname_str_dbg(smb_fname)));
7085 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7086 set_grp) != 0) {
7087 status = map_nt_error_from_unix(errno);
7088 if (delete_on_fail) {
7089 SMB_VFS_UNLINK(conn, smb_fname);
7091 return status;
7095 /* Deal with any size changes. */
7097 status = smb_set_file_size(conn, req,
7098 fsp,
7099 smb_fname,
7100 &sbuf,
7101 size,
7102 false);
7103 if (!NT_STATUS_IS_OK(status)) {
7104 return status;
7107 /* Deal with any time changes. */
7108 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7109 /* No change, don't cancel anything. */
7110 return status;
7113 id = vfs_file_id_from_sbuf(conn, &sbuf);
7114 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7115 all_fsps = file_find_di_next(all_fsps)) {
7117 * We're setting the time explicitly for UNIX.
7118 * Cancel any pending changes over all handles.
7120 all_fsps->update_write_time_on_close = false;
7121 TALLOC_FREE(all_fsps->update_write_time_event);
7125 * Override the "setting_write_time"
7126 * parameter here as it almost does what
7127 * we need. Just remember if we modified
7128 * mtime and send the notify ourselves.
7130 if (null_timespec(ft.mtime)) {
7131 modify_mtime = false;
7134 status = smb_set_file_time(conn,
7135 fsp,
7136 smb_fname,
7137 &ft,
7138 false);
7139 if (modify_mtime) {
7140 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7141 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7143 return status;
7146 /****************************************************************************
7147 Deal with SMB_SET_FILE_UNIX_INFO2.
7148 ****************************************************************************/
7150 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7151 struct smb_request *req,
7152 const char *pdata,
7153 int total_data,
7154 files_struct *fsp,
7155 const struct smb_filename *smb_fname)
7157 NTSTATUS status;
7158 uint32 smb_fflags;
7159 uint32 smb_fmask;
7161 if (total_data < 116) {
7162 return NT_STATUS_INVALID_PARAMETER;
7165 /* Start by setting all the fields that are common between UNIX_BASIC
7166 * and UNIX_INFO2.
7168 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7169 fsp, smb_fname);
7170 if (!NT_STATUS_IS_OK(status)) {
7171 return status;
7174 smb_fflags = IVAL(pdata, 108);
7175 smb_fmask = IVAL(pdata, 112);
7177 /* NB: We should only attempt to alter the file flags if the client
7178 * sends a non-zero mask.
7180 if (smb_fmask != 0) {
7181 int stat_fflags = 0;
7183 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7184 smb_fmask, &stat_fflags)) {
7185 /* Client asked to alter a flag we don't understand. */
7186 return NT_STATUS_INVALID_PARAMETER;
7189 if (fsp && fsp->fh->fd != -1) {
7190 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7191 return NT_STATUS_NOT_SUPPORTED;
7192 } else {
7193 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7194 stat_fflags) != 0) {
7195 return map_nt_error_from_unix(errno);
7200 /* XXX: need to add support for changing the create_time here. You
7201 * can do this for paths on Darwin with setattrlist(2). The right way
7202 * to hook this up is probably by extending the VFS utimes interface.
7205 return NT_STATUS_OK;
7208 /****************************************************************************
7209 Create a directory with POSIX semantics.
7210 ****************************************************************************/
7212 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7213 struct smb_request *req,
7214 char **ppdata,
7215 int total_data,
7216 struct smb_filename *smb_fname,
7217 int *pdata_return_size)
7219 NTSTATUS status = NT_STATUS_OK;
7220 uint32 raw_unixmode = 0;
7221 uint32 mod_unixmode = 0;
7222 mode_t unixmode = (mode_t)0;
7223 files_struct *fsp = NULL;
7224 uint16 info_level_return = 0;
7225 int info;
7226 char *pdata = *ppdata;
7228 if (total_data < 18) {
7229 return NT_STATUS_INVALID_PARAMETER;
7232 raw_unixmode = IVAL(pdata,8);
7233 /* Next 4 bytes are not yet defined. */
7235 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7236 PERM_NEW_DIR, &unixmode);
7237 if (!NT_STATUS_IS_OK(status)) {
7238 return status;
7241 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7243 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7244 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7246 status = SMB_VFS_CREATE_FILE(
7247 conn, /* conn */
7248 req, /* req */
7249 0, /* root_dir_fid */
7250 smb_fname, /* fname */
7251 FILE_READ_ATTRIBUTES, /* access_mask */
7252 FILE_SHARE_NONE, /* share_access */
7253 FILE_CREATE, /* create_disposition*/
7254 FILE_DIRECTORY_FILE, /* create_options */
7255 mod_unixmode, /* file_attributes */
7256 0, /* oplock_request */
7257 0, /* allocation_size */
7258 0, /* private_flags */
7259 NULL, /* sd */
7260 NULL, /* ea_list */
7261 &fsp, /* result */
7262 &info); /* pinfo */
7264 if (NT_STATUS_IS_OK(status)) {
7265 close_file(req, fsp, NORMAL_CLOSE);
7268 info_level_return = SVAL(pdata,16);
7270 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7271 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7272 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7273 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7274 } else {
7275 *pdata_return_size = 12;
7278 /* Realloc the data size */
7279 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7280 if (*ppdata == NULL) {
7281 *pdata_return_size = 0;
7282 return NT_STATUS_NO_MEMORY;
7284 pdata = *ppdata;
7286 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7287 SSVAL(pdata,2,0); /* No fnum. */
7288 SIVAL(pdata,4,info); /* Was directory created. */
7290 switch (info_level_return) {
7291 case SMB_QUERY_FILE_UNIX_BASIC:
7292 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7293 SSVAL(pdata,10,0); /* Padding. */
7294 store_file_unix_basic(conn, pdata + 12, fsp,
7295 &smb_fname->st);
7296 break;
7297 case SMB_QUERY_FILE_UNIX_INFO2:
7298 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7299 SSVAL(pdata,10,0); /* Padding. */
7300 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7301 &smb_fname->st);
7302 break;
7303 default:
7304 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7305 SSVAL(pdata,10,0); /* Padding. */
7306 break;
7309 return status;
7312 /****************************************************************************
7313 Open/Create a file with POSIX semantics.
7314 ****************************************************************************/
7316 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7317 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7319 static NTSTATUS smb_posix_open(connection_struct *conn,
7320 struct smb_request *req,
7321 char **ppdata,
7322 int total_data,
7323 struct smb_filename *smb_fname,
7324 int *pdata_return_size)
7326 bool extended_oplock_granted = False;
7327 char *pdata = *ppdata;
7328 uint32 flags = 0;
7329 uint32 wire_open_mode = 0;
7330 uint32 raw_unixmode = 0;
7331 uint32 mod_unixmode = 0;
7332 uint32 create_disp = 0;
7333 uint32 access_mask = 0;
7334 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7335 NTSTATUS status = NT_STATUS_OK;
7336 mode_t unixmode = (mode_t)0;
7337 files_struct *fsp = NULL;
7338 int oplock_request = 0;
7339 int info = 0;
7340 uint16 info_level_return = 0;
7342 if (total_data < 18) {
7343 return NT_STATUS_INVALID_PARAMETER;
7346 flags = IVAL(pdata,0);
7347 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7348 if (oplock_request) {
7349 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7352 wire_open_mode = IVAL(pdata,4);
7354 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7355 return smb_posix_mkdir(conn, req,
7356 ppdata,
7357 total_data,
7358 smb_fname,
7359 pdata_return_size);
7362 switch (wire_open_mode & SMB_ACCMODE) {
7363 case SMB_O_RDONLY:
7364 access_mask = SMB_O_RDONLY_MAPPING;
7365 break;
7366 case SMB_O_WRONLY:
7367 access_mask = SMB_O_WRONLY_MAPPING;
7368 break;
7369 case SMB_O_RDWR:
7370 access_mask = (SMB_O_RDONLY_MAPPING|
7371 SMB_O_WRONLY_MAPPING);
7372 break;
7373 default:
7374 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7375 (unsigned int)wire_open_mode ));
7376 return NT_STATUS_INVALID_PARAMETER;
7379 wire_open_mode &= ~SMB_ACCMODE;
7381 /* First take care of O_CREAT|O_EXCL interactions. */
7382 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7383 case (SMB_O_CREAT | SMB_O_EXCL):
7384 /* File exists fail. File not exist create. */
7385 create_disp = FILE_CREATE;
7386 break;
7387 case SMB_O_CREAT:
7388 /* File exists open. File not exist create. */
7389 create_disp = FILE_OPEN_IF;
7390 break;
7391 case SMB_O_EXCL:
7392 /* O_EXCL on its own without O_CREAT is undefined.
7393 We deliberately ignore it as some versions of
7394 Linux CIFSFS can send a bare O_EXCL on the
7395 wire which other filesystems in the kernel
7396 ignore. See bug 9519 for details. */
7398 /* Fallthrough. */
7400 case 0:
7401 /* File exists open. File not exist fail. */
7402 create_disp = FILE_OPEN;
7403 break;
7404 default:
7405 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7406 (unsigned int)wire_open_mode ));
7407 return NT_STATUS_INVALID_PARAMETER;
7410 /* Next factor in the effects of O_TRUNC. */
7411 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7413 if (wire_open_mode & SMB_O_TRUNC) {
7414 switch (create_disp) {
7415 case FILE_CREATE:
7416 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7417 /* Leave create_disp alone as
7418 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7420 /* File exists fail. File not exist create. */
7421 break;
7422 case FILE_OPEN_IF:
7423 /* SMB_O_CREAT | SMB_O_TRUNC */
7424 /* File exists overwrite. File not exist create. */
7425 create_disp = FILE_OVERWRITE_IF;
7426 break;
7427 case FILE_OPEN:
7428 /* SMB_O_TRUNC */
7429 /* File exists overwrite. File not exist fail. */
7430 create_disp = FILE_OVERWRITE;
7431 break;
7432 default:
7433 /* Cannot get here. */
7434 smb_panic("smb_posix_open: logic error");
7435 return NT_STATUS_INVALID_PARAMETER;
7439 raw_unixmode = IVAL(pdata,8);
7440 /* Next 4 bytes are not yet defined. */
7442 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7443 (VALID_STAT(smb_fname->st) ?
7444 PERM_EXISTING_FILE : PERM_NEW_FILE),
7445 &unixmode);
7447 if (!NT_STATUS_IS_OK(status)) {
7448 return status;
7451 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7453 if (wire_open_mode & SMB_O_SYNC) {
7454 create_options |= FILE_WRITE_THROUGH;
7456 if (wire_open_mode & SMB_O_APPEND) {
7457 access_mask |= FILE_APPEND_DATA;
7459 if (wire_open_mode & SMB_O_DIRECT) {
7460 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7463 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7464 VALID_STAT_OF_DIR(smb_fname->st)) {
7465 if (access_mask != SMB_O_RDONLY_MAPPING) {
7466 return NT_STATUS_FILE_IS_A_DIRECTORY;
7468 create_options &= ~FILE_NON_DIRECTORY_FILE;
7469 create_options |= FILE_DIRECTORY_FILE;
7472 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7473 smb_fname_str_dbg(smb_fname),
7474 (unsigned int)wire_open_mode,
7475 (unsigned int)unixmode ));
7477 status = SMB_VFS_CREATE_FILE(
7478 conn, /* conn */
7479 req, /* req */
7480 0, /* root_dir_fid */
7481 smb_fname, /* fname */
7482 access_mask, /* access_mask */
7483 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7484 FILE_SHARE_DELETE),
7485 create_disp, /* create_disposition*/
7486 create_options, /* create_options */
7487 mod_unixmode, /* file_attributes */
7488 oplock_request, /* oplock_request */
7489 0, /* allocation_size */
7490 0, /* private_flags */
7491 NULL, /* sd */
7492 NULL, /* ea_list */
7493 &fsp, /* result */
7494 &info); /* pinfo */
7496 if (!NT_STATUS_IS_OK(status)) {
7497 return status;
7500 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7501 extended_oplock_granted = True;
7504 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7505 extended_oplock_granted = True;
7508 info_level_return = SVAL(pdata,16);
7510 /* Allocate the correct return size. */
7512 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7513 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7514 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7515 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7516 } else {
7517 *pdata_return_size = 12;
7520 /* Realloc the data size */
7521 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7522 if (*ppdata == NULL) {
7523 close_file(req, fsp, ERROR_CLOSE);
7524 *pdata_return_size = 0;
7525 return NT_STATUS_NO_MEMORY;
7527 pdata = *ppdata;
7529 if (extended_oplock_granted) {
7530 if (flags & REQUEST_BATCH_OPLOCK) {
7531 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7532 } else {
7533 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7535 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7536 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7537 } else {
7538 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7541 SSVAL(pdata,2,fsp->fnum);
7542 SIVAL(pdata,4,info); /* Was file created etc. */
7544 switch (info_level_return) {
7545 case SMB_QUERY_FILE_UNIX_BASIC:
7546 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7547 SSVAL(pdata,10,0); /* padding. */
7548 store_file_unix_basic(conn, pdata + 12, fsp,
7549 &smb_fname->st);
7550 break;
7551 case SMB_QUERY_FILE_UNIX_INFO2:
7552 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7553 SSVAL(pdata,10,0); /* padding. */
7554 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7555 &smb_fname->st);
7556 break;
7557 default:
7558 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7559 SSVAL(pdata,10,0); /* padding. */
7560 break;
7562 return NT_STATUS_OK;
7565 /****************************************************************************
7566 Delete a file with POSIX semantics.
7567 ****************************************************************************/
7569 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7570 struct smb_request *req,
7571 const char *pdata,
7572 int total_data,
7573 struct smb_filename *smb_fname)
7575 NTSTATUS status = NT_STATUS_OK;
7576 files_struct *fsp = NULL;
7577 uint16 flags = 0;
7578 char del = 1;
7579 int info = 0;
7580 int create_options = 0;
7581 int i;
7582 struct share_mode_lock *lck = NULL;
7584 if (total_data < 2) {
7585 return NT_STATUS_INVALID_PARAMETER;
7588 flags = SVAL(pdata,0);
7590 if (!VALID_STAT(smb_fname->st)) {
7591 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7594 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7595 !VALID_STAT_OF_DIR(smb_fname->st)) {
7596 return NT_STATUS_NOT_A_DIRECTORY;
7599 DEBUG(10,("smb_posix_unlink: %s %s\n",
7600 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7601 smb_fname_str_dbg(smb_fname)));
7603 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7604 create_options |= FILE_DIRECTORY_FILE;
7607 status = SMB_VFS_CREATE_FILE(
7608 conn, /* conn */
7609 req, /* req */
7610 0, /* root_dir_fid */
7611 smb_fname, /* fname */
7612 DELETE_ACCESS, /* access_mask */
7613 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7614 FILE_SHARE_DELETE),
7615 FILE_OPEN, /* create_disposition*/
7616 create_options, /* create_options */
7617 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7618 0, /* oplock_request */
7619 0, /* allocation_size */
7620 0, /* private_flags */
7621 NULL, /* sd */
7622 NULL, /* ea_list */
7623 &fsp, /* result */
7624 &info); /* pinfo */
7626 if (!NT_STATUS_IS_OK(status)) {
7627 return status;
7631 * Don't lie to client. If we can't really delete due to
7632 * non-POSIX opens return SHARING_VIOLATION.
7635 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7636 NULL);
7637 if (lck == NULL) {
7638 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7639 "lock for file %s\n", fsp_str_dbg(fsp)));
7640 close_file(req, fsp, NORMAL_CLOSE);
7641 return NT_STATUS_INVALID_PARAMETER;
7645 * See if others still have the file open. If this is the case, then
7646 * don't delete. If all opens are POSIX delete we can set the delete
7647 * on close disposition.
7649 for (i=0; i<lck->num_share_modes; i++) {
7650 struct share_mode_entry *e = &lck->share_modes[i];
7651 if (is_valid_share_mode_entry(e)) {
7652 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7653 continue;
7655 /* Fail with sharing violation. */
7656 TALLOC_FREE(lck);
7657 close_file(req, fsp, NORMAL_CLOSE);
7658 return NT_STATUS_SHARING_VIOLATION;
7663 * Set the delete on close.
7665 status = smb_set_file_disposition_info(conn,
7666 &del,
7668 fsp,
7669 smb_fname);
7671 TALLOC_FREE(lck);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 close_file(req, fsp, NORMAL_CLOSE);
7675 return status;
7677 return close_file(req, fsp, NORMAL_CLOSE);
7680 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7681 struct smb_request *req,
7682 TALLOC_CTX *mem_ctx,
7683 uint16_t info_level,
7684 files_struct *fsp,
7685 struct smb_filename *smb_fname,
7686 char **ppdata, int total_data,
7687 int *ret_data_size)
7689 char *pdata = *ppdata;
7690 NTSTATUS status = NT_STATUS_OK;
7691 int data_return_size = 0;
7693 *ret_data_size = 0;
7695 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7696 return NT_STATUS_INVALID_LEVEL;
7699 if (!CAN_WRITE(conn)) {
7700 /* Allow POSIX opens. The open path will deny
7701 * any non-readonly opens. */
7702 if (info_level != SMB_POSIX_PATH_OPEN) {
7703 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7707 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7708 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7709 fsp ? fsp->fnum : -1, info_level, total_data));
7711 switch (info_level) {
7713 case SMB_INFO_STANDARD:
7715 status = smb_set_info_standard(conn,
7716 pdata,
7717 total_data,
7718 fsp,
7719 smb_fname);
7720 break;
7723 case SMB_INFO_SET_EA:
7725 status = smb_info_set_ea(conn,
7726 pdata,
7727 total_data,
7728 fsp,
7729 smb_fname);
7730 break;
7733 case SMB_SET_FILE_BASIC_INFO:
7734 case SMB_FILE_BASIC_INFORMATION:
7736 status = smb_set_file_basic_info(conn,
7737 pdata,
7738 total_data,
7739 fsp,
7740 smb_fname);
7741 break;
7744 case SMB_FILE_ALLOCATION_INFORMATION:
7745 case SMB_SET_FILE_ALLOCATION_INFO:
7747 status = smb_set_file_allocation_info(conn, req,
7748 pdata,
7749 total_data,
7750 fsp,
7751 smb_fname);
7752 break;
7755 case SMB_FILE_END_OF_FILE_INFORMATION:
7756 case SMB_SET_FILE_END_OF_FILE_INFO:
7759 * XP/Win7 both fail after the createfile with
7760 * SMB_SET_FILE_END_OF_FILE_INFO but not
7761 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7762 * The level is known here, so pass it down
7763 * appropriately.
7765 bool should_fail =
7766 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7768 status = smb_set_file_end_of_file_info(conn, req,
7769 pdata,
7770 total_data,
7771 fsp,
7772 smb_fname,
7773 should_fail);
7774 break;
7777 case SMB_FILE_DISPOSITION_INFORMATION:
7778 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7780 #if 0
7781 /* JRA - We used to just ignore this on a path ?
7782 * Shouldn't this be invalid level on a pathname
7783 * based call ?
7785 if (tran_call != TRANSACT2_SETFILEINFO) {
7786 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7788 #endif
7789 status = smb_set_file_disposition_info(conn,
7790 pdata,
7791 total_data,
7792 fsp,
7793 smb_fname);
7794 break;
7797 case SMB_FILE_POSITION_INFORMATION:
7799 status = smb_file_position_information(conn,
7800 pdata,
7801 total_data,
7802 fsp);
7803 break;
7806 case SMB_FILE_FULL_EA_INFORMATION:
7808 status = smb_set_file_full_ea_info(conn,
7809 pdata,
7810 total_data,
7811 fsp);
7812 break;
7815 /* From tridge Samba4 :
7816 * MODE_INFORMATION in setfileinfo (I have no
7817 * idea what "mode information" on a file is - it takes a value of 0,
7818 * 2, 4 or 6. What could it be?).
7821 case SMB_FILE_MODE_INFORMATION:
7823 status = smb_file_mode_information(conn,
7824 pdata,
7825 total_data);
7826 break;
7830 * CIFS UNIX extensions.
7833 case SMB_SET_FILE_UNIX_BASIC:
7835 status = smb_set_file_unix_basic(conn, req,
7836 pdata,
7837 total_data,
7838 fsp,
7839 smb_fname);
7840 break;
7843 case SMB_SET_FILE_UNIX_INFO2:
7845 status = smb_set_file_unix_info2(conn, req,
7846 pdata,
7847 total_data,
7848 fsp,
7849 smb_fname);
7850 break;
7853 case SMB_SET_FILE_UNIX_LINK:
7855 if (fsp) {
7856 /* We must have a pathname for this. */
7857 return NT_STATUS_INVALID_LEVEL;
7859 status = smb_set_file_unix_link(conn, req, pdata,
7860 total_data, smb_fname);
7861 break;
7864 case SMB_SET_FILE_UNIX_HLINK:
7866 if (fsp) {
7867 /* We must have a pathname for this. */
7868 return NT_STATUS_INVALID_LEVEL;
7870 status = smb_set_file_unix_hlink(conn, req,
7871 pdata, total_data,
7872 smb_fname);
7873 break;
7876 case SMB_FILE_RENAME_INFORMATION:
7878 status = smb_file_rename_information(conn, req,
7879 pdata, total_data,
7880 fsp, smb_fname);
7881 break;
7884 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7886 /* SMB2 rename information. */
7887 status = smb2_file_rename_information(conn, req,
7888 pdata, total_data,
7889 fsp, smb_fname);
7890 break;
7893 case SMB_FILE_LINK_INFORMATION:
7895 status = smb_file_link_information(conn, req,
7896 pdata, total_data,
7897 fsp, smb_fname);
7898 break;
7901 #if defined(HAVE_POSIX_ACLS)
7902 case SMB_SET_POSIX_ACL:
7904 status = smb_set_posix_acl(conn,
7905 pdata,
7906 total_data,
7907 fsp,
7908 smb_fname);
7909 break;
7911 #endif
7913 case SMB_SET_POSIX_LOCK:
7915 if (!fsp) {
7916 return NT_STATUS_INVALID_LEVEL;
7918 status = smb_set_posix_lock(conn, req,
7919 pdata, total_data, fsp);
7920 break;
7923 case SMB_POSIX_PATH_OPEN:
7925 if (fsp) {
7926 /* We must have a pathname for this. */
7927 return NT_STATUS_INVALID_LEVEL;
7930 status = smb_posix_open(conn, req,
7931 ppdata,
7932 total_data,
7933 smb_fname,
7934 &data_return_size);
7935 break;
7938 case SMB_POSIX_PATH_UNLINK:
7940 if (fsp) {
7941 /* We must have a pathname for this. */
7942 return NT_STATUS_INVALID_LEVEL;
7945 status = smb_posix_unlink(conn, req,
7946 pdata,
7947 total_data,
7948 smb_fname);
7949 break;
7952 default:
7953 return NT_STATUS_INVALID_LEVEL;
7956 if (!NT_STATUS_IS_OK(status)) {
7957 return status;
7960 *ret_data_size = data_return_size;
7961 return NT_STATUS_OK;
7964 /****************************************************************************
7965 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7966 ****************************************************************************/
7968 static void call_trans2setfilepathinfo(connection_struct *conn,
7969 struct smb_request *req,
7970 unsigned int tran_call,
7971 char **pparams, int total_params,
7972 char **ppdata, int total_data,
7973 unsigned int max_data_bytes)
7975 char *params = *pparams;
7976 char *pdata = *ppdata;
7977 uint16 info_level;
7978 struct smb_filename *smb_fname = NULL;
7979 files_struct *fsp = NULL;
7980 NTSTATUS status = NT_STATUS_OK;
7981 int data_return_size = 0;
7983 if (!params) {
7984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7985 return;
7988 if (tran_call == TRANSACT2_SETFILEINFO) {
7989 if (total_params < 4) {
7990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7991 return;
7994 fsp = file_fsp(req, SVAL(params,0));
7995 /* Basic check for non-null fsp. */
7996 if (!check_fsp_open(conn, req, fsp)) {
7997 return;
7999 info_level = SVAL(params,2);
8001 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8002 &smb_fname);
8003 if (!NT_STATUS_IS_OK(status)) {
8004 reply_nterror(req, status);
8005 return;
8008 if(fsp->fh->fd == -1) {
8010 * This is actually a SETFILEINFO on a directory
8011 * handle (returned from an NT SMB). NT5.0 seems
8012 * to do this call. JRA.
8014 if (INFO_LEVEL_IS_UNIX(info_level)) {
8015 /* Always do lstat for UNIX calls. */
8016 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8017 DEBUG(3,("call_trans2setfilepathinfo: "
8018 "SMB_VFS_LSTAT of %s failed "
8019 "(%s)\n",
8020 smb_fname_str_dbg(smb_fname),
8021 strerror(errno)));
8022 reply_nterror(req, map_nt_error_from_unix(errno));
8023 return;
8025 } else {
8026 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8027 DEBUG(3,("call_trans2setfilepathinfo: "
8028 "fileinfo of %s failed (%s)\n",
8029 smb_fname_str_dbg(smb_fname),
8030 strerror(errno)));
8031 reply_nterror(req, map_nt_error_from_unix(errno));
8032 return;
8035 } else if (fsp->print_file) {
8037 * Doing a DELETE_ON_CLOSE should cancel a print job.
8039 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8040 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8042 DEBUG(3,("call_trans2setfilepathinfo: "
8043 "Cancelling print job (%s)\n",
8044 fsp_str_dbg(fsp)));
8046 SSVAL(params,0,0);
8047 send_trans2_replies(conn, req, params, 2,
8048 *ppdata, 0,
8049 max_data_bytes);
8050 return;
8051 } else {
8052 reply_nterror(req,
8053 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8054 return;
8056 } else {
8058 * Original code - this is an open file.
8060 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8061 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8062 "of fnum %d failed (%s)\n", fsp->fnum,
8063 strerror(errno)));
8064 reply_nterror(req, map_nt_error_from_unix(errno));
8065 return;
8068 } else {
8069 char *fname = NULL;
8070 uint32_t ucf_flags = 0;
8072 /* set path info */
8073 if (total_params < 7) {
8074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8075 return;
8078 info_level = SVAL(params,0);
8079 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8080 total_params - 6, STR_TERMINATE,
8081 &status);
8082 if (!NT_STATUS_IS_OK(status)) {
8083 reply_nterror(req, status);
8084 return;
8087 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8088 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8089 info_level == SMB_FILE_RENAME_INFORMATION ||
8090 info_level == SMB_POSIX_PATH_UNLINK) {
8091 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8094 status = filename_convert(req, conn,
8095 req->flags2 & FLAGS2_DFS_PATHNAMES,
8096 fname,
8097 ucf_flags,
8098 NULL,
8099 &smb_fname);
8100 if (!NT_STATUS_IS_OK(status)) {
8101 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8102 reply_botherror(req,
8103 NT_STATUS_PATH_NOT_COVERED,
8104 ERRSRV, ERRbadpath);
8105 return;
8107 reply_nterror(req, status);
8108 return;
8111 if (INFO_LEVEL_IS_UNIX(info_level)) {
8113 * For CIFS UNIX extensions the target name may not exist.
8116 /* Always do lstat for UNIX calls. */
8117 SMB_VFS_LSTAT(conn, smb_fname);
8119 } else if (!VALID_STAT(smb_fname->st) &&
8120 SMB_VFS_STAT(conn, smb_fname)) {
8121 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8122 "%s failed (%s)\n",
8123 smb_fname_str_dbg(smb_fname),
8124 strerror(errno)));
8125 reply_nterror(req, map_nt_error_from_unix(errno));
8126 return;
8130 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8131 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8132 fsp ? fsp->fnum : -1, info_level,total_data));
8134 /* Realloc the parameter size */
8135 *pparams = (char *)SMB_REALLOC(*pparams,2);
8136 if (*pparams == NULL) {
8137 reply_nterror(req, NT_STATUS_NO_MEMORY);
8138 return;
8140 params = *pparams;
8142 SSVAL(params,0,0);
8144 status = smbd_do_setfilepathinfo(conn, req, req,
8145 info_level,
8146 fsp,
8147 smb_fname,
8148 ppdata, total_data,
8149 &data_return_size);
8150 if (!NT_STATUS_IS_OK(status)) {
8151 if (open_was_deferred(req->mid)) {
8152 /* We have re-scheduled this call. */
8153 return;
8155 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8156 /* We have re-scheduled this call. */
8157 return;
8159 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8160 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8161 ERRSRV, ERRbadpath);
8162 return;
8164 if (info_level == SMB_POSIX_PATH_OPEN) {
8165 reply_openerror(req, status);
8166 return;
8169 reply_nterror(req, status);
8170 return;
8173 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8174 max_data_bytes);
8176 return;
8179 /****************************************************************************
8180 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8181 ****************************************************************************/
8183 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8184 char **pparams, int total_params,
8185 char **ppdata, int total_data,
8186 unsigned int max_data_bytes)
8188 struct smb_filename *smb_dname = NULL;
8189 char *params = *pparams;
8190 char *pdata = *ppdata;
8191 char *directory = NULL;
8192 NTSTATUS status = NT_STATUS_OK;
8193 struct ea_list *ea_list = NULL;
8194 TALLOC_CTX *ctx = talloc_tos();
8196 if (!CAN_WRITE(conn)) {
8197 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8198 return;
8201 if (total_params < 5) {
8202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8203 return;
8206 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8207 total_params - 4, STR_TERMINATE,
8208 &status);
8209 if (!NT_STATUS_IS_OK(status)) {
8210 reply_nterror(req, status);
8211 return;
8214 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8216 status = filename_convert(ctx,
8217 conn,
8218 req->flags2 & FLAGS2_DFS_PATHNAMES,
8219 directory,
8221 NULL,
8222 &smb_dname);
8224 if (!NT_STATUS_IS_OK(status)) {
8225 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8226 reply_botherror(req,
8227 NT_STATUS_PATH_NOT_COVERED,
8228 ERRSRV, ERRbadpath);
8229 return;
8231 reply_nterror(req, status);
8232 return;
8236 * OS/2 workplace shell seems to send SET_EA requests of "null"
8237 * length (4 bytes containing IVAL 4).
8238 * They seem to have no effect. Bug #3212. JRA.
8241 if (total_data && (total_data != 4)) {
8242 /* Any data in this call is an EA list. */
8243 if (total_data < 10) {
8244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8245 goto out;
8248 if (IVAL(pdata,0) > total_data) {
8249 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8250 IVAL(pdata,0), (unsigned int)total_data));
8251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8252 goto out;
8255 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8256 total_data - 4);
8257 if (!ea_list) {
8258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8259 goto out;
8262 if (!lp_ea_support(SNUM(conn))) {
8263 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8264 goto out;
8267 /* If total_data == 4 Windows doesn't care what values
8268 * are placed in that field, it just ignores them.
8269 * The System i QNTC IBM SMB client puts bad values here,
8270 * so ignore them. */
8272 status = create_directory(conn, req, smb_dname);
8274 if (!NT_STATUS_IS_OK(status)) {
8275 reply_nterror(req, status);
8276 goto out;
8279 /* Try and set any given EA. */
8280 if (ea_list) {
8281 status = set_ea(conn, NULL, smb_dname, ea_list);
8282 if (!NT_STATUS_IS_OK(status)) {
8283 reply_nterror(req, status);
8284 goto out;
8288 /* Realloc the parameter and data sizes */
8289 *pparams = (char *)SMB_REALLOC(*pparams,2);
8290 if(*pparams == NULL) {
8291 reply_nterror(req, NT_STATUS_NO_MEMORY);
8292 goto out;
8294 params = *pparams;
8296 SSVAL(params,0,0);
8298 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8300 out:
8301 TALLOC_FREE(smb_dname);
8302 return;
8305 /****************************************************************************
8306 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8307 We don't actually do this - we just send a null response.
8308 ****************************************************************************/
8310 static void call_trans2findnotifyfirst(connection_struct *conn,
8311 struct smb_request *req,
8312 char **pparams, int total_params,
8313 char **ppdata, int total_data,
8314 unsigned int max_data_bytes)
8316 char *params = *pparams;
8317 uint16 info_level;
8319 if (total_params < 6) {
8320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8321 return;
8324 info_level = SVAL(params,4);
8325 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8327 switch (info_level) {
8328 case 1:
8329 case 2:
8330 break;
8331 default:
8332 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8333 return;
8336 /* Realloc the parameter and data sizes */
8337 *pparams = (char *)SMB_REALLOC(*pparams,6);
8338 if (*pparams == NULL) {
8339 reply_nterror(req, NT_STATUS_NO_MEMORY);
8340 return;
8342 params = *pparams;
8344 SSVAL(params,0,fnf_handle);
8345 SSVAL(params,2,0); /* No changes */
8346 SSVAL(params,4,0); /* No EA errors */
8348 fnf_handle++;
8350 if(fnf_handle == 0)
8351 fnf_handle = 257;
8353 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8355 return;
8358 /****************************************************************************
8359 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8360 changes). Currently this does nothing.
8361 ****************************************************************************/
8363 static void call_trans2findnotifynext(connection_struct *conn,
8364 struct smb_request *req,
8365 char **pparams, int total_params,
8366 char **ppdata, int total_data,
8367 unsigned int max_data_bytes)
8369 char *params = *pparams;
8371 DEBUG(3,("call_trans2findnotifynext\n"));
8373 /* Realloc the parameter and data sizes */
8374 *pparams = (char *)SMB_REALLOC(*pparams,4);
8375 if (*pparams == NULL) {
8376 reply_nterror(req, NT_STATUS_NO_MEMORY);
8377 return;
8379 params = *pparams;
8381 SSVAL(params,0,0); /* No changes */
8382 SSVAL(params,2,0); /* No EA errors */
8384 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8386 return;
8389 /****************************************************************************
8390 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8391 ****************************************************************************/
8393 static void call_trans2getdfsreferral(connection_struct *conn,
8394 struct smb_request *req,
8395 char **pparams, int total_params,
8396 char **ppdata, int total_data,
8397 unsigned int max_data_bytes)
8399 char *params = *pparams;
8400 char *pathname = NULL;
8401 int reply_size = 0;
8402 int max_referral_level;
8403 NTSTATUS status = NT_STATUS_OK;
8404 TALLOC_CTX *ctx = talloc_tos();
8406 DEBUG(10,("call_trans2getdfsreferral\n"));
8408 if (total_params < 3) {
8409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8410 return;
8413 max_referral_level = SVAL(params,0);
8415 if(!lp_host_msdfs()) {
8416 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8417 return;
8420 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8421 total_params - 2, STR_TERMINATE);
8422 if (!pathname) {
8423 reply_nterror(req, NT_STATUS_NOT_FOUND);
8424 return;
8426 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8427 ppdata,&status)) < 0) {
8428 reply_nterror(req, status);
8429 return;
8432 SSVAL(req->inbuf, smb_flg2,
8433 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8434 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8436 return;
8439 #define LMCAT_SPL 0x53
8440 #define LMFUNC_GETJOBID 0x60
8442 /****************************************************************************
8443 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8444 ****************************************************************************/
8446 static void call_trans2ioctl(connection_struct *conn,
8447 struct smb_request *req,
8448 char **pparams, int total_params,
8449 char **ppdata, int total_data,
8450 unsigned int max_data_bytes)
8452 char *pdata = *ppdata;
8453 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8455 /* check for an invalid fid before proceeding */
8457 if (!fsp) {
8458 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8459 return;
8462 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8463 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8464 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8465 if (*ppdata == NULL) {
8466 reply_nterror(req, NT_STATUS_NO_MEMORY);
8467 return;
8469 pdata = *ppdata;
8471 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8472 CAN ACCEPT THIS IN UNICODE. JRA. */
8474 /* Job number */
8475 if (fsp->print_file) {
8476 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8477 } else {
8478 SSVAL(pdata, 0, 0);
8480 srvstr_push(pdata, req->flags2, pdata + 2,
8481 global_myname(), 15,
8482 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8483 srvstr_push(pdata, req->flags2, pdata+18,
8484 lp_servicename(SNUM(conn)), 13,
8485 STR_ASCII|STR_TERMINATE); /* Service name */
8486 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8487 max_data_bytes);
8488 return;
8491 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8492 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8495 /****************************************************************************
8496 Reply to a SMBfindclose (stop trans2 directory search).
8497 ****************************************************************************/
8499 void reply_findclose(struct smb_request *req)
8501 int dptr_num;
8502 struct smbd_server_connection *sconn = req->sconn;
8504 START_PROFILE(SMBfindclose);
8506 if (req->wct < 1) {
8507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8508 END_PROFILE(SMBfindclose);
8509 return;
8512 dptr_num = SVALS(req->vwv+0, 0);
8514 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8516 dptr_close(sconn, &dptr_num);
8518 reply_outbuf(req, 0, 0);
8520 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8522 END_PROFILE(SMBfindclose);
8523 return;
8526 /****************************************************************************
8527 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8528 ****************************************************************************/
8530 void reply_findnclose(struct smb_request *req)
8532 int dptr_num;
8534 START_PROFILE(SMBfindnclose);
8536 if (req->wct < 1) {
8537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8538 END_PROFILE(SMBfindnclose);
8539 return;
8542 dptr_num = SVAL(req->vwv+0, 0);
8544 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8546 /* We never give out valid handles for a
8547 findnotifyfirst - so any dptr_num is ok here.
8548 Just ignore it. */
8550 reply_outbuf(req, 0, 0);
8552 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8554 END_PROFILE(SMBfindnclose);
8555 return;
8558 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8559 struct trans_state *state)
8561 if (get_Protocol() >= PROTOCOL_NT1) {
8562 req->flags2 |= 0x40; /* IS_LONG_NAME */
8563 SSVAL(req->inbuf,smb_flg2,req->flags2);
8566 if (conn->encrypt_level == Required && !req->encrypted) {
8567 if (state->call != TRANSACT2_QFSINFO &&
8568 state->call != TRANSACT2_SETFSINFO) {
8569 DEBUG(0,("handle_trans2: encryption required "
8570 "with call 0x%x\n",
8571 (unsigned int)state->call));
8572 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8573 return;
8577 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8579 /* Now we must call the relevant TRANS2 function */
8580 switch(state->call) {
8581 case TRANSACT2_OPEN:
8583 START_PROFILE(Trans2_open);
8584 call_trans2open(conn, req,
8585 &state->param, state->total_param,
8586 &state->data, state->total_data,
8587 state->max_data_return);
8588 END_PROFILE(Trans2_open);
8589 break;
8592 case TRANSACT2_FINDFIRST:
8594 START_PROFILE(Trans2_findfirst);
8595 call_trans2findfirst(conn, req,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_findfirst);
8600 break;
8603 case TRANSACT2_FINDNEXT:
8605 START_PROFILE(Trans2_findnext);
8606 call_trans2findnext(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_findnext);
8611 break;
8614 case TRANSACT2_QFSINFO:
8616 START_PROFILE(Trans2_qfsinfo);
8617 call_trans2qfsinfo(conn, req,
8618 &state->param, state->total_param,
8619 &state->data, state->total_data,
8620 state->max_data_return);
8621 END_PROFILE(Trans2_qfsinfo);
8622 break;
8625 case TRANSACT2_SETFSINFO:
8627 START_PROFILE(Trans2_setfsinfo);
8628 call_trans2setfsinfo(conn, req,
8629 &state->param, state->total_param,
8630 &state->data, state->total_data,
8631 state->max_data_return);
8632 END_PROFILE(Trans2_setfsinfo);
8633 break;
8636 case TRANSACT2_QPATHINFO:
8637 case TRANSACT2_QFILEINFO:
8639 START_PROFILE(Trans2_qpathinfo);
8640 call_trans2qfilepathinfo(conn, req, state->call,
8641 &state->param, state->total_param,
8642 &state->data, state->total_data,
8643 state->max_data_return);
8644 END_PROFILE(Trans2_qpathinfo);
8645 break;
8648 case TRANSACT2_SETPATHINFO:
8649 case TRANSACT2_SETFILEINFO:
8651 START_PROFILE(Trans2_setpathinfo);
8652 call_trans2setfilepathinfo(conn, req, state->call,
8653 &state->param, state->total_param,
8654 &state->data, state->total_data,
8655 state->max_data_return);
8656 END_PROFILE(Trans2_setpathinfo);
8657 break;
8660 case TRANSACT2_FINDNOTIFYFIRST:
8662 START_PROFILE(Trans2_findnotifyfirst);
8663 call_trans2findnotifyfirst(conn, req,
8664 &state->param, state->total_param,
8665 &state->data, state->total_data,
8666 state->max_data_return);
8667 END_PROFILE(Trans2_findnotifyfirst);
8668 break;
8671 case TRANSACT2_FINDNOTIFYNEXT:
8673 START_PROFILE(Trans2_findnotifynext);
8674 call_trans2findnotifynext(conn, req,
8675 &state->param, state->total_param,
8676 &state->data, state->total_data,
8677 state->max_data_return);
8678 END_PROFILE(Trans2_findnotifynext);
8679 break;
8682 case TRANSACT2_MKDIR:
8684 START_PROFILE(Trans2_mkdir);
8685 call_trans2mkdir(conn, req,
8686 &state->param, state->total_param,
8687 &state->data, state->total_data,
8688 state->max_data_return);
8689 END_PROFILE(Trans2_mkdir);
8690 break;
8693 case TRANSACT2_GET_DFS_REFERRAL:
8695 START_PROFILE(Trans2_get_dfs_referral);
8696 call_trans2getdfsreferral(conn, req,
8697 &state->param, state->total_param,
8698 &state->data, state->total_data,
8699 state->max_data_return);
8700 END_PROFILE(Trans2_get_dfs_referral);
8701 break;
8704 case TRANSACT2_IOCTL:
8706 START_PROFILE(Trans2_ioctl);
8707 call_trans2ioctl(conn, req,
8708 &state->param, state->total_param,
8709 &state->data, state->total_data,
8710 state->max_data_return);
8711 END_PROFILE(Trans2_ioctl);
8712 break;
8715 default:
8716 /* Error in request */
8717 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8718 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8722 /****************************************************************************
8723 Reply to a SMBtrans2.
8724 ****************************************************************************/
8726 void reply_trans2(struct smb_request *req)
8728 connection_struct *conn = req->conn;
8729 unsigned int dsoff;
8730 unsigned int dscnt;
8731 unsigned int psoff;
8732 unsigned int pscnt;
8733 unsigned int tran_call;
8734 struct trans_state *state;
8735 NTSTATUS result;
8737 START_PROFILE(SMBtrans2);
8739 if (req->wct < 14) {
8740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8741 END_PROFILE(SMBtrans2);
8742 return;
8745 dsoff = SVAL(req->vwv+12, 0);
8746 dscnt = SVAL(req->vwv+11, 0);
8747 psoff = SVAL(req->vwv+10, 0);
8748 pscnt = SVAL(req->vwv+9, 0);
8749 tran_call = SVAL(req->vwv+14, 0);
8751 result = allow_new_trans(conn->pending_trans, req->mid);
8752 if (!NT_STATUS_IS_OK(result)) {
8753 DEBUG(2, ("Got invalid trans2 request: %s\n",
8754 nt_errstr(result)));
8755 reply_nterror(req, result);
8756 END_PROFILE(SMBtrans2);
8757 return;
8760 if (IS_IPC(conn)) {
8761 switch (tran_call) {
8762 /* List the allowed trans2 calls on IPC$ */
8763 case TRANSACT2_OPEN:
8764 case TRANSACT2_GET_DFS_REFERRAL:
8765 case TRANSACT2_QFILEINFO:
8766 case TRANSACT2_QFSINFO:
8767 case TRANSACT2_SETFSINFO:
8768 break;
8769 default:
8770 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8771 END_PROFILE(SMBtrans2);
8772 return;
8776 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8777 DEBUG(0, ("talloc failed\n"));
8778 reply_nterror(req, NT_STATUS_NO_MEMORY);
8779 END_PROFILE(SMBtrans2);
8780 return;
8783 state->cmd = SMBtrans2;
8785 state->mid = req->mid;
8786 state->vuid = req->vuid;
8787 state->setup_count = SVAL(req->vwv+13, 0);
8788 state->setup = NULL;
8789 state->total_param = SVAL(req->vwv+0, 0);
8790 state->param = NULL;
8791 state->total_data = SVAL(req->vwv+1, 0);
8792 state->data = NULL;
8793 state->max_param_return = SVAL(req->vwv+2, 0);
8794 state->max_data_return = SVAL(req->vwv+3, 0);
8795 state->max_setup_return = SVAL(req->vwv+4, 0);
8796 state->close_on_completion = BITSETW(req->vwv+5, 0);
8797 state->one_way = BITSETW(req->vwv+5, 1);
8799 state->call = tran_call;
8801 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8802 is so as a sanity check */
8803 if (state->setup_count != 1) {
8805 * Need to have rc=0 for ioctl to get job id for OS/2.
8806 * Network printing will fail if function is not successful.
8807 * Similar function in reply.c will be used if protocol
8808 * is LANMAN1.0 instead of LM1.2X002.
8809 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8810 * outbuf doesn't have to be set(only job id is used).
8812 if ( (state->setup_count == 4)
8813 && (tran_call == TRANSACT2_IOCTL)
8814 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8815 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8816 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8817 } else {
8818 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8819 DEBUG(2,("Transaction is %d\n",tran_call));
8820 TALLOC_FREE(state);
8821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8822 END_PROFILE(SMBtrans2);
8823 return;
8827 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8828 goto bad_param;
8830 if (state->total_data) {
8832 if (trans_oob(state->total_data, 0, dscnt)
8833 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8834 goto bad_param;
8837 /* Can't use talloc here, the core routines do realloc on the
8838 * params and data. */
8839 state->data = (char *)SMB_MALLOC(state->total_data);
8840 if (state->data == NULL) {
8841 DEBUG(0,("reply_trans2: data malloc fail for %u "
8842 "bytes !\n", (unsigned int)state->total_data));
8843 TALLOC_FREE(state);
8844 reply_nterror(req, NT_STATUS_NO_MEMORY);
8845 END_PROFILE(SMBtrans2);
8846 return;
8849 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8852 if (state->total_param) {
8854 if (trans_oob(state->total_param, 0, pscnt)
8855 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8856 goto bad_param;
8859 /* Can't use talloc here, the core routines do realloc on the
8860 * params and data. */
8861 state->param = (char *)SMB_MALLOC(state->total_param);
8862 if (state->param == NULL) {
8863 DEBUG(0,("reply_trans: param malloc fail for %u "
8864 "bytes !\n", (unsigned int)state->total_param));
8865 SAFE_FREE(state->data);
8866 TALLOC_FREE(state);
8867 reply_nterror(req, NT_STATUS_NO_MEMORY);
8868 END_PROFILE(SMBtrans2);
8869 return;
8872 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8875 state->received_data = dscnt;
8876 state->received_param = pscnt;
8878 if ((state->received_param == state->total_param) &&
8879 (state->received_data == state->total_data)) {
8881 handle_trans2(conn, req, state);
8883 SAFE_FREE(state->data);
8884 SAFE_FREE(state->param);
8885 TALLOC_FREE(state);
8886 END_PROFILE(SMBtrans2);
8887 return;
8890 DLIST_ADD(conn->pending_trans, state);
8892 /* We need to send an interim response then receive the rest
8893 of the parameter/data bytes */
8894 reply_outbuf(req, 0, 0);
8895 show_msg((char *)req->outbuf);
8896 END_PROFILE(SMBtrans2);
8897 return;
8899 bad_param:
8901 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8902 SAFE_FREE(state->data);
8903 SAFE_FREE(state->param);
8904 TALLOC_FREE(state);
8905 END_PROFILE(SMBtrans2);
8906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8910 /****************************************************************************
8911 Reply to a SMBtranss2
8912 ****************************************************************************/
8914 void reply_transs2(struct smb_request *req)
8916 connection_struct *conn = req->conn;
8917 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8918 struct trans_state *state;
8920 START_PROFILE(SMBtranss2);
8922 show_msg((char *)req->inbuf);
8924 /* Windows clients expect all replies to
8925 a transact secondary (SMBtranss2 0x33)
8926 to have a command code of transact
8927 (SMBtrans2 0x32). See bug #8989
8928 and also [MS-CIFS] section 2.2.4.47.2
8929 for details.
8931 req->cmd = SMBtrans2;
8933 if (req->wct < 8) {
8934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8935 END_PROFILE(SMBtranss2);
8936 return;
8939 for (state = conn->pending_trans; state != NULL;
8940 state = state->next) {
8941 if (state->mid == req->mid) {
8942 break;
8946 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8948 END_PROFILE(SMBtranss2);
8949 return;
8952 /* Revise state->total_param and state->total_data in case they have
8953 changed downwards */
8955 if (SVAL(req->vwv+0, 0) < state->total_param)
8956 state->total_param = SVAL(req->vwv+0, 0);
8957 if (SVAL(req->vwv+1, 0) < state->total_data)
8958 state->total_data = SVAL(req->vwv+1, 0);
8960 pcnt = SVAL(req->vwv+2, 0);
8961 poff = SVAL(req->vwv+3, 0);
8962 pdisp = SVAL(req->vwv+4, 0);
8964 dcnt = SVAL(req->vwv+5, 0);
8965 doff = SVAL(req->vwv+6, 0);
8966 ddisp = SVAL(req->vwv+7, 0);
8968 state->received_param += pcnt;
8969 state->received_data += dcnt;
8971 if ((state->received_data > state->total_data) ||
8972 (state->received_param > state->total_param))
8973 goto bad_param;
8975 if (pcnt) {
8976 if (trans_oob(state->total_param, pdisp, pcnt)
8977 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8978 goto bad_param;
8980 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8983 if (dcnt) {
8984 if (trans_oob(state->total_data, ddisp, dcnt)
8985 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8986 goto bad_param;
8988 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8991 if ((state->received_param < state->total_param) ||
8992 (state->received_data < state->total_data)) {
8993 END_PROFILE(SMBtranss2);
8994 return;
8997 handle_trans2(conn, req, state);
8999 DLIST_REMOVE(conn->pending_trans, state);
9000 SAFE_FREE(state->data);
9001 SAFE_FREE(state->param);
9002 TALLOC_FREE(state);
9004 END_PROFILE(SMBtranss2);
9005 return;
9007 bad_param:
9009 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9010 DLIST_REMOVE(conn->pending_trans, state);
9011 SAFE_FREE(state->data);
9012 SAFE_FREE(state->param);
9013 TALLOC_FREE(state);
9014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9015 END_PROFILE(SMBtranss2);
9016 return;