s3-auth: smbd needs auth.h
[Samba.git] / source3 / smbd / trans2.c
blob4890de3a5ceabedff5ebf52bbfb91b35c5c6844b
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 "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
38 #define DIR_ENTRY_SAFETY_MARGIN 4096
40 static char *store_file_unix_basic(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 static char *store_file_unix_basic_info2(connection_struct *conn,
46 char *pdata,
47 files_struct *fsp,
48 const SMB_STRUCT_STAT *psbuf);
50 /********************************************************************
51 Roundup a value to the nearest allocation roundup size boundary.
52 Only do this for Windows clients.
53 ********************************************************************/
55 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
57 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
59 /* Only roundup for Windows clients. */
60 enum remote_arch_types ra_type = get_remote_arch();
61 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
62 val = SMB_ROUNDUP(val,rval);
64 return val;
67 /********************************************************************
68 Create a 64 bit FileIndex. If the file is on the same device as
69 the root of the share, just return the 64-bit inode. If it isn't,
70 mangle as we used to do.
71 ********************************************************************/
73 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
75 uint64_t file_index;
76 if (conn->base_share_dev == psbuf->st_ex_dev) {
77 return (uint64_t)psbuf->st_ex_ino;
79 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
80 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
81 return file_index;
84 /****************************************************************************
85 Utility functions for dealing with extended attributes.
86 ****************************************************************************/
88 /****************************************************************************
89 Refuse to allow clients to overwrite our private xattrs.
90 ****************************************************************************/
92 static bool samba_private_attr_name(const char *unix_ea_name)
94 static const char * const prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
97 SAMBA_XATTR_MARKER,
98 XATTR_NTACL_NAME,
99 NULL
102 int i;
104 for (i = 0; prohibited_ea_names[i]; i++) {
105 if (strequal( prohibited_ea_names[i], unix_ea_name))
106 return true;
108 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
109 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
110 return true;
112 return false;
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
120 files_struct *fsp, const char *fname,
121 const char *ea_name, struct ea_struct *pea)
123 /* Get the value of this xattr. Max size is 64k. */
124 size_t attr_size = 256;
125 char *val = NULL;
126 ssize_t sizeret;
128 again:
130 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
131 if (!val) {
132 return NT_STATUS_NO_MEMORY;
135 if (fsp && fsp->fh->fd != -1) {
136 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
137 } else {
138 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
141 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
142 attr_size = 65536;
143 goto again;
146 if (sizeret == -1) {
147 return map_nt_error_from_unix(errno);
150 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
151 dump_data(10, (uint8 *)val, sizeret);
153 pea->flags = 0;
154 if (strnequal(ea_name, "user.", 5)) {
155 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
156 } else {
157 pea->name = talloc_strdup(mem_ctx, ea_name);
159 if (pea->name == NULL) {
160 TALLOC_FREE(val);
161 return NT_STATUS_NO_MEMORY;
163 pea->value.data = (unsigned char *)val;
164 pea->value.length = (size_t)sizeret;
165 return NT_STATUS_OK;
168 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
169 files_struct *fsp, const char *fname,
170 char ***pnames, size_t *pnum_names)
172 /* Get a list of all xattrs. Max namesize is 64k. */
173 size_t ea_namelist_size = 1024;
174 char *ea_namelist = NULL;
176 char *p;
177 char **names, **tmp;
178 size_t num_names;
179 ssize_t sizeret = -1;
181 if (!lp_ea_support(SNUM(conn))) {
182 if (pnames) {
183 *pnames = NULL;
185 *pnum_names = 0;
186 return NT_STATUS_OK;
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 if (names == NULL) {
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
205 TALLOC_FREE(names);
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
211 ea_namelist_size);
212 } else {
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
214 ea_namelist_size);
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
220 else {
221 break;
225 if (sizeret == -1) {
226 TALLOC_FREE(names);
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
233 if (sizeret == 0) {
234 TALLOC_FREE(names);
235 if (pnames) {
236 *pnames = NULL;
238 *pnum_names = 0;
239 return NT_STATUS_OK;
243 * Ensure the result is 0-terminated
246 if (ea_namelist[sizeret-1] != '\0') {
247 TALLOC_FREE(names);
248 return NT_STATUS_INTERNAL_ERROR;
252 * count the names
254 num_names = 0;
256 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
257 num_names += 1;
260 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
261 if (tmp == NULL) {
262 DEBUG(0, ("talloc failed\n"));
263 TALLOC_FREE(names);
264 return NT_STATUS_NO_MEMORY;
267 names = tmp;
268 num_names = 0;
270 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
271 names[num_names++] = p;
274 if (pnames) {
275 *pnames = names;
276 } else {
277 TALLOC_FREE(names);
279 *pnum_names = num_names;
280 return NT_STATUS_OK;
283 /****************************************************************************
284 Return a linked list of the total EA's. Plus the total size
285 ****************************************************************************/
287 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
288 const char *fname, size_t *pea_total_len)
290 /* Get a list of all xattrs. Max namesize is 64k. */
291 size_t i, num_names;
292 char **names;
293 struct ea_list *ea_list_head = NULL;
294 NTSTATUS status;
296 *pea_total_len = 0;
298 if (!lp_ea_support(SNUM(conn))) {
299 return NULL;
302 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
303 &names, &num_names);
305 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
306 return NULL;
309 for (i=0; i<num_names; i++) {
310 struct ea_list *listp;
311 fstring dos_ea_name;
313 if (strnequal(names[i], "system.", 7)
314 || samba_private_attr_name(names[i]))
315 continue;
317 listp = TALLOC_P(mem_ctx, struct ea_list);
318 if (listp == NULL) {
319 return NULL;
322 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
323 fname, names[i],
324 &listp->ea))) {
325 return NULL;
328 push_ascii_fstring(dos_ea_name, listp->ea.name);
330 *pea_total_len +=
331 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
333 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
334 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
335 (unsigned int)listp->ea.value.length));
337 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
341 /* Add on 4 for total length. */
342 if (*pea_total_len) {
343 *pea_total_len += 4;
346 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
347 (unsigned int)*pea_total_len));
349 return ea_list_head;
352 /****************************************************************************
353 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
354 that was filled.
355 ****************************************************************************/
357 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
358 connection_struct *conn, struct ea_list *ea_list)
360 unsigned int ret_data_size = 4;
361 char *p = pdata;
363 SMB_ASSERT(total_data_size >= 4);
365 if (!lp_ea_support(SNUM(conn))) {
366 SIVAL(pdata,4,0);
367 return 4;
370 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
371 size_t dos_namelen;
372 fstring dos_ea_name;
373 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
374 dos_namelen = strlen(dos_ea_name);
375 if (dos_namelen > 255 || dos_namelen == 0) {
376 break;
378 if (ea_list->ea.value.length > 65535) {
379 break;
381 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
382 break;
385 /* We know we have room. */
386 SCVAL(p,0,ea_list->ea.flags);
387 SCVAL(p,1,dos_namelen);
388 SSVAL(p,2,ea_list->ea.value.length);
389 fstrcpy(p+4, dos_ea_name);
390 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
392 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
393 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
396 ret_data_size = PTR_DIFF(p, pdata);
397 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
398 SIVAL(pdata,0,ret_data_size);
399 return ret_data_size;
402 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
403 char *pdata,
404 unsigned int total_data_size,
405 unsigned int *ret_data_size,
406 connection_struct *conn,
407 struct ea_list *ea_list)
409 uint8_t *p = (uint8_t *)pdata;
410 uint8_t *last_start = NULL;
412 *ret_data_size = 0;
414 if (!lp_ea_support(SNUM(conn))) {
415 return NT_STATUS_NO_EAS_ON_FILE;
418 for (; ea_list; ea_list = ea_list->next) {
419 size_t dos_namelen;
420 fstring dos_ea_name;
421 size_t this_size;
423 if (last_start) {
424 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
426 last_start = p;
428 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
429 dos_namelen = strlen(dos_ea_name);
430 if (dos_namelen > 255 || dos_namelen == 0) {
431 return NT_STATUS_INTERNAL_ERROR;
433 if (ea_list->ea.value.length > 65535) {
434 return NT_STATUS_INTERNAL_ERROR;
437 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
439 if (ea_list->next) {
440 size_t pad = 4 - (this_size % 4);
441 this_size += pad;
444 if (this_size > total_data_size) {
445 return NT_STATUS_INFO_LENGTH_MISMATCH;
448 /* We know we have room. */
449 SIVAL(p, 0x00, 0); /* next offset */
450 SCVAL(p, 0x04, ea_list->ea.flags);
451 SCVAL(p, 0x05, dos_namelen);
452 SSVAL(p, 0x06, ea_list->ea.value.length);
453 fstrcpy((char *)(p+0x08), dos_ea_name);
454 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
456 total_data_size -= this_size;
457 p += this_size;
460 *ret_data_size = PTR_DIFF(p, pdata);
461 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
462 return NT_STATUS_OK;
465 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
467 size_t total_ea_len = 0;
468 TALLOC_CTX *mem_ctx = NULL;
470 if (!lp_ea_support(SNUM(conn))) {
471 return 0;
473 mem_ctx = talloc_tos();
474 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
475 return total_ea_len;
478 /****************************************************************************
479 Ensure the EA name is case insensitive by matching any existing EA name.
480 ****************************************************************************/
482 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
484 size_t total_ea_len;
485 TALLOC_CTX *mem_ctx = talloc_tos();
486 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
488 for (; ea_list; ea_list = ea_list->next) {
489 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
490 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
491 &unix_ea_name[5], ea_list->ea.name));
492 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
493 break;
498 /****************************************************************************
499 Set or delete an extended attribute.
500 ****************************************************************************/
502 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
503 const struct smb_filename *smb_fname, struct ea_list *ea_list)
505 char *fname = NULL;
507 if (!lp_ea_support(SNUM(conn))) {
508 return NT_STATUS_EAS_NOT_SUPPORTED;
511 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
512 return NT_STATUS_ACCESS_DENIED;
515 /* For now setting EAs on streams isn't supported. */
516 fname = smb_fname->base_name;
518 for (;ea_list; ea_list = ea_list->next) {
519 int ret;
520 fstring unix_ea_name;
522 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
523 fstrcat(unix_ea_name, ea_list->ea.name);
525 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
527 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
529 if (samba_private_attr_name(unix_ea_name)) {
530 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
531 return NT_STATUS_ACCESS_DENIED;
534 if (ea_list->ea.value.length == 0) {
535 /* Remove the attribute. */
536 if (fsp && (fsp->fh->fd != -1)) {
537 DEBUG(10,("set_ea: deleting ea name %s on "
538 "file %s by file descriptor.\n",
539 unix_ea_name, fsp_str_dbg(fsp)));
540 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
541 } else {
542 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
543 unix_ea_name, fname));
544 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
546 #ifdef ENOATTR
547 /* Removing a non existent attribute always succeeds. */
548 if (ret == -1 && errno == ENOATTR) {
549 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
550 unix_ea_name));
551 ret = 0;
553 #endif
554 } else {
555 if (fsp && (fsp->fh->fd != -1)) {
556 DEBUG(10,("set_ea: setting ea name %s on file "
557 "%s by file descriptor.\n",
558 unix_ea_name, fsp_str_dbg(fsp)));
559 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
560 ea_list->ea.value.data, ea_list->ea.value.length, 0);
561 } else {
562 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
563 unix_ea_name, fname));
564 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
565 ea_list->ea.value.data, ea_list->ea.value.length, 0);
569 if (ret == -1) {
570 #ifdef ENOTSUP
571 if (errno == ENOTSUP) {
572 return NT_STATUS_EAS_NOT_SUPPORTED;
574 #endif
575 return map_nt_error_from_unix(errno);
579 return NT_STATUS_OK;
581 /****************************************************************************
582 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
583 ****************************************************************************/
585 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
587 struct ea_list *ea_list_head = NULL;
588 size_t converted_size, offset = 0;
590 while (offset + 2 < data_size) {
591 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
592 unsigned int namelen = CVAL(pdata,offset);
594 offset++; /* Go past the namelen byte. */
596 /* integer wrap paranioa. */
597 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
598 (offset > data_size) || (namelen > data_size) ||
599 (offset + namelen >= data_size)) {
600 break;
602 /* Ensure the name is null terminated. */
603 if (pdata[offset + namelen] != '\0') {
604 return NULL;
606 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
607 &converted_size)) {
608 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
609 "failed: %s", strerror(errno)));
611 if (!eal->ea.name) {
612 return NULL;
615 offset += (namelen + 1); /* Go past the name + terminating zero. */
616 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
617 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
620 return ea_list_head;
623 /****************************************************************************
624 Read one EA list entry from the buffer.
625 ****************************************************************************/
627 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
629 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
630 uint16 val_len;
631 unsigned int namelen;
632 size_t converted_size;
634 if (!eal) {
635 return NULL;
638 if (data_size < 6) {
639 return NULL;
642 eal->ea.flags = CVAL(pdata,0);
643 namelen = CVAL(pdata,1);
644 val_len = SVAL(pdata,2);
646 if (4 + namelen + 1 + val_len > data_size) {
647 return NULL;
650 /* Ensure the name is null terminated. */
651 if (pdata[namelen + 4] != '\0') {
652 return NULL;
654 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
655 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
656 strerror(errno)));
658 if (!eal->ea.name) {
659 return NULL;
662 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
663 if (!eal->ea.value.data) {
664 return NULL;
667 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
669 /* Ensure we're null terminated just in case we print the value. */
670 eal->ea.value.data[val_len] = '\0';
671 /* But don't count the null. */
672 eal->ea.value.length--;
674 if (pbytes_used) {
675 *pbytes_used = 4 + namelen + 1 + val_len;
678 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
679 dump_data(10, eal->ea.value.data, eal->ea.value.length);
681 return eal;
684 /****************************************************************************
685 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
686 ****************************************************************************/
688 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
690 struct ea_list *ea_list_head = NULL;
691 size_t offset = 0;
692 size_t bytes_used = 0;
694 while (offset < data_size) {
695 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
697 if (!eal) {
698 return NULL;
701 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
702 offset += bytes_used;
705 return ea_list_head;
708 /****************************************************************************
709 Count the total EA size needed.
710 ****************************************************************************/
712 static size_t ea_list_size(struct ea_list *ealist)
714 fstring dos_ea_name;
715 struct ea_list *listp;
716 size_t ret = 0;
718 for (listp = ealist; listp; listp = listp->next) {
719 push_ascii_fstring(dos_ea_name, listp->ea.name);
720 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
722 /* Add on 4 for total length. */
723 if (ret) {
724 ret += 4;
727 return ret;
730 /****************************************************************************
731 Return a union of EA's from a file list and a list of names.
732 The TALLOC context for the two lists *MUST* be identical as we steal
733 memory from one list to add to another. JRA.
734 ****************************************************************************/
736 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
738 struct ea_list *nlistp, *flistp;
740 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
741 for (flistp = file_list; flistp; flistp = flistp->next) {
742 if (strequal(nlistp->ea.name, flistp->ea.name)) {
743 break;
747 if (flistp) {
748 /* Copy the data from this entry. */
749 nlistp->ea.flags = flistp->ea.flags;
750 nlistp->ea.value = flistp->ea.value;
751 } else {
752 /* Null entry. */
753 nlistp->ea.flags = 0;
754 ZERO_STRUCT(nlistp->ea.value);
758 *total_ea_len = ea_list_size(name_list);
759 return name_list;
762 /****************************************************************************
763 Send the required number of replies back.
764 We assume all fields other than the data fields are
765 set correctly for the type of call.
766 HACK ! Always assumes smb_setup field is zero.
767 ****************************************************************************/
769 void send_trans2_replies(connection_struct *conn,
770 struct smb_request *req,
771 const char *params,
772 int paramsize,
773 const char *pdata,
774 int datasize,
775 int max_data_bytes)
777 /* As we are using a protocol > LANMAN1 then the max_send
778 variable must have been set in the sessetupX call.
779 This takes precedence over the max_xmit field in the
780 global struct. These different max_xmit variables should
781 be merged as this is now too confusing */
783 int data_to_send = datasize;
784 int params_to_send = paramsize;
785 int useable_space;
786 const char *pp = params;
787 const char *pd = pdata;
788 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
789 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
790 int data_alignment_offset = 0;
791 bool overflow = False;
792 struct smbd_server_connection *sconn = req->sconn;
793 int max_send = sconn->smb1.sessions.max_send;
795 /* Modify the data_to_send and datasize and set the error if
796 we're trying to send more than max_data_bytes. We still send
797 the part of the packet(s) that fit. Strange, but needed
798 for OS/2. */
800 if (max_data_bytes > 0 && datasize > max_data_bytes) {
801 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
802 max_data_bytes, datasize ));
803 datasize = data_to_send = max_data_bytes;
804 overflow = True;
807 /* If there genuinely are no parameters or data to send just send the empty packet */
809 if(params_to_send == 0 && data_to_send == 0) {
810 reply_outbuf(req, 10, 0);
811 show_msg((char *)req->outbuf);
812 if (!srv_send_smb(sconn,
813 (char *)req->outbuf,
814 true, req->seqnum+1,
815 IS_CONN_ENCRYPTED(conn),
816 &req->pcd)) {
817 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
819 TALLOC_FREE(req->outbuf);
820 return;
823 /* When sending params and data ensure that both are nicely aligned */
824 /* Only do this alignment when there is also data to send - else
825 can cause NT redirector problems. */
827 if (((params_to_send % 4) != 0) && (data_to_send != 0))
828 data_alignment_offset = 4 - (params_to_send % 4);
830 /* Space is bufsize minus Netbios over TCP header minus SMB header */
831 /* The alignment_offset is to align the param bytes on an even byte
832 boundary. NT 4.0 Beta needs this to work correctly. */
834 useable_space = max_send - (smb_size
835 + 2 * 10 /* wct */
836 + alignment_offset
837 + data_alignment_offset);
839 if (useable_space < 0) {
840 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
841 "= %d!!!", useable_space));
842 exit_server_cleanly("send_trans2_replies: Not enough space");
845 while (params_to_send || data_to_send) {
846 /* Calculate whether we will totally or partially fill this packet */
848 total_sent_thistime = params_to_send + data_to_send;
850 /* We can never send more than useable_space */
852 * Note that 'useable_space' does not include the alignment offsets,
853 * but we must include the alignment offsets in the calculation of
854 * the length of the data we send over the wire, as the alignment offsets
855 * are sent here. Fix from Marc_Jacobsen@hp.com.
858 total_sent_thistime = MIN(total_sent_thistime, useable_space);
860 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
861 + data_alignment_offset);
864 * We might have SMBtrans2s in req which was transferred to
865 * the outbuf, fix that.
867 SCVAL(req->outbuf, smb_com, SMBtrans2);
869 /* Set total params and data to be sent */
870 SSVAL(req->outbuf,smb_tprcnt,paramsize);
871 SSVAL(req->outbuf,smb_tdrcnt,datasize);
873 /* Calculate how many parameters and data we can fit into
874 * this packet. Parameters get precedence
877 params_sent_thistime = MIN(params_to_send,useable_space);
878 data_sent_thistime = useable_space - params_sent_thistime;
879 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
881 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
883 /* smb_proff is the offset from the start of the SMB header to the
884 parameter bytes, however the first 4 bytes of outbuf are
885 the Netbios over TCP header. Thus use smb_base() to subtract
886 them from the calculation */
888 SSVAL(req->outbuf,smb_proff,
889 ((smb_buf(req->outbuf)+alignment_offset)
890 - smb_base(req->outbuf)));
892 if(params_sent_thistime == 0)
893 SSVAL(req->outbuf,smb_prdisp,0);
894 else
895 /* Absolute displacement of param bytes sent in this packet */
896 SSVAL(req->outbuf,smb_prdisp,pp - params);
898 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
899 if(data_sent_thistime == 0) {
900 SSVAL(req->outbuf,smb_droff,0);
901 SSVAL(req->outbuf,smb_drdisp, 0);
902 } else {
903 /* The offset of the data bytes is the offset of the
904 parameter bytes plus the number of parameters being sent this time */
905 SSVAL(req->outbuf, smb_droff,
906 ((smb_buf(req->outbuf)+alignment_offset)
907 - smb_base(req->outbuf))
908 + params_sent_thistime + data_alignment_offset);
909 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
912 /* Initialize the padding for alignment */
914 if (alignment_offset != 0) {
915 memset(smb_buf(req->outbuf), 0, alignment_offset);
918 /* Copy the param bytes into the packet */
920 if(params_sent_thistime) {
921 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
922 params_sent_thistime);
925 /* Copy in the data bytes */
926 if(data_sent_thistime) {
927 if (data_alignment_offset != 0) {
928 memset((smb_buf(req->outbuf)+alignment_offset+
929 params_sent_thistime), 0,
930 data_alignment_offset);
932 memcpy(smb_buf(req->outbuf)+alignment_offset
933 +params_sent_thistime+data_alignment_offset,
934 pd,data_sent_thistime);
937 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
938 params_sent_thistime, data_sent_thistime, useable_space));
939 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
940 params_to_send, data_to_send, paramsize, datasize));
942 if (overflow) {
943 error_packet_set((char *)req->outbuf,
944 ERRDOS,ERRbufferoverflow,
945 STATUS_BUFFER_OVERFLOW,
946 __LINE__,__FILE__);
949 /* Send the packet */
950 show_msg((char *)req->outbuf);
951 if (!srv_send_smb(sconn,
952 (char *)req->outbuf,
953 true, req->seqnum+1,
954 IS_CONN_ENCRYPTED(conn),
955 &req->pcd))
956 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
958 TALLOC_FREE(req->outbuf);
960 pp += params_sent_thistime;
961 pd += data_sent_thistime;
963 params_to_send -= params_sent_thistime;
964 data_to_send -= data_sent_thistime;
966 /* Sanity check */
967 if(params_to_send < 0 || data_to_send < 0) {
968 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
969 params_to_send, data_to_send));
970 return;
974 return;
977 /****************************************************************************
978 Reply to a TRANSACT2_OPEN.
979 ****************************************************************************/
981 static void call_trans2open(connection_struct *conn,
982 struct smb_request *req,
983 char **pparams, int total_params,
984 char **ppdata, int total_data,
985 unsigned int max_data_bytes)
987 struct smb_filename *smb_fname = NULL;
988 char *params = *pparams;
989 char *pdata = *ppdata;
990 int deny_mode;
991 int32 open_attr;
992 bool oplock_request;
993 #if 0
994 bool return_additional_info;
995 int16 open_sattr;
996 time_t open_time;
997 #endif
998 int open_ofun;
999 uint32 open_size;
1000 char *pname;
1001 char *fname = NULL;
1002 SMB_OFF_T size=0;
1003 int fattr=0,mtime=0;
1004 SMB_INO_T inode = 0;
1005 int smb_action = 0;
1006 files_struct *fsp;
1007 struct ea_list *ea_list = NULL;
1008 uint16 flags = 0;
1009 NTSTATUS status;
1010 uint32 access_mask;
1011 uint32 share_mode;
1012 uint32 create_disposition;
1013 uint32 create_options = 0;
1014 uint32_t private_flags = 0;
1015 TALLOC_CTX *ctx = talloc_tos();
1018 * Ensure we have enough parameters to perform the operation.
1021 if (total_params < 29) {
1022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1023 goto out;
1026 flags = SVAL(params, 0);
1027 deny_mode = SVAL(params, 2);
1028 open_attr = SVAL(params,6);
1029 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1030 if (oplock_request) {
1031 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1034 #if 0
1035 return_additional_info = BITSETW(params,0);
1036 open_sattr = SVAL(params, 4);
1037 open_time = make_unix_date3(params+8);
1038 #endif
1039 open_ofun = SVAL(params,12);
1040 open_size = IVAL(params,14);
1041 pname = &params[28];
1043 if (IS_IPC(conn)) {
1044 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1045 goto out;
1048 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1049 total_params - 28, STR_TERMINATE,
1050 &status);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 reply_nterror(req, status);
1053 goto out;
1056 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1057 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1058 (unsigned int)open_ofun, open_size));
1060 status = filename_convert(ctx,
1061 conn,
1062 req->flags2 & FLAGS2_DFS_PATHNAMES,
1063 fname,
1065 NULL,
1066 &smb_fname);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1069 reply_botherror(req,
1070 NT_STATUS_PATH_NOT_COVERED,
1071 ERRSRV, ERRbadpath);
1072 goto out;
1074 reply_nterror(req, status);
1075 goto out;
1078 if (open_ofun == 0) {
1079 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1080 goto out;
1083 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1084 &access_mask, &share_mode,
1085 &create_disposition,
1086 &create_options,
1087 &private_flags)) {
1088 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1089 goto out;
1092 /* Any data in this call is an EA list. */
1093 if (total_data && (total_data != 4)) {
1094 if (total_data < 10) {
1095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1096 goto out;
1099 if (IVAL(pdata,0) > total_data) {
1100 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1101 IVAL(pdata,0), (unsigned int)total_data));
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1103 goto out;
1106 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1107 total_data - 4);
1108 if (!ea_list) {
1109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1110 goto out;
1113 if (!lp_ea_support(SNUM(conn))) {
1114 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1115 goto out;
1119 status = SMB_VFS_CREATE_FILE(
1120 conn, /* conn */
1121 req, /* req */
1122 0, /* root_dir_fid */
1123 smb_fname, /* fname */
1124 access_mask, /* access_mask */
1125 share_mode, /* share_access */
1126 create_disposition, /* create_disposition*/
1127 create_options, /* create_options */
1128 open_attr, /* file_attributes */
1129 oplock_request, /* oplock_request */
1130 open_size, /* allocation_size */
1131 private_flags,
1132 NULL, /* sd */
1133 ea_list, /* ea_list */
1134 &fsp, /* result */
1135 &smb_action); /* psbuf */
1137 if (!NT_STATUS_IS_OK(status)) {
1138 if (open_was_deferred(req->mid)) {
1139 /* We have re-scheduled this call. */
1140 goto out;
1142 reply_openerror(req, status);
1143 goto out;
1146 size = get_file_size_stat(&smb_fname->st);
1147 fattr = dos_mode(conn, smb_fname);
1148 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1149 inode = smb_fname->st.st_ex_ino;
1150 if (fattr & aDIR) {
1151 close_file(req, fsp, ERROR_CLOSE);
1152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1153 goto out;
1156 /* Realloc the size of parameters and data we will return */
1157 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1158 if(*pparams == NULL ) {
1159 reply_nterror(req, NT_STATUS_NO_MEMORY);
1160 goto out;
1162 params = *pparams;
1164 SSVAL(params,0,fsp->fnum);
1165 SSVAL(params,2,fattr);
1166 srv_put_dos_date2(params,4, mtime);
1167 SIVAL(params,8, (uint32)size);
1168 SSVAL(params,12,deny_mode);
1169 SSVAL(params,14,0); /* open_type - file or directory. */
1170 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1172 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1173 smb_action |= EXTENDED_OPLOCK_GRANTED;
1176 SSVAL(params,18,smb_action);
1179 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1181 SIVAL(params,20,inode);
1182 SSVAL(params,24,0); /* Padding. */
1183 if (flags & 8) {
1184 uint32 ea_size = estimate_ea_size(conn, fsp,
1185 fsp->fsp_name->base_name);
1186 SIVAL(params, 26, ea_size);
1187 } else {
1188 SIVAL(params, 26, 0);
1191 /* Send the required number of replies */
1192 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1193 out:
1194 TALLOC_FREE(smb_fname);
1197 /*********************************************************
1198 Routine to check if a given string matches exactly.
1199 as a special case a mask of "." does NOT match. That
1200 is required for correct wildcard semantics
1201 Case can be significant or not.
1202 **********************************************************/
1204 static bool exact_match(bool has_wild,
1205 bool case_sensitive,
1206 const char *str,
1207 const char *mask)
1209 if (mask[0] == '.' && mask[1] == 0) {
1210 return false;
1213 if (has_wild) {
1214 return false;
1217 if (case_sensitive) {
1218 return strcmp(str,mask)==0;
1219 } else {
1220 return StrCaseCmp(str,mask) == 0;
1224 /****************************************************************************
1225 Return the filetype for UNIX extensions.
1226 ****************************************************************************/
1228 static uint32 unix_filetype(mode_t mode)
1230 if(S_ISREG(mode))
1231 return UNIX_TYPE_FILE;
1232 else if(S_ISDIR(mode))
1233 return UNIX_TYPE_DIR;
1234 #ifdef S_ISLNK
1235 else if(S_ISLNK(mode))
1236 return UNIX_TYPE_SYMLINK;
1237 #endif
1238 #ifdef S_ISCHR
1239 else if(S_ISCHR(mode))
1240 return UNIX_TYPE_CHARDEV;
1241 #endif
1242 #ifdef S_ISBLK
1243 else if(S_ISBLK(mode))
1244 return UNIX_TYPE_BLKDEV;
1245 #endif
1246 #ifdef S_ISFIFO
1247 else if(S_ISFIFO(mode))
1248 return UNIX_TYPE_FIFO;
1249 #endif
1250 #ifdef S_ISSOCK
1251 else if(S_ISSOCK(mode))
1252 return UNIX_TYPE_SOCKET;
1253 #endif
1255 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1256 return UNIX_TYPE_UNKNOWN;
1259 /****************************************************************************
1260 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1261 ****************************************************************************/
1263 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1265 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1266 const SMB_STRUCT_STAT *psbuf,
1267 uint32 perms,
1268 enum perm_type ptype,
1269 mode_t *ret_perms)
1271 mode_t ret = 0;
1273 if (perms == SMB_MODE_NO_CHANGE) {
1274 if (!VALID_STAT(*psbuf)) {
1275 return NT_STATUS_INVALID_PARAMETER;
1276 } else {
1277 *ret_perms = psbuf->st_ex_mode;
1278 return NT_STATUS_OK;
1282 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1283 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1284 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1285 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1286 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1287 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1288 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1289 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1290 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1291 #ifdef S_ISVTX
1292 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1293 #endif
1294 #ifdef S_ISGID
1295 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1296 #endif
1297 #ifdef S_ISUID
1298 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1299 #endif
1301 switch (ptype) {
1302 case PERM_NEW_FILE:
1303 /* Apply mode mask */
1304 ret &= lp_create_mask(SNUM(conn));
1305 /* Add in force bits */
1306 ret |= lp_force_create_mode(SNUM(conn));
1307 break;
1308 case PERM_NEW_DIR:
1309 ret &= lp_dir_mask(SNUM(conn));
1310 /* Add in force bits */
1311 ret |= lp_force_dir_mode(SNUM(conn));
1312 break;
1313 case PERM_EXISTING_FILE:
1314 /* Apply mode mask */
1315 ret &= lp_security_mask(SNUM(conn));
1316 /* Add in force bits */
1317 ret |= lp_force_security_mode(SNUM(conn));
1318 break;
1319 case PERM_EXISTING_DIR:
1320 /* Apply mode mask */
1321 ret &= lp_dir_security_mask(SNUM(conn));
1322 /* Add in force bits */
1323 ret |= lp_force_dir_security_mode(SNUM(conn));
1324 break;
1327 *ret_perms = ret;
1328 return NT_STATUS_OK;
1331 /****************************************************************************
1332 Needed to show the msdfs symlinks as directories. Modifies psbuf
1333 to be a directory if it's a msdfs link.
1334 ****************************************************************************/
1336 static bool check_msdfs_link(connection_struct *conn,
1337 const char *pathname,
1338 SMB_STRUCT_STAT *psbuf)
1340 int saved_errno = errno;
1341 if(lp_host_msdfs() &&
1342 lp_msdfs_root(SNUM(conn)) &&
1343 is_msdfs_link(conn, pathname, psbuf)) {
1345 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1346 "as a directory\n",
1347 pathname));
1348 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1349 errno = saved_errno;
1350 return true;
1352 errno = saved_errno;
1353 return false;
1357 /****************************************************************************
1358 Get a level dependent lanman2 dir entry.
1359 ****************************************************************************/
1361 struct smbd_dirptr_lanman2_state {
1362 connection_struct *conn;
1363 uint32_t info_level;
1364 bool check_mangled_names;
1365 bool has_wild;
1366 bool got_exact_match;
1369 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1370 void *private_data,
1371 const char *dname,
1372 const char *mask,
1373 char **_fname)
1375 struct smbd_dirptr_lanman2_state *state =
1376 (struct smbd_dirptr_lanman2_state *)private_data;
1377 bool ok;
1378 char mangled_name[13]; /* mangled 8.3 name. */
1379 bool got_match;
1380 const char *fname;
1382 /* Mangle fname if it's an illegal name. */
1383 if (mangle_must_mangle(dname, state->conn->params)) {
1384 ok = name_to_8_3(dname, mangled_name,
1385 true, state->conn->params);
1386 if (!ok) {
1387 return false;
1389 fname = mangled_name;
1390 } else {
1391 fname = dname;
1394 got_match = exact_match(state->has_wild,
1395 state->conn->case_sensitive,
1396 fname, mask);
1397 state->got_exact_match = got_match;
1398 if (!got_match) {
1399 got_match = mask_match(fname, mask,
1400 state->conn->case_sensitive);
1403 if(!got_match && state->check_mangled_names &&
1404 !mangle_is_8_3(fname, false, state->conn->params)) {
1406 * It turns out that NT matches wildcards against
1407 * both long *and* short names. This may explain some
1408 * of the wildcard wierdness from old DOS clients
1409 * that some people have been seeing.... JRA.
1411 /* Force the mangling into 8.3. */
1412 ok = name_to_8_3(fname, mangled_name,
1413 false, state->conn->params);
1414 if (!ok) {
1415 return false;
1418 got_match = exact_match(state->has_wild,
1419 state->conn->case_sensitive,
1420 mangled_name, mask);
1421 state->got_exact_match = got_match;
1422 if (!got_match) {
1423 got_match = mask_match(mangled_name, mask,
1424 state->conn->case_sensitive);
1428 if (!got_match) {
1429 return false;
1432 *_fname = talloc_strdup(ctx, fname);
1433 if (*_fname == NULL) {
1434 return false;
1437 return true;
1440 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1441 void *private_data,
1442 struct smb_filename *smb_fname,
1443 uint32_t *_mode)
1445 struct smbd_dirptr_lanman2_state *state =
1446 (struct smbd_dirptr_lanman2_state *)private_data;
1447 bool ms_dfs_link = false;
1448 uint32_t mode = 0;
1450 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1451 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1452 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1453 "Couldn't lstat [%s] (%s)\n",
1454 smb_fname_str_dbg(smb_fname),
1455 strerror(errno)));
1456 return false;
1458 } else if (!VALID_STAT(smb_fname->st) &&
1459 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1460 /* Needed to show the msdfs symlinks as
1461 * directories */
1463 ms_dfs_link = check_msdfs_link(state->conn,
1464 smb_fname->base_name,
1465 &smb_fname->st);
1466 if (!ms_dfs_link) {
1467 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1468 "Couldn't stat [%s] (%s)\n",
1469 smb_fname_str_dbg(smb_fname),
1470 strerror(errno)));
1471 return false;
1475 if (ms_dfs_link) {
1476 mode = dos_mode_msdfs(state->conn, smb_fname);
1477 } else {
1478 mode = dos_mode(state->conn, smb_fname);
1481 *_mode = mode;
1482 return true;
1485 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1486 connection_struct *conn,
1487 uint16_t flags2,
1488 uint32_t info_level,
1489 struct ea_list *name_list,
1490 bool check_mangled_names,
1491 bool requires_resume_key,
1492 uint32_t mode,
1493 const char *fname,
1494 const struct smb_filename *smb_fname,
1495 int space_remaining,
1496 uint8_t align,
1497 bool do_pad,
1498 char *base_data,
1499 char **ppdata,
1500 char *end_data,
1501 bool *out_of_space,
1502 uint64_t *last_entry_off)
1504 char *p, *q, *pdata = *ppdata;
1505 uint32_t reskey=0;
1506 uint64_t file_size = 0;
1507 uint64_t allocation_size = 0;
1508 uint64_t file_index = 0;
1509 uint32_t len;
1510 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1511 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1512 time_t c_date = (time_t)0;
1513 char *nameptr;
1514 char *last_entry_ptr;
1515 bool was_8_3;
1516 int off;
1517 int pad = 0;
1519 *out_of_space = false;
1521 ZERO_STRUCT(mdate_ts);
1522 ZERO_STRUCT(adate_ts);
1523 ZERO_STRUCT(create_date_ts);
1524 ZERO_STRUCT(cdate_ts);
1526 if (!(mode & aDIR)) {
1527 file_size = get_file_size_stat(&smb_fname->st);
1529 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1531 file_index = get_FileIndex(conn, &smb_fname->st);
1533 mdate_ts = smb_fname->st.st_ex_mtime;
1534 adate_ts = smb_fname->st.st_ex_atime;
1535 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1536 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1538 if (lp_dos_filetime_resolution(SNUM(conn))) {
1539 dos_filetime_timespec(&create_date_ts);
1540 dos_filetime_timespec(&mdate_ts);
1541 dos_filetime_timespec(&adate_ts);
1542 dos_filetime_timespec(&cdate_ts);
1545 create_date = convert_timespec_to_time_t(create_date_ts);
1546 mdate = convert_timespec_to_time_t(mdate_ts);
1547 adate = convert_timespec_to_time_t(adate_ts);
1548 c_date = convert_timespec_to_time_t(cdate_ts);
1550 /* align the record */
1551 SMB_ASSERT(align >= 1);
1553 off = (int)PTR_DIFF(pdata, base_data);
1554 pad = (off + (align-1)) & ~(align-1);
1555 pad -= off;
1557 if (pad && pad > space_remaining) {
1558 *out_of_space = true;
1559 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1560 "for padding (wanted %u, had %d)\n",
1561 (unsigned int)pad,
1562 space_remaining ));
1563 return false; /* Not finished - just out of space */
1566 off += pad;
1567 /* initialize padding to 0 */
1568 if (pad) {
1569 memset(pdata, 0, pad);
1571 space_remaining -= pad;
1573 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1574 space_remaining ));
1576 pdata += pad;
1577 p = pdata;
1578 last_entry_ptr = p;
1580 pad = 0;
1581 off = 0;
1583 switch (info_level) {
1584 case SMB_FIND_INFO_STANDARD:
1585 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1586 if(requires_resume_key) {
1587 SIVAL(p,0,reskey);
1588 p += 4;
1590 srv_put_dos_date2(p,0,create_date);
1591 srv_put_dos_date2(p,4,adate);
1592 srv_put_dos_date2(p,8,mdate);
1593 SIVAL(p,12,(uint32)file_size);
1594 SIVAL(p,16,(uint32)allocation_size);
1595 SSVAL(p,20,mode);
1596 p += 23;
1597 nameptr = p;
1598 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1599 p += ucs2_align(base_data, p, 0);
1601 len = srvstr_push(base_data, flags2, p,
1602 fname, PTR_DIFF(end_data, p),
1603 STR_TERMINATE);
1604 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1605 if (len > 2) {
1606 SCVAL(nameptr, -1, len - 2);
1607 } else {
1608 SCVAL(nameptr, -1, 0);
1610 } else {
1611 if (len > 1) {
1612 SCVAL(nameptr, -1, len - 1);
1613 } else {
1614 SCVAL(nameptr, -1, 0);
1617 p += len;
1618 break;
1620 case SMB_FIND_EA_SIZE:
1621 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1622 if (requires_resume_key) {
1623 SIVAL(p,0,reskey);
1624 p += 4;
1626 srv_put_dos_date2(p,0,create_date);
1627 srv_put_dos_date2(p,4,adate);
1628 srv_put_dos_date2(p,8,mdate);
1629 SIVAL(p,12,(uint32)file_size);
1630 SIVAL(p,16,(uint32)allocation_size);
1631 SSVAL(p,20,mode);
1633 unsigned int ea_size = estimate_ea_size(conn, NULL,
1634 smb_fname->base_name);
1635 SIVAL(p,22,ea_size); /* Extended attributes */
1637 p += 27;
1638 nameptr = p - 1;
1639 len = srvstr_push(base_data, flags2,
1640 p, fname, PTR_DIFF(end_data, p),
1641 STR_TERMINATE | STR_NOALIGN);
1642 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1643 if (len > 2) {
1644 len -= 2;
1645 } else {
1646 len = 0;
1648 } else {
1649 if (len > 1) {
1650 len -= 1;
1651 } else {
1652 len = 0;
1655 SCVAL(nameptr,0,len);
1656 p += len;
1657 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1658 break;
1660 case SMB_FIND_EA_LIST:
1662 struct ea_list *file_list = NULL;
1663 size_t ea_len = 0;
1665 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1666 if (!name_list) {
1667 return false;
1669 if (requires_resume_key) {
1670 SIVAL(p,0,reskey);
1671 p += 4;
1673 srv_put_dos_date2(p,0,create_date);
1674 srv_put_dos_date2(p,4,adate);
1675 srv_put_dos_date2(p,8,mdate);
1676 SIVAL(p,12,(uint32)file_size);
1677 SIVAL(p,16,(uint32)allocation_size);
1678 SSVAL(p,20,mode);
1679 p += 22; /* p now points to the EA area. */
1681 file_list = get_ea_list_from_file(ctx, conn, NULL,
1682 smb_fname->base_name,
1683 &ea_len);
1684 name_list = ea_list_union(name_list, file_list, &ea_len);
1686 /* We need to determine if this entry will fit in the space available. */
1687 /* Max string size is 255 bytes. */
1688 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1689 *out_of_space = true;
1690 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1691 "(wanted %u, had %d)\n",
1692 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1693 space_remaining ));
1694 return False; /* Not finished - just out of space */
1697 /* Push the ea_data followed by the name. */
1698 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1699 nameptr = p;
1700 len = srvstr_push(base_data, flags2,
1701 p + 1, fname, PTR_DIFF(end_data, p+1),
1702 STR_TERMINATE | STR_NOALIGN);
1703 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1704 if (len > 2) {
1705 len -= 2;
1706 } else {
1707 len = 0;
1709 } else {
1710 if (len > 1) {
1711 len -= 1;
1712 } else {
1713 len = 0;
1716 SCVAL(nameptr,0,len);
1717 p += len + 1;
1718 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1719 break;
1722 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1723 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1724 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1725 p += 4;
1726 SIVAL(p,0,reskey); p += 4;
1727 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1728 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1729 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1730 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1731 SOFF_T(p,0,file_size); p += 8;
1732 SOFF_T(p,0,allocation_size); p += 8;
1733 SIVAL(p,0,mode); p += 4;
1734 q = p; p += 4; /* q is placeholder for name length. */
1736 unsigned int ea_size = estimate_ea_size(conn, NULL,
1737 smb_fname->base_name);
1738 SIVAL(p,0,ea_size); /* Extended attributes */
1739 p += 4;
1741 /* Clear the short name buffer. This is
1742 * IMPORTANT as not doing so will trigger
1743 * a Win2k client bug. JRA.
1745 if (!was_8_3 && check_mangled_names) {
1746 char mangled_name[13]; /* mangled 8.3 name. */
1747 if (!name_to_8_3(fname,mangled_name,True,
1748 conn->params)) {
1749 /* Error - mangle failed ! */
1750 memset(mangled_name,'\0',12);
1752 mangled_name[12] = 0;
1753 len = srvstr_push(base_data, flags2,
1754 p+2, mangled_name, 24,
1755 STR_UPPER|STR_UNICODE);
1756 if (len < 24) {
1757 memset(p + 2 + len,'\0',24 - len);
1759 SSVAL(p, 0, len);
1760 } else {
1761 memset(p,'\0',26);
1763 p += 2 + 24;
1764 len = srvstr_push(base_data, flags2, p,
1765 fname, PTR_DIFF(end_data, p),
1766 STR_TERMINATE_ASCII);
1767 SIVAL(q,0,len);
1768 p += len;
1770 len = PTR_DIFF(p, pdata);
1771 pad = (len + (align-1)) & ~(align-1);
1773 * offset to the next entry, the caller
1774 * will overwrite it for the last entry
1775 * that's why we always include the padding
1777 SIVAL(pdata,0,pad);
1779 * set padding to zero
1781 if (do_pad) {
1782 memset(p, 0, pad - len);
1783 p = pdata + pad;
1784 } else {
1785 p = pdata + len;
1787 break;
1789 case SMB_FIND_FILE_DIRECTORY_INFO:
1790 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1791 p += 4;
1792 SIVAL(p,0,reskey); p += 4;
1793 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1794 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1796 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1797 SOFF_T(p,0,file_size); p += 8;
1798 SOFF_T(p,0,allocation_size); p += 8;
1799 SIVAL(p,0,mode); p += 4;
1800 len = srvstr_push(base_data, flags2,
1801 p + 4, fname, PTR_DIFF(end_data, p+4),
1802 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,len);
1804 p += 4 + len;
1806 len = PTR_DIFF(p, pdata);
1807 pad = (len + (align-1)) & ~(align-1);
1809 * offset to the next entry, the caller
1810 * will overwrite it for the last entry
1811 * that's why we always include the padding
1813 SIVAL(pdata,0,pad);
1815 * set padding to zero
1817 if (do_pad) {
1818 memset(p, 0, pad - len);
1819 p = pdata + pad;
1820 } else {
1821 p = pdata + len;
1823 break;
1825 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1826 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1827 p += 4;
1828 SIVAL(p,0,reskey); p += 4;
1829 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1830 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1831 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1832 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1833 SOFF_T(p,0,file_size); p += 8;
1834 SOFF_T(p,0,allocation_size); p += 8;
1835 SIVAL(p,0,mode); p += 4;
1836 q = p; p += 4; /* q is placeholder for name length. */
1838 unsigned int ea_size = estimate_ea_size(conn, NULL,
1839 smb_fname->base_name);
1840 SIVAL(p,0,ea_size); /* Extended attributes */
1841 p +=4;
1843 len = srvstr_push(base_data, flags2, p,
1844 fname, PTR_DIFF(end_data, p),
1845 STR_TERMINATE_ASCII);
1846 SIVAL(q, 0, len);
1847 p += len;
1849 len = PTR_DIFF(p, pdata);
1850 pad = (len + (align-1)) & ~(align-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1856 SIVAL(pdata,0,pad);
1858 * set padding to zero
1860 if (do_pad) {
1861 memset(p, 0, pad - len);
1862 p = pdata + pad;
1863 } else {
1864 p = pdata + len;
1866 break;
1868 case SMB_FIND_FILE_NAMES_INFO:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1870 p += 4;
1871 SIVAL(p,0,reskey); p += 4;
1872 p += 4;
1873 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1874 acl on a dir (tridge) */
1875 len = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE_ASCII);
1878 SIVAL(p, -4, len);
1879 p += len;
1881 len = PTR_DIFF(p, pdata);
1882 pad = (len + (align-1)) & ~(align-1);
1884 * offset to the next entry, the caller
1885 * will overwrite it for the last entry
1886 * that's why we always include the padding
1888 SIVAL(pdata,0,pad);
1890 * set padding to zero
1892 if (do_pad) {
1893 memset(p, 0, pad - len);
1894 p = pdata + pad;
1895 } else {
1896 p = pdata + len;
1898 break;
1900 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1901 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1902 p += 4;
1903 SIVAL(p,0,reskey); p += 4;
1904 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1908 SOFF_T(p,0,file_size); p += 8;
1909 SOFF_T(p,0,allocation_size); p += 8;
1910 SIVAL(p,0,mode); p += 4;
1911 q = p; p += 4; /* q is placeholder for name length. */
1913 unsigned int ea_size = estimate_ea_size(conn, NULL,
1914 smb_fname->base_name);
1915 SIVAL(p,0,ea_size); /* Extended attributes */
1916 p +=4;
1918 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1919 SBVAL(p,0,file_index); p += 8;
1920 len = srvstr_push(base_data, flags2, p,
1921 fname, PTR_DIFF(end_data, p),
1922 STR_TERMINATE_ASCII);
1923 SIVAL(q, 0, len);
1924 p += len;
1926 len = PTR_DIFF(p, pdata);
1927 pad = (len + (align-1)) & ~(align-1);
1929 * offset to the next entry, the caller
1930 * will overwrite it for the last entry
1931 * that's why we always include the padding
1933 SIVAL(pdata,0,pad);
1935 * set padding to zero
1937 if (do_pad) {
1938 memset(p, 0, pad - len);
1939 p = pdata + pad;
1940 } else {
1941 p = pdata + len;
1943 break;
1945 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1947 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1948 p += 4;
1949 SIVAL(p,0,reskey); p += 4;
1950 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1951 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1952 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1953 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1954 SOFF_T(p,0,file_size); p += 8;
1955 SOFF_T(p,0,allocation_size); p += 8;
1956 SIVAL(p,0,mode); p += 4;
1957 q = p; p += 4; /* q is placeholder for name length */
1959 unsigned int ea_size = estimate_ea_size(conn, NULL,
1960 smb_fname->base_name);
1961 SIVAL(p,0,ea_size); /* Extended attributes */
1962 p +=4;
1964 /* Clear the short name buffer. This is
1965 * IMPORTANT as not doing so will trigger
1966 * a Win2k client bug. JRA.
1968 if (!was_8_3 && check_mangled_names) {
1969 char mangled_name[13]; /* mangled 8.3 name. */
1970 if (!name_to_8_3(fname,mangled_name,True,
1971 conn->params)) {
1972 /* Error - mangle failed ! */
1973 memset(mangled_name,'\0',12);
1975 mangled_name[12] = 0;
1976 len = srvstr_push(base_data, flags2,
1977 p+2, mangled_name, 24,
1978 STR_UPPER|STR_UNICODE);
1979 SSVAL(p, 0, len);
1980 if (len < 24) {
1981 memset(p + 2 + len,'\0',24 - len);
1983 SSVAL(p, 0, len);
1984 } else {
1985 memset(p,'\0',26);
1987 p += 26;
1988 SSVAL(p,0,0); p += 2; /* Reserved ? */
1989 SBVAL(p,0,file_index); p += 8;
1990 len = srvstr_push(base_data, flags2, p,
1991 fname, PTR_DIFF(end_data, p),
1992 STR_TERMINATE_ASCII);
1993 SIVAL(q,0,len);
1994 p += len;
1996 len = PTR_DIFF(p, pdata);
1997 pad = (len + (align-1)) & ~(align-1);
1999 * offset to the next entry, the caller
2000 * will overwrite it for the last entry
2001 * that's why we always include the padding
2003 SIVAL(pdata,0,pad);
2005 * set padding to zero
2007 if (do_pad) {
2008 memset(p, 0, pad - len);
2009 p = pdata + pad;
2010 } else {
2011 p = pdata + len;
2013 break;
2015 /* CIFS UNIX Extension. */
2017 case SMB_FIND_FILE_UNIX:
2018 case SMB_FIND_FILE_UNIX_INFO2:
2019 p+= 4;
2020 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2022 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2024 if (info_level == SMB_FIND_FILE_UNIX) {
2025 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2026 p = store_file_unix_basic(conn, p,
2027 NULL, &smb_fname->st);
2028 len = srvstr_push(base_data, flags2, p,
2029 fname, PTR_DIFF(end_data, p),
2030 STR_TERMINATE);
2031 } else {
2032 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2033 p = store_file_unix_basic_info2(conn, p,
2034 NULL, &smb_fname->st);
2035 nameptr = p;
2036 p += 4;
2037 len = srvstr_push(base_data, flags2, p, fname,
2038 PTR_DIFF(end_data, p), 0);
2039 SIVAL(nameptr, 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 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2063 break;
2065 default:
2066 return false;
2069 if (PTR_DIFF(p,pdata) > space_remaining) {
2070 *out_of_space = true;
2071 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2072 "(wanted %u, had %d)\n",
2073 (unsigned int)PTR_DIFF(p,pdata),
2074 space_remaining ));
2075 return false; /* Not finished - just out of space */
2078 /* Setup the last entry pointer, as an offset from base_data */
2079 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2080 /* Advance the data pointer to the next slot */
2081 *ppdata = p;
2083 return true;
2086 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2087 connection_struct *conn,
2088 struct dptr_struct *dirptr,
2089 uint16 flags2,
2090 const char *path_mask,
2091 uint32 dirtype,
2092 int info_level,
2093 int requires_resume_key,
2094 bool dont_descend,
2095 bool ask_sharemode,
2096 uint8_t align,
2097 bool do_pad,
2098 char **ppdata,
2099 char *base_data,
2100 char *end_data,
2101 int space_remaining,
2102 bool *out_of_space,
2103 bool *got_exact_match,
2104 int *_last_entry_off,
2105 struct ea_list *name_list)
2107 const char *p;
2108 const char *mask = NULL;
2109 long prev_dirpos = 0;
2110 uint32_t mode = 0;
2111 char *fname = NULL;
2112 struct smb_filename *smb_fname = NULL;
2113 struct smbd_dirptr_lanman2_state state;
2114 bool ok;
2115 uint64_t last_entry_off = 0;
2117 ZERO_STRUCT(state);
2118 state.conn = conn;
2119 state.info_level = info_level;
2120 state.check_mangled_names = lp_manglednames(conn->params);
2121 state.has_wild = dptr_has_wild(dirptr);
2122 state.got_exact_match = false;
2124 *out_of_space = false;
2125 *got_exact_match = false;
2127 p = strrchr_m(path_mask,'/');
2128 if(p != NULL) {
2129 if(p[1] == '\0') {
2130 mask = "*.*";
2131 } else {
2132 mask = p+1;
2134 } else {
2135 mask = path_mask;
2138 ok = smbd_dirptr_get_entry(ctx,
2139 dirptr,
2140 mask,
2141 dirtype,
2142 dont_descend,
2143 ask_sharemode,
2144 smbd_dirptr_lanman2_match_fn,
2145 smbd_dirptr_lanman2_mode_fn,
2146 &state,
2147 &fname,
2148 &smb_fname,
2149 &mode,
2150 &prev_dirpos);
2151 if (!ok) {
2152 return false;
2155 *got_exact_match = state.got_exact_match;
2157 ok = smbd_marshall_dir_entry(ctx,
2158 conn,
2159 flags2,
2160 info_level,
2161 name_list,
2162 state.check_mangled_names,
2163 requires_resume_key,
2164 mode,
2165 fname,
2166 smb_fname,
2167 space_remaining,
2168 align,
2169 do_pad,
2170 base_data,
2171 ppdata,
2172 end_data,
2173 out_of_space,
2174 &last_entry_off);
2175 TALLOC_FREE(fname);
2176 TALLOC_FREE(smb_fname);
2177 if (*out_of_space) {
2178 dptr_SeekDir(dirptr, prev_dirpos);
2179 return false;
2181 if (!ok) {
2182 return false;
2185 *_last_entry_off = last_entry_off;
2186 return true;
2189 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2190 connection_struct *conn,
2191 struct dptr_struct *dirptr,
2192 uint16 flags2,
2193 const char *path_mask,
2194 uint32 dirtype,
2195 int info_level,
2196 bool requires_resume_key,
2197 bool dont_descend,
2198 bool ask_sharemode,
2199 char **ppdata,
2200 char *base_data,
2201 char *end_data,
2202 int space_remaining,
2203 bool *out_of_space,
2204 bool *got_exact_match,
2205 int *last_entry_off,
2206 struct ea_list *name_list)
2208 uint8_t align = 4;
2209 const bool do_pad = true;
2211 if (info_level >= 1 && info_level <= 3) {
2212 /* No alignment on earlier info levels. */
2213 align = 1;
2216 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2217 path_mask, dirtype, info_level,
2218 requires_resume_key, dont_descend, ask_sharemode,
2219 align, do_pad,
2220 ppdata, base_data, end_data,
2221 space_remaining,
2222 out_of_space, got_exact_match,
2223 last_entry_off, name_list);
2226 /****************************************************************************
2227 Reply to a TRANS2_FINDFIRST.
2228 ****************************************************************************/
2230 static void call_trans2findfirst(connection_struct *conn,
2231 struct smb_request *req,
2232 char **pparams, int total_params,
2233 char **ppdata, int total_data,
2234 unsigned int max_data_bytes)
2236 /* We must be careful here that we don't return more than the
2237 allowed number of data bytes. If this means returning fewer than
2238 maxentries then so be it. We assume that the redirector has
2239 enough room for the fixed number of parameter bytes it has
2240 requested. */
2241 struct smb_filename *smb_dname = NULL;
2242 char *params = *pparams;
2243 char *pdata = *ppdata;
2244 char *data_end;
2245 uint32 dirtype;
2246 int maxentries;
2247 uint16 findfirst_flags;
2248 bool close_after_first;
2249 bool close_if_end;
2250 bool requires_resume_key;
2251 int info_level;
2252 char *directory = NULL;
2253 char *mask = NULL;
2254 char *p;
2255 int last_entry_off=0;
2256 int dptr_num = -1;
2257 int numentries = 0;
2258 int i;
2259 bool finished = False;
2260 bool dont_descend = False;
2261 bool out_of_space = False;
2262 int space_remaining;
2263 bool mask_contains_wcard = False;
2264 struct ea_list *ea_list = NULL;
2265 NTSTATUS ntstatus = NT_STATUS_OK;
2266 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2267 TALLOC_CTX *ctx = talloc_tos();
2268 struct dptr_struct *dirptr = NULL;
2269 struct smbd_server_connection *sconn = req->sconn;
2271 if (total_params < 13) {
2272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2273 goto out;
2276 dirtype = SVAL(params,0);
2277 maxentries = SVAL(params,2);
2278 findfirst_flags = SVAL(params,4);
2279 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2280 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2281 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2282 info_level = SVAL(params,6);
2284 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2285 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2286 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2287 info_level, max_data_bytes));
2289 if (!maxentries) {
2290 /* W2K3 seems to treat zero as 1. */
2291 maxentries = 1;
2294 switch (info_level) {
2295 case SMB_FIND_INFO_STANDARD:
2296 case SMB_FIND_EA_SIZE:
2297 case SMB_FIND_EA_LIST:
2298 case SMB_FIND_FILE_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_NAMES_INFO:
2301 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2302 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2304 break;
2305 case SMB_FIND_FILE_UNIX:
2306 case SMB_FIND_FILE_UNIX_INFO2:
2307 /* Always use filesystem for UNIX mtime query. */
2308 ask_sharemode = false;
2309 if (!lp_unix_extensions()) {
2310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2311 goto out;
2313 break;
2314 default:
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2316 goto out;
2319 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2320 params+12, total_params - 12,
2321 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2322 if (!NT_STATUS_IS_OK(ntstatus)) {
2323 reply_nterror(req, ntstatus);
2324 goto out;
2327 ntstatus = filename_convert(ctx, conn,
2328 req->flags2 & FLAGS2_DFS_PATHNAMES,
2329 directory,
2330 (UCF_SAVE_LCOMP |
2331 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2332 &mask_contains_wcard,
2333 &smb_dname);
2334 if (!NT_STATUS_IS_OK(ntstatus)) {
2335 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2336 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2337 ERRSRV, ERRbadpath);
2338 goto out;
2340 reply_nterror(req, ntstatus);
2341 goto out;
2344 mask = smb_dname->original_lcomp;
2346 directory = smb_dname->base_name;
2348 p = strrchr_m(directory,'/');
2349 if(p == NULL) {
2350 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2351 if((directory[0] == '.') && (directory[1] == '\0')) {
2352 mask = talloc_strdup(ctx,"*");
2353 if (!mask) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355 goto out;
2357 mask_contains_wcard = True;
2359 } else {
2360 *p = 0;
2363 if (p == NULL || p == directory) {
2364 /* Ensure we don't have a directory name of "". */
2365 directory = talloc_strdup(talloc_tos(), ".");
2366 if (!directory) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2368 goto out;
2372 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2374 if (info_level == SMB_FIND_EA_LIST) {
2375 uint32 ea_size;
2377 if (total_data < 4) {
2378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2379 goto out;
2382 ea_size = IVAL(pdata,0);
2383 if (ea_size != total_data) {
2384 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2385 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2387 goto out;
2390 if (!lp_ea_support(SNUM(conn))) {
2391 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2392 goto out;
2395 /* Pull out the list of names. */
2396 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2397 if (!ea_list) {
2398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2399 goto out;
2403 *ppdata = (char *)SMB_REALLOC(
2404 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2405 if(*ppdata == NULL ) {
2406 reply_nterror(req, NT_STATUS_NO_MEMORY);
2407 goto out;
2409 pdata = *ppdata;
2410 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2412 /* Realloc the params space */
2413 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2414 if (*pparams == NULL) {
2415 reply_nterror(req, NT_STATUS_NO_MEMORY);
2416 goto out;
2418 params = *pparams;
2420 /* Save the wildcard match and attribs we are using on this directory -
2421 needed as lanman2 assumes these are being saved between calls */
2423 ntstatus = dptr_create(conn,
2424 NULL, /* fsp */
2425 directory,
2426 False,
2427 True,
2428 req->smbpid,
2429 mask,
2430 mask_contains_wcard,
2431 dirtype,
2432 &dirptr);
2434 if (!NT_STATUS_IS_OK(ntstatus)) {
2435 reply_nterror(req, ntstatus);
2436 goto out;
2439 dptr_num = dptr_dnum(dirptr);
2440 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2442 /* Initialize per TRANS2_FIND_FIRST operation data */
2443 dptr_init_search_op(dirptr);
2445 /* We don't need to check for VOL here as this is returned by
2446 a different TRANS2 call. */
2448 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2449 directory,lp_dontdescend(SNUM(conn))));
2450 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2451 dont_descend = True;
2453 p = pdata;
2454 space_remaining = max_data_bytes;
2455 out_of_space = False;
2457 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2458 bool got_exact_match = False;
2460 /* this is a heuristic to avoid seeking the dirptr except when
2461 absolutely necessary. It allows for a filename of about 40 chars */
2462 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2463 out_of_space = True;
2464 finished = False;
2465 } else {
2466 finished = !get_lanman2_dir_entry(ctx,
2467 conn,
2468 dirptr,
2469 req->flags2,
2470 mask,dirtype,info_level,
2471 requires_resume_key,dont_descend,
2472 ask_sharemode,
2473 &p,pdata,data_end,
2474 space_remaining, &out_of_space,
2475 &got_exact_match,
2476 &last_entry_off, ea_list);
2479 if (finished && out_of_space)
2480 finished = False;
2482 if (!finished && !out_of_space)
2483 numentries++;
2486 * As an optimisation if we know we aren't looking
2487 * for a wildcard name (ie. the name matches the wildcard exactly)
2488 * then we can finish on any (first) match.
2489 * This speeds up large directory searches. JRA.
2492 if(got_exact_match)
2493 finished = True;
2495 /* Ensure space_remaining never goes -ve. */
2496 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2497 space_remaining = 0;
2498 out_of_space = true;
2499 } else {
2500 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2504 /* Check if we can close the dirptr */
2505 if(close_after_first || (finished && close_if_end)) {
2506 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2507 dptr_close(sconn, &dptr_num);
2511 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2512 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2513 * the protocol level is less than NT1. Tested with smbclient. JRA.
2514 * This should fix the OS/2 client bug #2335.
2517 if(numentries == 0) {
2518 dptr_close(sconn, &dptr_num);
2519 if (get_Protocol() < PROTOCOL_NT1) {
2520 reply_force_doserror(req, ERRDOS, ERRnofiles);
2521 goto out;
2522 } else {
2523 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2524 ERRDOS, ERRbadfile);
2525 goto out;
2529 /* At this point pdata points to numentries directory entries. */
2531 /* Set up the return parameter block */
2532 SSVAL(params,0,dptr_num);
2533 SSVAL(params,2,numentries);
2534 SSVAL(params,4,finished);
2535 SSVAL(params,6,0); /* Never an EA error */
2536 SSVAL(params,8,last_entry_off);
2538 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2539 max_data_bytes);
2541 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2542 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2543 if (!directory) {
2544 reply_nterror(req, NT_STATUS_NO_MEMORY);
2548 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2549 smb_fn_name(req->cmd),
2550 mask, directory, dirtype, numentries ) );
2553 * Force a name mangle here to ensure that the
2554 * mask as an 8.3 name is top of the mangled cache.
2555 * The reasons for this are subtle. Don't remove
2556 * this code unless you know what you are doing
2557 * (see PR#13758). JRA.
2560 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2561 char mangled_name[13];
2562 name_to_8_3(mask, mangled_name, True, conn->params);
2564 out:
2565 TALLOC_FREE(smb_dname);
2566 return;
2569 /****************************************************************************
2570 Reply to a TRANS2_FINDNEXT.
2571 ****************************************************************************/
2573 static void call_trans2findnext(connection_struct *conn,
2574 struct smb_request *req,
2575 char **pparams, int total_params,
2576 char **ppdata, int total_data,
2577 unsigned int max_data_bytes)
2579 /* We must be careful here that we don't return more than the
2580 allowed number of data bytes. If this means returning fewer than
2581 maxentries then so be it. We assume that the redirector has
2582 enough room for the fixed number of parameter bytes it has
2583 requested. */
2584 char *params = *pparams;
2585 char *pdata = *ppdata;
2586 char *data_end;
2587 int dptr_num;
2588 int maxentries;
2589 uint16 info_level;
2590 uint32 resume_key;
2591 uint16 findnext_flags;
2592 bool close_after_request;
2593 bool close_if_end;
2594 bool requires_resume_key;
2595 bool continue_bit;
2596 bool mask_contains_wcard = False;
2597 char *resume_name = NULL;
2598 const char *mask = NULL;
2599 const char *directory = NULL;
2600 char *p = NULL;
2601 uint16 dirtype;
2602 int numentries = 0;
2603 int i, last_entry_off=0;
2604 bool finished = False;
2605 bool dont_descend = False;
2606 bool out_of_space = False;
2607 int space_remaining;
2608 struct ea_list *ea_list = NULL;
2609 NTSTATUS ntstatus = NT_STATUS_OK;
2610 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2611 TALLOC_CTX *ctx = talloc_tos();
2612 struct dptr_struct *dirptr;
2613 struct smbd_server_connection *sconn = req->sconn;
2615 if (total_params < 13) {
2616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2617 return;
2620 dptr_num = SVAL(params,0);
2621 maxentries = SVAL(params,2);
2622 info_level = SVAL(params,4);
2623 resume_key = IVAL(params,6);
2624 findnext_flags = SVAL(params,10);
2625 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2626 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2627 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2628 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2630 if (!continue_bit) {
2631 /* We only need resume_name if continue_bit is zero. */
2632 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2633 params+12,
2634 total_params - 12, STR_TERMINATE, &ntstatus,
2635 &mask_contains_wcard);
2636 if (!NT_STATUS_IS_OK(ntstatus)) {
2637 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2638 complain (it thinks we're asking for the directory above the shared
2639 path or an invalid name). Catch this as the resume name is only compared, never used in
2640 a file access. JRA. */
2641 srvstr_pull_talloc(ctx, params, req->flags2,
2642 &resume_name, params+12,
2643 total_params - 12,
2644 STR_TERMINATE);
2646 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2647 reply_nterror(req, ntstatus);
2648 return;
2653 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2654 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2655 resume_key = %d resume name = %s continue=%d level = %d\n",
2656 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2657 requires_resume_key, resume_key,
2658 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2660 if (!maxentries) {
2661 /* W2K3 seems to treat zero as 1. */
2662 maxentries = 1;
2665 switch (info_level) {
2666 case SMB_FIND_INFO_STANDARD:
2667 case SMB_FIND_EA_SIZE:
2668 case SMB_FIND_EA_LIST:
2669 case SMB_FIND_FILE_DIRECTORY_INFO:
2670 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2671 case SMB_FIND_FILE_NAMES_INFO:
2672 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2673 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2675 break;
2676 case SMB_FIND_FILE_UNIX:
2677 case SMB_FIND_FILE_UNIX_INFO2:
2678 /* Always use filesystem for UNIX mtime query. */
2679 ask_sharemode = false;
2680 if (!lp_unix_extensions()) {
2681 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2682 return;
2684 break;
2685 default:
2686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2687 return;
2690 if (info_level == SMB_FIND_EA_LIST) {
2691 uint32 ea_size;
2693 if (total_data < 4) {
2694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2695 return;
2698 ea_size = IVAL(pdata,0);
2699 if (ea_size != total_data) {
2700 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2701 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2703 return;
2706 if (!lp_ea_support(SNUM(conn))) {
2707 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2708 return;
2711 /* Pull out the list of names. */
2712 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2713 if (!ea_list) {
2714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2715 return;
2719 *ppdata = (char *)SMB_REALLOC(
2720 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2721 if(*ppdata == NULL) {
2722 reply_nterror(req, NT_STATUS_NO_MEMORY);
2723 return;
2726 pdata = *ppdata;
2727 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2729 /* Realloc the params space */
2730 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2731 if(*pparams == NULL ) {
2732 reply_nterror(req, NT_STATUS_NO_MEMORY);
2733 return;
2736 params = *pparams;
2738 /* Check that the dptr is valid */
2739 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2740 reply_nterror(req, STATUS_NO_MORE_FILES);
2741 return;
2744 directory = dptr_path(sconn, dptr_num);
2746 /* Get the wildcard mask from the dptr */
2747 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2748 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2749 reply_nterror(req, STATUS_NO_MORE_FILES);
2750 return;
2753 mask = p;
2755 /* Get the attr mask from the dptr */
2756 dirtype = dptr_attr(sconn, dptr_num);
2758 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2759 dptr_num, mask, dirtype,
2760 (long)dirptr,
2761 dptr_TellDir(dirptr)));
2763 /* Initialize per TRANS2_FIND_NEXT operation data */
2764 dptr_init_search_op(dirptr);
2766 /* We don't need to check for VOL here as this is returned by
2767 a different TRANS2 call. */
2769 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2770 directory,lp_dontdescend(SNUM(conn))));
2771 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2772 dont_descend = True;
2774 p = pdata;
2775 space_remaining = max_data_bytes;
2776 out_of_space = False;
2779 * Seek to the correct position. We no longer use the resume key but
2780 * depend on the last file name instead.
2783 if(!continue_bit && resume_name && *resume_name) {
2784 SMB_STRUCT_STAT st;
2786 long current_pos = 0;
2788 * Remember, name_to_8_3 is called by
2789 * get_lanman2_dir_entry(), so the resume name
2790 * could be mangled. Ensure we check the unmangled name.
2793 if (mangle_is_mangled(resume_name, conn->params)) {
2794 char *new_resume_name = NULL;
2795 mangle_lookup_name_from_8_3(ctx,
2796 resume_name,
2797 &new_resume_name,
2798 conn->params);
2799 if (new_resume_name) {
2800 resume_name = new_resume_name;
2805 * Fix for NT redirector problem triggered by resume key indexes
2806 * changing between directory scans. We now return a resume key of 0
2807 * and instead look for the filename to continue from (also given
2808 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2809 * findfirst/findnext (as is usual) then the directory pointer
2810 * should already be at the correct place.
2813 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2814 } /* end if resume_name && !continue_bit */
2816 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2817 bool got_exact_match = False;
2819 /* this is a heuristic to avoid seeking the dirptr except when
2820 absolutely necessary. It allows for a filename of about 40 chars */
2821 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2822 out_of_space = True;
2823 finished = False;
2824 } else {
2825 finished = !get_lanman2_dir_entry(ctx,
2826 conn,
2827 dirptr,
2828 req->flags2,
2829 mask,dirtype,info_level,
2830 requires_resume_key,dont_descend,
2831 ask_sharemode,
2832 &p,pdata,data_end,
2833 space_remaining, &out_of_space,
2834 &got_exact_match,
2835 &last_entry_off, ea_list);
2838 if (finished && out_of_space)
2839 finished = False;
2841 if (!finished && !out_of_space)
2842 numentries++;
2845 * As an optimisation if we know we aren't looking
2846 * for a wildcard name (ie. the name matches the wildcard exactly)
2847 * then we can finish on any (first) match.
2848 * This speeds up large directory searches. JRA.
2851 if(got_exact_match)
2852 finished = True;
2854 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2857 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2858 smb_fn_name(req->cmd),
2859 mask, directory, dirtype, numentries ) );
2861 /* Check if we can close the dirptr */
2862 if(close_after_request || (finished && close_if_end)) {
2863 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2864 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2867 /* Set up the return parameter block */
2868 SSVAL(params,0,numentries);
2869 SSVAL(params,2,finished);
2870 SSVAL(params,4,0); /* Never an EA error */
2871 SSVAL(params,6,last_entry_off);
2873 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2874 max_data_bytes);
2876 return;
2879 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2881 E_md4hash(lp_servicename(SNUM(conn)),objid);
2882 return objid;
2885 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2887 SMB_ASSERT(extended_info != NULL);
2889 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2890 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2891 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2892 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2893 #ifdef SAMBA_VERSION_REVISION
2894 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2895 #endif
2896 extended_info->samba_subversion = 0;
2897 #ifdef SAMBA_VERSION_RC_RELEASE
2898 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2899 #else
2900 #ifdef SAMBA_VERSION_PRE_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2902 #endif
2903 #endif
2904 #ifdef SAMBA_VERSION_VENDOR_PATCH
2905 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2906 #endif
2907 extended_info->samba_gitcommitdate = 0;
2908 #ifdef SAMBA_VERSION_COMMIT_TIME
2909 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2910 #endif
2912 memset(extended_info->samba_version_string, 0,
2913 sizeof(extended_info->samba_version_string));
2915 snprintf (extended_info->samba_version_string,
2916 sizeof(extended_info->samba_version_string),
2917 "%s", samba_version_string());
2920 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2921 TALLOC_CTX *mem_ctx,
2922 uint16_t info_level,
2923 uint16_t flags2,
2924 unsigned int max_data_bytes,
2925 char **ppdata,
2926 int *ret_data_len)
2928 char *pdata, *end_data;
2929 int data_len = 0, len;
2930 const char *vname = volume_label(SNUM(conn));
2931 int snum = SNUM(conn);
2932 char *fstype = lp_fstype(SNUM(conn));
2933 uint32 additional_flags = 0;
2934 struct smb_filename smb_fname_dot;
2935 SMB_STRUCT_STAT st;
2937 if (IS_IPC(conn)) {
2938 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2939 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2940 "info level (0x%x) on IPC$.\n",
2941 (unsigned int)info_level));
2942 return NT_STATUS_ACCESS_DENIED;
2946 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2948 ZERO_STRUCT(smb_fname_dot);
2949 smb_fname_dot.base_name = discard_const_p(char, ".");
2951 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2952 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2953 return map_nt_error_from_unix(errno);
2956 st = smb_fname_dot.st;
2958 *ppdata = (char *)SMB_REALLOC(
2959 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2960 if (*ppdata == NULL) {
2961 return NT_STATUS_NO_MEMORY;
2964 pdata = *ppdata;
2965 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2966 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2968 switch (info_level) {
2969 case SMB_INFO_ALLOCATION:
2971 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2972 data_len = 18;
2973 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2974 return map_nt_error_from_unix(errno);
2977 block_size = lp_block_size(snum);
2978 if (bsize < block_size) {
2979 uint64_t factor = block_size/bsize;
2980 bsize = block_size;
2981 dsize /= factor;
2982 dfree /= factor;
2984 if (bsize > block_size) {
2985 uint64_t factor = bsize/block_size;
2986 bsize = block_size;
2987 dsize *= factor;
2988 dfree *= factor;
2990 bytes_per_sector = 512;
2991 sectors_per_unit = bsize/bytes_per_sector;
2993 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2994 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2995 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2997 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2998 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2999 SIVAL(pdata,l1_cUnit,dsize);
3000 SIVAL(pdata,l1_cUnitAvail,dfree);
3001 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3002 break;
3005 case SMB_INFO_VOLUME:
3006 /* Return volume name */
3008 * Add volume serial number - hash of a combination of
3009 * the called hostname and the service name.
3011 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3013 * Win2k3 and previous mess this up by sending a name length
3014 * one byte short. I believe only older clients (OS/2 Win9x) use
3015 * this call so try fixing this by adding a terminating null to
3016 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3018 len = srvstr_push(
3019 pdata, flags2,
3020 pdata+l2_vol_szVolLabel, vname,
3021 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3022 STR_NOALIGN|STR_TERMINATE);
3023 SCVAL(pdata,l2_vol_cch,len);
3024 data_len = l2_vol_szVolLabel + len;
3025 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3026 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3027 len, vname));
3028 break;
3030 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3031 case SMB_FS_ATTRIBUTE_INFORMATION:
3033 additional_flags = 0;
3034 #if defined(HAVE_SYS_QUOTAS)
3035 additional_flags |= FILE_VOLUME_QUOTAS;
3036 #endif
3038 if(lp_nt_acl_support(SNUM(conn))) {
3039 additional_flags |= FILE_PERSISTENT_ACLS;
3042 /* Capabilities are filled in at connection time through STATVFS call */
3043 additional_flags |= conn->fs_capabilities;
3044 additional_flags |= lp_parm_int(conn->params->service,
3045 "share", "fake_fscaps",
3048 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3049 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3050 additional_flags); /* FS ATTRIBUTES */
3052 SIVAL(pdata,4,255); /* Max filename component length */
3053 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3054 and will think we can't do long filenames */
3055 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3056 PTR_DIFF(end_data, pdata+12),
3057 STR_UNICODE);
3058 SIVAL(pdata,8,len);
3059 data_len = 12 + len;
3060 break;
3062 case SMB_QUERY_FS_LABEL_INFO:
3063 case SMB_FS_LABEL_INFORMATION:
3064 len = srvstr_push(pdata, flags2, pdata+4, vname,
3065 PTR_DIFF(end_data, pdata+4), 0);
3066 data_len = 4 + len;
3067 SIVAL(pdata,0,len);
3068 break;
3070 case SMB_QUERY_FS_VOLUME_INFO:
3071 case SMB_FS_VOLUME_INFORMATION:
3074 * Add volume serial number - hash of a combination of
3075 * the called hostname and the service name.
3077 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3078 (str_checksum(get_local_machine_name())<<16));
3080 /* Max label len is 32 characters. */
3081 len = srvstr_push(pdata, flags2, pdata+18, vname,
3082 PTR_DIFF(end_data, pdata+18),
3083 STR_UNICODE);
3084 SIVAL(pdata,12,len);
3085 data_len = 18+len;
3087 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3088 (int)strlen(vname),vname, lp_servicename(snum)));
3089 break;
3091 case SMB_QUERY_FS_SIZE_INFO:
3092 case SMB_FS_SIZE_INFORMATION:
3094 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3095 data_len = 24;
3096 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3097 return map_nt_error_from_unix(errno);
3099 block_size = lp_block_size(snum);
3100 if (bsize < block_size) {
3101 uint64_t factor = block_size/bsize;
3102 bsize = block_size;
3103 dsize /= factor;
3104 dfree /= factor;
3106 if (bsize > block_size) {
3107 uint64_t factor = bsize/block_size;
3108 bsize = block_size;
3109 dsize *= factor;
3110 dfree *= factor;
3112 bytes_per_sector = 512;
3113 sectors_per_unit = bsize/bytes_per_sector;
3114 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3115 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3116 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3117 SBIG_UINT(pdata,0,dsize);
3118 SBIG_UINT(pdata,8,dfree);
3119 SIVAL(pdata,16,sectors_per_unit);
3120 SIVAL(pdata,20,bytes_per_sector);
3121 break;
3124 case SMB_FS_FULL_SIZE_INFORMATION:
3126 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3127 data_len = 32;
3128 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3129 return map_nt_error_from_unix(errno);
3131 block_size = lp_block_size(snum);
3132 if (bsize < block_size) {
3133 uint64_t factor = block_size/bsize;
3134 bsize = block_size;
3135 dsize /= factor;
3136 dfree /= factor;
3138 if (bsize > block_size) {
3139 uint64_t factor = bsize/block_size;
3140 bsize = block_size;
3141 dsize *= factor;
3142 dfree *= factor;
3144 bytes_per_sector = 512;
3145 sectors_per_unit = bsize/bytes_per_sector;
3146 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3147 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3148 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3149 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3150 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3151 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3152 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3153 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3154 break;
3157 case SMB_QUERY_FS_DEVICE_INFO:
3158 case SMB_FS_DEVICE_INFORMATION:
3160 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3162 if (!CAN_WRITE(conn)) {
3163 characteristics |= FILE_READ_ONLY_DEVICE;
3165 data_len = 8;
3166 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3167 SIVAL(pdata,4,characteristics);
3168 break;
3171 #ifdef HAVE_SYS_QUOTAS
3172 case SMB_FS_QUOTA_INFORMATION:
3174 * what we have to send --metze:
3176 * Unknown1: 24 NULL bytes
3177 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3178 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3179 * Quota Flags: 2 byte :
3180 * Unknown3: 6 NULL bytes
3182 * 48 bytes total
3184 * details for Quota Flags:
3186 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3187 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3188 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3189 * 0x0001 Enable Quotas: enable quota for this fs
3193 /* we need to fake up a fsp here,
3194 * because its not send in this call
3196 files_struct fsp;
3197 SMB_NTQUOTA_STRUCT quotas;
3199 ZERO_STRUCT(fsp);
3200 ZERO_STRUCT(quotas);
3202 fsp.conn = conn;
3203 fsp.fnum = -1;
3205 /* access check */
3206 if (conn->session_info->utok.uid != sec_initial_uid()) {
3207 DEBUG(0,("set_user_quota: access_denied "
3208 "service [%s] user [%s]\n",
3209 lp_servicename(SNUM(conn)),
3210 conn->session_info->unix_name));
3211 return NT_STATUS_ACCESS_DENIED;
3214 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3215 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3216 return map_nt_error_from_unix(errno);
3219 data_len = 48;
3221 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3222 lp_servicename(SNUM(conn))));
3224 /* Unknown1 24 NULL bytes*/
3225 SBIG_UINT(pdata,0,(uint64_t)0);
3226 SBIG_UINT(pdata,8,(uint64_t)0);
3227 SBIG_UINT(pdata,16,(uint64_t)0);
3229 /* Default Soft Quota 8 bytes */
3230 SBIG_UINT(pdata,24,quotas.softlim);
3232 /* Default Hard Quota 8 bytes */
3233 SBIG_UINT(pdata,32,quotas.hardlim);
3235 /* Quota flag 2 bytes */
3236 SSVAL(pdata,40,quotas.qflags);
3238 /* Unknown3 6 NULL bytes */
3239 SSVAL(pdata,42,0);
3240 SIVAL(pdata,44,0);
3242 break;
3244 #endif /* HAVE_SYS_QUOTAS */
3245 case SMB_FS_OBJECTID_INFORMATION:
3247 unsigned char objid[16];
3248 struct smb_extended_info extended_info;
3249 memcpy(pdata,create_volume_objectid(conn, objid),16);
3250 samba_extended_info_version (&extended_info);
3251 SIVAL(pdata,16,extended_info.samba_magic);
3252 SIVAL(pdata,20,extended_info.samba_version);
3253 SIVAL(pdata,24,extended_info.samba_subversion);
3254 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3255 memcpy(pdata+36,extended_info.samba_version_string,28);
3256 data_len = 64;
3257 break;
3261 * Query the version and capabilities of the CIFS UNIX extensions
3262 * in use.
3265 case SMB_QUERY_CIFS_UNIX_INFO:
3267 bool large_write = lp_min_receive_file_size() &&
3268 !srv_is_signing_active(conn->sconn);
3269 bool large_read = !srv_is_signing_active(conn->sconn);
3270 int encrypt_caps = 0;
3272 if (!lp_unix_extensions()) {
3273 return NT_STATUS_INVALID_LEVEL;
3276 switch (conn->encrypt_level) {
3277 case 0:
3278 encrypt_caps = 0;
3279 break;
3280 case 1:
3281 case Auto:
3282 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3283 break;
3284 case Required:
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3286 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3287 large_write = false;
3288 large_read = false;
3289 break;
3292 data_len = 12;
3293 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3294 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3296 /* We have POSIX ACLs, pathname, encryption,
3297 * large read/write, and locking capability. */
3299 SBIG_UINT(pdata,4,((uint64_t)(
3300 CIFS_UNIX_POSIX_ACLS_CAP|
3301 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3302 CIFS_UNIX_FCNTL_LOCKS_CAP|
3303 CIFS_UNIX_EXTATTR_CAP|
3304 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3305 encrypt_caps|
3306 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3307 (large_write ?
3308 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3309 break;
3312 case SMB_QUERY_POSIX_FS_INFO:
3314 int rc;
3315 vfs_statvfs_struct svfs;
3317 if (!lp_unix_extensions()) {
3318 return NT_STATUS_INVALID_LEVEL;
3321 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3323 if (!rc) {
3324 data_len = 56;
3325 SIVAL(pdata,0,svfs.OptimalTransferSize);
3326 SIVAL(pdata,4,svfs.BlockSize);
3327 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3328 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3329 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3330 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3331 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3332 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3333 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3334 #ifdef EOPNOTSUPP
3335 } else if (rc == EOPNOTSUPP) {
3336 return NT_STATUS_INVALID_LEVEL;
3337 #endif /* EOPNOTSUPP */
3338 } else {
3339 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3340 return NT_STATUS_DOS(ERRSRV, ERRerror);
3342 break;
3345 case SMB_QUERY_POSIX_WHOAMI:
3347 uint32_t flags = 0;
3348 uint32_t sid_bytes;
3349 int i;
3351 if (!lp_unix_extensions()) {
3352 return NT_STATUS_INVALID_LEVEL;
3355 if (max_data_bytes < 40) {
3356 return NT_STATUS_BUFFER_TOO_SMALL;
3359 /* We ARE guest if global_sid_Builtin_Guests is
3360 * in our list of SIDs.
3362 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3363 conn->session_info->security_token)) {
3364 flags |= SMB_WHOAMI_GUEST;
3367 /* We are NOT guest if global_sid_Authenticated_Users
3368 * is in our list of SIDs.
3370 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3371 conn->session_info->security_token)) {
3372 flags &= ~SMB_WHOAMI_GUEST;
3375 /* NOTE: 8 bytes for UID/GID, irrespective of native
3376 * platform size. This matches
3377 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3379 data_len = 4 /* flags */
3380 + 4 /* flag mask */
3381 + 8 /* uid */
3382 + 8 /* gid */
3383 + 4 /* ngroups */
3384 + 4 /* num_sids */
3385 + 4 /* SID bytes */
3386 + 4 /* pad/reserved */
3387 + (conn->session_info->utok.ngroups * 8)
3388 /* groups list */
3389 + (conn->session_info->security_token->num_sids *
3390 SID_MAX_SIZE)
3391 /* SID list */;
3393 SIVAL(pdata, 0, flags);
3394 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3395 SBIG_UINT(pdata, 8,
3396 (uint64_t)conn->session_info->utok.uid);
3397 SBIG_UINT(pdata, 16,
3398 (uint64_t)conn->session_info->utok.gid);
3401 if (data_len >= max_data_bytes) {
3402 /* Potential overflow, skip the GIDs and SIDs. */
3404 SIVAL(pdata, 24, 0); /* num_groups */
3405 SIVAL(pdata, 28, 0); /* num_sids */
3406 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3407 SIVAL(pdata, 36, 0); /* reserved */
3409 data_len = 40;
3410 break;
3413 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3414 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3416 /* We walk the SID list twice, but this call is fairly
3417 * infrequent, and I don't expect that it's performance
3418 * sensitive -- jpeach
3420 for (i = 0, sid_bytes = 0;
3421 i < conn->session_info->security_token->num_sids; ++i) {
3422 sid_bytes += ndr_size_dom_sid(
3423 &conn->session_info->security_token->sids[i],
3427 /* SID list byte count */
3428 SIVAL(pdata, 32, sid_bytes);
3430 /* 4 bytes pad/reserved - must be zero */
3431 SIVAL(pdata, 36, 0);
3432 data_len = 40;
3434 /* GID list */
3435 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3436 SBIG_UINT(pdata, data_len,
3437 (uint64_t)conn->session_info->utok.groups[i]);
3438 data_len += 8;
3441 /* SID list */
3442 for (i = 0;
3443 i < conn->session_info->security_token->num_sids; ++i) {
3444 int sid_len = ndr_size_dom_sid(
3445 &conn->session_info->security_token->sids[i],
3448 sid_linearize(pdata + data_len, sid_len,
3449 &conn->session_info->security_token->sids[i]);
3450 data_len += sid_len;
3453 break;
3456 case SMB_MAC_QUERY_FS_INFO:
3458 * Thursby MAC extension... ONLY on NTFS filesystems
3459 * once we do streams then we don't need this
3461 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3462 data_len = 88;
3463 SIVAL(pdata,84,0x100); /* Don't support mac... */
3464 break;
3466 /* drop through */
3467 default:
3468 return NT_STATUS_INVALID_LEVEL;
3471 *ret_data_len = data_len;
3472 return NT_STATUS_OK;
3475 /****************************************************************************
3476 Reply to a TRANS2_QFSINFO (query filesystem info).
3477 ****************************************************************************/
3479 static void call_trans2qfsinfo(connection_struct *conn,
3480 struct smb_request *req,
3481 char **pparams, int total_params,
3482 char **ppdata, int total_data,
3483 unsigned int max_data_bytes)
3485 char *params = *pparams;
3486 uint16_t info_level;
3487 int data_len = 0;
3488 NTSTATUS status;
3490 if (total_params < 2) {
3491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3492 return;
3495 info_level = SVAL(params,0);
3497 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3498 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3499 DEBUG(0,("call_trans2qfsinfo: encryption required "
3500 "and info level 0x%x sent.\n",
3501 (unsigned int)info_level));
3502 exit_server_cleanly("encryption required "
3503 "on connection");
3504 return;
3508 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3510 status = smbd_do_qfsinfo(conn, req,
3511 info_level,
3512 req->flags2,
3513 max_data_bytes,
3514 ppdata, &data_len);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 reply_nterror(req, status);
3517 return;
3520 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3521 max_data_bytes);
3523 DEBUG( 4, ( "%s info_level = %d\n",
3524 smb_fn_name(req->cmd), info_level) );
3526 return;
3529 /****************************************************************************
3530 Reply to a TRANS2_SETFSINFO (set filesystem info).
3531 ****************************************************************************/
3533 static void call_trans2setfsinfo(connection_struct *conn,
3534 struct smb_request *req,
3535 char **pparams, int total_params,
3536 char **ppdata, int total_data,
3537 unsigned int max_data_bytes)
3539 char *pdata = *ppdata;
3540 char *params = *pparams;
3541 uint16 info_level;
3543 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3545 /* */
3546 if (total_params < 4) {
3547 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3548 total_params));
3549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550 return;
3553 info_level = SVAL(params,2);
3555 if (IS_IPC(conn)) {
3556 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3557 info_level != SMB_SET_CIFS_UNIX_INFO) {
3558 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3559 "info level (0x%x) on IPC$.\n",
3560 (unsigned int)info_level));
3561 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3562 return;
3566 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3567 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3568 DEBUG(0,("call_trans2setfsinfo: encryption required "
3569 "and info level 0x%x sent.\n",
3570 (unsigned int)info_level));
3571 exit_server_cleanly("encryption required "
3572 "on connection");
3573 return;
3577 switch(info_level) {
3578 case SMB_SET_CIFS_UNIX_INFO:
3580 uint16 client_unix_major;
3581 uint16 client_unix_minor;
3582 uint32 client_unix_cap_low;
3583 uint32 client_unix_cap_high;
3585 if (!lp_unix_extensions()) {
3586 reply_nterror(req,
3587 NT_STATUS_INVALID_LEVEL);
3588 return;
3591 /* There should be 12 bytes of capabilities set. */
3592 if (total_data < 8) {
3593 reply_nterror(
3594 req,
3595 NT_STATUS_INVALID_PARAMETER);
3596 return;
3598 client_unix_major = SVAL(pdata,0);
3599 client_unix_minor = SVAL(pdata,2);
3600 client_unix_cap_low = IVAL(pdata,4);
3601 client_unix_cap_high = IVAL(pdata,8);
3602 /* Just print these values for now. */
3603 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3604 cap_low = 0x%x, cap_high = 0x%x\n",
3605 (unsigned int)client_unix_major,
3606 (unsigned int)client_unix_minor,
3607 (unsigned int)client_unix_cap_low,
3608 (unsigned int)client_unix_cap_high ));
3610 /* Here is where we must switch to posix pathname processing... */
3611 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3612 lp_set_posix_pathnames();
3613 mangle_change_to_posix();
3616 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3617 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3618 /* Client that knows how to do posix locks,
3619 * but not posix open/mkdir operations. Set a
3620 * default type for read/write checks. */
3622 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3625 break;
3628 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3630 NTSTATUS status;
3631 size_t param_len = 0;
3632 size_t data_len = total_data;
3634 if (!lp_unix_extensions()) {
3635 reply_nterror(
3636 req,
3637 NT_STATUS_INVALID_LEVEL);
3638 return;
3641 if (lp_smb_encrypt(SNUM(conn)) == false) {
3642 reply_nterror(
3643 req,
3644 NT_STATUS_NOT_SUPPORTED);
3645 return;
3648 if (req->sconn->smb1.echo_handler.trusted_fde) {
3649 DEBUG( 2,("call_trans2setfsinfo: "
3650 "request transport encryption disabled"
3651 "with 'fork echo handler = yes'\n"));
3652 reply_nterror(
3653 req,
3654 NT_STATUS_NOT_SUPPORTED);
3655 return;
3658 DEBUG( 4,("call_trans2setfsinfo: "
3659 "request transport encryption.\n"));
3661 status = srv_request_encryption_setup(conn,
3662 (unsigned char **)ppdata,
3663 &data_len,
3664 (unsigned char **)pparams,
3665 &param_len);
3667 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3668 !NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3670 return;
3673 send_trans2_replies(conn, req,
3674 *pparams,
3675 param_len,
3676 *ppdata,
3677 data_len,
3678 max_data_bytes);
3680 if (NT_STATUS_IS_OK(status)) {
3681 /* Server-side transport
3682 * encryption is now *on*. */
3683 status = srv_encryption_start(conn);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 exit_server_cleanly(
3686 "Failure in setting "
3687 "up encrypted transport");
3690 return;
3693 case SMB_FS_QUOTA_INFORMATION:
3695 files_struct *fsp = NULL;
3696 SMB_NTQUOTA_STRUCT quotas;
3698 ZERO_STRUCT(quotas);
3700 /* access check */
3701 if ((conn->session_info->utok.uid != sec_initial_uid())
3702 ||!CAN_WRITE(conn)) {
3703 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3704 lp_servicename(SNUM(conn)),
3705 conn->session_info->unix_name));
3706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3707 return;
3710 /* note: normaly there're 48 bytes,
3711 * but we didn't use the last 6 bytes for now
3712 * --metze
3714 fsp = file_fsp(req, SVAL(params,0));
3716 if (!check_fsp_ntquota_handle(conn, req,
3717 fsp)) {
3718 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3719 reply_nterror(
3720 req, NT_STATUS_INVALID_HANDLE);
3721 return;
3724 if (total_data < 42) {
3725 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3726 total_data));
3727 reply_nterror(
3728 req,
3729 NT_STATUS_INVALID_PARAMETER);
3730 return;
3733 /* unknown_1 24 NULL bytes in pdata*/
3735 /* the soft quotas 8 bytes (uint64_t)*/
3736 quotas.softlim = (uint64_t)IVAL(pdata,24);
3737 #ifdef LARGE_SMB_OFF_T
3738 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3739 #else /* LARGE_SMB_OFF_T */
3740 if ((IVAL(pdata,28) != 0)&&
3741 ((quotas.softlim != 0xFFFFFFFF)||
3742 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3743 /* more than 32 bits? */
3744 reply_nterror(
3745 req,
3746 NT_STATUS_INVALID_PARAMETER);
3747 return;
3749 #endif /* LARGE_SMB_OFF_T */
3751 /* the hard quotas 8 bytes (uint64_t)*/
3752 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3753 #ifdef LARGE_SMB_OFF_T
3754 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3755 #else /* LARGE_SMB_OFF_T */
3756 if ((IVAL(pdata,36) != 0)&&
3757 ((quotas.hardlim != 0xFFFFFFFF)||
3758 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3759 /* more than 32 bits? */
3760 reply_nterror(
3761 req,
3762 NT_STATUS_INVALID_PARAMETER);
3763 return;
3765 #endif /* LARGE_SMB_OFF_T */
3767 /* quota_flags 2 bytes **/
3768 quotas.qflags = SVAL(pdata,40);
3770 /* unknown_2 6 NULL bytes follow*/
3772 /* now set the quotas */
3773 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3774 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3775 reply_nterror(req, map_nt_error_from_unix(errno));
3776 return;
3779 break;
3781 default:
3782 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3783 info_level));
3784 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3785 return;
3786 break;
3790 * sending this reply works fine,
3791 * but I'm not sure it's the same
3792 * like windows do...
3793 * --metze
3795 reply_outbuf(req, 10, 0);
3798 #if defined(HAVE_POSIX_ACLS)
3799 /****************************************************************************
3800 Utility function to count the number of entries in a POSIX acl.
3801 ****************************************************************************/
3803 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3805 unsigned int ace_count = 0;
3806 int entry_id = SMB_ACL_FIRST_ENTRY;
3807 SMB_ACL_ENTRY_T entry;
3809 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3810 /* get_next... */
3811 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3812 entry_id = SMB_ACL_NEXT_ENTRY;
3814 ace_count++;
3816 return ace_count;
3819 /****************************************************************************
3820 Utility function to marshall a POSIX acl into wire format.
3821 ****************************************************************************/
3823 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3825 int entry_id = SMB_ACL_FIRST_ENTRY;
3826 SMB_ACL_ENTRY_T entry;
3828 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3829 SMB_ACL_TAG_T tagtype;
3830 SMB_ACL_PERMSET_T permset;
3831 unsigned char perms = 0;
3832 unsigned int own_grp;
3834 /* get_next... */
3835 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3836 entry_id = SMB_ACL_NEXT_ENTRY;
3839 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3840 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3841 return False;
3844 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3845 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3846 return False;
3849 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3850 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3851 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3853 SCVAL(pdata,1,perms);
3855 switch (tagtype) {
3856 case SMB_ACL_USER_OBJ:
3857 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3858 own_grp = (unsigned int)pst->st_ex_uid;
3859 SIVAL(pdata,2,own_grp);
3860 SIVAL(pdata,6,0);
3861 break;
3862 case SMB_ACL_USER:
3864 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3865 if (!puid) {
3866 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3867 return False;
3869 own_grp = (unsigned int)*puid;
3870 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3871 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3872 SIVAL(pdata,2,own_grp);
3873 SIVAL(pdata,6,0);
3874 break;
3876 case SMB_ACL_GROUP_OBJ:
3877 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3878 own_grp = (unsigned int)pst->st_ex_gid;
3879 SIVAL(pdata,2,own_grp);
3880 SIVAL(pdata,6,0);
3881 break;
3882 case SMB_ACL_GROUP:
3884 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3885 if (!pgid) {
3886 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3887 return False;
3889 own_grp = (unsigned int)*pgid;
3890 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3891 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3892 SIVAL(pdata,2,own_grp);
3893 SIVAL(pdata,6,0);
3894 break;
3896 case SMB_ACL_MASK:
3897 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3898 SIVAL(pdata,2,0xFFFFFFFF);
3899 SIVAL(pdata,6,0xFFFFFFFF);
3900 break;
3901 case SMB_ACL_OTHER:
3902 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3903 SIVAL(pdata,2,0xFFFFFFFF);
3904 SIVAL(pdata,6,0xFFFFFFFF);
3905 break;
3906 default:
3907 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3908 return False;
3910 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3913 return True;
3915 #endif
3917 /****************************************************************************
3918 Store the FILE_UNIX_BASIC info.
3919 ****************************************************************************/
3921 static char *store_file_unix_basic(connection_struct *conn,
3922 char *pdata,
3923 files_struct *fsp,
3924 const SMB_STRUCT_STAT *psbuf)
3926 uint64_t file_index = get_FileIndex(conn, psbuf);
3928 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3929 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3931 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3932 pdata += 8;
3934 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3935 pdata += 8;
3937 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3938 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3939 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3940 pdata += 24;
3942 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3943 SIVAL(pdata,4,0);
3944 pdata += 8;
3946 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3947 SIVAL(pdata,4,0);
3948 pdata += 8;
3950 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3951 pdata += 4;
3953 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3954 SIVAL(pdata,4,0);
3955 pdata += 8;
3957 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3958 SIVAL(pdata,4,0);
3959 pdata += 8;
3961 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3962 pdata += 8;
3964 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3965 SIVAL(pdata,4,0);
3966 pdata += 8;
3968 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3969 SIVAL(pdata,4,0);
3970 pdata += 8;
3972 return pdata;
3975 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3976 * the chflags(2) (or equivalent) flags.
3978 * XXX: this really should be behind the VFS interface. To do this, we would
3979 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3980 * Each VFS module could then implement its own mapping as appropriate for the
3981 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3983 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3984 info2_flags_map[] =
3986 #ifdef UF_NODUMP
3987 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3988 #endif
3990 #ifdef UF_IMMUTABLE
3991 { UF_IMMUTABLE, EXT_IMMUTABLE },
3992 #endif
3994 #ifdef UF_APPEND
3995 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3996 #endif
3998 #ifdef UF_HIDDEN
3999 { UF_HIDDEN, EXT_HIDDEN },
4000 #endif
4002 /* Do not remove. We need to guarantee that this array has at least one
4003 * entry to build on HP-UX.
4005 { 0, 0 }
4009 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4010 uint32 *smb_fflags, uint32 *smb_fmask)
4012 int i;
4014 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4015 *smb_fmask |= info2_flags_map[i].smb_fflag;
4016 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4017 *smb_fflags |= info2_flags_map[i].smb_fflag;
4022 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4023 const uint32 smb_fflags,
4024 const uint32 smb_fmask,
4025 int *stat_fflags)
4027 uint32 max_fmask = 0;
4028 int i;
4030 *stat_fflags = psbuf->st_ex_flags;
4032 /* For each flags requested in smb_fmask, check the state of the
4033 * corresponding flag in smb_fflags and set or clear the matching
4034 * stat flag.
4037 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4038 max_fmask |= info2_flags_map[i].smb_fflag;
4039 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4040 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4041 *stat_fflags |= info2_flags_map[i].stat_fflag;
4042 } else {
4043 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4048 /* If smb_fmask is asking to set any bits that are not supported by
4049 * our flag mappings, we should fail.
4051 if ((smb_fmask & max_fmask) != smb_fmask) {
4052 return False;
4055 return True;
4059 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4060 * of file flags and birth (create) time.
4062 static char *store_file_unix_basic_info2(connection_struct *conn,
4063 char *pdata,
4064 files_struct *fsp,
4065 const SMB_STRUCT_STAT *psbuf)
4067 uint32 file_flags = 0;
4068 uint32 flags_mask = 0;
4070 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4072 /* Create (birth) time 64 bit */
4073 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4074 pdata += 8;
4076 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4077 SIVAL(pdata, 0, file_flags); /* flags */
4078 SIVAL(pdata, 4, flags_mask); /* mask */
4079 pdata += 8;
4081 return pdata;
4084 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4085 const struct stream_struct *streams,
4086 char *data,
4087 unsigned int max_data_bytes,
4088 unsigned int *data_size)
4090 unsigned int i;
4091 unsigned int ofs = 0;
4093 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4094 unsigned int next_offset;
4095 size_t namelen;
4096 smb_ucs2_t *namebuf;
4098 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4099 streams[i].name, &namelen) ||
4100 namelen <= 2)
4102 return NT_STATUS_INVALID_PARAMETER;
4106 * name_buf is now null-terminated, we need to marshall as not
4107 * terminated
4110 namelen -= 2;
4112 SIVAL(data, ofs+4, namelen);
4113 SOFF_T(data, ofs+8, streams[i].size);
4114 SOFF_T(data, ofs+16, streams[i].alloc_size);
4115 memcpy(data+ofs+24, namebuf, namelen);
4116 TALLOC_FREE(namebuf);
4118 next_offset = ofs + 24 + namelen;
4120 if (i == num_streams-1) {
4121 SIVAL(data, ofs, 0);
4123 else {
4124 unsigned int align = ndr_align_size(next_offset, 8);
4126 memset(data+next_offset, 0, align);
4127 next_offset += align;
4129 SIVAL(data, ofs, next_offset - ofs);
4130 ofs = next_offset;
4133 ofs = next_offset;
4136 *data_size = ofs;
4138 return NT_STATUS_OK;
4141 /****************************************************************************
4142 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4143 ****************************************************************************/
4145 static void call_trans2qpipeinfo(connection_struct *conn,
4146 struct smb_request *req,
4147 unsigned int tran_call,
4148 char **pparams, int total_params,
4149 char **ppdata, int total_data,
4150 unsigned int max_data_bytes)
4152 char *params = *pparams;
4153 char *pdata = *ppdata;
4154 unsigned int data_size = 0;
4155 unsigned int param_size = 2;
4156 uint16 info_level;
4157 files_struct *fsp;
4159 if (!params) {
4160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4161 return;
4164 if (total_params < 4) {
4165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4166 return;
4169 fsp = file_fsp(req, SVAL(params,0));
4170 if (!fsp_is_np(fsp)) {
4171 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4172 return;
4175 info_level = SVAL(params,2);
4177 *pparams = (char *)SMB_REALLOC(*pparams,2);
4178 if (*pparams == NULL) {
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4180 return;
4182 params = *pparams;
4183 SSVAL(params,0,0);
4184 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4185 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4186 if (*ppdata == NULL ) {
4187 reply_nterror(req, NT_STATUS_NO_MEMORY);
4188 return;
4190 pdata = *ppdata;
4192 switch (info_level) {
4193 case SMB_FILE_STANDARD_INFORMATION:
4194 memset(pdata,0,24);
4195 SOFF_T(pdata,0,4096LL);
4196 SIVAL(pdata,16,1);
4197 SIVAL(pdata,20,1);
4198 data_size = 24;
4199 break;
4201 default:
4202 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4203 return;
4206 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4207 max_data_bytes);
4209 return;
4212 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4213 TALLOC_CTX *mem_ctx,
4214 uint16_t info_level,
4215 files_struct *fsp,
4216 struct smb_filename *smb_fname,
4217 bool delete_pending,
4218 struct timespec write_time_ts,
4219 struct ea_list *ea_list,
4220 int lock_data_count,
4221 char *lock_data,
4222 uint16_t flags2,
4223 unsigned int max_data_bytes,
4224 char **ppdata,
4225 unsigned int *pdata_size)
4227 char *pdata = *ppdata;
4228 char *dstart, *dend;
4229 unsigned int data_size;
4230 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4231 time_t create_time, mtime, atime, c_time;
4232 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4233 char *p;
4234 char *base_name;
4235 char *dos_fname;
4236 int mode;
4237 int nlink;
4238 NTSTATUS status;
4239 uint64_t file_size = 0;
4240 uint64_t pos = 0;
4241 uint64_t allocation_size = 0;
4242 uint64_t file_index = 0;
4243 uint32_t access_mask = 0;
4245 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4246 return NT_STATUS_INVALID_LEVEL;
4249 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4250 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4251 info_level, max_data_bytes));
4253 mode = dos_mode(conn, smb_fname);
4254 nlink = psbuf->st_ex_nlink;
4256 if (nlink && (mode&aDIR)) {
4257 nlink = 1;
4260 if ((nlink > 0) && delete_pending) {
4261 nlink -= 1;
4264 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4265 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4266 if (*ppdata == NULL) {
4267 return NT_STATUS_NO_MEMORY;
4269 pdata = *ppdata;
4270 dstart = pdata;
4271 dend = dstart + data_size - 1;
4273 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4274 update_stat_ex_mtime(psbuf, write_time_ts);
4277 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4278 mtime_ts = psbuf->st_ex_mtime;
4279 atime_ts = psbuf->st_ex_atime;
4280 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4282 if (lp_dos_filetime_resolution(SNUM(conn))) {
4283 dos_filetime_timespec(&create_time_ts);
4284 dos_filetime_timespec(&mtime_ts);
4285 dos_filetime_timespec(&atime_ts);
4286 dos_filetime_timespec(&ctime_ts);
4289 create_time = convert_timespec_to_time_t(create_time_ts);
4290 mtime = convert_timespec_to_time_t(mtime_ts);
4291 atime = convert_timespec_to_time_t(atime_ts);
4292 c_time = convert_timespec_to_time_t(ctime_ts);
4294 p = strrchr_m(smb_fname->base_name,'/');
4295 if (!p)
4296 base_name = smb_fname->base_name;
4297 else
4298 base_name = p+1;
4300 /* NT expects the name to be in an exact form of the *full*
4301 filename. See the trans2 torture test */
4302 if (ISDOT(base_name)) {
4303 dos_fname = talloc_strdup(mem_ctx, "\\");
4304 if (!dos_fname) {
4305 return NT_STATUS_NO_MEMORY;
4307 } else {
4308 dos_fname = talloc_asprintf(mem_ctx,
4309 "\\%s",
4310 smb_fname->base_name);
4311 if (!dos_fname) {
4312 return NT_STATUS_NO_MEMORY;
4314 if (is_ntfs_stream_smb_fname(smb_fname)) {
4315 dos_fname = talloc_asprintf(dos_fname, "%s",
4316 smb_fname->stream_name);
4317 if (!dos_fname) {
4318 return NT_STATUS_NO_MEMORY;
4322 string_replace(dos_fname, '/', '\\');
4325 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4327 if (!fsp) {
4328 /* Do we have this path open ? */
4329 files_struct *fsp1;
4330 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4331 fsp1 = file_find_di_first(conn->sconn, fileid);
4332 if (fsp1 && fsp1->initial_allocation_size) {
4333 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4337 if (!(mode & aDIR)) {
4338 file_size = get_file_size_stat(psbuf);
4341 if (fsp) {
4342 pos = fsp->fh->position_information;
4345 if (fsp) {
4346 access_mask = fsp->access_mask;
4347 } else {
4348 /* GENERIC_EXECUTE mapping from Windows */
4349 access_mask = 0x12019F;
4352 /* This should be an index number - looks like
4353 dev/ino to me :-)
4355 I think this causes us to fail the IFSKIT
4356 BasicFileInformationTest. -tpot */
4357 file_index = get_FileIndex(conn, psbuf);
4359 switch (info_level) {
4360 case SMB_INFO_STANDARD:
4361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4362 data_size = 22;
4363 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4364 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4365 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4366 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4367 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4368 SSVAL(pdata,l1_attrFile,mode);
4369 break;
4371 case SMB_INFO_QUERY_EA_SIZE:
4373 unsigned int ea_size =
4374 estimate_ea_size(conn, fsp,
4375 smb_fname->base_name);
4376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4377 data_size = 26;
4378 srv_put_dos_date2(pdata,0,create_time);
4379 srv_put_dos_date2(pdata,4,atime);
4380 srv_put_dos_date2(pdata,8,mtime); /* write time */
4381 SIVAL(pdata,12,(uint32)file_size);
4382 SIVAL(pdata,16,(uint32)allocation_size);
4383 SSVAL(pdata,20,mode);
4384 SIVAL(pdata,22,ea_size);
4385 break;
4388 case SMB_INFO_IS_NAME_VALID:
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4390 if (fsp) {
4391 /* os/2 needs this ? really ?*/
4392 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4394 /* This is only reached for qpathinfo */
4395 data_size = 0;
4396 break;
4398 case SMB_INFO_QUERY_EAS_FROM_LIST:
4400 size_t total_ea_len = 0;
4401 struct ea_list *ea_file_list = NULL;
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4405 ea_file_list =
4406 get_ea_list_from_file(mem_ctx, conn, fsp,
4407 smb_fname->base_name,
4408 &total_ea_len);
4409 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4411 if (!ea_list || (total_ea_len > data_size)) {
4412 data_size = 4;
4413 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4414 break;
4417 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4418 break;
4421 case SMB_INFO_QUERY_ALL_EAS:
4423 /* We have data_size bytes to put EA's into. */
4424 size_t total_ea_len = 0;
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4428 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4429 smb_fname->base_name,
4430 &total_ea_len);
4431 if (!ea_list || (total_ea_len > data_size)) {
4432 data_size = 4;
4433 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4434 break;
4437 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4438 break;
4441 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4443 /* This is FileFullEaInformation - 0xF which maps to
4444 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4446 /* We have data_size bytes to put EA's into. */
4447 size_t total_ea_len = 0;
4448 struct ea_list *ea_file_list = NULL;
4450 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4452 /*TODO: add filtering and index handling */
4454 ea_file_list =
4455 get_ea_list_from_file(mem_ctx, conn, fsp,
4456 smb_fname->base_name,
4457 &total_ea_len);
4458 if (!ea_file_list) {
4459 return NT_STATUS_NO_EAS_ON_FILE;
4462 status = fill_ea_chained_buffer(mem_ctx,
4463 pdata,
4464 data_size,
4465 &data_size,
4466 conn, ea_file_list);
4467 if (!NT_STATUS_IS_OK(status)) {
4468 return status;
4470 break;
4473 case SMB_FILE_BASIC_INFORMATION:
4474 case SMB_QUERY_FILE_BASIC_INFO:
4476 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4478 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4479 } else {
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4481 data_size = 40;
4482 SIVAL(pdata,36,0);
4484 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4485 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4486 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4487 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4488 SIVAL(pdata,32,mode);
4490 DEBUG(5,("SMB_QFBI - "));
4491 DEBUG(5,("create: %s ", ctime(&create_time)));
4492 DEBUG(5,("access: %s ", ctime(&atime)));
4493 DEBUG(5,("write: %s ", ctime(&mtime)));
4494 DEBUG(5,("change: %s ", ctime(&c_time)));
4495 DEBUG(5,("mode: %x\n", mode));
4496 break;
4498 case SMB_FILE_STANDARD_INFORMATION:
4499 case SMB_QUERY_FILE_STANDARD_INFO:
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4502 data_size = 24;
4503 SOFF_T(pdata,0,allocation_size);
4504 SOFF_T(pdata,8,file_size);
4505 SIVAL(pdata,16,nlink);
4506 SCVAL(pdata,20,delete_pending?1:0);
4507 SCVAL(pdata,21,(mode&aDIR)?1:0);
4508 SSVAL(pdata,22,0); /* Padding. */
4509 break;
4511 case SMB_FILE_EA_INFORMATION:
4512 case SMB_QUERY_FILE_EA_INFO:
4514 unsigned int ea_size =
4515 estimate_ea_size(conn, fsp, smb_fname->base_name);
4516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4517 data_size = 4;
4518 SIVAL(pdata,0,ea_size);
4519 break;
4522 /* Get the 8.3 name - used if NT SMB was negotiated. */
4523 case SMB_QUERY_FILE_ALT_NAME_INFO:
4524 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4526 int len;
4527 char mangled_name[13];
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4529 if (!name_to_8_3(base_name,mangled_name,
4530 True,conn->params)) {
4531 return NT_STATUS_NO_MEMORY;
4533 len = srvstr_push(dstart, flags2,
4534 pdata+4, mangled_name,
4535 PTR_DIFF(dend, pdata+4),
4536 STR_UNICODE);
4537 data_size = 4 + len;
4538 SIVAL(pdata,0,len);
4539 break;
4542 case SMB_QUERY_FILE_NAME_INFO:
4544 int len;
4546 this must be *exactly* right for ACLs on mapped drives to work
4548 len = srvstr_push(dstart, flags2,
4549 pdata+4, dos_fname,
4550 PTR_DIFF(dend, pdata+4),
4551 STR_UNICODE);
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4553 data_size = 4 + len;
4554 SIVAL(pdata,0,len);
4555 break;
4558 case SMB_FILE_ALLOCATION_INFORMATION:
4559 case SMB_QUERY_FILE_ALLOCATION_INFO:
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4561 data_size = 8;
4562 SOFF_T(pdata,0,allocation_size);
4563 break;
4565 case SMB_FILE_END_OF_FILE_INFORMATION:
4566 case SMB_QUERY_FILE_END_OF_FILEINFO:
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4568 data_size = 8;
4569 SOFF_T(pdata,0,file_size);
4570 break;
4572 case SMB_QUERY_FILE_ALL_INFO:
4573 case SMB_FILE_ALL_INFORMATION:
4575 int len;
4576 unsigned int ea_size =
4577 estimate_ea_size(conn, fsp, smb_fname->base_name);
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4579 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4580 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4581 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4582 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4583 SIVAL(pdata,32,mode);
4584 SIVAL(pdata,36,0); /* padding. */
4585 pdata += 40;
4586 SOFF_T(pdata,0,allocation_size);
4587 SOFF_T(pdata,8,file_size);
4588 SIVAL(pdata,16,nlink);
4589 SCVAL(pdata,20,delete_pending);
4590 SCVAL(pdata,21,(mode&aDIR)?1:0);
4591 SSVAL(pdata,22,0);
4592 pdata += 24;
4593 SIVAL(pdata,0,ea_size);
4594 pdata += 4; /* EA info */
4595 len = srvstr_push(dstart, flags2,
4596 pdata+4, dos_fname,
4597 PTR_DIFF(dend, pdata+4),
4598 STR_UNICODE);
4599 SIVAL(pdata,0,len);
4600 pdata += 4 + len;
4601 data_size = PTR_DIFF(pdata,(*ppdata));
4602 break;
4605 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4607 int len;
4608 unsigned int ea_size =
4609 estimate_ea_size(conn, fsp, smb_fname->base_name);
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4611 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4612 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4613 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4614 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4615 SIVAL(pdata, 0x20, mode);
4616 SIVAL(pdata, 0x24, 0); /* padding. */
4617 SBVAL(pdata, 0x28, allocation_size);
4618 SBVAL(pdata, 0x30, file_size);
4619 SIVAL(pdata, 0x38, nlink);
4620 SCVAL(pdata, 0x3C, delete_pending);
4621 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4622 SSVAL(pdata, 0x3E, 0); /* padding */
4623 SBVAL(pdata, 0x40, file_index);
4624 SIVAL(pdata, 0x48, ea_size);
4625 SIVAL(pdata, 0x4C, access_mask);
4626 SBVAL(pdata, 0x50, pos);
4627 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4628 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4630 pdata += 0x60;
4632 len = srvstr_push(dstart, flags2,
4633 pdata+4, dos_fname,
4634 PTR_DIFF(dend, pdata+4),
4635 STR_UNICODE);
4636 SIVAL(pdata,0,len);
4637 pdata += 4 + len;
4638 data_size = PTR_DIFF(pdata,(*ppdata));
4639 break;
4641 case SMB_FILE_INTERNAL_INFORMATION:
4643 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4644 SBVAL(pdata, 0, file_index);
4645 data_size = 8;
4646 break;
4648 case SMB_FILE_ACCESS_INFORMATION:
4649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4650 SIVAL(pdata, 0, access_mask);
4651 data_size = 4;
4652 break;
4654 case SMB_FILE_NAME_INFORMATION:
4655 /* Pathname with leading '\'. */
4657 size_t byte_len;
4658 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4660 SIVAL(pdata,0,byte_len);
4661 data_size = 4 + byte_len;
4662 break;
4665 case SMB_FILE_DISPOSITION_INFORMATION:
4666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4667 data_size = 1;
4668 SCVAL(pdata,0,delete_pending);
4669 break;
4671 case SMB_FILE_POSITION_INFORMATION:
4672 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4673 data_size = 8;
4674 SOFF_T(pdata,0,pos);
4675 break;
4677 case SMB_FILE_MODE_INFORMATION:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4679 SIVAL(pdata,0,mode);
4680 data_size = 4;
4681 break;
4683 case SMB_FILE_ALIGNMENT_INFORMATION:
4684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4685 SIVAL(pdata,0,0); /* No alignment needed. */
4686 data_size = 4;
4687 break;
4690 * NT4 server just returns "invalid query" to this - if we try
4691 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4692 * want this. JRA.
4694 /* The first statement above is false - verified using Thursby
4695 * client against NT4 -- gcolley.
4697 case SMB_QUERY_FILE_STREAM_INFO:
4698 case SMB_FILE_STREAM_INFORMATION: {
4699 unsigned int num_streams;
4700 struct stream_struct *streams;
4702 DEBUG(10,("smbd_do_qfilepathinfo: "
4703 "SMB_FILE_STREAM_INFORMATION\n"));
4705 if (is_ntfs_stream_smb_fname(smb_fname)) {
4706 return NT_STATUS_INVALID_PARAMETER;
4709 status = SMB_VFS_STREAMINFO(
4710 conn, fsp, smb_fname->base_name, talloc_tos(),
4711 &num_streams, &streams);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 DEBUG(10, ("could not get stream info: %s\n",
4715 nt_errstr(status)));
4716 return status;
4719 status = marshall_stream_info(num_streams, streams,
4720 pdata, max_data_bytes,
4721 &data_size);
4723 if (!NT_STATUS_IS_OK(status)) {
4724 DEBUG(10, ("marshall_stream_info failed: %s\n",
4725 nt_errstr(status)));
4726 return status;
4729 TALLOC_FREE(streams);
4731 break;
4733 case SMB_QUERY_COMPRESSION_INFO:
4734 case SMB_FILE_COMPRESSION_INFORMATION:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4736 SOFF_T(pdata,0,file_size);
4737 SIVAL(pdata,8,0); /* ??? */
4738 SIVAL(pdata,12,0); /* ??? */
4739 data_size = 16;
4740 break;
4742 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4744 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4745 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4746 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4747 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4748 SOFF_T(pdata,32,allocation_size);
4749 SOFF_T(pdata,40,file_size);
4750 SIVAL(pdata,48,mode);
4751 SIVAL(pdata,52,0); /* ??? */
4752 data_size = 56;
4753 break;
4755 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4757 SIVAL(pdata,0,mode);
4758 SIVAL(pdata,4,0);
4759 data_size = 8;
4760 break;
4763 * CIFS UNIX Extensions.
4766 case SMB_QUERY_FILE_UNIX_BASIC:
4768 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4769 data_size = PTR_DIFF(pdata,(*ppdata));
4771 DEBUG(4,("smbd_do_qfilepathinfo: "
4772 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4773 dump_data(4, (uint8_t *)(*ppdata), data_size);
4775 break;
4777 case SMB_QUERY_FILE_UNIX_INFO2:
4779 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4780 data_size = PTR_DIFF(pdata,(*ppdata));
4783 int i;
4784 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4786 for (i=0; i<100; i++)
4787 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4788 DEBUG(4,("\n"));
4791 break;
4793 case SMB_QUERY_FILE_UNIX_LINK:
4795 int len;
4796 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4798 if (!buffer) {
4799 return NT_STATUS_NO_MEMORY;
4802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4803 #ifdef S_ISLNK
4804 if(!S_ISLNK(psbuf->st_ex_mode)) {
4805 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4807 #else
4808 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4809 #endif
4810 len = SMB_VFS_READLINK(conn,
4811 smb_fname->base_name,
4812 buffer, PATH_MAX);
4813 if (len == -1) {
4814 return map_nt_error_from_unix(errno);
4816 buffer[len] = 0;
4817 len = srvstr_push(dstart, flags2,
4818 pdata, buffer,
4819 PTR_DIFF(dend, pdata),
4820 STR_TERMINATE);
4821 pdata += len;
4822 data_size = PTR_DIFF(pdata,(*ppdata));
4824 break;
4827 #if defined(HAVE_POSIX_ACLS)
4828 case SMB_QUERY_POSIX_ACL:
4830 SMB_ACL_T file_acl = NULL;
4831 SMB_ACL_T def_acl = NULL;
4832 uint16 num_file_acls = 0;
4833 uint16 num_def_acls = 0;
4835 if (fsp && fsp->fh->fd != -1) {
4836 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4837 } else {
4838 file_acl =
4839 SMB_VFS_SYS_ACL_GET_FILE(conn,
4840 smb_fname->base_name,
4841 SMB_ACL_TYPE_ACCESS);
4844 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4845 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4846 "not implemented on "
4847 "filesystem containing %s\n",
4848 smb_fname->base_name));
4849 return NT_STATUS_NOT_IMPLEMENTED;
4852 if (S_ISDIR(psbuf->st_ex_mode)) {
4853 if (fsp && fsp->is_directory) {
4854 def_acl =
4855 SMB_VFS_SYS_ACL_GET_FILE(
4856 conn,
4857 fsp->fsp_name->base_name,
4858 SMB_ACL_TYPE_DEFAULT);
4859 } else {
4860 def_acl =
4861 SMB_VFS_SYS_ACL_GET_FILE(
4862 conn,
4863 smb_fname->base_name,
4864 SMB_ACL_TYPE_DEFAULT);
4866 def_acl = free_empty_sys_acl(conn, def_acl);
4869 num_file_acls = count_acl_entries(conn, file_acl);
4870 num_def_acls = count_acl_entries(conn, def_acl);
4872 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4873 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4874 data_size,
4875 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4876 SMB_POSIX_ACL_HEADER_SIZE) ));
4877 if (file_acl) {
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4880 if (def_acl) {
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4883 return NT_STATUS_BUFFER_TOO_SMALL;
4886 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4887 SSVAL(pdata,2,num_file_acls);
4888 SSVAL(pdata,4,num_def_acls);
4889 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4890 if (file_acl) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4893 if (def_acl) {
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4896 return NT_STATUS_INTERNAL_ERROR;
4898 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4899 if (file_acl) {
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4902 if (def_acl) {
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4905 return NT_STATUS_INTERNAL_ERROR;
4908 if (file_acl) {
4909 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4911 if (def_acl) {
4912 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4914 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4915 break;
4917 #endif
4920 case SMB_QUERY_POSIX_LOCK:
4922 uint64_t count;
4923 uint64_t offset;
4924 uint64_t smblctx;
4925 enum brl_type lock_type;
4927 /* We need an open file with a real fd for this. */
4928 if (!fsp || fsp->fh->fd == -1) {
4929 return NT_STATUS_INVALID_LEVEL;
4932 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4937 case POSIX_LOCK_TYPE_READ:
4938 lock_type = READ_LOCK;
4939 break;
4940 case POSIX_LOCK_TYPE_WRITE:
4941 lock_type = WRITE_LOCK;
4942 break;
4943 case POSIX_LOCK_TYPE_UNLOCK:
4944 default:
4945 /* There's no point in asking for an unlock... */
4946 return NT_STATUS_INVALID_PARAMETER;
4949 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4950 #if defined(HAVE_LONGLONG)
4951 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4952 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4953 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4954 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4955 #else /* HAVE_LONGLONG */
4956 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4957 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4958 #endif /* HAVE_LONGLONG */
4960 status = query_lock(fsp,
4961 &smblctx,
4962 &count,
4963 &offset,
4964 &lock_type,
4965 POSIX_LOCK);
4967 if (ERROR_WAS_LOCK_DENIED(status)) {
4968 /* Here we need to report who has it locked... */
4969 data_size = POSIX_LOCK_DATA_SIZE;
4971 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4972 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4973 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4974 #if defined(HAVE_LONGLONG)
4975 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4976 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4977 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4978 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4979 #else /* HAVE_LONGLONG */
4980 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4981 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4982 #endif /* HAVE_LONGLONG */
4984 } else if (NT_STATUS_IS_OK(status)) {
4985 /* For success we just return a copy of what we sent
4986 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4987 data_size = POSIX_LOCK_DATA_SIZE;
4988 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4989 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4990 } else {
4991 return status;
4993 break;
4996 default:
4997 return NT_STATUS_INVALID_LEVEL;
5000 *pdata_size = data_size;
5001 return NT_STATUS_OK;
5004 /****************************************************************************
5005 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5006 file name or file id).
5007 ****************************************************************************/
5009 static void call_trans2qfilepathinfo(connection_struct *conn,
5010 struct smb_request *req,
5011 unsigned int tran_call,
5012 char **pparams, int total_params,
5013 char **ppdata, int total_data,
5014 unsigned int max_data_bytes)
5016 char *params = *pparams;
5017 char *pdata = *ppdata;
5018 uint16 info_level;
5019 unsigned int data_size = 0;
5020 unsigned int param_size = 2;
5021 struct smb_filename *smb_fname = NULL;
5022 bool delete_pending = False;
5023 struct timespec write_time_ts;
5024 files_struct *fsp = NULL;
5025 struct file_id fileid;
5026 struct ea_list *ea_list = NULL;
5027 int lock_data_count = 0;
5028 char *lock_data = NULL;
5029 NTSTATUS status = NT_STATUS_OK;
5031 if (!params) {
5032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033 return;
5036 ZERO_STRUCT(write_time_ts);
5038 if (tran_call == TRANSACT2_QFILEINFO) {
5039 if (total_params < 4) {
5040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5041 return;
5044 if (IS_IPC(conn)) {
5045 call_trans2qpipeinfo(conn, req, tran_call,
5046 pparams, total_params,
5047 ppdata, total_data,
5048 max_data_bytes);
5049 return;
5052 fsp = file_fsp(req, SVAL(params,0));
5053 info_level = SVAL(params,2);
5055 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5057 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5059 return;
5062 /* Initial check for valid fsp ptr. */
5063 if (!check_fsp_open(conn, req, fsp)) {
5064 return;
5067 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5068 &smb_fname);
5069 if (!NT_STATUS_IS_OK(status)) {
5070 reply_nterror(req, status);
5071 return;
5074 if(fsp->fake_file_handle) {
5076 * This is actually for the QUOTA_FAKE_FILE --metze
5079 /* We know this name is ok, it's already passed the checks. */
5081 } else if(fsp->fh->fd == -1) {
5083 * This is actually a QFILEINFO on a directory
5084 * handle (returned from an NT SMB). NT5.0 seems
5085 * to do this call. JRA.
5088 if (INFO_LEVEL_IS_UNIX(info_level)) {
5089 /* Always do lstat for UNIX calls. */
5090 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5091 DEBUG(3,("call_trans2qfilepathinfo: "
5092 "SMB_VFS_LSTAT of %s failed "
5093 "(%s)\n",
5094 smb_fname_str_dbg(smb_fname),
5095 strerror(errno)));
5096 reply_nterror(req,
5097 map_nt_error_from_unix(errno));
5098 return;
5100 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5101 DEBUG(3,("call_trans2qfilepathinfo: "
5102 "SMB_VFS_STAT of %s failed (%s)\n",
5103 smb_fname_str_dbg(smb_fname),
5104 strerror(errno)));
5105 reply_nterror(req,
5106 map_nt_error_from_unix(errno));
5107 return;
5110 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5111 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5112 } else {
5114 * Original code - this is an open file.
5116 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5117 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5118 fsp->fnum, strerror(errno)));
5119 reply_nterror(req,
5120 map_nt_error_from_unix(errno));
5121 return;
5123 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5124 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5127 } else {
5128 uint32_t name_hash;
5129 char *fname = NULL;
5131 /* qpathinfo */
5132 if (total_params < 7) {
5133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5134 return;
5137 info_level = SVAL(params,0);
5139 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5141 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5142 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5143 return;
5146 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5147 total_params - 6,
5148 STR_TERMINATE, &status);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 reply_nterror(req, status);
5151 return;
5154 status = filename_convert(req,
5155 conn,
5156 req->flags2 & FLAGS2_DFS_PATHNAMES,
5157 fname,
5159 NULL,
5160 &smb_fname);
5161 if (!NT_STATUS_IS_OK(status)) {
5162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5163 reply_botherror(req,
5164 NT_STATUS_PATH_NOT_COVERED,
5165 ERRSRV, ERRbadpath);
5166 return;
5168 reply_nterror(req, status);
5169 return;
5172 /* If this is a stream, check if there is a delete_pending. */
5173 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5174 && is_ntfs_stream_smb_fname(smb_fname)) {
5175 struct smb_filename *smb_fname_base = NULL;
5177 /* Create an smb_filename with stream_name == NULL. */
5178 status =
5179 create_synthetic_smb_fname(talloc_tos(),
5180 smb_fname->base_name,
5181 NULL, NULL,
5182 &smb_fname_base);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 reply_nterror(req, status);
5185 return;
5188 if (INFO_LEVEL_IS_UNIX(info_level)) {
5189 /* Always do lstat for UNIX calls. */
5190 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5191 DEBUG(3,("call_trans2qfilepathinfo: "
5192 "SMB_VFS_LSTAT of %s failed "
5193 "(%s)\n",
5194 smb_fname_str_dbg(smb_fname_base),
5195 strerror(errno)));
5196 TALLOC_FREE(smb_fname_base);
5197 reply_nterror(req,
5198 map_nt_error_from_unix(errno));
5199 return;
5201 } else {
5202 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "fileinfo of %s failed "
5205 "(%s)\n",
5206 smb_fname_str_dbg(smb_fname_base),
5207 strerror(errno)));
5208 TALLOC_FREE(smb_fname_base);
5209 reply_nterror(req,
5210 map_nt_error_from_unix(errno));
5211 return;
5215 status = file_name_hash(conn,
5216 smb_fname_str_dbg(smb_fname_base),
5217 &name_hash);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 TALLOC_FREE(smb_fname_base);
5220 reply_nterror(req, status);
5221 return;
5224 fileid = vfs_file_id_from_sbuf(conn,
5225 &smb_fname_base->st);
5226 TALLOC_FREE(smb_fname_base);
5227 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5228 if (delete_pending) {
5229 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5230 return;
5234 if (INFO_LEVEL_IS_UNIX(info_level)) {
5235 /* Always do lstat for UNIX calls. */
5236 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5237 DEBUG(3,("call_trans2qfilepathinfo: "
5238 "SMB_VFS_LSTAT of %s failed (%s)\n",
5239 smb_fname_str_dbg(smb_fname),
5240 strerror(errno)));
5241 reply_nterror(req,
5242 map_nt_error_from_unix(errno));
5243 return;
5246 } else {
5247 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "SMB_VFS_STAT of %s failed (%s)\n",
5250 smb_fname_str_dbg(smb_fname),
5251 strerror(errno)));
5252 reply_nterror(req,
5253 map_nt_error_from_unix(errno));
5254 return;
5258 status = file_name_hash(conn,
5259 smb_fname_str_dbg(smb_fname),
5260 &name_hash);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 reply_nterror(req, status);
5263 return;
5266 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5267 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5268 if (delete_pending) {
5269 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5270 return;
5274 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5275 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5276 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5278 /* Pull out any data sent here before we realloc. */
5279 switch (info_level) {
5280 case SMB_INFO_QUERY_EAS_FROM_LIST:
5282 /* Pull any EA list from the data portion. */
5283 uint32 ea_size;
5285 if (total_data < 4) {
5286 reply_nterror(
5287 req, NT_STATUS_INVALID_PARAMETER);
5288 return;
5290 ea_size = IVAL(pdata,0);
5292 if (total_data > 0 && ea_size != total_data) {
5293 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5294 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5295 reply_nterror(
5296 req, NT_STATUS_INVALID_PARAMETER);
5297 return;
5300 if (!lp_ea_support(SNUM(conn))) {
5301 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5302 return;
5305 /* Pull out the list of names. */
5306 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5307 if (!ea_list) {
5308 reply_nterror(
5309 req, NT_STATUS_INVALID_PARAMETER);
5310 return;
5312 break;
5315 case SMB_QUERY_POSIX_LOCK:
5317 if (fsp == NULL || fsp->fh->fd == -1) {
5318 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5319 return;
5322 if (total_data != POSIX_LOCK_DATA_SIZE) {
5323 reply_nterror(
5324 req, NT_STATUS_INVALID_PARAMETER);
5325 return;
5328 /* Copy the lock range data. */
5329 lock_data = (char *)TALLOC_MEMDUP(
5330 req, pdata, total_data);
5331 if (!lock_data) {
5332 reply_nterror(req, NT_STATUS_NO_MEMORY);
5333 return;
5335 lock_data_count = total_data;
5337 default:
5338 break;
5341 *pparams = (char *)SMB_REALLOC(*pparams,2);
5342 if (*pparams == NULL) {
5343 reply_nterror(req, NT_STATUS_NO_MEMORY);
5344 return;
5346 params = *pparams;
5347 SSVAL(params,0,0);
5350 * draft-leach-cifs-v1-spec-02.txt
5351 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5352 * says:
5354 * The requested information is placed in the Data portion of the
5355 * transaction response. For the information levels greater than 0x100,
5356 * the transaction response has 1 parameter word which should be
5357 * ignored by the client.
5359 * However Windows only follows this rule for the IS_NAME_VALID call.
5361 switch (info_level) {
5362 case SMB_INFO_IS_NAME_VALID:
5363 param_size = 0;
5364 break;
5367 if ((info_level & 0xFF00) == 0xFF00) {
5369 * We use levels that start with 0xFF00
5370 * internally to represent SMB2 specific levels
5372 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5373 return;
5376 status = smbd_do_qfilepathinfo(conn, req, info_level,
5377 fsp, smb_fname,
5378 delete_pending, write_time_ts,
5379 ea_list,
5380 lock_data_count, lock_data,
5381 req->flags2, max_data_bytes,
5382 ppdata, &data_size);
5383 if (!NT_STATUS_IS_OK(status)) {
5384 reply_nterror(req, status);
5385 return;
5388 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5389 max_data_bytes);
5391 return;
5394 /****************************************************************************
5395 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5396 code.
5397 ****************************************************************************/
5399 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5400 connection_struct *conn,
5401 struct smb_request *req,
5402 bool overwrite_if_exists,
5403 const struct smb_filename *smb_fname_old,
5404 struct smb_filename *smb_fname_new)
5406 NTSTATUS status = NT_STATUS_OK;
5408 /* source must already exist. */
5409 if (!VALID_STAT(smb_fname_old->st)) {
5410 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5413 if (VALID_STAT(smb_fname_new->st)) {
5414 if (overwrite_if_exists) {
5415 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5416 return NT_STATUS_FILE_IS_A_DIRECTORY;
5418 status = unlink_internals(conn,
5419 req,
5420 FILE_ATTRIBUTE_NORMAL,
5421 smb_fname_new,
5422 false);
5423 if (!NT_STATUS_IS_OK(status)) {
5424 return status;
5426 } else {
5427 /* Disallow if newname already exists. */
5428 return NT_STATUS_OBJECT_NAME_COLLISION;
5432 /* No links from a directory. */
5433 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5434 return NT_STATUS_FILE_IS_A_DIRECTORY;
5437 /* Setting a hardlink to/from a stream isn't currently supported. */
5438 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5439 is_ntfs_stream_smb_fname(smb_fname_new)) {
5440 return NT_STATUS_INVALID_PARAMETER;
5443 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5444 smb_fname_old->base_name, smb_fname_new->base_name));
5446 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5447 smb_fname_new->base_name) != 0) {
5448 status = map_nt_error_from_unix(errno);
5449 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5450 nt_errstr(status), smb_fname_old->base_name,
5451 smb_fname_new->base_name));
5453 return status;
5456 /****************************************************************************
5457 Deal with setting the time from any of the setfilepathinfo functions.
5458 ****************************************************************************/
5460 NTSTATUS smb_set_file_time(connection_struct *conn,
5461 files_struct *fsp,
5462 const struct smb_filename *smb_fname,
5463 struct smb_file_time *ft,
5464 bool setting_write_time)
5466 struct smb_filename smb_fname_base;
5467 uint32 action =
5468 FILE_NOTIFY_CHANGE_LAST_ACCESS
5469 |FILE_NOTIFY_CHANGE_LAST_WRITE
5470 |FILE_NOTIFY_CHANGE_CREATION;
5472 if (!VALID_STAT(smb_fname->st)) {
5473 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5476 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5477 return NT_STATUS_ACCESS_DENIED;
5480 /* get some defaults (no modifications) if any info is zero or -1. */
5481 if (null_timespec(ft->create_time)) {
5482 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5485 if (null_timespec(ft->atime)) {
5486 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5489 if (null_timespec(ft->mtime)) {
5490 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5493 if (!setting_write_time) {
5494 /* ft->mtime comes from change time, not write time. */
5495 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5498 /* Ensure the resolution is the correct for
5499 * what we can store on this filesystem. */
5501 round_timespec(conn->ts_res, &ft->create_time);
5502 round_timespec(conn->ts_res, &ft->ctime);
5503 round_timespec(conn->ts_res, &ft->atime);
5504 round_timespec(conn->ts_res, &ft->mtime);
5506 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5507 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5508 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5509 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5510 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5511 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5512 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5513 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5515 if (setting_write_time) {
5517 * This was a Windows setfileinfo on an open file.
5518 * NT does this a lot. We also need to
5519 * set the time here, as it can be read by
5520 * FindFirst/FindNext and with the patch for bug #2045
5521 * in smbd/fileio.c it ensures that this timestamp is
5522 * kept sticky even after a write. We save the request
5523 * away and will set it on file close and after a write. JRA.
5526 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5527 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5529 if (fsp != NULL) {
5530 if (fsp->base_fsp) {
5531 set_sticky_write_time_fsp(fsp->base_fsp,
5532 ft->mtime);
5533 } else {
5534 set_sticky_write_time_fsp(fsp, ft->mtime);
5536 } else {
5537 set_sticky_write_time_path(
5538 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5539 ft->mtime);
5543 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5545 /* Always call ntimes on the base, even if a stream was passed in. */
5546 smb_fname_base = *smb_fname;
5547 smb_fname_base.stream_name = NULL;
5549 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5550 return map_nt_error_from_unix(errno);
5553 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5554 smb_fname->base_name);
5555 return NT_STATUS_OK;
5558 /****************************************************************************
5559 Deal with setting the dosmode from any of the setfilepathinfo functions.
5560 ****************************************************************************/
5562 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5563 const struct smb_filename *smb_fname,
5564 uint32 dosmode)
5566 struct smb_filename *smb_fname_base = NULL;
5567 NTSTATUS status;
5569 if (!VALID_STAT(smb_fname->st)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5573 /* Always operate on the base_name, even if a stream was passed in. */
5574 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5575 NULL, &smb_fname->st,
5576 &smb_fname_base);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 return status;
5581 if (dosmode) {
5582 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5583 dosmode |= aDIR;
5584 } else {
5585 dosmode &= ~aDIR;
5589 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5591 /* check the mode isn't different, before changing it */
5592 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5593 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5594 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5595 (unsigned int)dosmode));
5597 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5598 false)) {
5599 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5600 "%s failed (%s)\n",
5601 smb_fname_str_dbg(smb_fname_base),
5602 strerror(errno)));
5603 status = map_nt_error_from_unix(errno);
5604 goto out;
5607 status = NT_STATUS_OK;
5608 out:
5609 TALLOC_FREE(smb_fname_base);
5610 return status;
5613 /****************************************************************************
5614 Deal with setting the size from any of the setfilepathinfo functions.
5615 ****************************************************************************/
5617 static NTSTATUS smb_set_file_size(connection_struct *conn,
5618 struct smb_request *req,
5619 files_struct *fsp,
5620 const struct smb_filename *smb_fname,
5621 const SMB_STRUCT_STAT *psbuf,
5622 SMB_OFF_T size,
5623 bool fail_after_createfile)
5625 NTSTATUS status = NT_STATUS_OK;
5626 struct smb_filename *smb_fname_tmp = NULL;
5627 files_struct *new_fsp = NULL;
5629 if (!VALID_STAT(*psbuf)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5633 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5634 return NT_STATUS_ACCESS_DENIED;
5637 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5639 if (size == get_file_size_stat(psbuf)) {
5640 return NT_STATUS_OK;
5643 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5644 smb_fname_str_dbg(smb_fname), (double)size));
5646 if (fsp && fsp->fh->fd != -1) {
5647 /* Handle based call. */
5648 if (vfs_set_filelen(fsp, size) == -1) {
5649 return map_nt_error_from_unix(errno);
5651 trigger_write_time_update_immediate(fsp);
5652 return NT_STATUS_OK;
5655 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 return status;
5660 smb_fname_tmp->st = *psbuf;
5662 status = SMB_VFS_CREATE_FILE(
5663 conn, /* conn */
5664 req, /* req */
5665 0, /* root_dir_fid */
5666 smb_fname_tmp, /* fname */
5667 FILE_WRITE_DATA, /* access_mask */
5668 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5669 FILE_SHARE_DELETE),
5670 FILE_OPEN, /* create_disposition*/
5671 0, /* create_options */
5672 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5673 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5674 0, /* allocation_size */
5675 0, /* private_flags */
5676 NULL, /* sd */
5677 NULL, /* ea_list */
5678 &new_fsp, /* result */
5679 NULL); /* pinfo */
5681 TALLOC_FREE(smb_fname_tmp);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 /* NB. We check for open_was_deferred in the caller. */
5685 return status;
5688 /* See RAW-SFILEINFO-END-OF-FILE */
5689 if (fail_after_createfile) {
5690 close_file(req, new_fsp,NORMAL_CLOSE);
5691 return NT_STATUS_INVALID_LEVEL;
5694 if (vfs_set_filelen(new_fsp, size) == -1) {
5695 status = map_nt_error_from_unix(errno);
5696 close_file(req, new_fsp,NORMAL_CLOSE);
5697 return status;
5700 trigger_write_time_update_immediate(new_fsp);
5701 close_file(req, new_fsp,NORMAL_CLOSE);
5702 return NT_STATUS_OK;
5705 /****************************************************************************
5706 Deal with SMB_INFO_SET_EA.
5707 ****************************************************************************/
5709 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5710 const char *pdata,
5711 int total_data,
5712 files_struct *fsp,
5713 const struct smb_filename *smb_fname)
5715 struct ea_list *ea_list = NULL;
5716 TALLOC_CTX *ctx = NULL;
5717 NTSTATUS status = NT_STATUS_OK;
5719 if (total_data < 10) {
5721 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5722 length. They seem to have no effect. Bug #3212. JRA */
5724 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5725 /* We're done. We only get EA info in this call. */
5726 return NT_STATUS_OK;
5729 return NT_STATUS_INVALID_PARAMETER;
5732 if (IVAL(pdata,0) > total_data) {
5733 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5734 IVAL(pdata,0), (unsigned int)total_data));
5735 return NT_STATUS_INVALID_PARAMETER;
5738 ctx = talloc_tos();
5739 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5740 if (!ea_list) {
5741 return NT_STATUS_INVALID_PARAMETER;
5744 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5745 return NT_STATUS_ACCESS_DENIED;
5748 status = set_ea(conn, fsp, smb_fname, ea_list);
5750 return status;
5753 /****************************************************************************
5754 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5755 ****************************************************************************/
5757 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5758 const char *pdata,
5759 int total_data,
5760 files_struct *fsp)
5762 struct ea_list *ea_list = NULL;
5763 NTSTATUS status;
5765 if (!fsp) {
5766 return NT_STATUS_INVALID_HANDLE;
5769 if (!lp_ea_support(SNUM(conn))) {
5770 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5771 "EA's not supported.\n",
5772 (unsigned int)total_data));
5773 return NT_STATUS_EAS_NOT_SUPPORTED;
5776 if (total_data < 10) {
5777 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5778 "too small.\n",
5779 (unsigned int)total_data));
5780 return NT_STATUS_INVALID_PARAMETER;
5783 ea_list = read_nttrans_ea_list(talloc_tos(),
5784 pdata,
5785 total_data);
5787 if (!ea_list) {
5788 return NT_STATUS_INVALID_PARAMETER;
5791 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5792 return NT_STATUS_ACCESS_DENIED;
5795 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5797 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5798 smb_fname_str_dbg(fsp->fsp_name),
5799 nt_errstr(status) ));
5801 return status;
5805 /****************************************************************************
5806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5807 ****************************************************************************/
5809 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5810 const char *pdata,
5811 int total_data,
5812 files_struct *fsp,
5813 struct smb_filename *smb_fname)
5815 NTSTATUS status = NT_STATUS_OK;
5816 bool delete_on_close;
5817 uint32 dosmode = 0;
5819 if (total_data < 1) {
5820 return NT_STATUS_INVALID_PARAMETER;
5823 if (fsp == NULL) {
5824 return NT_STATUS_INVALID_HANDLE;
5827 delete_on_close = (CVAL(pdata,0) ? True : False);
5828 dosmode = dos_mode(conn, smb_fname);
5830 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5831 "delete_on_close = %u\n",
5832 smb_fname_str_dbg(smb_fname),
5833 (unsigned int)dosmode,
5834 (unsigned int)delete_on_close ));
5836 if (delete_on_close) {
5837 status = can_set_delete_on_close(fsp, dosmode);
5838 if (!NT_STATUS_IS_OK(status)) {
5839 return status;
5843 /* The set is across all open files on this dev/inode pair. */
5844 if (!set_delete_on_close(fsp, delete_on_close,
5845 &conn->session_info->utok)) {
5846 return NT_STATUS_ACCESS_DENIED;
5848 return NT_STATUS_OK;
5851 /****************************************************************************
5852 Deal with SMB_FILE_POSITION_INFORMATION.
5853 ****************************************************************************/
5855 static NTSTATUS smb_file_position_information(connection_struct *conn,
5856 const char *pdata,
5857 int total_data,
5858 files_struct *fsp)
5860 uint64_t position_information;
5862 if (total_data < 8) {
5863 return NT_STATUS_INVALID_PARAMETER;
5866 if (fsp == NULL) {
5867 /* Ignore on pathname based set. */
5868 return NT_STATUS_OK;
5871 position_information = (uint64_t)IVAL(pdata,0);
5872 #ifdef LARGE_SMB_OFF_T
5873 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5874 #else /* LARGE_SMB_OFF_T */
5875 if (IVAL(pdata,4) != 0) {
5876 /* more than 32 bits? */
5877 return NT_STATUS_INVALID_PARAMETER;
5879 #endif /* LARGE_SMB_OFF_T */
5881 DEBUG(10,("smb_file_position_information: Set file position "
5882 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5883 (double)position_information));
5884 fsp->fh->position_information = position_information;
5885 return NT_STATUS_OK;
5888 /****************************************************************************
5889 Deal with SMB_FILE_MODE_INFORMATION.
5890 ****************************************************************************/
5892 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5893 const char *pdata,
5894 int total_data)
5896 uint32 mode;
5898 if (total_data < 4) {
5899 return NT_STATUS_INVALID_PARAMETER;
5901 mode = IVAL(pdata,0);
5902 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5903 return NT_STATUS_INVALID_PARAMETER;
5905 return NT_STATUS_OK;
5908 /****************************************************************************
5909 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5910 ****************************************************************************/
5912 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5913 struct smb_request *req,
5914 const char *pdata,
5915 int total_data,
5916 const struct smb_filename *smb_fname)
5918 char *link_target = NULL;
5919 const char *newname = smb_fname->base_name;
5920 TALLOC_CTX *ctx = talloc_tos();
5922 /* Set a symbolic link. */
5923 /* Don't allow this if follow links is false. */
5925 if (total_data == 0) {
5926 return NT_STATUS_INVALID_PARAMETER;
5929 if (!lp_symlinks(SNUM(conn))) {
5930 return NT_STATUS_ACCESS_DENIED;
5933 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5934 total_data, STR_TERMINATE);
5936 if (!link_target) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5941 newname, link_target ));
5943 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5944 return map_nt_error_from_unix(errno);
5947 return NT_STATUS_OK;
5950 /****************************************************************************
5951 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5952 ****************************************************************************/
5954 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5955 struct smb_request *req,
5956 const char *pdata, int total_data,
5957 struct smb_filename *smb_fname_new)
5959 char *oldname = NULL;
5960 struct smb_filename *smb_fname_old = NULL;
5961 TALLOC_CTX *ctx = talloc_tos();
5962 NTSTATUS status = NT_STATUS_OK;
5964 /* Set a hard link. */
5965 if (total_data == 0) {
5966 return NT_STATUS_INVALID_PARAMETER;
5969 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5970 total_data, STR_TERMINATE, &status);
5971 if (!NT_STATUS_IS_OK(status)) {
5972 return status;
5975 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5976 smb_fname_str_dbg(smb_fname_new), oldname));
5978 status = filename_convert(ctx,
5979 conn,
5980 req->flags2 & FLAGS2_DFS_PATHNAMES,
5981 oldname,
5983 NULL,
5984 &smb_fname_old);
5985 if (!NT_STATUS_IS_OK(status)) {
5986 return status;
5989 return hardlink_internals(ctx, conn, req, false,
5990 smb_fname_old, smb_fname_new);
5993 /****************************************************************************
5994 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5995 ****************************************************************************/
5997 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5998 struct smb_request *req,
5999 const char *pdata,
6000 int total_data,
6001 files_struct *fsp,
6002 struct smb_filename *smb_fname_src)
6004 bool overwrite;
6005 uint32_t len;
6006 char *newname = NULL;
6007 struct smb_filename *smb_fname_dst = NULL;
6008 NTSTATUS status = NT_STATUS_OK;
6009 TALLOC_CTX *ctx = talloc_tos();
6011 if (!fsp) {
6012 return NT_STATUS_INVALID_HANDLE;
6015 if (total_data < 20) {
6016 return NT_STATUS_INVALID_PARAMETER;
6019 overwrite = (CVAL(pdata,0) ? True : False);
6020 len = IVAL(pdata,16);
6022 if (len > (total_data - 20) || (len == 0)) {
6023 return NT_STATUS_INVALID_PARAMETER;
6026 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6027 &pdata[20], len, STR_TERMINATE,
6028 &status);
6029 if (!NT_STATUS_IS_OK(status)) {
6030 return status;
6033 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6034 newname));
6036 status = filename_convert(ctx,
6037 conn,
6038 req->flags2 & FLAGS2_DFS_PATHNAMES,
6039 newname,
6040 UCF_SAVE_LCOMP,
6041 NULL,
6042 &smb_fname_dst);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 return status;
6047 if (fsp->base_fsp) {
6048 /* newname must be a stream name. */
6049 if (newname[0] != ':') {
6050 return NT_STATUS_NOT_SUPPORTED;
6053 /* Create an smb_fname to call rename_internals_fsp() with. */
6054 status = create_synthetic_smb_fname(talloc_tos(),
6055 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6056 &smb_fname_dst);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 goto out;
6062 * Set the original last component, since
6063 * rename_internals_fsp() requires it.
6065 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6066 newname);
6067 if (smb_fname_dst->original_lcomp == NULL) {
6068 status = NT_STATUS_NO_MEMORY;
6069 goto out;
6074 DEBUG(10,("smb2_file_rename_information: "
6075 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6076 fsp->fnum, fsp_str_dbg(fsp),
6077 smb_fname_str_dbg(smb_fname_dst)));
6078 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6079 overwrite);
6081 out:
6082 TALLOC_FREE(smb_fname_dst);
6083 return status;
6086 static NTSTATUS smb_file_link_information(connection_struct *conn,
6087 struct smb_request *req,
6088 const char *pdata,
6089 int total_data,
6090 files_struct *fsp,
6091 struct smb_filename *smb_fname_src)
6093 bool overwrite;
6094 uint32_t len;
6095 char *newname = NULL;
6096 struct smb_filename *smb_fname_dst = NULL;
6097 NTSTATUS status = NT_STATUS_OK;
6098 TALLOC_CTX *ctx = talloc_tos();
6100 if (!fsp) {
6101 return NT_STATUS_INVALID_HANDLE;
6104 if (total_data < 20) {
6105 return NT_STATUS_INVALID_PARAMETER;
6108 overwrite = (CVAL(pdata,0) ? true : false);
6109 len = IVAL(pdata,16);
6111 if (len > (total_data - 20) || (len == 0)) {
6112 return NT_STATUS_INVALID_PARAMETER;
6115 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6116 &pdata[20], len, STR_TERMINATE,
6117 &status);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 return status;
6122 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6123 newname));
6125 status = filename_convert(ctx,
6126 conn,
6127 req->flags2 & FLAGS2_DFS_PATHNAMES,
6128 newname,
6129 UCF_SAVE_LCOMP,
6130 NULL,
6131 &smb_fname_dst);
6132 if (!NT_STATUS_IS_OK(status)) {
6133 return status;
6136 if (fsp->base_fsp) {
6137 /* No stream names. */
6138 return NT_STATUS_NOT_SUPPORTED;
6141 DEBUG(10,("smb_file_link_information: "
6142 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6143 fsp->fnum, fsp_str_dbg(fsp),
6144 smb_fname_str_dbg(smb_fname_dst)));
6145 status = hardlink_internals(ctx,
6146 conn,
6147 req,
6148 overwrite,
6149 fsp->fsp_name,
6150 smb_fname_dst);
6152 TALLOC_FREE(smb_fname_dst);
6153 return status;
6156 /****************************************************************************
6157 Deal with SMB_FILE_RENAME_INFORMATION.
6158 ****************************************************************************/
6160 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6161 struct smb_request *req,
6162 const char *pdata,
6163 int total_data,
6164 files_struct *fsp,
6165 struct smb_filename *smb_fname_src)
6167 bool overwrite;
6168 uint32 root_fid;
6169 uint32 len;
6170 char *newname = NULL;
6171 struct smb_filename *smb_fname_dst = NULL;
6172 bool dest_has_wcard = False;
6173 NTSTATUS status = NT_STATUS_OK;
6174 char *p;
6175 TALLOC_CTX *ctx = talloc_tos();
6177 if (total_data < 13) {
6178 return NT_STATUS_INVALID_PARAMETER;
6181 overwrite = (CVAL(pdata,0) ? True : False);
6182 root_fid = IVAL(pdata,4);
6183 len = IVAL(pdata,8);
6185 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6186 return NT_STATUS_INVALID_PARAMETER;
6189 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6190 len, 0, &status,
6191 &dest_has_wcard);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 return status;
6196 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6197 newname));
6199 status = resolve_dfspath_wcard(ctx, conn,
6200 req->flags2 & FLAGS2_DFS_PATHNAMES,
6201 newname,
6202 true,
6203 &newname,
6204 &dest_has_wcard);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 return status;
6209 /* Check the new name has no '/' characters. */
6210 if (strchr_m(newname, '/')) {
6211 return NT_STATUS_NOT_SUPPORTED;
6214 if (fsp && fsp->base_fsp) {
6215 /* newname must be a stream name. */
6216 if (newname[0] != ':') {
6217 return NT_STATUS_NOT_SUPPORTED;
6220 /* Create an smb_fname to call rename_internals_fsp() with. */
6221 status = create_synthetic_smb_fname(talloc_tos(),
6222 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6223 &smb_fname_dst);
6224 if (!NT_STATUS_IS_OK(status)) {
6225 goto out;
6229 * Set the original last component, since
6230 * rename_internals_fsp() requires it.
6232 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6233 newname);
6234 if (smb_fname_dst->original_lcomp == NULL) {
6235 status = NT_STATUS_NO_MEMORY;
6236 goto out;
6239 } else {
6241 * Build up an smb_fname_dst based on the filename passed in.
6242 * We basically just strip off the last component, and put on
6243 * the newname instead.
6245 char *base_name = NULL;
6247 /* newname must *not* be a stream name. */
6248 if (newname[0] == ':') {
6249 return NT_STATUS_NOT_SUPPORTED;
6253 * Strip off the last component (filename) of the path passed
6254 * in.
6256 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6257 if (!base_name) {
6258 return NT_STATUS_NO_MEMORY;
6260 p = strrchr_m(base_name, '/');
6261 if (p) {
6262 p[1] = '\0';
6263 } else {
6264 base_name = talloc_strdup(ctx, "");
6265 if (!base_name) {
6266 return NT_STATUS_NO_MEMORY;
6269 /* Append the new name. */
6270 base_name = talloc_asprintf_append(base_name,
6271 "%s",
6272 newname);
6273 if (!base_name) {
6274 return NT_STATUS_NO_MEMORY;
6277 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6278 (UCF_SAVE_LCOMP |
6279 (dest_has_wcard ?
6280 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6281 0)));
6283 /* If an error we expect this to be
6284 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6286 if (!NT_STATUS_IS_OK(status)) {
6287 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6288 status)) {
6289 goto out;
6291 /* Create an smb_fname to call rename_internals_fsp() */
6292 status = create_synthetic_smb_fname(ctx,
6293 base_name, NULL,
6294 NULL,
6295 &smb_fname_dst);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 goto out;
6302 if (fsp) {
6303 DEBUG(10,("smb_file_rename_information: "
6304 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6305 fsp->fnum, fsp_str_dbg(fsp),
6306 smb_fname_str_dbg(smb_fname_dst)));
6307 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6308 overwrite);
6309 } else {
6310 DEBUG(10,("smb_file_rename_information: "
6311 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6312 smb_fname_str_dbg(smb_fname_src),
6313 smb_fname_str_dbg(smb_fname_dst)));
6314 status = rename_internals(ctx, conn, req, smb_fname_src,
6315 smb_fname_dst, 0, overwrite, false,
6316 dest_has_wcard,
6317 FILE_WRITE_ATTRIBUTES);
6319 out:
6320 TALLOC_FREE(smb_fname_dst);
6321 return status;
6324 /****************************************************************************
6325 Deal with SMB_SET_POSIX_ACL.
6326 ****************************************************************************/
6328 #if defined(HAVE_POSIX_ACLS)
6329 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6330 const char *pdata,
6331 int total_data,
6332 files_struct *fsp,
6333 const struct smb_filename *smb_fname)
6335 uint16 posix_acl_version;
6336 uint16 num_file_acls;
6337 uint16 num_def_acls;
6338 bool valid_file_acls = True;
6339 bool valid_def_acls = True;
6341 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6342 return NT_STATUS_INVALID_PARAMETER;
6344 posix_acl_version = SVAL(pdata,0);
6345 num_file_acls = SVAL(pdata,2);
6346 num_def_acls = SVAL(pdata,4);
6348 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6349 valid_file_acls = False;
6350 num_file_acls = 0;
6353 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6354 valid_def_acls = False;
6355 num_def_acls = 0;
6358 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6359 return NT_STATUS_INVALID_PARAMETER;
6362 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6363 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6364 return NT_STATUS_INVALID_PARAMETER;
6367 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6368 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6369 (unsigned int)num_file_acls,
6370 (unsigned int)num_def_acls));
6372 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6373 smb_fname->base_name, num_file_acls,
6374 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6375 return map_nt_error_from_unix(errno);
6378 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6379 smb_fname->base_name, &smb_fname->st, num_def_acls,
6380 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6381 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6382 return map_nt_error_from_unix(errno);
6384 return NT_STATUS_OK;
6386 #endif
6388 /****************************************************************************
6389 Deal with SMB_SET_POSIX_LOCK.
6390 ****************************************************************************/
6392 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6393 struct smb_request *req,
6394 const char *pdata,
6395 int total_data,
6396 files_struct *fsp)
6398 uint64_t count;
6399 uint64_t offset;
6400 uint64_t smblctx;
6401 bool blocking_lock = False;
6402 enum brl_type lock_type;
6404 NTSTATUS status = NT_STATUS_OK;
6406 if (fsp == NULL || fsp->fh->fd == -1) {
6407 return NT_STATUS_INVALID_HANDLE;
6410 if (total_data != POSIX_LOCK_DATA_SIZE) {
6411 return NT_STATUS_INVALID_PARAMETER;
6414 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6415 case POSIX_LOCK_TYPE_READ:
6416 lock_type = READ_LOCK;
6417 break;
6418 case POSIX_LOCK_TYPE_WRITE:
6419 /* Return the right POSIX-mappable error code for files opened read-only. */
6420 if (!fsp->can_write) {
6421 return NT_STATUS_INVALID_HANDLE;
6423 lock_type = WRITE_LOCK;
6424 break;
6425 case POSIX_LOCK_TYPE_UNLOCK:
6426 lock_type = UNLOCK_LOCK;
6427 break;
6428 default:
6429 return NT_STATUS_INVALID_PARAMETER;
6432 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6433 blocking_lock = False;
6434 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6435 blocking_lock = True;
6436 } else {
6437 return NT_STATUS_INVALID_PARAMETER;
6440 if (!lp_blocking_locks(SNUM(conn))) {
6441 blocking_lock = False;
6444 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6445 #if defined(HAVE_LONGLONG)
6446 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6447 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6448 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6449 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6450 #else /* HAVE_LONGLONG */
6451 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6452 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6453 #endif /* HAVE_LONGLONG */
6455 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6456 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6457 fsp_str_dbg(fsp),
6458 (unsigned int)lock_type,
6459 (unsigned long long)smblctx,
6460 (double)count,
6461 (double)offset ));
6463 if (lock_type == UNLOCK_LOCK) {
6464 status = do_unlock(req->sconn->msg_ctx,
6465 fsp,
6466 smblctx,
6467 count,
6468 offset,
6469 POSIX_LOCK);
6470 } else {
6471 uint64_t block_smblctx;
6473 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6474 fsp,
6475 smblctx,
6476 count,
6477 offset,
6478 lock_type,
6479 POSIX_LOCK,
6480 blocking_lock,
6481 &status,
6482 &block_smblctx,
6483 NULL);
6485 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6487 * A blocking lock was requested. Package up
6488 * this smb into a queued request and push it
6489 * onto the blocking lock queue.
6491 if(push_blocking_lock_request(br_lck,
6492 req,
6493 fsp,
6494 -1, /* infinite timeout. */
6496 smblctx,
6497 lock_type,
6498 POSIX_LOCK,
6499 offset,
6500 count,
6501 block_smblctx)) {
6502 TALLOC_FREE(br_lck);
6503 return status;
6506 TALLOC_FREE(br_lck);
6509 return status;
6512 /****************************************************************************
6513 Deal with SMB_SET_FILE_BASIC_INFO.
6514 ****************************************************************************/
6516 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6517 const char *pdata,
6518 int total_data,
6519 files_struct *fsp,
6520 const struct smb_filename *smb_fname)
6522 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6523 struct smb_file_time ft;
6524 uint32 dosmode = 0;
6525 NTSTATUS status = NT_STATUS_OK;
6527 ZERO_STRUCT(ft);
6529 if (total_data < 36) {
6530 return NT_STATUS_INVALID_PARAMETER;
6533 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6534 return NT_STATUS_ACCESS_DENIED;
6537 /* Set the attributes */
6538 dosmode = IVAL(pdata,32);
6539 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6540 if (!NT_STATUS_IS_OK(status)) {
6541 return status;
6544 /* create time */
6545 ft.create_time = interpret_long_date(pdata);
6547 /* access time */
6548 ft.atime = interpret_long_date(pdata+8);
6550 /* write time. */
6551 ft.mtime = interpret_long_date(pdata+16);
6553 /* change time. */
6554 ft.ctime = interpret_long_date(pdata+24);
6556 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6557 smb_fname_str_dbg(smb_fname)));
6559 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6560 true);
6563 /****************************************************************************
6564 Deal with SMB_INFO_STANDARD.
6565 ****************************************************************************/
6567 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6568 const char *pdata,
6569 int total_data,
6570 files_struct *fsp,
6571 const struct smb_filename *smb_fname)
6573 struct smb_file_time ft;
6575 ZERO_STRUCT(ft);
6577 if (total_data < 12) {
6578 return NT_STATUS_INVALID_PARAMETER;
6581 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6582 return NT_STATUS_ACCESS_DENIED;
6585 /* create time */
6586 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6587 /* access time */
6588 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6589 /* write time */
6590 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6592 DEBUG(10,("smb_set_info_standard: file %s\n",
6593 smb_fname_str_dbg(smb_fname)));
6595 return smb_set_file_time(conn,
6596 fsp,
6597 smb_fname,
6598 &ft,
6599 true);
6602 /****************************************************************************
6603 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6604 ****************************************************************************/
6606 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6607 struct smb_request *req,
6608 const char *pdata,
6609 int total_data,
6610 files_struct *fsp,
6611 struct smb_filename *smb_fname)
6613 uint64_t allocation_size = 0;
6614 NTSTATUS status = NT_STATUS_OK;
6615 files_struct *new_fsp = NULL;
6617 if (!VALID_STAT(smb_fname->st)) {
6618 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6621 if (total_data < 8) {
6622 return NT_STATUS_INVALID_PARAMETER;
6625 allocation_size = (uint64_t)IVAL(pdata,0);
6626 #ifdef LARGE_SMB_OFF_T
6627 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6628 #else /* LARGE_SMB_OFF_T */
6629 if (IVAL(pdata,4) != 0) {
6630 /* more than 32 bits? */
6631 return NT_STATUS_INVALID_PARAMETER;
6633 #endif /* LARGE_SMB_OFF_T */
6635 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6636 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6637 (double)allocation_size));
6639 if (allocation_size) {
6640 allocation_size = smb_roundup(conn, allocation_size);
6643 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6644 return NT_STATUS_ACCESS_DENIED;
6647 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6648 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6649 (double)allocation_size));
6651 if (fsp && fsp->fh->fd != -1) {
6652 /* Open file handle. */
6653 /* Only change if needed. */
6654 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6655 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6656 return map_nt_error_from_unix(errno);
6659 /* But always update the time. */
6661 * This is equivalent to a write. Ensure it's seen immediately
6662 * if there are no pending writes.
6664 trigger_write_time_update_immediate(fsp);
6665 return NT_STATUS_OK;
6668 /* Pathname or stat or directory file. */
6669 status = SMB_VFS_CREATE_FILE(
6670 conn, /* conn */
6671 req, /* req */
6672 0, /* root_dir_fid */
6673 smb_fname, /* fname */
6674 FILE_WRITE_DATA, /* access_mask */
6675 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6676 FILE_SHARE_DELETE),
6677 FILE_OPEN, /* create_disposition*/
6678 0, /* create_options */
6679 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6680 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6681 0, /* allocation_size */
6682 0, /* private_flags */
6683 NULL, /* sd */
6684 NULL, /* ea_list */
6685 &new_fsp, /* result */
6686 NULL); /* pinfo */
6688 if (!NT_STATUS_IS_OK(status)) {
6689 /* NB. We check for open_was_deferred in the caller. */
6690 return status;
6693 /* Only change if needed. */
6694 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6695 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6696 status = map_nt_error_from_unix(errno);
6697 close_file(req, new_fsp, NORMAL_CLOSE);
6698 return status;
6702 /* Changing the allocation size should set the last mod time. */
6704 * This is equivalent to a write. Ensure it's seen immediately
6705 * if there are no pending writes.
6707 trigger_write_time_update_immediate(new_fsp);
6709 close_file(req, new_fsp, NORMAL_CLOSE);
6710 return NT_STATUS_OK;
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6718 struct smb_request *req,
6719 const char *pdata,
6720 int total_data,
6721 files_struct *fsp,
6722 const struct smb_filename *smb_fname,
6723 bool fail_after_createfile)
6725 SMB_OFF_T size;
6727 if (total_data < 8) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 size = IVAL(pdata,0);
6732 #ifdef LARGE_SMB_OFF_T
6733 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6734 #else /* LARGE_SMB_OFF_T */
6735 if (IVAL(pdata,4) != 0) {
6736 /* more than 32 bits? */
6737 return NT_STATUS_INVALID_PARAMETER;
6739 #endif /* LARGE_SMB_OFF_T */
6740 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6741 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6742 (double)size));
6744 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6745 return NT_STATUS_ACCESS_DENIED;
6748 return smb_set_file_size(conn, req,
6749 fsp,
6750 smb_fname,
6751 &smb_fname->st,
6752 size,
6753 fail_after_createfile);
6756 /****************************************************************************
6757 Allow a UNIX info mknod.
6758 ****************************************************************************/
6760 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6761 const char *pdata,
6762 int total_data,
6763 const struct smb_filename *smb_fname)
6765 uint32 file_type = IVAL(pdata,56);
6766 #if defined(HAVE_MAKEDEV)
6767 uint32 dev_major = IVAL(pdata,60);
6768 uint32 dev_minor = IVAL(pdata,68);
6769 #endif
6770 SMB_DEV_T dev = (SMB_DEV_T)0;
6771 uint32 raw_unixmode = IVAL(pdata,84);
6772 NTSTATUS status;
6773 mode_t unixmode;
6775 if (total_data < 100) {
6776 return NT_STATUS_INVALID_PARAMETER;
6779 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6780 PERM_NEW_FILE, &unixmode);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 return status;
6785 #if defined(HAVE_MAKEDEV)
6786 dev = makedev(dev_major, dev_minor);
6787 #endif
6789 switch (file_type) {
6790 #if defined(S_IFIFO)
6791 case UNIX_TYPE_FIFO:
6792 unixmode |= S_IFIFO;
6793 break;
6794 #endif
6795 #if defined(S_IFSOCK)
6796 case UNIX_TYPE_SOCKET:
6797 unixmode |= S_IFSOCK;
6798 break;
6799 #endif
6800 #if defined(S_IFCHR)
6801 case UNIX_TYPE_CHARDEV:
6802 unixmode |= S_IFCHR;
6803 break;
6804 #endif
6805 #if defined(S_IFBLK)
6806 case UNIX_TYPE_BLKDEV:
6807 unixmode |= S_IFBLK;
6808 break;
6809 #endif
6810 default:
6811 return NT_STATUS_INVALID_PARAMETER;
6814 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6815 "%.0f mode 0%o for file %s\n", (double)dev,
6816 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6818 /* Ok - do the mknod. */
6819 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6820 return map_nt_error_from_unix(errno);
6823 /* If any of the other "set" calls fail we
6824 * don't want to end up with a half-constructed mknod.
6827 if (lp_inherit_perms(SNUM(conn))) {
6828 char *parent;
6829 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6830 &parent, NULL)) {
6831 return NT_STATUS_NO_MEMORY;
6833 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6834 unixmode);
6835 TALLOC_FREE(parent);
6838 return NT_STATUS_OK;
6841 /****************************************************************************
6842 Deal with SMB_SET_FILE_UNIX_BASIC.
6843 ****************************************************************************/
6845 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6846 struct smb_request *req,
6847 const char *pdata,
6848 int total_data,
6849 files_struct *fsp,
6850 const struct smb_filename *smb_fname)
6852 struct smb_file_time ft;
6853 uint32 raw_unixmode;
6854 mode_t unixmode;
6855 SMB_OFF_T size = 0;
6856 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6857 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6858 NTSTATUS status = NT_STATUS_OK;
6859 bool delete_on_fail = False;
6860 enum perm_type ptype;
6861 files_struct *all_fsps = NULL;
6862 bool modify_mtime = true;
6863 struct file_id id;
6864 struct smb_filename *smb_fname_tmp = NULL;
6865 SMB_STRUCT_STAT sbuf;
6867 ZERO_STRUCT(ft);
6869 if (total_data < 100) {
6870 return NT_STATUS_INVALID_PARAMETER;
6873 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6874 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6875 size=IVAL(pdata,0); /* first 8 Bytes are size */
6876 #ifdef LARGE_SMB_OFF_T
6877 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6878 #else /* LARGE_SMB_OFF_T */
6879 if (IVAL(pdata,4) != 0) {
6880 /* more than 32 bits? */
6881 return NT_STATUS_INVALID_PARAMETER;
6883 #endif /* LARGE_SMB_OFF_T */
6886 ft.atime = interpret_long_date(pdata+24); /* access_time */
6887 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6888 set_owner = (uid_t)IVAL(pdata,40);
6889 set_grp = (gid_t)IVAL(pdata,48);
6890 raw_unixmode = IVAL(pdata,84);
6892 if (VALID_STAT(smb_fname->st)) {
6893 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6894 ptype = PERM_EXISTING_DIR;
6895 } else {
6896 ptype = PERM_EXISTING_FILE;
6898 } else {
6899 ptype = PERM_NEW_FILE;
6902 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6903 ptype, &unixmode);
6904 if (!NT_STATUS_IS_OK(status)) {
6905 return status;
6908 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6909 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6910 smb_fname_str_dbg(smb_fname), (double)size,
6911 (unsigned int)set_owner, (unsigned int)set_grp,
6912 (int)raw_unixmode));
6914 sbuf = smb_fname->st;
6916 if (!VALID_STAT(sbuf)) {
6918 * The only valid use of this is to create character and block
6919 * devices, and named pipes. This is deprecated (IMHO) and
6920 * a new info level should be used for mknod. JRA.
6923 status = smb_unix_mknod(conn,
6924 pdata,
6925 total_data,
6926 smb_fname);
6927 if (!NT_STATUS_IS_OK(status)) {
6928 return status;
6931 status = copy_smb_filename(talloc_tos(), smb_fname,
6932 &smb_fname_tmp);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 return status;
6937 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6938 status = map_nt_error_from_unix(errno);
6939 TALLOC_FREE(smb_fname_tmp);
6940 SMB_VFS_UNLINK(conn, smb_fname);
6941 return status;
6944 sbuf = smb_fname_tmp->st;
6945 smb_fname = smb_fname_tmp;
6947 /* Ensure we don't try and change anything else. */
6948 raw_unixmode = SMB_MODE_NO_CHANGE;
6949 size = get_file_size_stat(&sbuf);
6950 ft.atime = sbuf.st_ex_atime;
6951 ft.mtime = sbuf.st_ex_mtime;
6953 * We continue here as we might want to change the
6954 * owner uid/gid.
6956 delete_on_fail = True;
6959 #if 1
6960 /* Horrible backwards compatibility hack as an old server bug
6961 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6962 * */
6964 if (!size) {
6965 size = get_file_size_stat(&sbuf);
6967 #endif
6970 * Deal with the UNIX specific mode set.
6973 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6974 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6975 "setting mode 0%o for file %s\n",
6976 (unsigned int)unixmode,
6977 smb_fname_str_dbg(smb_fname)));
6978 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6979 return map_nt_error_from_unix(errno);
6984 * Deal with the UNIX specific uid set.
6987 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6988 (sbuf.st_ex_uid != set_owner)) {
6989 int ret;
6991 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6992 "changing owner %u for path %s\n",
6993 (unsigned int)set_owner,
6994 smb_fname_str_dbg(smb_fname)));
6996 if (S_ISLNK(sbuf.st_ex_mode)) {
6997 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6998 set_owner, (gid_t)-1);
6999 } else {
7000 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7001 set_owner, (gid_t)-1);
7004 if (ret != 0) {
7005 status = map_nt_error_from_unix(errno);
7006 if (delete_on_fail) {
7007 SMB_VFS_UNLINK(conn, smb_fname);
7009 return status;
7014 * Deal with the UNIX specific gid set.
7017 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7018 (sbuf.st_ex_gid != set_grp)) {
7019 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7020 "changing group %u for file %s\n",
7021 (unsigned int)set_owner,
7022 smb_fname_str_dbg(smb_fname)));
7023 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7024 set_grp) != 0) {
7025 status = map_nt_error_from_unix(errno);
7026 if (delete_on_fail) {
7027 SMB_VFS_UNLINK(conn, smb_fname);
7029 return status;
7033 /* Deal with any size changes. */
7035 status = smb_set_file_size(conn, req,
7036 fsp,
7037 smb_fname,
7038 &sbuf,
7039 size,
7040 false);
7041 if (!NT_STATUS_IS_OK(status)) {
7042 return status;
7045 /* Deal with any time changes. */
7046 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7047 /* No change, don't cancel anything. */
7048 return status;
7051 id = vfs_file_id_from_sbuf(conn, &sbuf);
7052 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7053 all_fsps = file_find_di_next(all_fsps)) {
7055 * We're setting the time explicitly for UNIX.
7056 * Cancel any pending changes over all handles.
7058 all_fsps->update_write_time_on_close = false;
7059 TALLOC_FREE(all_fsps->update_write_time_event);
7063 * Override the "setting_write_time"
7064 * parameter here as it almost does what
7065 * we need. Just remember if we modified
7066 * mtime and send the notify ourselves.
7068 if (null_timespec(ft.mtime)) {
7069 modify_mtime = false;
7072 status = smb_set_file_time(conn,
7073 fsp,
7074 smb_fname,
7075 &ft,
7076 false);
7077 if (modify_mtime) {
7078 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7079 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7081 return status;
7084 /****************************************************************************
7085 Deal with SMB_SET_FILE_UNIX_INFO2.
7086 ****************************************************************************/
7088 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7089 struct smb_request *req,
7090 const char *pdata,
7091 int total_data,
7092 files_struct *fsp,
7093 const struct smb_filename *smb_fname)
7095 NTSTATUS status;
7096 uint32 smb_fflags;
7097 uint32 smb_fmask;
7099 if (total_data < 116) {
7100 return NT_STATUS_INVALID_PARAMETER;
7103 /* Start by setting all the fields that are common between UNIX_BASIC
7104 * and UNIX_INFO2.
7106 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7107 fsp, smb_fname);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 return status;
7112 smb_fflags = IVAL(pdata, 108);
7113 smb_fmask = IVAL(pdata, 112);
7115 /* NB: We should only attempt to alter the file flags if the client
7116 * sends a non-zero mask.
7118 if (smb_fmask != 0) {
7119 int stat_fflags = 0;
7121 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7122 smb_fmask, &stat_fflags)) {
7123 /* Client asked to alter a flag we don't understand. */
7124 return NT_STATUS_INVALID_PARAMETER;
7127 if (fsp && fsp->fh->fd != -1) {
7128 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7129 return NT_STATUS_NOT_SUPPORTED;
7130 } else {
7131 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7132 stat_fflags) != 0) {
7133 return map_nt_error_from_unix(errno);
7138 /* XXX: need to add support for changing the create_time here. You
7139 * can do this for paths on Darwin with setattrlist(2). The right way
7140 * to hook this up is probably by extending the VFS utimes interface.
7143 return NT_STATUS_OK;
7146 /****************************************************************************
7147 Create a directory with POSIX semantics.
7148 ****************************************************************************/
7150 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7151 struct smb_request *req,
7152 char **ppdata,
7153 int total_data,
7154 struct smb_filename *smb_fname,
7155 int *pdata_return_size)
7157 NTSTATUS status = NT_STATUS_OK;
7158 uint32 raw_unixmode = 0;
7159 uint32 mod_unixmode = 0;
7160 mode_t unixmode = (mode_t)0;
7161 files_struct *fsp = NULL;
7162 uint16 info_level_return = 0;
7163 int info;
7164 char *pdata = *ppdata;
7166 if (total_data < 18) {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 raw_unixmode = IVAL(pdata,8);
7171 /* Next 4 bytes are not yet defined. */
7173 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7174 PERM_NEW_DIR, &unixmode);
7175 if (!NT_STATUS_IS_OK(status)) {
7176 return status;
7179 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7181 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7182 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7184 status = SMB_VFS_CREATE_FILE(
7185 conn, /* conn */
7186 req, /* req */
7187 0, /* root_dir_fid */
7188 smb_fname, /* fname */
7189 FILE_READ_ATTRIBUTES, /* access_mask */
7190 FILE_SHARE_NONE, /* share_access */
7191 FILE_CREATE, /* create_disposition*/
7192 FILE_DIRECTORY_FILE, /* create_options */
7193 mod_unixmode, /* file_attributes */
7194 0, /* oplock_request */
7195 0, /* allocation_size */
7196 0, /* private_flags */
7197 NULL, /* sd */
7198 NULL, /* ea_list */
7199 &fsp, /* result */
7200 &info); /* pinfo */
7202 if (NT_STATUS_IS_OK(status)) {
7203 close_file(req, fsp, NORMAL_CLOSE);
7206 info_level_return = SVAL(pdata,16);
7208 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7209 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7210 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7211 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7212 } else {
7213 *pdata_return_size = 12;
7216 /* Realloc the data size */
7217 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7218 if (*ppdata == NULL) {
7219 *pdata_return_size = 0;
7220 return NT_STATUS_NO_MEMORY;
7222 pdata = *ppdata;
7224 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7225 SSVAL(pdata,2,0); /* No fnum. */
7226 SIVAL(pdata,4,info); /* Was directory created. */
7228 switch (info_level_return) {
7229 case SMB_QUERY_FILE_UNIX_BASIC:
7230 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7231 SSVAL(pdata,10,0); /* Padding. */
7232 store_file_unix_basic(conn, pdata + 12, fsp,
7233 &smb_fname->st);
7234 break;
7235 case SMB_QUERY_FILE_UNIX_INFO2:
7236 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7237 SSVAL(pdata,10,0); /* Padding. */
7238 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7239 &smb_fname->st);
7240 break;
7241 default:
7242 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7243 SSVAL(pdata,10,0); /* Padding. */
7244 break;
7247 return status;
7250 /****************************************************************************
7251 Open/Create a file with POSIX semantics.
7252 ****************************************************************************/
7254 static NTSTATUS smb_posix_open(connection_struct *conn,
7255 struct smb_request *req,
7256 char **ppdata,
7257 int total_data,
7258 struct smb_filename *smb_fname,
7259 int *pdata_return_size)
7261 bool extended_oplock_granted = False;
7262 char *pdata = *ppdata;
7263 uint32 flags = 0;
7264 uint32 wire_open_mode = 0;
7265 uint32 raw_unixmode = 0;
7266 uint32 mod_unixmode = 0;
7267 uint32 create_disp = 0;
7268 uint32 access_mask = 0;
7269 uint32 create_options = 0;
7270 NTSTATUS status = NT_STATUS_OK;
7271 mode_t unixmode = (mode_t)0;
7272 files_struct *fsp = NULL;
7273 int oplock_request = 0;
7274 int info = 0;
7275 uint16 info_level_return = 0;
7277 if (total_data < 18) {
7278 return NT_STATUS_INVALID_PARAMETER;
7281 flags = IVAL(pdata,0);
7282 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7283 if (oplock_request) {
7284 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7287 wire_open_mode = IVAL(pdata,4);
7289 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7290 return smb_posix_mkdir(conn, req,
7291 ppdata,
7292 total_data,
7293 smb_fname,
7294 pdata_return_size);
7297 switch (wire_open_mode & SMB_ACCMODE) {
7298 case SMB_O_RDONLY:
7299 access_mask = FILE_READ_DATA;
7300 break;
7301 case SMB_O_WRONLY:
7302 access_mask = FILE_WRITE_DATA;
7303 break;
7304 case SMB_O_RDWR:
7305 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7306 break;
7307 default:
7308 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7309 (unsigned int)wire_open_mode ));
7310 return NT_STATUS_INVALID_PARAMETER;
7313 wire_open_mode &= ~SMB_ACCMODE;
7315 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7316 create_disp = FILE_CREATE;
7317 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7318 create_disp = FILE_OVERWRITE_IF;
7319 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7320 create_disp = FILE_OPEN_IF;
7321 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7322 create_disp = FILE_OPEN;
7323 } else {
7324 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7325 (unsigned int)wire_open_mode ));
7326 return NT_STATUS_INVALID_PARAMETER;
7329 raw_unixmode = IVAL(pdata,8);
7330 /* Next 4 bytes are not yet defined. */
7332 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7333 (VALID_STAT(smb_fname->st) ?
7334 PERM_EXISTING_FILE : PERM_NEW_FILE),
7335 &unixmode);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 return status;
7341 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7343 if (wire_open_mode & SMB_O_SYNC) {
7344 create_options |= FILE_WRITE_THROUGH;
7346 if (wire_open_mode & SMB_O_APPEND) {
7347 access_mask |= FILE_APPEND_DATA;
7349 if (wire_open_mode & SMB_O_DIRECT) {
7350 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7353 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7354 smb_fname_str_dbg(smb_fname),
7355 (unsigned int)wire_open_mode,
7356 (unsigned int)unixmode ));
7358 status = SMB_VFS_CREATE_FILE(
7359 conn, /* conn */
7360 req, /* req */
7361 0, /* root_dir_fid */
7362 smb_fname, /* fname */
7363 access_mask, /* access_mask */
7364 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7365 FILE_SHARE_DELETE),
7366 create_disp, /* create_disposition*/
7367 FILE_NON_DIRECTORY_FILE, /* create_options */
7368 mod_unixmode, /* file_attributes */
7369 oplock_request, /* oplock_request */
7370 0, /* allocation_size */
7371 0, /* private_flags */
7372 NULL, /* sd */
7373 NULL, /* ea_list */
7374 &fsp, /* result */
7375 &info); /* pinfo */
7377 if (!NT_STATUS_IS_OK(status)) {
7378 return status;
7381 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7382 extended_oplock_granted = True;
7385 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7386 extended_oplock_granted = True;
7389 info_level_return = SVAL(pdata,16);
7391 /* Allocate the correct return size. */
7393 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7394 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7395 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7396 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7397 } else {
7398 *pdata_return_size = 12;
7401 /* Realloc the data size */
7402 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7403 if (*ppdata == NULL) {
7404 close_file(req, fsp, ERROR_CLOSE);
7405 *pdata_return_size = 0;
7406 return NT_STATUS_NO_MEMORY;
7408 pdata = *ppdata;
7410 if (extended_oplock_granted) {
7411 if (flags & REQUEST_BATCH_OPLOCK) {
7412 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7413 } else {
7414 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7416 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7417 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7418 } else {
7419 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7422 SSVAL(pdata,2,fsp->fnum);
7423 SIVAL(pdata,4,info); /* Was file created etc. */
7425 switch (info_level_return) {
7426 case SMB_QUERY_FILE_UNIX_BASIC:
7427 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7428 SSVAL(pdata,10,0); /* padding. */
7429 store_file_unix_basic(conn, pdata + 12, fsp,
7430 &smb_fname->st);
7431 break;
7432 case SMB_QUERY_FILE_UNIX_INFO2:
7433 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7434 SSVAL(pdata,10,0); /* padding. */
7435 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7436 &smb_fname->st);
7437 break;
7438 default:
7439 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7440 SSVAL(pdata,10,0); /* padding. */
7441 break;
7443 return NT_STATUS_OK;
7446 /****************************************************************************
7447 Delete a file with POSIX semantics.
7448 ****************************************************************************/
7450 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7451 struct smb_request *req,
7452 const char *pdata,
7453 int total_data,
7454 struct smb_filename *smb_fname)
7456 NTSTATUS status = NT_STATUS_OK;
7457 files_struct *fsp = NULL;
7458 uint16 flags = 0;
7459 char del = 1;
7460 int info = 0;
7461 int create_options = 0;
7462 int i;
7463 struct share_mode_lock *lck = NULL;
7465 if (total_data < 2) {
7466 return NT_STATUS_INVALID_PARAMETER;
7469 flags = SVAL(pdata,0);
7471 if (!VALID_STAT(smb_fname->st)) {
7472 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7475 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7476 !VALID_STAT_OF_DIR(smb_fname->st)) {
7477 return NT_STATUS_NOT_A_DIRECTORY;
7480 DEBUG(10,("smb_posix_unlink: %s %s\n",
7481 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7482 smb_fname_str_dbg(smb_fname)));
7484 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7485 create_options |= FILE_DIRECTORY_FILE;
7488 status = SMB_VFS_CREATE_FILE(
7489 conn, /* conn */
7490 req, /* req */
7491 0, /* root_dir_fid */
7492 smb_fname, /* fname */
7493 DELETE_ACCESS, /* access_mask */
7494 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7495 FILE_SHARE_DELETE),
7496 FILE_OPEN, /* create_disposition*/
7497 create_options, /* create_options */
7498 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7499 0, /* oplock_request */
7500 0, /* allocation_size */
7501 0, /* private_flags */
7502 NULL, /* sd */
7503 NULL, /* ea_list */
7504 &fsp, /* result */
7505 &info); /* pinfo */
7507 if (!NT_STATUS_IS_OK(status)) {
7508 return status;
7512 * Don't lie to client. If we can't really delete due to
7513 * non-POSIX opens return SHARING_VIOLATION.
7516 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7517 NULL);
7518 if (lck == NULL) {
7519 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7520 "lock for file %s\n", fsp_str_dbg(fsp)));
7521 close_file(req, fsp, NORMAL_CLOSE);
7522 return NT_STATUS_INVALID_PARAMETER;
7526 * See if others still have the file open. If this is the case, then
7527 * don't delete. If all opens are POSIX delete we can set the delete
7528 * on close disposition.
7530 for (i=0; i<lck->num_share_modes; i++) {
7531 struct share_mode_entry *e = &lck->share_modes[i];
7532 if (is_valid_share_mode_entry(e)) {
7533 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7534 continue;
7536 /* Fail with sharing violation. */
7537 close_file(req, fsp, NORMAL_CLOSE);
7538 TALLOC_FREE(lck);
7539 return NT_STATUS_SHARING_VIOLATION;
7544 * Set the delete on close.
7546 status = smb_set_file_disposition_info(conn,
7547 &del,
7549 fsp,
7550 smb_fname);
7552 if (!NT_STATUS_IS_OK(status)) {
7553 close_file(req, fsp, NORMAL_CLOSE);
7554 TALLOC_FREE(lck);
7555 return status;
7557 TALLOC_FREE(lck);
7558 return close_file(req, fsp, NORMAL_CLOSE);
7561 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7562 struct smb_request *req,
7563 TALLOC_CTX *mem_ctx,
7564 uint16_t info_level,
7565 files_struct *fsp,
7566 struct smb_filename *smb_fname,
7567 char **ppdata, int total_data,
7568 int *ret_data_size)
7570 char *pdata = *ppdata;
7571 NTSTATUS status = NT_STATUS_OK;
7572 int data_return_size = 0;
7574 *ret_data_size = 0;
7576 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7577 return NT_STATUS_INVALID_LEVEL;
7580 if (!CAN_WRITE(conn)) {
7581 /* Allow POSIX opens. The open path will deny
7582 * any non-readonly opens. */
7583 if (info_level != SMB_POSIX_PATH_OPEN) {
7584 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7588 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7589 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7590 fsp ? fsp->fnum : -1, info_level, total_data));
7592 switch (info_level) {
7594 case SMB_INFO_STANDARD:
7596 status = smb_set_info_standard(conn,
7597 pdata,
7598 total_data,
7599 fsp,
7600 smb_fname);
7601 break;
7604 case SMB_INFO_SET_EA:
7606 status = smb_info_set_ea(conn,
7607 pdata,
7608 total_data,
7609 fsp,
7610 smb_fname);
7611 break;
7614 case SMB_SET_FILE_BASIC_INFO:
7615 case SMB_FILE_BASIC_INFORMATION:
7617 status = smb_set_file_basic_info(conn,
7618 pdata,
7619 total_data,
7620 fsp,
7621 smb_fname);
7622 break;
7625 case SMB_FILE_ALLOCATION_INFORMATION:
7626 case SMB_SET_FILE_ALLOCATION_INFO:
7628 status = smb_set_file_allocation_info(conn, req,
7629 pdata,
7630 total_data,
7631 fsp,
7632 smb_fname);
7633 break;
7636 case SMB_FILE_END_OF_FILE_INFORMATION:
7637 case SMB_SET_FILE_END_OF_FILE_INFO:
7640 * XP/Win7 both fail after the createfile with
7641 * SMB_SET_FILE_END_OF_FILE_INFO but not
7642 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7643 * The level is known here, so pass it down
7644 * appropriately.
7646 bool should_fail =
7647 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7649 status = smb_set_file_end_of_file_info(conn, req,
7650 pdata,
7651 total_data,
7652 fsp,
7653 smb_fname,
7654 should_fail);
7655 break;
7658 case SMB_FILE_DISPOSITION_INFORMATION:
7659 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7661 #if 0
7662 /* JRA - We used to just ignore this on a path ?
7663 * Shouldn't this be invalid level on a pathname
7664 * based call ?
7666 if (tran_call != TRANSACT2_SETFILEINFO) {
7667 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7669 #endif
7670 status = smb_set_file_disposition_info(conn,
7671 pdata,
7672 total_data,
7673 fsp,
7674 smb_fname);
7675 break;
7678 case SMB_FILE_POSITION_INFORMATION:
7680 status = smb_file_position_information(conn,
7681 pdata,
7682 total_data,
7683 fsp);
7684 break;
7687 case SMB_FILE_FULL_EA_INFORMATION:
7689 status = smb_set_file_full_ea_info(conn,
7690 pdata,
7691 total_data,
7692 fsp);
7693 break;
7696 /* From tridge Samba4 :
7697 * MODE_INFORMATION in setfileinfo (I have no
7698 * idea what "mode information" on a file is - it takes a value of 0,
7699 * 2, 4 or 6. What could it be?).
7702 case SMB_FILE_MODE_INFORMATION:
7704 status = smb_file_mode_information(conn,
7705 pdata,
7706 total_data);
7707 break;
7711 * CIFS UNIX extensions.
7714 case SMB_SET_FILE_UNIX_BASIC:
7716 status = smb_set_file_unix_basic(conn, req,
7717 pdata,
7718 total_data,
7719 fsp,
7720 smb_fname);
7721 break;
7724 case SMB_SET_FILE_UNIX_INFO2:
7726 status = smb_set_file_unix_info2(conn, req,
7727 pdata,
7728 total_data,
7729 fsp,
7730 smb_fname);
7731 break;
7734 case SMB_SET_FILE_UNIX_LINK:
7736 if (fsp) {
7737 /* We must have a pathname for this. */
7738 return NT_STATUS_INVALID_LEVEL;
7740 status = smb_set_file_unix_link(conn, req, pdata,
7741 total_data, smb_fname);
7742 break;
7745 case SMB_SET_FILE_UNIX_HLINK:
7747 if (fsp) {
7748 /* We must have a pathname for this. */
7749 return NT_STATUS_INVALID_LEVEL;
7751 status = smb_set_file_unix_hlink(conn, req,
7752 pdata, total_data,
7753 smb_fname);
7754 break;
7757 case SMB_FILE_RENAME_INFORMATION:
7759 status = smb_file_rename_information(conn, req,
7760 pdata, total_data,
7761 fsp, smb_fname);
7762 break;
7765 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7767 /* SMB2 rename information. */
7768 status = smb2_file_rename_information(conn, req,
7769 pdata, total_data,
7770 fsp, smb_fname);
7771 break;
7774 case SMB_FILE_LINK_INFORMATION:
7776 status = smb_file_link_information(conn, req,
7777 pdata, total_data,
7778 fsp, smb_fname);
7779 break;
7782 #if defined(HAVE_POSIX_ACLS)
7783 case SMB_SET_POSIX_ACL:
7785 status = smb_set_posix_acl(conn,
7786 pdata,
7787 total_data,
7788 fsp,
7789 smb_fname);
7790 break;
7792 #endif
7794 case SMB_SET_POSIX_LOCK:
7796 if (!fsp) {
7797 return NT_STATUS_INVALID_LEVEL;
7799 status = smb_set_posix_lock(conn, req,
7800 pdata, total_data, fsp);
7801 break;
7804 case SMB_POSIX_PATH_OPEN:
7806 if (fsp) {
7807 /* We must have a pathname for this. */
7808 return NT_STATUS_INVALID_LEVEL;
7811 status = smb_posix_open(conn, req,
7812 ppdata,
7813 total_data,
7814 smb_fname,
7815 &data_return_size);
7816 break;
7819 case SMB_POSIX_PATH_UNLINK:
7821 if (fsp) {
7822 /* We must have a pathname for this. */
7823 return NT_STATUS_INVALID_LEVEL;
7826 status = smb_posix_unlink(conn, req,
7827 pdata,
7828 total_data,
7829 smb_fname);
7830 break;
7833 default:
7834 return NT_STATUS_INVALID_LEVEL;
7837 if (!NT_STATUS_IS_OK(status)) {
7838 return status;
7841 *ret_data_size = data_return_size;
7842 return NT_STATUS_OK;
7845 /****************************************************************************
7846 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7847 ****************************************************************************/
7849 static void call_trans2setfilepathinfo(connection_struct *conn,
7850 struct smb_request *req,
7851 unsigned int tran_call,
7852 char **pparams, int total_params,
7853 char **ppdata, int total_data,
7854 unsigned int max_data_bytes)
7856 char *params = *pparams;
7857 char *pdata = *ppdata;
7858 uint16 info_level;
7859 struct smb_filename *smb_fname = NULL;
7860 files_struct *fsp = NULL;
7861 NTSTATUS status = NT_STATUS_OK;
7862 int data_return_size = 0;
7864 if (!params) {
7865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7866 return;
7869 if (tran_call == TRANSACT2_SETFILEINFO) {
7870 if (total_params < 4) {
7871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7872 return;
7875 fsp = file_fsp(req, SVAL(params,0));
7876 /* Basic check for non-null fsp. */
7877 if (!check_fsp_open(conn, req, fsp)) {
7878 return;
7880 info_level = SVAL(params,2);
7882 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7883 &smb_fname);
7884 if (!NT_STATUS_IS_OK(status)) {
7885 reply_nterror(req, status);
7886 return;
7889 if(fsp->fh->fd == -1) {
7891 * This is actually a SETFILEINFO on a directory
7892 * handle (returned from an NT SMB). NT5.0 seems
7893 * to do this call. JRA.
7895 if (INFO_LEVEL_IS_UNIX(info_level)) {
7896 /* Always do lstat for UNIX calls. */
7897 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7898 DEBUG(3,("call_trans2setfilepathinfo: "
7899 "SMB_VFS_LSTAT of %s failed "
7900 "(%s)\n",
7901 smb_fname_str_dbg(smb_fname),
7902 strerror(errno)));
7903 reply_nterror(req, map_nt_error_from_unix(errno));
7904 return;
7906 } else {
7907 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7908 DEBUG(3,("call_trans2setfilepathinfo: "
7909 "fileinfo of %s failed (%s)\n",
7910 smb_fname_str_dbg(smb_fname),
7911 strerror(errno)));
7912 reply_nterror(req, map_nt_error_from_unix(errno));
7913 return;
7916 } else if (fsp->print_file) {
7918 * Doing a DELETE_ON_CLOSE should cancel a print job.
7920 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7921 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7923 DEBUG(3,("call_trans2setfilepathinfo: "
7924 "Cancelling print job (%s)\n",
7925 fsp_str_dbg(fsp)));
7927 SSVAL(params,0,0);
7928 send_trans2_replies(conn, req, params, 2,
7929 *ppdata, 0,
7930 max_data_bytes);
7931 return;
7932 } else {
7933 reply_nterror(req,
7934 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7935 return;
7937 } else {
7939 * Original code - this is an open file.
7941 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7942 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7943 "of fnum %d failed (%s)\n", fsp->fnum,
7944 strerror(errno)));
7945 reply_nterror(req, map_nt_error_from_unix(errno));
7946 return;
7949 } else {
7950 char *fname = NULL;
7952 /* set path info */
7953 if (total_params < 7) {
7954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7955 return;
7958 info_level = SVAL(params,0);
7959 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7960 total_params - 6, STR_TERMINATE,
7961 &status);
7962 if (!NT_STATUS_IS_OK(status)) {
7963 reply_nterror(req, status);
7964 return;
7967 status = filename_convert(req, conn,
7968 req->flags2 & FLAGS2_DFS_PATHNAMES,
7969 fname,
7971 NULL,
7972 &smb_fname);
7973 if (!NT_STATUS_IS_OK(status)) {
7974 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7975 reply_botherror(req,
7976 NT_STATUS_PATH_NOT_COVERED,
7977 ERRSRV, ERRbadpath);
7978 return;
7980 reply_nterror(req, status);
7981 return;
7984 if (INFO_LEVEL_IS_UNIX(info_level)) {
7986 * For CIFS UNIX extensions the target name may not exist.
7989 /* Always do lstat for UNIX calls. */
7990 SMB_VFS_LSTAT(conn, smb_fname);
7992 } else if (!VALID_STAT(smb_fname->st) &&
7993 SMB_VFS_STAT(conn, smb_fname)) {
7994 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7995 "%s failed (%s)\n",
7996 smb_fname_str_dbg(smb_fname),
7997 strerror(errno)));
7998 reply_nterror(req, map_nt_error_from_unix(errno));
7999 return;
8003 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8004 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8005 fsp ? fsp->fnum : -1, info_level,total_data));
8007 /* Realloc the parameter size */
8008 *pparams = (char *)SMB_REALLOC(*pparams,2);
8009 if (*pparams == NULL) {
8010 reply_nterror(req, NT_STATUS_NO_MEMORY);
8011 return;
8013 params = *pparams;
8015 SSVAL(params,0,0);
8017 status = smbd_do_setfilepathinfo(conn, req, req,
8018 info_level,
8019 fsp,
8020 smb_fname,
8021 ppdata, total_data,
8022 &data_return_size);
8023 if (!NT_STATUS_IS_OK(status)) {
8024 if (open_was_deferred(req->mid)) {
8025 /* We have re-scheduled this call. */
8026 return;
8028 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8029 /* We have re-scheduled this call. */
8030 return;
8032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8033 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8034 ERRSRV, ERRbadpath);
8035 return;
8037 if (info_level == SMB_POSIX_PATH_OPEN) {
8038 reply_openerror(req, status);
8039 return;
8042 reply_nterror(req, status);
8043 return;
8046 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8047 max_data_bytes);
8049 return;
8052 /****************************************************************************
8053 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8054 ****************************************************************************/
8056 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8057 char **pparams, int total_params,
8058 char **ppdata, int total_data,
8059 unsigned int max_data_bytes)
8061 struct smb_filename *smb_dname = NULL;
8062 char *params = *pparams;
8063 char *pdata = *ppdata;
8064 char *directory = NULL;
8065 NTSTATUS status = NT_STATUS_OK;
8066 struct ea_list *ea_list = NULL;
8067 TALLOC_CTX *ctx = talloc_tos();
8069 if (!CAN_WRITE(conn)) {
8070 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8071 return;
8074 if (total_params < 5) {
8075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8076 return;
8079 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8080 total_params - 4, STR_TERMINATE,
8081 &status);
8082 if (!NT_STATUS_IS_OK(status)) {
8083 reply_nterror(req, status);
8084 return;
8087 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8089 status = filename_convert(ctx,
8090 conn,
8091 req->flags2 & FLAGS2_DFS_PATHNAMES,
8092 directory,
8094 NULL,
8095 &smb_dname);
8097 if (!NT_STATUS_IS_OK(status)) {
8098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8099 reply_botherror(req,
8100 NT_STATUS_PATH_NOT_COVERED,
8101 ERRSRV, ERRbadpath);
8102 return;
8104 reply_nterror(req, status);
8105 return;
8109 * OS/2 workplace shell seems to send SET_EA requests of "null"
8110 * length (4 bytes containing IVAL 4).
8111 * They seem to have no effect. Bug #3212. JRA.
8114 if (total_data && (total_data != 4)) {
8115 /* Any data in this call is an EA list. */
8116 if (total_data < 10) {
8117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8118 goto out;
8121 if (IVAL(pdata,0) > total_data) {
8122 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8123 IVAL(pdata,0), (unsigned int)total_data));
8124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8125 goto out;
8128 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8129 total_data - 4);
8130 if (!ea_list) {
8131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8132 goto out;
8135 if (!lp_ea_support(SNUM(conn))) {
8136 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8137 goto out;
8140 /* If total_data == 4 Windows doesn't care what values
8141 * are placed in that field, it just ignores them.
8142 * The System i QNTC IBM SMB client puts bad values here,
8143 * so ignore them. */
8145 status = create_directory(conn, req, smb_dname);
8147 if (!NT_STATUS_IS_OK(status)) {
8148 reply_nterror(req, status);
8149 goto out;
8152 /* Try and set any given EA. */
8153 if (ea_list) {
8154 status = set_ea(conn, NULL, smb_dname, ea_list);
8155 if (!NT_STATUS_IS_OK(status)) {
8156 reply_nterror(req, status);
8157 goto out;
8161 /* Realloc the parameter and data sizes */
8162 *pparams = (char *)SMB_REALLOC(*pparams,2);
8163 if(*pparams == NULL) {
8164 reply_nterror(req, NT_STATUS_NO_MEMORY);
8165 goto out;
8167 params = *pparams;
8169 SSVAL(params,0,0);
8171 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8173 out:
8174 TALLOC_FREE(smb_dname);
8175 return;
8178 /****************************************************************************
8179 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8180 We don't actually do this - we just send a null response.
8181 ****************************************************************************/
8183 static void call_trans2findnotifyfirst(connection_struct *conn,
8184 struct smb_request *req,
8185 char **pparams, int total_params,
8186 char **ppdata, int total_data,
8187 unsigned int max_data_bytes)
8189 char *params = *pparams;
8190 uint16 info_level;
8192 if (total_params < 6) {
8193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8194 return;
8197 info_level = SVAL(params,4);
8198 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8200 switch (info_level) {
8201 case 1:
8202 case 2:
8203 break;
8204 default:
8205 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8206 return;
8209 /* Realloc the parameter and data sizes */
8210 *pparams = (char *)SMB_REALLOC(*pparams,6);
8211 if (*pparams == NULL) {
8212 reply_nterror(req, NT_STATUS_NO_MEMORY);
8213 return;
8215 params = *pparams;
8217 SSVAL(params,0,fnf_handle);
8218 SSVAL(params,2,0); /* No changes */
8219 SSVAL(params,4,0); /* No EA errors */
8221 fnf_handle++;
8223 if(fnf_handle == 0)
8224 fnf_handle = 257;
8226 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8228 return;
8231 /****************************************************************************
8232 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8233 changes). Currently this does nothing.
8234 ****************************************************************************/
8236 static void call_trans2findnotifynext(connection_struct *conn,
8237 struct smb_request *req,
8238 char **pparams, int total_params,
8239 char **ppdata, int total_data,
8240 unsigned int max_data_bytes)
8242 char *params = *pparams;
8244 DEBUG(3,("call_trans2findnotifynext\n"));
8246 /* Realloc the parameter and data sizes */
8247 *pparams = (char *)SMB_REALLOC(*pparams,4);
8248 if (*pparams == NULL) {
8249 reply_nterror(req, NT_STATUS_NO_MEMORY);
8250 return;
8252 params = *pparams;
8254 SSVAL(params,0,0); /* No changes */
8255 SSVAL(params,2,0); /* No EA errors */
8257 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8259 return;
8262 /****************************************************************************
8263 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8264 ****************************************************************************/
8266 static void call_trans2getdfsreferral(connection_struct *conn,
8267 struct smb_request *req,
8268 char **pparams, int total_params,
8269 char **ppdata, int total_data,
8270 unsigned int max_data_bytes)
8272 char *params = *pparams;
8273 char *pathname = NULL;
8274 int reply_size = 0;
8275 int max_referral_level;
8276 NTSTATUS status = NT_STATUS_OK;
8277 TALLOC_CTX *ctx = talloc_tos();
8279 DEBUG(10,("call_trans2getdfsreferral\n"));
8281 if (total_params < 3) {
8282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8283 return;
8286 max_referral_level = SVAL(params,0);
8288 if(!lp_host_msdfs()) {
8289 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8290 return;
8293 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8294 total_params - 2, STR_TERMINATE);
8295 if (!pathname) {
8296 reply_nterror(req, NT_STATUS_NOT_FOUND);
8297 return;
8299 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8300 ppdata,&status)) < 0) {
8301 reply_nterror(req, status);
8302 return;
8305 SSVAL(req->inbuf, smb_flg2,
8306 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8307 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8309 return;
8312 #define LMCAT_SPL 0x53
8313 #define LMFUNC_GETJOBID 0x60
8315 /****************************************************************************
8316 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8317 ****************************************************************************/
8319 static void call_trans2ioctl(connection_struct *conn,
8320 struct smb_request *req,
8321 char **pparams, int total_params,
8322 char **ppdata, int total_data,
8323 unsigned int max_data_bytes)
8325 char *pdata = *ppdata;
8326 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8328 /* check for an invalid fid before proceeding */
8330 if (!fsp) {
8331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8332 return;
8335 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8336 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8337 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8338 if (*ppdata == NULL) {
8339 reply_nterror(req, NT_STATUS_NO_MEMORY);
8340 return;
8342 pdata = *ppdata;
8344 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8345 CAN ACCEPT THIS IN UNICODE. JRA. */
8347 /* Job number */
8348 if (fsp->print_file) {
8349 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8350 } else {
8351 SSVAL(pdata, 0, 0);
8353 srvstr_push(pdata, req->flags2, pdata + 2,
8354 global_myname(), 15,
8355 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8356 srvstr_push(pdata, req->flags2, pdata+18,
8357 lp_servicename(SNUM(conn)), 13,
8358 STR_ASCII|STR_TERMINATE); /* Service name */
8359 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8360 max_data_bytes);
8361 return;
8364 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8365 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8368 /****************************************************************************
8369 Reply to a SMBfindclose (stop trans2 directory search).
8370 ****************************************************************************/
8372 void reply_findclose(struct smb_request *req)
8374 int dptr_num;
8375 struct smbd_server_connection *sconn = req->sconn;
8377 START_PROFILE(SMBfindclose);
8379 if (req->wct < 1) {
8380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8381 END_PROFILE(SMBfindclose);
8382 return;
8385 dptr_num = SVALS(req->vwv+0, 0);
8387 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8389 dptr_close(sconn, &dptr_num);
8391 reply_outbuf(req, 0, 0);
8393 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8395 END_PROFILE(SMBfindclose);
8396 return;
8399 /****************************************************************************
8400 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8401 ****************************************************************************/
8403 void reply_findnclose(struct smb_request *req)
8405 int dptr_num;
8407 START_PROFILE(SMBfindnclose);
8409 if (req->wct < 1) {
8410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8411 END_PROFILE(SMBfindnclose);
8412 return;
8415 dptr_num = SVAL(req->vwv+0, 0);
8417 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8419 /* We never give out valid handles for a
8420 findnotifyfirst - so any dptr_num is ok here.
8421 Just ignore it. */
8423 reply_outbuf(req, 0, 0);
8425 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8427 END_PROFILE(SMBfindnclose);
8428 return;
8431 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8432 struct trans_state *state)
8434 if (get_Protocol() >= PROTOCOL_NT1) {
8435 req->flags2 |= 0x40; /* IS_LONG_NAME */
8436 SSVAL(req->inbuf,smb_flg2,req->flags2);
8439 if (conn->encrypt_level == Required && !req->encrypted) {
8440 if (state->call != TRANSACT2_QFSINFO &&
8441 state->call != TRANSACT2_SETFSINFO) {
8442 DEBUG(0,("handle_trans2: encryption required "
8443 "with call 0x%x\n",
8444 (unsigned int)state->call));
8445 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8446 return;
8450 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8452 /* Now we must call the relevant TRANS2 function */
8453 switch(state->call) {
8454 case TRANSACT2_OPEN:
8456 START_PROFILE(Trans2_open);
8457 call_trans2open(conn, req,
8458 &state->param, state->total_param,
8459 &state->data, state->total_data,
8460 state->max_data_return);
8461 END_PROFILE(Trans2_open);
8462 break;
8465 case TRANSACT2_FINDFIRST:
8467 START_PROFILE(Trans2_findfirst);
8468 call_trans2findfirst(conn, req,
8469 &state->param, state->total_param,
8470 &state->data, state->total_data,
8471 state->max_data_return);
8472 END_PROFILE(Trans2_findfirst);
8473 break;
8476 case TRANSACT2_FINDNEXT:
8478 START_PROFILE(Trans2_findnext);
8479 call_trans2findnext(conn, req,
8480 &state->param, state->total_param,
8481 &state->data, state->total_data,
8482 state->max_data_return);
8483 END_PROFILE(Trans2_findnext);
8484 break;
8487 case TRANSACT2_QFSINFO:
8489 START_PROFILE(Trans2_qfsinfo);
8490 call_trans2qfsinfo(conn, req,
8491 &state->param, state->total_param,
8492 &state->data, state->total_data,
8493 state->max_data_return);
8494 END_PROFILE(Trans2_qfsinfo);
8495 break;
8498 case TRANSACT2_SETFSINFO:
8500 START_PROFILE(Trans2_setfsinfo);
8501 call_trans2setfsinfo(conn, req,
8502 &state->param, state->total_param,
8503 &state->data, state->total_data,
8504 state->max_data_return);
8505 END_PROFILE(Trans2_setfsinfo);
8506 break;
8509 case TRANSACT2_QPATHINFO:
8510 case TRANSACT2_QFILEINFO:
8512 START_PROFILE(Trans2_qpathinfo);
8513 call_trans2qfilepathinfo(conn, req, state->call,
8514 &state->param, state->total_param,
8515 &state->data, state->total_data,
8516 state->max_data_return);
8517 END_PROFILE(Trans2_qpathinfo);
8518 break;
8521 case TRANSACT2_SETPATHINFO:
8522 case TRANSACT2_SETFILEINFO:
8524 START_PROFILE(Trans2_setpathinfo);
8525 call_trans2setfilepathinfo(conn, req, state->call,
8526 &state->param, state->total_param,
8527 &state->data, state->total_data,
8528 state->max_data_return);
8529 END_PROFILE(Trans2_setpathinfo);
8530 break;
8533 case TRANSACT2_FINDNOTIFYFIRST:
8535 START_PROFILE(Trans2_findnotifyfirst);
8536 call_trans2findnotifyfirst(conn, req,
8537 &state->param, state->total_param,
8538 &state->data, state->total_data,
8539 state->max_data_return);
8540 END_PROFILE(Trans2_findnotifyfirst);
8541 break;
8544 case TRANSACT2_FINDNOTIFYNEXT:
8546 START_PROFILE(Trans2_findnotifynext);
8547 call_trans2findnotifynext(conn, req,
8548 &state->param, state->total_param,
8549 &state->data, state->total_data,
8550 state->max_data_return);
8551 END_PROFILE(Trans2_findnotifynext);
8552 break;
8555 case TRANSACT2_MKDIR:
8557 START_PROFILE(Trans2_mkdir);
8558 call_trans2mkdir(conn, req,
8559 &state->param, state->total_param,
8560 &state->data, state->total_data,
8561 state->max_data_return);
8562 END_PROFILE(Trans2_mkdir);
8563 break;
8566 case TRANSACT2_GET_DFS_REFERRAL:
8568 START_PROFILE(Trans2_get_dfs_referral);
8569 call_trans2getdfsreferral(conn, req,
8570 &state->param, state->total_param,
8571 &state->data, state->total_data,
8572 state->max_data_return);
8573 END_PROFILE(Trans2_get_dfs_referral);
8574 break;
8577 case TRANSACT2_IOCTL:
8579 START_PROFILE(Trans2_ioctl);
8580 call_trans2ioctl(conn, req,
8581 &state->param, state->total_param,
8582 &state->data, state->total_data,
8583 state->max_data_return);
8584 END_PROFILE(Trans2_ioctl);
8585 break;
8588 default:
8589 /* Error in request */
8590 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8591 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8595 /****************************************************************************
8596 Reply to a SMBtrans2.
8597 ****************************************************************************/
8599 void reply_trans2(struct smb_request *req)
8601 connection_struct *conn = req->conn;
8602 unsigned int dsoff;
8603 unsigned int dscnt;
8604 unsigned int psoff;
8605 unsigned int pscnt;
8606 unsigned int tran_call;
8607 struct trans_state *state;
8608 NTSTATUS result;
8610 START_PROFILE(SMBtrans2);
8612 if (req->wct < 14) {
8613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8614 END_PROFILE(SMBtrans2);
8615 return;
8618 dsoff = SVAL(req->vwv+12, 0);
8619 dscnt = SVAL(req->vwv+11, 0);
8620 psoff = SVAL(req->vwv+10, 0);
8621 pscnt = SVAL(req->vwv+9, 0);
8622 tran_call = SVAL(req->vwv+14, 0);
8624 result = allow_new_trans(conn->pending_trans, req->mid);
8625 if (!NT_STATUS_IS_OK(result)) {
8626 DEBUG(2, ("Got invalid trans2 request: %s\n",
8627 nt_errstr(result)));
8628 reply_nterror(req, result);
8629 END_PROFILE(SMBtrans2);
8630 return;
8633 if (IS_IPC(conn)) {
8634 switch (tran_call) {
8635 /* List the allowed trans2 calls on IPC$ */
8636 case TRANSACT2_OPEN:
8637 case TRANSACT2_GET_DFS_REFERRAL:
8638 case TRANSACT2_QFILEINFO:
8639 case TRANSACT2_QFSINFO:
8640 case TRANSACT2_SETFSINFO:
8641 break;
8642 default:
8643 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8644 END_PROFILE(SMBtrans2);
8645 return;
8649 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8650 DEBUG(0, ("talloc failed\n"));
8651 reply_nterror(req, NT_STATUS_NO_MEMORY);
8652 END_PROFILE(SMBtrans2);
8653 return;
8656 state->cmd = SMBtrans2;
8658 state->mid = req->mid;
8659 state->vuid = req->vuid;
8660 state->setup_count = SVAL(req->vwv+13, 0);
8661 state->setup = NULL;
8662 state->total_param = SVAL(req->vwv+0, 0);
8663 state->param = NULL;
8664 state->total_data = SVAL(req->vwv+1, 0);
8665 state->data = NULL;
8666 state->max_param_return = SVAL(req->vwv+2, 0);
8667 state->max_data_return = SVAL(req->vwv+3, 0);
8668 state->max_setup_return = SVAL(req->vwv+4, 0);
8669 state->close_on_completion = BITSETW(req->vwv+5, 0);
8670 state->one_way = BITSETW(req->vwv+5, 1);
8672 state->call = tran_call;
8674 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8675 is so as a sanity check */
8676 if (state->setup_count != 1) {
8678 * Need to have rc=0 for ioctl to get job id for OS/2.
8679 * Network printing will fail if function is not successful.
8680 * Similar function in reply.c will be used if protocol
8681 * is LANMAN1.0 instead of LM1.2X002.
8682 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8683 * outbuf doesn't have to be set(only job id is used).
8685 if ( (state->setup_count == 4)
8686 && (tran_call == TRANSACT2_IOCTL)
8687 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8688 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8689 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8690 } else {
8691 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8692 DEBUG(2,("Transaction is %d\n",tran_call));
8693 TALLOC_FREE(state);
8694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8695 END_PROFILE(SMBtrans2);
8696 return;
8700 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8701 goto bad_param;
8703 if (state->total_data) {
8705 if (trans_oob(state->total_data, 0, dscnt)
8706 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8707 goto bad_param;
8710 /* Can't use talloc here, the core routines do realloc on the
8711 * params and data. */
8712 state->data = (char *)SMB_MALLOC(state->total_data);
8713 if (state->data == NULL) {
8714 DEBUG(0,("reply_trans2: data malloc fail for %u "
8715 "bytes !\n", (unsigned int)state->total_data));
8716 TALLOC_FREE(state);
8717 reply_nterror(req, NT_STATUS_NO_MEMORY);
8718 END_PROFILE(SMBtrans2);
8719 return;
8722 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8725 if (state->total_param) {
8727 if (trans_oob(state->total_param, 0, pscnt)
8728 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8729 goto bad_param;
8732 /* Can't use talloc here, the core routines do realloc on the
8733 * params and data. */
8734 state->param = (char *)SMB_MALLOC(state->total_param);
8735 if (state->param == NULL) {
8736 DEBUG(0,("reply_trans: param malloc fail for %u "
8737 "bytes !\n", (unsigned int)state->total_param));
8738 SAFE_FREE(state->data);
8739 TALLOC_FREE(state);
8740 reply_nterror(req, NT_STATUS_NO_MEMORY);
8741 END_PROFILE(SMBtrans2);
8742 return;
8745 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8748 state->received_data = dscnt;
8749 state->received_param = pscnt;
8751 if ((state->received_param == state->total_param) &&
8752 (state->received_data == state->total_data)) {
8754 handle_trans2(conn, req, state);
8756 SAFE_FREE(state->data);
8757 SAFE_FREE(state->param);
8758 TALLOC_FREE(state);
8759 END_PROFILE(SMBtrans2);
8760 return;
8763 DLIST_ADD(conn->pending_trans, state);
8765 /* We need to send an interim response then receive the rest
8766 of the parameter/data bytes */
8767 reply_outbuf(req, 0, 0);
8768 show_msg((char *)req->outbuf);
8769 END_PROFILE(SMBtrans2);
8770 return;
8772 bad_param:
8774 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8775 SAFE_FREE(state->data);
8776 SAFE_FREE(state->param);
8777 TALLOC_FREE(state);
8778 END_PROFILE(SMBtrans2);
8779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8783 /****************************************************************************
8784 Reply to a SMBtranss2
8785 ****************************************************************************/
8787 void reply_transs2(struct smb_request *req)
8789 connection_struct *conn = req->conn;
8790 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8791 struct trans_state *state;
8793 START_PROFILE(SMBtranss2);
8795 show_msg((char *)req->inbuf);
8797 if (req->wct < 8) {
8798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8799 END_PROFILE(SMBtranss2);
8800 return;
8803 for (state = conn->pending_trans; state != NULL;
8804 state = state->next) {
8805 if (state->mid == req->mid) {
8806 break;
8810 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8812 END_PROFILE(SMBtranss2);
8813 return;
8816 /* Revise state->total_param and state->total_data in case they have
8817 changed downwards */
8819 if (SVAL(req->vwv+0, 0) < state->total_param)
8820 state->total_param = SVAL(req->vwv+0, 0);
8821 if (SVAL(req->vwv+1, 0) < state->total_data)
8822 state->total_data = SVAL(req->vwv+1, 0);
8824 pcnt = SVAL(req->vwv+2, 0);
8825 poff = SVAL(req->vwv+3, 0);
8826 pdisp = SVAL(req->vwv+4, 0);
8828 dcnt = SVAL(req->vwv+5, 0);
8829 doff = SVAL(req->vwv+6, 0);
8830 ddisp = SVAL(req->vwv+7, 0);
8832 state->received_param += pcnt;
8833 state->received_data += dcnt;
8835 if ((state->received_data > state->total_data) ||
8836 (state->received_param > state->total_param))
8837 goto bad_param;
8839 if (pcnt) {
8840 if (trans_oob(state->total_param, pdisp, pcnt)
8841 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8842 goto bad_param;
8844 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8847 if (dcnt) {
8848 if (trans_oob(state->total_data, ddisp, dcnt)
8849 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8850 goto bad_param;
8852 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8855 if ((state->received_param < state->total_param) ||
8856 (state->received_data < state->total_data)) {
8857 END_PROFILE(SMBtranss2);
8858 return;
8861 handle_trans2(conn, req, state);
8863 DLIST_REMOVE(conn->pending_trans, state);
8864 SAFE_FREE(state->data);
8865 SAFE_FREE(state->param);
8866 TALLOC_FREE(state);
8868 END_PROFILE(SMBtranss2);
8869 return;
8871 bad_param:
8873 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8874 DLIST_REMOVE(conn->pending_trans, state);
8875 SAFE_FREE(state->data);
8876 SAFE_FREE(state->param);
8877 TALLOC_FREE(state);
8878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8879 END_PROFILE(SMBtranss2);
8880 return;