Same fix as bug 8989 - Samba 3.5.x (and probably all other versions of Samba) does...
[Samba.git] / source3 / smbd / trans2.c
blob602280d9c18c2809a1126e73ded06ce982c45928
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 "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
57 return val;
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
68 uint64_t file_index;
69 if (conn->base_share_dev == psbuf->st_ex_dev) {
70 return (uint64_t)psbuf->st_ex_ino;
72 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
73 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
74 return file_index;
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name)
87 static const char * const prohibited_ea_names[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME,
89 SAMBA_XATTR_DOS_ATTRIB,
90 SAMBA_XATTR_MARKER,
91 XATTR_NTACL_NAME,
92 NULL
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return true;
101 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
103 return true;
105 return false;
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
113 files_struct *fsp, const char *fname,
114 const char *ea_name, struct ea_struct *pea)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size = 256;
118 char *val = NULL;
119 ssize_t sizeret;
121 again:
123 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
124 if (!val) {
125 return NT_STATUS_NO_MEMORY;
128 if (fsp && fsp->fh->fd != -1) {
129 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
130 } else {
131 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
134 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
135 attr_size = 65536;
136 goto again;
139 if (sizeret == -1) {
140 return map_nt_error_from_unix(errno);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
144 dump_data(10, (uint8 *)val, sizeret);
146 pea->flags = 0;
147 if (strnequal(ea_name, "user.", 5)) {
148 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
149 } else {
150 pea->name = talloc_strdup(mem_ctx, ea_name);
152 if (pea->name == NULL) {
153 TALLOC_FREE(val);
154 return NT_STATUS_NO_MEMORY;
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
158 return NT_STATUS_OK;
161 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
162 files_struct *fsp, const char *fname,
163 char ***pnames, size_t *pnum_names)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size = 1024;
167 char *ea_namelist = NULL;
169 char *p;
170 char **names, **tmp;
171 size_t num_names;
172 ssize_t sizeret = -1;
174 if (!lp_ea_support(SNUM(conn))) {
175 if (pnames) {
176 *pnames = NULL;
178 *pnum_names = 0;
179 return NT_STATUS_OK;
183 * TALLOC the result early to get the talloc hierarchy right.
186 names = TALLOC_ARRAY(mem_ctx, char *, 1);
187 if (names == NULL) {
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY;
192 while (ea_namelist_size <= 65536) {
194 ea_namelist = TALLOC_REALLOC_ARRAY(
195 names, ea_namelist, char, ea_namelist_size);
196 if (ea_namelist == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 TALLOC_FREE(names);
199 return NT_STATUS_NO_MEMORY;
202 if (fsp && fsp->fh->fd != -1) {
203 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
204 ea_namelist_size);
205 } else {
206 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
207 ea_namelist_size);
210 if ((sizeret == -1) && (errno == ERANGE)) {
211 ea_namelist_size *= 2;
213 else {
214 break;
218 if (sizeret == -1) {
219 TALLOC_FREE(names);
220 return map_nt_error_from_unix(errno);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret));
226 if (sizeret == 0) {
227 TALLOC_FREE(names);
228 if (pnames) {
229 *pnames = NULL;
231 *pnum_names = 0;
232 return NT_STATUS_OK;
236 * Ensure the result is 0-terminated
239 if (ea_namelist[sizeret-1] != '\0') {
240 TALLOC_FREE(names);
241 return NT_STATUS_INTERNAL_ERROR;
245 * count the names
247 num_names = 0;
249 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
250 num_names += 1;
253 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
254 if (tmp == NULL) {
255 DEBUG(0, ("talloc failed\n"));
256 TALLOC_FREE(names);
257 return NT_STATUS_NO_MEMORY;
260 names = tmp;
261 num_names = 0;
263 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
264 names[num_names++] = p;
267 if (pnames) {
268 *pnames = names;
269 } else {
270 TALLOC_FREE(names);
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
396 char *pdata,
397 unsigned int total_data_size,
398 unsigned int *ret_data_size,
399 connection_struct *conn,
400 struct ea_list *ea_list)
402 uint8_t *p = (uint8_t *)pdata;
403 uint8_t *last_start = NULL;
405 *ret_data_size = 0;
407 if (!lp_ea_support(SNUM(conn))) {
408 return NT_STATUS_NO_EAS_ON_FILE;
411 for (; ea_list; ea_list = ea_list->next) {
412 size_t dos_namelen;
413 fstring dos_ea_name;
414 size_t this_size;
416 if (last_start) {
417 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
419 last_start = p;
421 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
422 dos_namelen = strlen(dos_ea_name);
423 if (dos_namelen > 255 || dos_namelen == 0) {
424 return NT_STATUS_INTERNAL_ERROR;
426 if (ea_list->ea.value.length > 65535) {
427 return NT_STATUS_INTERNAL_ERROR;
430 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
432 if (ea_list->next) {
433 size_t pad = 4 - (this_size % 4);
434 this_size += pad;
437 if (this_size > total_data_size) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH;
441 /* We know we have room. */
442 SIVAL(p, 0x00, 0); /* next offset */
443 SCVAL(p, 0x04, ea_list->ea.flags);
444 SCVAL(p, 0x05, dos_namelen);
445 SSVAL(p, 0x06, ea_list->ea.value.length);
446 fstrcpy((char *)(p+0x08), dos_ea_name);
447 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
449 total_data_size -= this_size;
450 p += this_size;
453 *ret_data_size = PTR_DIFF(p, pdata);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
455 return NT_STATUS_OK;
458 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
460 size_t total_ea_len = 0;
461 TALLOC_CTX *mem_ctx = NULL;
463 if (!lp_ea_support(SNUM(conn))) {
464 return 0;
466 mem_ctx = talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
468 return total_ea_len;
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
477 size_t total_ea_len;
478 TALLOC_CTX *mem_ctx = talloc_tos();
479 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
481 for (; ea_list; ea_list = ea_list->next) {
482 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name[5], ea_list->ea.name));
485 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
486 break;
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
496 const struct smb_filename *smb_fname, struct ea_list *ea_list)
498 char *fname = NULL;
500 if (!lp_ea_support(SNUM(conn))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED;
504 /* For now setting EAs on streams isn't supported. */
505 fname = smb_fname->base_name;
507 for (;ea_list; ea_list = ea_list->next) {
508 int ret;
509 fstring unix_ea_name;
511 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name, ea_list->ea.name);
514 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
518 if (samba_private_attr_name(unix_ea_name)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
520 return NT_STATUS_ACCESS_DENIED;
523 if (ea_list->ea.value.length == 0) {
524 /* Remove the attribute. */
525 if (fsp && (fsp->fh->fd != -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name, fsp_str_dbg(fsp)));
529 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
530 } else {
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name, fname));
533 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
535 #ifdef ENOATTR
536 /* Removing a non existent attribute always succeeds. */
537 if (ret == -1 && errno == ENOATTR) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
539 unix_ea_name));
540 ret = 0;
542 #endif
543 } else {
544 if (fsp && (fsp->fh->fd != -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name, fsp_str_dbg(fsp)));
548 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
549 ea_list->ea.value.data, ea_list->ea.value.length, 0);
550 } else {
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name, fname));
553 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
554 ea_list->ea.value.data, ea_list->ea.value.length, 0);
558 if (ret == -1) {
559 #ifdef ENOTSUP
560 if (errno == ENOTSUP) {
561 return NT_STATUS_EAS_NOT_SUPPORTED;
563 #endif
564 return map_nt_error_from_unix(errno);
568 return NT_STATUS_OK;
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
576 struct ea_list *ea_list_head = NULL;
577 size_t converted_size, offset = 0;
579 while (offset + 2 < data_size) {
580 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
581 unsigned int namelen = CVAL(pdata,offset);
583 offset++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
587 (offset > data_size) || (namelen > data_size) ||
588 (offset + namelen >= data_size)) {
589 break;
591 /* Ensure the name is null terminated. */
592 if (pdata[offset + namelen] != '\0') {
593 return NULL;
595 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
596 &converted_size)) {
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno)));
600 if (!eal->ea.name) {
601 return NULL;
604 offset += (namelen + 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
609 return ea_list_head;
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
618 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
619 uint16 val_len;
620 unsigned int namelen;
621 size_t converted_size;
623 if (!eal) {
624 return NULL;
627 if (data_size < 6) {
628 return NULL;
631 eal->ea.flags = CVAL(pdata,0);
632 namelen = CVAL(pdata,1);
633 val_len = SVAL(pdata,2);
635 if (4 + namelen + 1 + val_len > data_size) {
636 return NULL;
639 /* Ensure the name is null terminated. */
640 if (pdata[namelen + 4] != '\0') {
641 return NULL;
643 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
645 strerror(errno)));
647 if (!eal->ea.name) {
648 return NULL;
651 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
652 if (!eal->ea.value.data) {
653 return NULL;
656 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal->ea.value.data[val_len] = '\0';
660 /* But don't count the null. */
661 eal->ea.value.length--;
663 if (pbytes_used) {
664 *pbytes_used = 4 + namelen + 1 + val_len;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
668 dump_data(10, eal->ea.value.data, eal->ea.value.length);
670 return eal;
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
679 struct ea_list *ea_list_head = NULL;
680 size_t offset = 0;
681 size_t bytes_used = 0;
683 while (offset < data_size) {
684 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
686 if (!eal) {
687 return NULL;
690 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
691 offset += bytes_used;
694 return ea_list_head;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list *ealist)
703 fstring dos_ea_name;
704 struct ea_list *listp;
705 size_t ret = 0;
707 for (listp = ealist; listp; listp = listp->next) {
708 push_ascii_fstring(dos_ea_name, listp->ea.name);
709 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
711 /* Add on 4 for total length. */
712 if (ret) {
713 ret += 4;
716 return ret;
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
727 struct ea_list *nlistp, *flistp;
729 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
730 for (flistp = file_list; flistp; flistp = flistp->next) {
731 if (strequal(nlistp->ea.name, flistp->ea.name)) {
732 break;
736 if (flistp) {
737 /* Copy the data from this entry. */
738 nlistp->ea.flags = flistp->ea.flags;
739 nlistp->ea.value = flistp->ea.value;
740 } else {
741 /* Null entry. */
742 nlistp->ea.flags = 0;
743 ZERO_STRUCT(nlistp->ea.value);
747 *total_ea_len = ea_list_size(name_list);
748 return name_list;
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct *conn,
759 struct smb_request *req,
760 const char *params,
761 int paramsize,
762 const char *pdata,
763 int datasize,
764 int max_data_bytes)
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send = datasize;
773 int params_to_send = paramsize;
774 int useable_space;
775 const char *pp = params;
776 const char *pd = pdata;
777 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
778 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset = 0;
780 bool overflow = False;
781 struct smbd_server_connection *sconn = smbd_server_conn;
782 int max_send = sconn->smb1.sessions.max_send;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
787 for OS/2. */
789 if (max_data_bytes > 0 && datasize > max_data_bytes) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes, datasize ));
792 datasize = data_to_send = max_data_bytes;
793 overflow = True;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send == 0 && data_to_send == 0) {
799 reply_outbuf(req, 10, 0);
800 show_msg((char *)req->outbuf);
801 if (!srv_send_smb(smbd_server_fd(),
802 (char *)req->outbuf,
803 true, req->seqnum+1,
804 IS_CONN_ENCRYPTED(conn),
805 &req->pcd)) {
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req->outbuf);
809 return;
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send % 4) != 0) && (data_to_send != 0))
817 data_alignment_offset = 4 - (params_to_send % 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space = max_send - (smb_size
824 + 2 * 10 /* wct */
825 + alignment_offset
826 + data_alignment_offset);
828 if (useable_space < 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send || data_to_send) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime = params_to_send + data_to_send;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime = MIN(total_sent_thistime, useable_space);
849 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
850 + data_alignment_offset);
852 /* Set total params and data to be sent */
853 SSVAL(req->outbuf,smb_tprcnt,paramsize);
854 SSVAL(req->outbuf,smb_tdrcnt,datasize);
856 /* Calculate how many parameters and data we can fit into
857 * this packet. Parameters get precedence
860 params_sent_thistime = MIN(params_to_send,useable_space);
861 data_sent_thistime = useable_space - params_sent_thistime;
862 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
864 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
866 /* smb_proff is the offset from the start of the SMB header to the
867 parameter bytes, however the first 4 bytes of outbuf are
868 the Netbios over TCP header. Thus use smb_base() to subtract
869 them from the calculation */
871 SSVAL(req->outbuf,smb_proff,
872 ((smb_buf(req->outbuf)+alignment_offset)
873 - smb_base(req->outbuf)));
875 if(params_sent_thistime == 0)
876 SSVAL(req->outbuf,smb_prdisp,0);
877 else
878 /* Absolute displacement of param bytes sent in this packet */
879 SSVAL(req->outbuf,smb_prdisp,pp - params);
881 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
882 if(data_sent_thistime == 0) {
883 SSVAL(req->outbuf,smb_droff,0);
884 SSVAL(req->outbuf,smb_drdisp, 0);
885 } else {
886 /* The offset of the data bytes is the offset of the
887 parameter bytes plus the number of parameters being sent this time */
888 SSVAL(req->outbuf, smb_droff,
889 ((smb_buf(req->outbuf)+alignment_offset)
890 - smb_base(req->outbuf))
891 + params_sent_thistime + data_alignment_offset);
892 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
895 /* Initialize the padding for alignment */
897 if (alignment_offset != 0) {
898 memset(smb_buf(req->outbuf), 0, alignment_offset);
901 /* Copy the param bytes into the packet */
903 if(params_sent_thistime) {
904 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
905 params_sent_thistime);
908 /* Copy in the data bytes */
909 if(data_sent_thistime) {
910 if (data_alignment_offset != 0) {
911 memset((smb_buf(req->outbuf)+alignment_offset+
912 params_sent_thistime), 0,
913 data_alignment_offset);
915 memcpy(smb_buf(req->outbuf)+alignment_offset
916 +params_sent_thistime+data_alignment_offset,
917 pd,data_sent_thistime);
920 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
921 params_sent_thistime, data_sent_thistime, useable_space));
922 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
923 params_to_send, data_to_send, paramsize, datasize));
925 if (overflow) {
926 error_packet_set((char *)req->outbuf,
927 ERRDOS,ERRbufferoverflow,
928 STATUS_BUFFER_OVERFLOW,
929 __LINE__,__FILE__);
932 /* Send the packet */
933 show_msg((char *)req->outbuf);
934 if (!srv_send_smb(smbd_server_fd(),
935 (char *)req->outbuf,
936 true, req->seqnum+1,
937 IS_CONN_ENCRYPTED(conn),
938 &req->pcd))
939 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
941 TALLOC_FREE(req->outbuf);
943 pp += params_sent_thistime;
944 pd += data_sent_thistime;
946 params_to_send -= params_sent_thistime;
947 data_to_send -= data_sent_thistime;
949 /* Sanity check */
950 if(params_to_send < 0 || data_to_send < 0) {
951 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
952 params_to_send, data_to_send));
953 return;
957 return;
960 /****************************************************************************
961 Reply to a TRANSACT2_OPEN.
962 ****************************************************************************/
964 static void call_trans2open(connection_struct *conn,
965 struct smb_request *req,
966 char **pparams, int total_params,
967 char **ppdata, int total_data,
968 unsigned int max_data_bytes)
970 struct smb_filename *smb_fname = NULL;
971 char *params = *pparams;
972 char *pdata = *ppdata;
973 int deny_mode;
974 int32 open_attr;
975 bool oplock_request;
976 #if 0
977 bool return_additional_info;
978 int16 open_sattr;
979 time_t open_time;
980 #endif
981 int open_ofun;
982 uint32 open_size;
983 char *pname;
984 char *fname = NULL;
985 SMB_OFF_T size=0;
986 int fattr=0,mtime=0;
987 SMB_INO_T inode = 0;
988 int smb_action = 0;
989 files_struct *fsp;
990 struct ea_list *ea_list = NULL;
991 uint16 flags = 0;
992 NTSTATUS status;
993 uint32 access_mask;
994 uint32 share_mode;
995 uint32 create_disposition;
996 uint32 create_options = 0;
997 TALLOC_CTX *ctx = talloc_tos();
1000 * Ensure we have enough parameters to perform the operation.
1003 if (total_params < 29) {
1004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1005 goto out;
1008 flags = SVAL(params, 0);
1009 deny_mode = SVAL(params, 2);
1010 open_attr = SVAL(params,6);
1011 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1012 if (oplock_request) {
1013 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1016 #if 0
1017 return_additional_info = BITSETW(params,0);
1018 open_sattr = SVAL(params, 4);
1019 open_time = make_unix_date3(params+8);
1020 #endif
1021 open_ofun = SVAL(params,12);
1022 open_size = IVAL(params,14);
1023 pname = &params[28];
1025 if (IS_IPC(conn)) {
1026 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1027 goto out;
1030 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1031 total_params - 28, STR_TERMINATE,
1032 &status);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 reply_nterror(req, status);
1035 goto out;
1038 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1039 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1040 (unsigned int)open_ofun, open_size));
1042 status = filename_convert(ctx,
1043 conn,
1044 req->flags2 & FLAGS2_DFS_PATHNAMES,
1045 fname,
1047 NULL,
1048 &smb_fname);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1051 reply_botherror(req,
1052 NT_STATUS_PATH_NOT_COVERED,
1053 ERRSRV, ERRbadpath);
1054 goto out;
1056 reply_nterror(req, status);
1057 goto out;
1060 if (open_ofun == 0) {
1061 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1062 goto out;
1065 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1066 open_ofun,
1067 &access_mask, &share_mode,
1068 &create_disposition,
1069 &create_options)) {
1070 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1071 goto out;
1074 /* Any data in this call is an EA list. */
1075 if (total_data && (total_data != 4)) {
1076 if (total_data < 10) {
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1078 goto out;
1081 if (IVAL(pdata,0) > total_data) {
1082 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1083 IVAL(pdata,0), (unsigned int)total_data));
1084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 goto out;
1088 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1089 total_data - 4);
1090 if (!ea_list) {
1091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1092 goto out;
1095 if (!lp_ea_support(SNUM(conn))) {
1096 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1097 goto out;
1101 status = SMB_VFS_CREATE_FILE(
1102 conn, /* conn */
1103 req, /* req */
1104 0, /* root_dir_fid */
1105 smb_fname, /* fname */
1106 access_mask, /* access_mask */
1107 share_mode, /* share_access */
1108 create_disposition, /* create_disposition*/
1109 create_options, /* create_options */
1110 open_attr, /* file_attributes */
1111 oplock_request, /* oplock_request */
1112 open_size, /* allocation_size */
1113 NULL, /* sd */
1114 ea_list, /* ea_list */
1115 &fsp, /* result */
1116 &smb_action); /* psbuf */
1118 if (!NT_STATUS_IS_OK(status)) {
1119 if (open_was_deferred(req->mid)) {
1120 /* We have re-scheduled this call. */
1121 goto out;
1123 reply_openerror(req, status);
1124 goto out;
1127 size = get_file_size_stat(&smb_fname->st);
1128 fattr = dos_mode(conn, smb_fname);
1129 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1130 inode = smb_fname->st.st_ex_ino;
1131 if (fattr & aDIR) {
1132 close_file(req, fsp, ERROR_CLOSE);
1133 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1134 goto out;
1137 /* Realloc the size of parameters and data we will return */
1138 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1139 if(*pparams == NULL ) {
1140 reply_nterror(req, NT_STATUS_NO_MEMORY);
1141 goto out;
1143 params = *pparams;
1145 SSVAL(params,0,fsp->fnum);
1146 SSVAL(params,2,fattr);
1147 srv_put_dos_date2(params,4, mtime);
1148 SIVAL(params,8, (uint32)size);
1149 SSVAL(params,12,deny_mode);
1150 SSVAL(params,14,0); /* open_type - file or directory. */
1151 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1153 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1154 smb_action |= EXTENDED_OPLOCK_GRANTED;
1157 SSVAL(params,18,smb_action);
1160 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1162 SIVAL(params,20,inode);
1163 SSVAL(params,24,0); /* Padding. */
1164 if (flags & 8) {
1165 uint32 ea_size = estimate_ea_size(conn, fsp,
1166 fsp->fsp_name->base_name);
1167 SIVAL(params, 26, ea_size);
1168 } else {
1169 SIVAL(params, 26, 0);
1172 /* Send the required number of replies */
1173 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1174 out:
1175 TALLOC_FREE(smb_fname);
1178 /*********************************************************
1179 Routine to check if a given string matches exactly.
1180 as a special case a mask of "." does NOT match. That
1181 is required for correct wildcard semantics
1182 Case can be significant or not.
1183 **********************************************************/
1185 static bool exact_match(bool has_wild,
1186 bool case_sensitive,
1187 const char *str,
1188 const char *mask)
1190 if (mask[0] == '.' && mask[1] == 0) {
1191 return false;
1194 if (has_wild) {
1195 return false;
1198 if (case_sensitive) {
1199 return strcmp(str,mask)==0;
1200 } else {
1201 return StrCaseCmp(str,mask) == 0;
1205 /****************************************************************************
1206 Return the filetype for UNIX extensions.
1207 ****************************************************************************/
1209 static uint32 unix_filetype(mode_t mode)
1211 if(S_ISREG(mode))
1212 return UNIX_TYPE_FILE;
1213 else if(S_ISDIR(mode))
1214 return UNIX_TYPE_DIR;
1215 #ifdef S_ISLNK
1216 else if(S_ISLNK(mode))
1217 return UNIX_TYPE_SYMLINK;
1218 #endif
1219 #ifdef S_ISCHR
1220 else if(S_ISCHR(mode))
1221 return UNIX_TYPE_CHARDEV;
1222 #endif
1223 #ifdef S_ISBLK
1224 else if(S_ISBLK(mode))
1225 return UNIX_TYPE_BLKDEV;
1226 #endif
1227 #ifdef S_ISFIFO
1228 else if(S_ISFIFO(mode))
1229 return UNIX_TYPE_FIFO;
1230 #endif
1231 #ifdef S_ISSOCK
1232 else if(S_ISSOCK(mode))
1233 return UNIX_TYPE_SOCKET;
1234 #endif
1236 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1237 return UNIX_TYPE_UNKNOWN;
1240 /****************************************************************************
1241 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1242 ****************************************************************************/
1244 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1246 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1247 const SMB_STRUCT_STAT *psbuf,
1248 uint32 perms,
1249 enum perm_type ptype,
1250 mode_t *ret_perms)
1252 mode_t ret = 0;
1254 if (perms == SMB_MODE_NO_CHANGE) {
1255 if (!VALID_STAT(*psbuf)) {
1256 return NT_STATUS_INVALID_PARAMETER;
1257 } else {
1258 *ret_perms = psbuf->st_ex_mode;
1259 return NT_STATUS_OK;
1263 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1264 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1265 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1266 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1267 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1268 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1269 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1270 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1271 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1272 #ifdef S_ISVTX
1273 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1274 #endif
1275 #ifdef S_ISGID
1276 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1277 #endif
1278 #ifdef S_ISUID
1279 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1280 #endif
1282 switch (ptype) {
1283 case PERM_NEW_FILE:
1284 /* Apply mode mask */
1285 ret &= lp_create_mask(SNUM(conn));
1286 /* Add in force bits */
1287 ret |= lp_force_create_mode(SNUM(conn));
1288 break;
1289 case PERM_NEW_DIR:
1290 ret &= lp_dir_mask(SNUM(conn));
1291 /* Add in force bits */
1292 ret |= lp_force_dir_mode(SNUM(conn));
1293 break;
1294 case PERM_EXISTING_FILE:
1295 /* Apply mode mask */
1296 ret &= lp_security_mask(SNUM(conn));
1297 /* Add in force bits */
1298 ret |= lp_force_security_mode(SNUM(conn));
1299 break;
1300 case PERM_EXISTING_DIR:
1301 /* Apply mode mask */
1302 ret &= lp_dir_security_mask(SNUM(conn));
1303 /* Add in force bits */
1304 ret |= lp_force_dir_security_mode(SNUM(conn));
1305 break;
1308 *ret_perms = ret;
1309 return NT_STATUS_OK;
1312 /****************************************************************************
1313 Needed to show the msdfs symlinks as directories. Modifies psbuf
1314 to be a directory if it's a msdfs link.
1315 ****************************************************************************/
1317 static bool check_msdfs_link(connection_struct *conn,
1318 const char *pathname,
1319 SMB_STRUCT_STAT *psbuf)
1321 int saved_errno = errno;
1322 if(lp_host_msdfs() &&
1323 lp_msdfs_root(SNUM(conn)) &&
1324 is_msdfs_link(conn, pathname, psbuf)) {
1326 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1327 "as a directory\n",
1328 pathname));
1329 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1330 errno = saved_errno;
1331 return true;
1333 errno = saved_errno;
1334 return false;
1338 /****************************************************************************
1339 Get a level dependent lanman2 dir entry.
1340 ****************************************************************************/
1342 struct smbd_dirptr_lanman2_state {
1343 connection_struct *conn;
1344 uint32_t info_level;
1345 bool check_mangled_names;
1346 bool has_wild;
1347 bool got_exact_match;
1350 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1351 void *private_data,
1352 const char *dname,
1353 const char *mask,
1354 char **_fname)
1356 struct smbd_dirptr_lanman2_state *state =
1357 (struct smbd_dirptr_lanman2_state *)private_data;
1358 bool ok;
1359 char mangled_name[13]; /* mangled 8.3 name. */
1360 bool got_match;
1361 const char *fname;
1363 /* Mangle fname if it's an illegal name. */
1364 if (mangle_must_mangle(dname, state->conn->params)) {
1365 ok = name_to_8_3(dname, mangled_name,
1366 true, state->conn->params);
1367 if (!ok) {
1368 return false;
1370 fname = mangled_name;
1371 } else {
1372 fname = dname;
1375 got_match = exact_match(state->has_wild,
1376 state->conn->case_sensitive,
1377 fname, mask);
1378 state->got_exact_match = got_match;
1379 if (!got_match) {
1380 got_match = mask_match(fname, mask,
1381 state->conn->case_sensitive);
1384 if(!got_match && state->check_mangled_names &&
1385 !mangle_is_8_3(fname, false, state->conn->params)) {
1387 * It turns out that NT matches wildcards against
1388 * both long *and* short names. This may explain some
1389 * of the wildcard wierdness from old DOS clients
1390 * that some people have been seeing.... JRA.
1392 /* Force the mangling into 8.3. */
1393 ok = name_to_8_3(fname, mangled_name,
1394 false, state->conn->params);
1395 if (!ok) {
1396 return false;
1399 got_match = exact_match(state->has_wild,
1400 state->conn->case_sensitive,
1401 mangled_name, mask);
1402 state->got_exact_match = got_match;
1403 if (!got_match) {
1404 got_match = mask_match(mangled_name, mask,
1405 state->conn->case_sensitive);
1409 if (!got_match) {
1410 return false;
1413 *_fname = talloc_strdup(ctx, fname);
1414 if (*_fname == NULL) {
1415 return false;
1418 return true;
1421 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1422 void *private_data,
1423 struct smb_filename *smb_fname,
1424 uint32_t *_mode)
1426 struct smbd_dirptr_lanman2_state *state =
1427 (struct smbd_dirptr_lanman2_state *)private_data;
1428 bool ms_dfs_link = false;
1429 uint32_t mode = 0;
1431 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1432 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1433 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1434 "Couldn't lstat [%s] (%s)\n",
1435 smb_fname_str_dbg(smb_fname),
1436 strerror(errno)));
1437 return false;
1439 } else if (!VALID_STAT(smb_fname->st) &&
1440 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1441 /* Needed to show the msdfs symlinks as
1442 * directories */
1444 ms_dfs_link = check_msdfs_link(state->conn,
1445 smb_fname->base_name,
1446 &smb_fname->st);
1447 if (!ms_dfs_link) {
1448 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1449 "Couldn't stat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname),
1451 strerror(errno)));
1452 return false;
1456 if (ms_dfs_link) {
1457 mode = dos_mode_msdfs(state->conn, smb_fname);
1458 } else {
1459 mode = dos_mode(state->conn, smb_fname);
1462 *_mode = mode;
1463 return true;
1466 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1467 connection_struct *conn,
1468 uint16_t flags2,
1469 uint32_t info_level,
1470 struct ea_list *name_list,
1471 bool check_mangled_names,
1472 bool requires_resume_key,
1473 uint32_t mode,
1474 const char *fname,
1475 const struct smb_filename *smb_fname,
1476 uint64_t space_remaining,
1477 uint8_t align,
1478 bool do_pad,
1479 char *base_data,
1480 char **ppdata,
1481 char *end_data,
1482 bool *out_of_space,
1483 uint64_t *last_entry_off)
1485 char *p, *q, *pdata = *ppdata;
1486 uint32_t reskey=0;
1487 uint64_t file_size = 0;
1488 uint64_t allocation_size = 0;
1489 uint64_t file_index = 0;
1490 uint32_t len;
1491 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1492 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1493 time_t c_date = (time_t)0;
1494 char *nameptr;
1495 char *last_entry_ptr;
1496 bool was_8_3;
1497 off_t off;
1498 off_t pad = 0;
1500 *out_of_space = false;
1502 ZERO_STRUCT(mdate_ts);
1503 ZERO_STRUCT(adate_ts);
1504 ZERO_STRUCT(create_date_ts);
1505 ZERO_STRUCT(cdate_ts);
1507 if (!(mode & aDIR)) {
1508 file_size = get_file_size_stat(&smb_fname->st);
1510 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1512 file_index = get_FileIndex(conn, &smb_fname->st);
1514 mdate_ts = smb_fname->st.st_ex_mtime;
1515 adate_ts = smb_fname->st.st_ex_atime;
1516 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1517 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1519 if (lp_dos_filetime_resolution(SNUM(conn))) {
1520 dos_filetime_timespec(&create_date_ts);
1521 dos_filetime_timespec(&mdate_ts);
1522 dos_filetime_timespec(&adate_ts);
1523 dos_filetime_timespec(&cdate_ts);
1526 create_date = convert_timespec_to_time_t(create_date_ts);
1527 mdate = convert_timespec_to_time_t(mdate_ts);
1528 adate = convert_timespec_to_time_t(adate_ts);
1529 c_date = convert_timespec_to_time_t(cdate_ts);
1531 /* align the record */
1532 off = PTR_DIFF(pdata, base_data);
1533 pad = (off + (align-1)) & ~(align-1);
1534 pad -= off;
1535 off += pad;
1536 /* initialize padding to 0 */
1537 if (pad) {
1538 memset(pdata, 0, pad);
1540 space_remaining -= pad;
1542 pdata += pad;
1543 p = pdata;
1544 last_entry_ptr = p;
1546 pad = 0;
1547 off = 0;
1549 switch (info_level) {
1550 case SMB_FIND_INFO_STANDARD:
1551 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1552 if(requires_resume_key) {
1553 SIVAL(p,0,reskey);
1554 p += 4;
1556 srv_put_dos_date2(p,0,create_date);
1557 srv_put_dos_date2(p,4,adate);
1558 srv_put_dos_date2(p,8,mdate);
1559 SIVAL(p,12,(uint32)file_size);
1560 SIVAL(p,16,(uint32)allocation_size);
1561 SSVAL(p,20,mode);
1562 p += 23;
1563 nameptr = p;
1564 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1565 p += ucs2_align(base_data, p, 0);
1567 len = srvstr_push(base_data, flags2, p,
1568 fname, PTR_DIFF(end_data, p),
1569 STR_TERMINATE);
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 if (len > 2) {
1572 SCVAL(nameptr, -1, len - 2);
1573 } else {
1574 SCVAL(nameptr, -1, 0);
1576 } else {
1577 if (len > 1) {
1578 SCVAL(nameptr, -1, len - 1);
1579 } else {
1580 SCVAL(nameptr, -1, 0);
1583 p += len;
1584 break;
1586 case SMB_FIND_EA_SIZE:
1587 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1588 if (requires_resume_key) {
1589 SIVAL(p,0,reskey);
1590 p += 4;
1592 srv_put_dos_date2(p,0,create_date);
1593 srv_put_dos_date2(p,4,adate);
1594 srv_put_dos_date2(p,8,mdate);
1595 SIVAL(p,12,(uint32)file_size);
1596 SIVAL(p,16,(uint32)allocation_size);
1597 SSVAL(p,20,mode);
1599 unsigned int ea_size = estimate_ea_size(conn, NULL,
1600 smb_fname->base_name);
1601 SIVAL(p,22,ea_size); /* Extended attributes */
1603 p += 27;
1604 nameptr = p - 1;
1605 len = srvstr_push(base_data, flags2,
1606 p, fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE | STR_NOALIGN);
1608 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 if (len > 2) {
1610 len -= 2;
1611 } else {
1612 len = 0;
1614 } else {
1615 if (len > 1) {
1616 len -= 1;
1617 } else {
1618 len = 0;
1621 SCVAL(nameptr,0,len);
1622 p += len;
1623 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1624 break;
1626 case SMB_FIND_EA_LIST:
1628 struct ea_list *file_list = NULL;
1629 size_t ea_len = 0;
1631 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1632 if (!name_list) {
1633 return false;
1635 if (requires_resume_key) {
1636 SIVAL(p,0,reskey);
1637 p += 4;
1639 srv_put_dos_date2(p,0,create_date);
1640 srv_put_dos_date2(p,4,adate);
1641 srv_put_dos_date2(p,8,mdate);
1642 SIVAL(p,12,(uint32)file_size);
1643 SIVAL(p,16,(uint32)allocation_size);
1644 SSVAL(p,20,mode);
1645 p += 22; /* p now points to the EA area. */
1647 file_list = get_ea_list_from_file(ctx, conn, NULL,
1648 smb_fname->base_name,
1649 &ea_len);
1650 name_list = ea_list_union(name_list, file_list, &ea_len);
1652 /* We need to determine if this entry will fit in the space available. */
1653 /* Max string size is 255 bytes. */
1654 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1655 *out_of_space = true;
1656 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1657 return False; /* Not finished - just out of space */
1660 /* Push the ea_data followed by the name. */
1661 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1662 nameptr = p;
1663 len = srvstr_push(base_data, flags2,
1664 p + 1, fname, PTR_DIFF(end_data, p+1),
1665 STR_TERMINATE | STR_NOALIGN);
1666 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1667 if (len > 2) {
1668 len -= 2;
1669 } else {
1670 len = 0;
1672 } else {
1673 if (len > 1) {
1674 len -= 1;
1675 } else {
1676 len = 0;
1679 SCVAL(nameptr,0,len);
1680 p += len + 1;
1681 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1682 break;
1685 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1686 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1687 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1688 p += 4;
1689 SIVAL(p,0,reskey); p += 4;
1690 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1691 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1692 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1693 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1694 SOFF_T(p,0,file_size); p += 8;
1695 SOFF_T(p,0,allocation_size); p += 8;
1696 SIVAL(p,0,mode); p += 4;
1697 q = p; p += 4; /* q is placeholder for name length. */
1699 unsigned int ea_size = estimate_ea_size(conn, NULL,
1700 smb_fname->base_name);
1701 SIVAL(p,0,ea_size); /* Extended attributes */
1702 p += 4;
1704 /* Clear the short name buffer. This is
1705 * IMPORTANT as not doing so will trigger
1706 * a Win2k client bug. JRA.
1708 if (!was_8_3 && check_mangled_names) {
1709 char mangled_name[13]; /* mangled 8.3 name. */
1710 if (!name_to_8_3(fname,mangled_name,True,
1711 conn->params)) {
1712 /* Error - mangle failed ! */
1713 memset(mangled_name,'\0',12);
1715 mangled_name[12] = 0;
1716 len = srvstr_push(base_data, flags2,
1717 p+2, mangled_name, 24,
1718 STR_UPPER|STR_UNICODE);
1719 if (len < 24) {
1720 memset(p + 2 + len,'\0',24 - len);
1722 SSVAL(p, 0, len);
1723 } else {
1724 memset(p,'\0',26);
1726 p += 2 + 24;
1727 len = srvstr_push(base_data, flags2, p,
1728 fname, PTR_DIFF(end_data, p),
1729 STR_TERMINATE_ASCII);
1730 SIVAL(q,0,len);
1731 p += len;
1733 len = PTR_DIFF(p, pdata);
1734 pad = (len + (align-1)) & ~(align-1);
1736 * offset to the next entry, the caller
1737 * will overwrite it for the last entry
1738 * that's why we always include the padding
1740 SIVAL(pdata,0,pad);
1742 * set padding to zero
1744 if (do_pad) {
1745 memset(p, 0, pad - len);
1746 p = pdata + pad;
1747 } else {
1748 p = pdata + len;
1750 break;
1752 case SMB_FIND_FILE_DIRECTORY_INFO:
1753 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1754 p += 4;
1755 SIVAL(p,0,reskey); p += 4;
1756 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1760 SOFF_T(p,0,file_size); p += 8;
1761 SOFF_T(p,0,allocation_size); p += 8;
1762 SIVAL(p,0,mode); p += 4;
1763 len = srvstr_push(base_data, flags2,
1764 p + 4, fname, PTR_DIFF(end_data, p+4),
1765 STR_TERMINATE_ASCII);
1766 SIVAL(p,0,len);
1767 p += 4 + len;
1769 len = PTR_DIFF(p, pdata);
1770 pad = (len + (align-1)) & ~(align-1);
1772 * offset to the next entry, the caller
1773 * will overwrite it for the last entry
1774 * that's why we always include the padding
1776 SIVAL(pdata,0,pad);
1778 * set padding to zero
1780 if (do_pad) {
1781 memset(p, 0, pad - len);
1782 p = pdata + pad;
1783 } else {
1784 p = pdata + len;
1786 break;
1788 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1789 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1790 p += 4;
1791 SIVAL(p,0,reskey); p += 4;
1792 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1793 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1794 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1795 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1796 SOFF_T(p,0,file_size); p += 8;
1797 SOFF_T(p,0,allocation_size); p += 8;
1798 SIVAL(p,0,mode); p += 4;
1799 q = p; p += 4; /* q is placeholder for name length. */
1801 unsigned int ea_size = estimate_ea_size(conn, NULL,
1802 smb_fname->base_name);
1803 SIVAL(p,0,ea_size); /* Extended attributes */
1804 p +=4;
1806 len = srvstr_push(base_data, flags2, p,
1807 fname, PTR_DIFF(end_data, p),
1808 STR_TERMINATE_ASCII);
1809 SIVAL(q, 0, len);
1810 p += len;
1812 len = PTR_DIFF(p, pdata);
1813 pad = (len + (align-1)) & ~(align-1);
1815 * offset to the next entry, the caller
1816 * will overwrite it for the last entry
1817 * that's why we always include the padding
1819 SIVAL(pdata,0,pad);
1821 * set padding to zero
1823 if (do_pad) {
1824 memset(p, 0, pad - len);
1825 p = pdata + pad;
1826 } else {
1827 p = pdata + len;
1829 break;
1831 case SMB_FIND_FILE_NAMES_INFO:
1832 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1833 p += 4;
1834 SIVAL(p,0,reskey); p += 4;
1835 p += 4;
1836 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1837 acl on a dir (tridge) */
1838 len = srvstr_push(base_data, flags2, p,
1839 fname, PTR_DIFF(end_data, p),
1840 STR_TERMINATE_ASCII);
1841 SIVAL(p, -4, len);
1842 p += len;
1844 len = PTR_DIFF(p, pdata);
1845 pad = (len + (align-1)) & ~(align-1);
1847 * offset to the next entry, the caller
1848 * will overwrite it for the last entry
1849 * that's why we always include the padding
1851 SIVAL(pdata,0,pad);
1853 * set padding to zero
1855 if (do_pad) {
1856 memset(p, 0, pad - len);
1857 p = pdata + pad;
1858 } else {
1859 p = pdata + len;
1861 break;
1863 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1864 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1865 p += 4;
1866 SIVAL(p,0,reskey); p += 4;
1867 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1868 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1869 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1870 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1871 SOFF_T(p,0,file_size); p += 8;
1872 SOFF_T(p,0,allocation_size); p += 8;
1873 SIVAL(p,0,mode); p += 4;
1874 q = p; p += 4; /* q is placeholder for name length. */
1876 unsigned int ea_size = estimate_ea_size(conn, NULL,
1877 smb_fname->base_name);
1878 SIVAL(p,0,ea_size); /* Extended attributes */
1879 p +=4;
1881 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1882 SBVAL(p,0,file_index); p += 8;
1883 len = srvstr_push(base_data, flags2, p,
1884 fname, PTR_DIFF(end_data, p),
1885 STR_TERMINATE_ASCII);
1886 SIVAL(q, 0, len);
1887 p += len;
1889 len = PTR_DIFF(p, pdata);
1890 pad = (len + (align-1)) & ~(align-1);
1892 * offset to the next entry, the caller
1893 * will overwrite it for the last entry
1894 * that's why we always include the padding
1896 SIVAL(pdata,0,pad);
1898 * set padding to zero
1900 if (do_pad) {
1901 memset(p, 0, pad - len);
1902 p = pdata + pad;
1903 } else {
1904 p = pdata + len;
1906 break;
1908 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1909 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1910 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1911 p += 4;
1912 SIVAL(p,0,reskey); p += 4;
1913 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1914 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1915 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1916 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1917 SOFF_T(p,0,file_size); p += 8;
1918 SOFF_T(p,0,allocation_size); p += 8;
1919 SIVAL(p,0,mode); p += 4;
1920 q = p; p += 4; /* q is placeholder for name length */
1922 unsigned int ea_size = estimate_ea_size(conn, NULL,
1923 smb_fname->base_name);
1924 SIVAL(p,0,ea_size); /* Extended attributes */
1925 p +=4;
1927 /* Clear the short name buffer. This is
1928 * IMPORTANT as not doing so will trigger
1929 * a Win2k client bug. JRA.
1931 if (!was_8_3 && check_mangled_names) {
1932 char mangled_name[13]; /* mangled 8.3 name. */
1933 if (!name_to_8_3(fname,mangled_name,True,
1934 conn->params)) {
1935 /* Error - mangle failed ! */
1936 memset(mangled_name,'\0',12);
1938 mangled_name[12] = 0;
1939 len = srvstr_push(base_data, flags2,
1940 p+2, mangled_name, 24,
1941 STR_UPPER|STR_UNICODE);
1942 SSVAL(p, 0, len);
1943 if (len < 24) {
1944 memset(p + 2 + len,'\0',24 - len);
1946 SSVAL(p, 0, len);
1947 } else {
1948 memset(p,'\0',26);
1950 p += 26;
1951 SSVAL(p,0,0); p += 2; /* Reserved ? */
1952 SBVAL(p,0,file_index); p += 8;
1953 len = srvstr_push(base_data, flags2, p,
1954 fname, PTR_DIFF(end_data, p),
1955 STR_TERMINATE_ASCII);
1956 SIVAL(q,0,len);
1957 p += len;
1959 len = PTR_DIFF(p, pdata);
1960 pad = (len + (align-1)) & ~(align-1);
1962 * offset to the next entry, the caller
1963 * will overwrite it for the last entry
1964 * that's why we always include the padding
1966 SIVAL(pdata,0,pad);
1968 * set padding to zero
1970 if (do_pad) {
1971 memset(p, 0, pad - len);
1972 p = pdata + pad;
1973 } else {
1974 p = pdata + len;
1976 break;
1978 /* CIFS UNIX Extension. */
1980 case SMB_FIND_FILE_UNIX:
1981 case SMB_FIND_FILE_UNIX_INFO2:
1982 p+= 4;
1983 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1985 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1987 if (info_level == SMB_FIND_FILE_UNIX) {
1988 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1989 p = store_file_unix_basic(conn, p,
1990 NULL, &smb_fname->st);
1991 len = srvstr_push(base_data, flags2, p,
1992 fname, PTR_DIFF(end_data, p),
1993 STR_TERMINATE);
1994 } else {
1995 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1996 p = store_file_unix_basic_info2(conn, p,
1997 NULL, &smb_fname->st);
1998 nameptr = p;
1999 p += 4;
2000 len = srvstr_push(base_data, flags2, p, fname,
2001 PTR_DIFF(end_data, p), 0);
2002 SIVAL(nameptr, 0, len);
2005 p += len;
2007 len = PTR_DIFF(p, pdata);
2008 pad = (len + (align-1)) & ~(align-1);
2010 * offset to the next entry, the caller
2011 * will overwrite it for the last entry
2012 * that's why we always include the padding
2014 SIVAL(pdata,0,pad);
2016 * set padding to zero
2018 if (do_pad) {
2019 memset(p, 0, pad - len);
2020 p = pdata + pad;
2021 } else {
2022 p = pdata + len;
2024 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2026 break;
2028 default:
2029 return false;
2032 if (PTR_DIFF(p,pdata) > space_remaining) {
2033 *out_of_space = true;
2034 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2035 return false; /* Not finished - just out of space */
2038 /* Setup the last entry pointer, as an offset from base_data */
2039 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2040 /* Advance the data pointer to the next slot */
2041 *ppdata = p;
2043 return true;
2046 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2047 connection_struct *conn,
2048 struct dptr_struct *dirptr,
2049 uint16 flags2,
2050 const char *path_mask,
2051 uint32 dirtype,
2052 int info_level,
2053 int requires_resume_key,
2054 bool dont_descend,
2055 bool ask_sharemode,
2056 uint8_t align,
2057 bool do_pad,
2058 char **ppdata,
2059 char *base_data,
2060 char *end_data,
2061 int space_remaining,
2062 bool *out_of_space,
2063 bool *got_exact_match,
2064 int *_last_entry_off,
2065 struct ea_list *name_list)
2067 const char *p;
2068 const char *mask = NULL;
2069 long prev_dirpos = 0;
2070 uint32_t mode = 0;
2071 char *fname = NULL;
2072 struct smb_filename *smb_fname = NULL;
2073 struct smbd_dirptr_lanman2_state state;
2074 bool ok;
2075 uint64_t last_entry_off = 0;
2077 ZERO_STRUCT(state);
2078 state.conn = conn;
2079 state.info_level = info_level;
2080 state.check_mangled_names = lp_manglednames(conn->params);
2081 state.has_wild = dptr_has_wild(dirptr);
2082 state.got_exact_match = false;
2084 *out_of_space = false;
2085 *got_exact_match = false;
2087 p = strrchr_m(path_mask,'/');
2088 if(p != NULL) {
2089 if(p[1] == '\0') {
2090 mask = "*.*";
2091 } else {
2092 mask = p+1;
2094 } else {
2095 mask = path_mask;
2098 ok = smbd_dirptr_get_entry(ctx,
2099 dirptr,
2100 mask,
2101 dirtype,
2102 dont_descend,
2103 ask_sharemode,
2104 smbd_dirptr_lanman2_match_fn,
2105 smbd_dirptr_lanman2_mode_fn,
2106 &state,
2107 &fname,
2108 &smb_fname,
2109 &mode,
2110 &prev_dirpos);
2111 if (!ok) {
2112 return false;
2115 *got_exact_match = state.got_exact_match;
2117 ok = smbd_marshall_dir_entry(ctx,
2118 conn,
2119 flags2,
2120 info_level,
2121 name_list,
2122 state.check_mangled_names,
2123 requires_resume_key,
2124 mode,
2125 fname,
2126 smb_fname,
2127 space_remaining,
2128 align,
2129 do_pad,
2130 base_data,
2131 ppdata,
2132 end_data,
2133 out_of_space,
2134 &last_entry_off);
2135 TALLOC_FREE(fname);
2136 TALLOC_FREE(smb_fname);
2137 if (*out_of_space) {
2138 dptr_SeekDir(dirptr, prev_dirpos);
2139 return false;
2141 if (!ok) {
2142 return false;
2145 *_last_entry_off = last_entry_off;
2146 return true;
2149 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2150 connection_struct *conn,
2151 struct dptr_struct *dirptr,
2152 uint16 flags2,
2153 const char *path_mask,
2154 uint32 dirtype,
2155 int info_level,
2156 bool requires_resume_key,
2157 bool dont_descend,
2158 bool ask_sharemode,
2159 char **ppdata,
2160 char *base_data,
2161 char *end_data,
2162 int space_remaining,
2163 bool *out_of_space,
2164 bool *got_exact_match,
2165 int *last_entry_off,
2166 struct ea_list *name_list)
2168 uint8_t align = 4;
2169 const bool do_pad = true;
2171 if (info_level >= 1 && info_level <= 3) {
2172 /* No alignment on earlier info levels. */
2173 align = 1;
2176 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2177 path_mask, dirtype, info_level,
2178 requires_resume_key, dont_descend, ask_sharemode,
2179 align, do_pad,
2180 ppdata, base_data, end_data,
2181 space_remaining,
2182 out_of_space, got_exact_match,
2183 last_entry_off, name_list);
2186 /****************************************************************************
2187 Reply to a TRANS2_FINDFIRST.
2188 ****************************************************************************/
2190 static void call_trans2findfirst(connection_struct *conn,
2191 struct smb_request *req,
2192 char **pparams, int total_params,
2193 char **ppdata, int total_data,
2194 unsigned int max_data_bytes)
2196 /* We must be careful here that we don't return more than the
2197 allowed number of data bytes. If this means returning fewer than
2198 maxentries then so be it. We assume that the redirector has
2199 enough room for the fixed number of parameter bytes it has
2200 requested. */
2201 struct smb_filename *smb_dname = NULL;
2202 char *params = *pparams;
2203 char *pdata = *ppdata;
2204 char *data_end;
2205 uint32 dirtype;
2206 int maxentries;
2207 uint16 findfirst_flags;
2208 bool close_after_first;
2209 bool close_if_end;
2210 bool requires_resume_key;
2211 int info_level;
2212 char *directory = NULL;
2213 char *mask = NULL;
2214 char *p;
2215 int last_entry_off=0;
2216 int dptr_num = -1;
2217 int numentries = 0;
2218 int i;
2219 bool finished = False;
2220 bool dont_descend = False;
2221 bool out_of_space = False;
2222 int space_remaining;
2223 bool mask_contains_wcard = False;
2224 struct ea_list *ea_list = NULL;
2225 NTSTATUS ntstatus = NT_STATUS_OK;
2226 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2227 TALLOC_CTX *ctx = talloc_tos();
2228 struct dptr_struct *dirptr = NULL;
2229 struct smbd_server_connection *sconn = smbd_server_conn;
2230 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2232 if (total_params < 13) {
2233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2234 goto out;
2237 dirtype = SVAL(params,0);
2238 maxentries = SVAL(params,2);
2239 findfirst_flags = SVAL(params,4);
2240 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2241 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2242 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2243 info_level = SVAL(params,6);
2245 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2246 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2247 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2248 info_level, max_data_bytes));
2250 if (!maxentries) {
2251 /* W2K3 seems to treat zero as 1. */
2252 maxentries = 1;
2255 switch (info_level) {
2256 case SMB_FIND_INFO_STANDARD:
2257 case SMB_FIND_EA_SIZE:
2258 case SMB_FIND_EA_LIST:
2259 case SMB_FIND_FILE_DIRECTORY_INFO:
2260 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2261 case SMB_FIND_FILE_NAMES_INFO:
2262 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2263 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2264 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2265 break;
2266 case SMB_FIND_FILE_UNIX:
2267 case SMB_FIND_FILE_UNIX_INFO2:
2268 /* Always use filesystem for UNIX mtime query. */
2269 ask_sharemode = false;
2270 if (!lp_unix_extensions()) {
2271 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2272 goto out;
2274 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2275 break;
2276 default:
2277 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2278 goto out;
2281 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2282 params+12, total_params - 12,
2283 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2284 if (!NT_STATUS_IS_OK(ntstatus)) {
2285 reply_nterror(req, ntstatus);
2286 goto out;
2289 ntstatus = filename_convert(ctx, conn,
2290 req->flags2 & FLAGS2_DFS_PATHNAMES,
2291 directory,
2292 ucf_flags,
2293 &mask_contains_wcard,
2294 &smb_dname);
2295 if (!NT_STATUS_IS_OK(ntstatus)) {
2296 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2297 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2298 ERRSRV, ERRbadpath);
2299 goto out;
2301 reply_nterror(req, ntstatus);
2302 goto out;
2305 mask = smb_dname->original_lcomp;
2307 directory = smb_dname->base_name;
2309 p = strrchr_m(directory,'/');
2310 if(p == NULL) {
2311 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2312 if((directory[0] == '.') && (directory[1] == '\0')) {
2313 mask = talloc_strdup(ctx,"*");
2314 if (!mask) {
2315 reply_nterror(req, NT_STATUS_NO_MEMORY);
2316 goto out;
2318 mask_contains_wcard = True;
2320 directory = talloc_strdup(talloc_tos(), "./");
2321 if (!directory) {
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2323 goto out;
2325 } else {
2326 *p = 0;
2329 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2331 if (info_level == SMB_FIND_EA_LIST) {
2332 uint32 ea_size;
2334 if (total_data < 4) {
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 goto out;
2339 ea_size = IVAL(pdata,0);
2340 if (ea_size != total_data) {
2341 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2342 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2344 goto out;
2347 if (!lp_ea_support(SNUM(conn))) {
2348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2349 goto out;
2352 /* Pull out the list of names. */
2353 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2354 if (!ea_list) {
2355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2356 goto out;
2360 *ppdata = (char *)SMB_REALLOC(
2361 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2362 if(*ppdata == NULL ) {
2363 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 goto out;
2366 pdata = *ppdata;
2367 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2369 /* Realloc the params space */
2370 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2371 if (*pparams == NULL) {
2372 reply_nterror(req, NT_STATUS_NO_MEMORY);
2373 goto out;
2375 params = *pparams;
2377 /* Save the wildcard match and attribs we are using on this directory -
2378 needed as lanman2 assumes these are being saved between calls */
2380 ntstatus = dptr_create(conn,
2381 directory,
2382 False,
2383 True,
2384 req->smbpid,
2385 mask,
2386 mask_contains_wcard,
2387 dirtype,
2388 &dirptr);
2390 if (!NT_STATUS_IS_OK(ntstatus)) {
2391 reply_nterror(req, ntstatus);
2392 goto out;
2395 dptr_num = dptr_dnum(dirptr);
2396 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2398 /* Initialize per TRANS2_FIND_FIRST operation data */
2399 dptr_init_search_op(dirptr);
2401 /* We don't need to check for VOL here as this is returned by
2402 a different TRANS2 call. */
2404 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2405 directory,lp_dontdescend(SNUM(conn))));
2406 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2407 dont_descend = True;
2409 p = pdata;
2410 space_remaining = max_data_bytes;
2411 out_of_space = False;
2413 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2414 bool got_exact_match = False;
2416 /* this is a heuristic to avoid seeking the dirptr except when
2417 absolutely necessary. It allows for a filename of about 40 chars */
2418 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2419 out_of_space = True;
2420 finished = False;
2421 } else {
2422 finished = !get_lanman2_dir_entry(ctx,
2423 conn,
2424 dirptr,
2425 req->flags2,
2426 mask,dirtype,info_level,
2427 requires_resume_key,dont_descend,
2428 ask_sharemode,
2429 &p,pdata,data_end,
2430 space_remaining, &out_of_space,
2431 &got_exact_match,
2432 &last_entry_off, ea_list);
2435 if (finished && out_of_space)
2436 finished = False;
2438 if (!finished && !out_of_space)
2439 numentries++;
2442 * As an optimisation if we know we aren't looking
2443 * for a wildcard name (ie. the name matches the wildcard exactly)
2444 * then we can finish on any (first) match.
2445 * This speeds up large directory searches. JRA.
2448 if(got_exact_match)
2449 finished = True;
2451 /* Ensure space_remaining never goes -ve. */
2452 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2453 space_remaining = 0;
2454 out_of_space = true;
2455 } else {
2456 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2460 /* Check if we can close the dirptr */
2461 if(close_after_first || (finished && close_if_end)) {
2462 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2463 dptr_close(sconn, &dptr_num);
2467 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2468 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2469 * the protocol level is less than NT1. Tested with smbclient. JRA.
2470 * This should fix the OS/2 client bug #2335.
2473 if(numentries == 0) {
2474 dptr_close(sconn, &dptr_num);
2475 if (get_Protocol() < PROTOCOL_NT1) {
2476 reply_force_doserror(req, ERRDOS, ERRnofiles);
2477 goto out;
2478 } else {
2479 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2480 ERRDOS, ERRbadfile);
2481 goto out;
2485 /* At this point pdata points to numentries directory entries. */
2487 /* Set up the return parameter block */
2488 SSVAL(params,0,dptr_num);
2489 SSVAL(params,2,numentries);
2490 SSVAL(params,4,finished);
2491 SSVAL(params,6,0); /* Never an EA error */
2492 SSVAL(params,8,last_entry_off);
2494 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2495 max_data_bytes);
2497 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2498 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2499 if (!directory) {
2500 reply_nterror(req, NT_STATUS_NO_MEMORY);
2504 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2505 smb_fn_name(req->cmd),
2506 mask, directory, dirtype, numentries ) );
2509 * Force a name mangle here to ensure that the
2510 * mask as an 8.3 name is top of the mangled cache.
2511 * The reasons for this are subtle. Don't remove
2512 * this code unless you know what you are doing
2513 * (see PR#13758). JRA.
2516 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2517 char mangled_name[13];
2518 name_to_8_3(mask, mangled_name, True, conn->params);
2520 out:
2521 TALLOC_FREE(smb_dname);
2522 return;
2525 /****************************************************************************
2526 Reply to a TRANS2_FINDNEXT.
2527 ****************************************************************************/
2529 static void call_trans2findnext(connection_struct *conn,
2530 struct smb_request *req,
2531 char **pparams, int total_params,
2532 char **ppdata, int total_data,
2533 unsigned int max_data_bytes)
2535 /* We must be careful here that we don't return more than the
2536 allowed number of data bytes. If this means returning fewer than
2537 maxentries then so be it. We assume that the redirector has
2538 enough room for the fixed number of parameter bytes it has
2539 requested. */
2540 char *params = *pparams;
2541 char *pdata = *ppdata;
2542 char *data_end;
2543 int dptr_num;
2544 int maxentries;
2545 uint16 info_level;
2546 uint32 resume_key;
2547 uint16 findnext_flags;
2548 bool close_after_request;
2549 bool close_if_end;
2550 bool requires_resume_key;
2551 bool continue_bit;
2552 bool mask_contains_wcard = False;
2553 char *resume_name = NULL;
2554 const char *mask = NULL;
2555 const char *directory = NULL;
2556 char *p = NULL;
2557 uint16 dirtype;
2558 int numentries = 0;
2559 int i, last_entry_off=0;
2560 bool finished = False;
2561 bool dont_descend = False;
2562 bool out_of_space = False;
2563 int space_remaining;
2564 struct ea_list *ea_list = NULL;
2565 NTSTATUS ntstatus = NT_STATUS_OK;
2566 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2567 TALLOC_CTX *ctx = talloc_tos();
2568 struct dptr_struct *dirptr;
2569 struct smbd_server_connection *sconn = smbd_server_conn;
2571 if (total_params < 13) {
2572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2573 return;
2576 dptr_num = SVAL(params,0);
2577 maxentries = SVAL(params,2);
2578 info_level = SVAL(params,4);
2579 resume_key = IVAL(params,6);
2580 findnext_flags = SVAL(params,10);
2581 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2582 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2583 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2584 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2586 if (!continue_bit) {
2587 /* We only need resume_name if continue_bit is zero. */
2588 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2589 params+12,
2590 total_params - 12, STR_TERMINATE, &ntstatus,
2591 &mask_contains_wcard);
2592 if (!NT_STATUS_IS_OK(ntstatus)) {
2593 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2594 complain (it thinks we're asking for the directory above the shared
2595 path or an invalid name). Catch this as the resume name is only compared, never used in
2596 a file access. JRA. */
2597 srvstr_pull_talloc(ctx, params, req->flags2,
2598 &resume_name, params+12,
2599 total_params - 12,
2600 STR_TERMINATE);
2602 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2603 reply_nterror(req, ntstatus);
2604 return;
2609 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2610 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2611 resume_key = %d resume name = %s continue=%d level = %d\n",
2612 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2613 requires_resume_key, resume_key,
2614 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2616 if (!maxentries) {
2617 /* W2K3 seems to treat zero as 1. */
2618 maxentries = 1;
2621 switch (info_level) {
2622 case SMB_FIND_INFO_STANDARD:
2623 case SMB_FIND_EA_SIZE:
2624 case SMB_FIND_EA_LIST:
2625 case SMB_FIND_FILE_DIRECTORY_INFO:
2626 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2627 case SMB_FIND_FILE_NAMES_INFO:
2628 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2629 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2630 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2631 break;
2632 case SMB_FIND_FILE_UNIX:
2633 case SMB_FIND_FILE_UNIX_INFO2:
2634 /* Always use filesystem for UNIX mtime query. */
2635 ask_sharemode = false;
2636 if (!lp_unix_extensions()) {
2637 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2638 return;
2640 break;
2641 default:
2642 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2643 return;
2646 if (info_level == SMB_FIND_EA_LIST) {
2647 uint32 ea_size;
2649 if (total_data < 4) {
2650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2651 return;
2654 ea_size = IVAL(pdata,0);
2655 if (ea_size != total_data) {
2656 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2657 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2659 return;
2662 if (!lp_ea_support(SNUM(conn))) {
2663 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2664 return;
2667 /* Pull out the list of names. */
2668 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2669 if (!ea_list) {
2670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2671 return;
2675 *ppdata = (char *)SMB_REALLOC(
2676 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2677 if(*ppdata == NULL) {
2678 reply_nterror(req, NT_STATUS_NO_MEMORY);
2679 return;
2682 pdata = *ppdata;
2683 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2685 /* Realloc the params space */
2686 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2687 if(*pparams == NULL ) {
2688 reply_nterror(req, NT_STATUS_NO_MEMORY);
2689 return;
2692 params = *pparams;
2694 /* Check that the dptr is valid */
2695 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2696 reply_nterror(req, STATUS_NO_MORE_FILES);
2697 return;
2700 directory = dptr_path(sconn, dptr_num);
2702 /* Get the wildcard mask from the dptr */
2703 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2704 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2705 reply_nterror(req, STATUS_NO_MORE_FILES);
2706 return;
2709 mask = p;
2711 /* Get the attr mask from the dptr */
2712 dirtype = dptr_attr(sconn, dptr_num);
2714 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2715 dptr_num, mask, dirtype,
2716 (long)dirptr,
2717 dptr_TellDir(dirptr)));
2719 /* Initialize per TRANS2_FIND_NEXT operation data */
2720 dptr_init_search_op(dirptr);
2722 /* We don't need to check for VOL here as this is returned by
2723 a different TRANS2 call. */
2725 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2726 directory,lp_dontdescend(SNUM(conn))));
2727 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2728 dont_descend = True;
2730 p = pdata;
2731 space_remaining = max_data_bytes;
2732 out_of_space = False;
2735 * Seek to the correct position. We no longer use the resume key but
2736 * depend on the last file name instead.
2739 if(!continue_bit && resume_name && *resume_name) {
2740 SMB_STRUCT_STAT st;
2742 long current_pos = 0;
2744 * Remember, name_to_8_3 is called by
2745 * get_lanman2_dir_entry(), so the resume name
2746 * could be mangled. Ensure we check the unmangled name.
2749 if (mangle_is_mangled(resume_name, conn->params)) {
2750 char *new_resume_name = NULL;
2751 mangle_lookup_name_from_8_3(ctx,
2752 resume_name,
2753 &new_resume_name,
2754 conn->params);
2755 if (new_resume_name) {
2756 resume_name = new_resume_name;
2761 * Fix for NT redirector problem triggered by resume key indexes
2762 * changing between directory scans. We now return a resume key of 0
2763 * and instead look for the filename to continue from (also given
2764 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2765 * findfirst/findnext (as is usual) then the directory pointer
2766 * should already be at the correct place.
2769 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2770 } /* end if resume_name && !continue_bit */
2772 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2773 bool got_exact_match = False;
2775 /* this is a heuristic to avoid seeking the dirptr except when
2776 absolutely necessary. It allows for a filename of about 40 chars */
2777 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2778 out_of_space = True;
2779 finished = False;
2780 } else {
2781 finished = !get_lanman2_dir_entry(ctx,
2782 conn,
2783 dirptr,
2784 req->flags2,
2785 mask,dirtype,info_level,
2786 requires_resume_key,dont_descend,
2787 ask_sharemode,
2788 &p,pdata,data_end,
2789 space_remaining, &out_of_space,
2790 &got_exact_match,
2791 &last_entry_off, ea_list);
2794 if (finished && out_of_space)
2795 finished = False;
2797 if (!finished && !out_of_space)
2798 numentries++;
2801 * As an optimisation if we know we aren't looking
2802 * for a wildcard name (ie. the name matches the wildcard exactly)
2803 * then we can finish on any (first) match.
2804 * This speeds up large directory searches. JRA.
2807 if(got_exact_match)
2808 finished = True;
2810 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2813 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2814 smb_fn_name(req->cmd),
2815 mask, directory, dirtype, numentries ) );
2817 /* Check if we can close the dirptr */
2818 if(close_after_request || (finished && close_if_end)) {
2819 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2820 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2823 /* Set up the return parameter block */
2824 SSVAL(params,0,numentries);
2825 SSVAL(params,2,finished);
2826 SSVAL(params,4,0); /* Never an EA error */
2827 SSVAL(params,6,last_entry_off);
2829 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2830 max_data_bytes);
2832 return;
2835 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2837 E_md4hash(lp_servicename(SNUM(conn)),objid);
2838 return objid;
2841 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2843 SMB_ASSERT(extended_info != NULL);
2845 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2846 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2847 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2848 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2849 #ifdef SAMBA_VERSION_REVISION
2850 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2851 #endif
2852 extended_info->samba_subversion = 0;
2853 #ifdef SAMBA_VERSION_RC_RELEASE
2854 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2855 #else
2856 #ifdef SAMBA_VERSION_PRE_RELEASE
2857 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2858 #endif
2859 #endif
2860 #ifdef SAMBA_VERSION_VENDOR_PATCH
2861 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2862 #endif
2863 extended_info->samba_gitcommitdate = 0;
2864 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2865 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2866 #endif
2868 memset(extended_info->samba_version_string, 0,
2869 sizeof(extended_info->samba_version_string));
2871 snprintf (extended_info->samba_version_string,
2872 sizeof(extended_info->samba_version_string),
2873 "%s", samba_version_string());
2876 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2877 TALLOC_CTX *mem_ctx,
2878 uint16_t info_level,
2879 uint16_t flags2,
2880 unsigned int max_data_bytes,
2881 char **ppdata,
2882 int *ret_data_len)
2884 char *pdata, *end_data;
2885 int data_len = 0, len;
2886 const char *vname = volume_label(SNUM(conn));
2887 int snum = SNUM(conn);
2888 char *fstype = lp_fstype(SNUM(conn));
2889 uint32 additional_flags = 0;
2890 struct smb_filename smb_fname_dot;
2891 SMB_STRUCT_STAT st;
2893 if (IS_IPC(conn)) {
2894 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2895 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2896 "info level (0x%x) on IPC$.\n",
2897 (unsigned int)info_level));
2898 return NT_STATUS_ACCESS_DENIED;
2902 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2904 ZERO_STRUCT(smb_fname_dot);
2905 smb_fname_dot.base_name = discard_const_p(char, ".");
2907 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2908 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2909 return map_nt_error_from_unix(errno);
2912 st = smb_fname_dot.st;
2914 *ppdata = (char *)SMB_REALLOC(
2915 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2916 if (*ppdata == NULL) {
2917 return NT_STATUS_NO_MEMORY;
2920 pdata = *ppdata;
2921 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2922 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2924 switch (info_level) {
2925 case SMB_INFO_ALLOCATION:
2927 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2928 data_len = 18;
2929 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2930 return map_nt_error_from_unix(errno);
2933 block_size = lp_block_size(snum);
2934 if (bsize < block_size) {
2935 uint64_t factor = block_size/bsize;
2936 bsize = block_size;
2937 dsize /= factor;
2938 dfree /= factor;
2940 if (bsize > block_size) {
2941 uint64_t factor = bsize/block_size;
2942 bsize = block_size;
2943 dsize *= factor;
2944 dfree *= factor;
2946 bytes_per_sector = 512;
2947 sectors_per_unit = bsize/bytes_per_sector;
2949 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2950 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2951 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2953 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2954 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2955 SIVAL(pdata,l1_cUnit,dsize);
2956 SIVAL(pdata,l1_cUnitAvail,dfree);
2957 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2958 break;
2961 case SMB_INFO_VOLUME:
2962 /* Return volume name */
2964 * Add volume serial number - hash of a combination of
2965 * the called hostname and the service name.
2967 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2969 * Win2k3 and previous mess this up by sending a name length
2970 * one byte short. I believe only older clients (OS/2 Win9x) use
2971 * this call so try fixing this by adding a terminating null to
2972 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2974 len = srvstr_push(
2975 pdata, flags2,
2976 pdata+l2_vol_szVolLabel, vname,
2977 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2978 STR_NOALIGN|STR_TERMINATE);
2979 SCVAL(pdata,l2_vol_cch,len);
2980 data_len = l2_vol_szVolLabel + len;
2981 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2982 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2983 len, vname));
2984 break;
2986 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2987 case SMB_FS_ATTRIBUTE_INFORMATION:
2989 additional_flags = 0;
2990 #if defined(HAVE_SYS_QUOTAS)
2991 additional_flags |= FILE_VOLUME_QUOTAS;
2992 #endif
2994 if(lp_nt_acl_support(SNUM(conn))) {
2995 additional_flags |= FILE_PERSISTENT_ACLS;
2998 /* Capabilities are filled in at connection time through STATVFS call */
2999 additional_flags |= conn->fs_capabilities;
3000 additional_flags |= lp_parm_int(conn->params->service,
3001 "share", "fake_fscaps",
3004 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3005 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3006 additional_flags); /* FS ATTRIBUTES */
3008 SIVAL(pdata,4,255); /* Max filename component length */
3009 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3010 and will think we can't do long filenames */
3011 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3012 PTR_DIFF(end_data, pdata+12),
3013 STR_UNICODE);
3014 SIVAL(pdata,8,len);
3015 data_len = 12 + len;
3016 break;
3018 case SMB_QUERY_FS_LABEL_INFO:
3019 case SMB_FS_LABEL_INFORMATION:
3020 len = srvstr_push(pdata, flags2, pdata+4, vname,
3021 PTR_DIFF(end_data, pdata+4), 0);
3022 data_len = 4 + len;
3023 SIVAL(pdata,0,len);
3024 break;
3026 case SMB_QUERY_FS_VOLUME_INFO:
3027 case SMB_FS_VOLUME_INFORMATION:
3030 * Add volume serial number - hash of a combination of
3031 * the called hostname and the service name.
3033 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3034 (str_checksum(get_local_machine_name())<<16));
3036 /* Max label len is 32 characters. */
3037 len = srvstr_push(pdata, flags2, pdata+18, vname,
3038 PTR_DIFF(end_data, pdata+18),
3039 STR_UNICODE);
3040 SIVAL(pdata,12,len);
3041 data_len = 18+len;
3043 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3044 (int)strlen(vname),vname, lp_servicename(snum)));
3045 break;
3047 case SMB_QUERY_FS_SIZE_INFO:
3048 case SMB_FS_SIZE_INFORMATION:
3050 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3051 data_len = 24;
3052 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3053 return map_nt_error_from_unix(errno);
3055 block_size = lp_block_size(snum);
3056 if (bsize < block_size) {
3057 uint64_t factor = block_size/bsize;
3058 bsize = block_size;
3059 dsize /= factor;
3060 dfree /= factor;
3062 if (bsize > block_size) {
3063 uint64_t factor = bsize/block_size;
3064 bsize = block_size;
3065 dsize *= factor;
3066 dfree *= factor;
3068 bytes_per_sector = 512;
3069 sectors_per_unit = bsize/bytes_per_sector;
3070 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3071 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3072 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3073 SBIG_UINT(pdata,0,dsize);
3074 SBIG_UINT(pdata,8,dfree);
3075 SIVAL(pdata,16,sectors_per_unit);
3076 SIVAL(pdata,20,bytes_per_sector);
3077 break;
3080 case SMB_FS_FULL_SIZE_INFORMATION:
3082 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3083 data_len = 32;
3084 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno);
3087 block_size = lp_block_size(snum);
3088 if (bsize < block_size) {
3089 uint64_t factor = block_size/bsize;
3090 bsize = block_size;
3091 dsize /= factor;
3092 dfree /= factor;
3094 if (bsize > block_size) {
3095 uint64_t factor = bsize/block_size;
3096 bsize = block_size;
3097 dsize *= factor;
3098 dfree *= factor;
3100 bytes_per_sector = 512;
3101 sectors_per_unit = bsize/bytes_per_sector;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3104 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3105 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3106 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3107 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3108 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3109 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3110 break;
3113 case SMB_QUERY_FS_DEVICE_INFO:
3114 case SMB_FS_DEVICE_INFORMATION:
3115 data_len = 8;
3116 SIVAL(pdata,0,0); /* dev type */
3117 SIVAL(pdata,4,0); /* characteristics */
3118 break;
3120 #ifdef HAVE_SYS_QUOTAS
3121 case SMB_FS_QUOTA_INFORMATION:
3123 * what we have to send --metze:
3125 * Unknown1: 24 NULL bytes
3126 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3127 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3128 * Quota Flags: 2 byte :
3129 * Unknown3: 6 NULL bytes
3131 * 48 bytes total
3133 * details for Quota Flags:
3135 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3136 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3137 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3138 * 0x0001 Enable Quotas: enable quota for this fs
3142 /* we need to fake up a fsp here,
3143 * because its not send in this call
3145 files_struct fsp;
3146 SMB_NTQUOTA_STRUCT quotas;
3148 ZERO_STRUCT(fsp);
3149 ZERO_STRUCT(quotas);
3151 fsp.conn = conn;
3152 fsp.fnum = -1;
3154 /* access check */
3155 if (conn->server_info->utok.uid != sec_initial_uid() &&
3156 !conn->admin_user) {
3157 DEBUG(0,("set_user_quota: access_denied "
3158 "service [%s] user [%s]\n",
3159 lp_servicename(SNUM(conn)),
3160 conn->server_info->unix_name));
3161 return NT_STATUS_ACCESS_DENIED;
3164 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3165 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3166 return map_nt_error_from_unix(errno);
3169 data_len = 48;
3171 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3172 lp_servicename(SNUM(conn))));
3174 /* Unknown1 24 NULL bytes*/
3175 SBIG_UINT(pdata,0,(uint64_t)0);
3176 SBIG_UINT(pdata,8,(uint64_t)0);
3177 SBIG_UINT(pdata,16,(uint64_t)0);
3179 /* Default Soft Quota 8 bytes */
3180 SBIG_UINT(pdata,24,quotas.softlim);
3182 /* Default Hard Quota 8 bytes */
3183 SBIG_UINT(pdata,32,quotas.hardlim);
3185 /* Quota flag 2 bytes */
3186 SSVAL(pdata,40,quotas.qflags);
3188 /* Unknown3 6 NULL bytes */
3189 SSVAL(pdata,42,0);
3190 SIVAL(pdata,44,0);
3192 break;
3194 #endif /* HAVE_SYS_QUOTAS */
3195 case SMB_FS_OBJECTID_INFORMATION:
3197 unsigned char objid[16];
3198 struct smb_extended_info extended_info;
3199 memcpy(pdata,create_volume_objectid(conn, objid),16);
3200 samba_extended_info_version (&extended_info);
3201 SIVAL(pdata,16,extended_info.samba_magic);
3202 SIVAL(pdata,20,extended_info.samba_version);
3203 SIVAL(pdata,24,extended_info.samba_subversion);
3204 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3205 memcpy(pdata+36,extended_info.samba_version_string,28);
3206 data_len = 64;
3207 break;
3211 * Query the version and capabilities of the CIFS UNIX extensions
3212 * in use.
3215 case SMB_QUERY_CIFS_UNIX_INFO:
3217 bool large_write = lp_min_receive_file_size() &&
3218 !srv_is_signing_active(smbd_server_conn);
3219 bool large_read = !srv_is_signing_active(smbd_server_conn);
3220 int encrypt_caps = 0;
3222 if (!lp_unix_extensions()) {
3223 return NT_STATUS_INVALID_LEVEL;
3226 switch (conn->encrypt_level) {
3227 case 0:
3228 encrypt_caps = 0;
3229 break;
3230 case 1:
3231 case Auto:
3232 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3233 break;
3234 case Required:
3235 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3236 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3237 large_write = false;
3238 large_read = false;
3239 break;
3242 data_len = 12;
3243 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3244 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3246 /* We have POSIX ACLs, pathname, encryption,
3247 * large read/write, and locking capability. */
3249 SBIG_UINT(pdata,4,((uint64_t)(
3250 CIFS_UNIX_POSIX_ACLS_CAP|
3251 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3252 CIFS_UNIX_FCNTL_LOCKS_CAP|
3253 CIFS_UNIX_EXTATTR_CAP|
3254 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3255 encrypt_caps|
3256 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3257 (large_write ?
3258 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3259 break;
3262 case SMB_QUERY_POSIX_FS_INFO:
3264 int rc;
3265 vfs_statvfs_struct svfs;
3267 if (!lp_unix_extensions()) {
3268 return NT_STATUS_INVALID_LEVEL;
3271 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3273 if (!rc) {
3274 data_len = 56;
3275 SIVAL(pdata,0,svfs.OptimalTransferSize);
3276 SIVAL(pdata,4,svfs.BlockSize);
3277 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3278 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3279 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3280 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3281 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3282 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3283 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3284 #ifdef EOPNOTSUPP
3285 } else if (rc == EOPNOTSUPP) {
3286 return NT_STATUS_INVALID_LEVEL;
3287 #endif /* EOPNOTSUPP */
3288 } else {
3289 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3290 return NT_STATUS_DOS(ERRSRV, ERRerror);
3292 break;
3295 case SMB_QUERY_POSIX_WHOAMI:
3297 uint32_t flags = 0;
3298 uint32_t sid_bytes;
3299 int i;
3301 if (!lp_unix_extensions()) {
3302 return NT_STATUS_INVALID_LEVEL;
3305 if (max_data_bytes < 40) {
3306 return NT_STATUS_BUFFER_TOO_SMALL;
3309 /* We ARE guest if global_sid_Builtin_Guests is
3310 * in our list of SIDs.
3312 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3313 conn->server_info->ptok)) {
3314 flags |= SMB_WHOAMI_GUEST;
3317 /* We are NOT guest if global_sid_Authenticated_Users
3318 * is in our list of SIDs.
3320 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3321 conn->server_info->ptok)) {
3322 flags &= ~SMB_WHOAMI_GUEST;
3325 /* NOTE: 8 bytes for UID/GID, irrespective of native
3326 * platform size. This matches
3327 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3329 data_len = 4 /* flags */
3330 + 4 /* flag mask */
3331 + 8 /* uid */
3332 + 8 /* gid */
3333 + 4 /* ngroups */
3334 + 4 /* num_sids */
3335 + 4 /* SID bytes */
3336 + 4 /* pad/reserved */
3337 + (conn->server_info->utok.ngroups * 8)
3338 /* groups list */
3339 + (conn->server_info->ptok->num_sids *
3340 SID_MAX_SIZE)
3341 /* SID list */;
3343 SIVAL(pdata, 0, flags);
3344 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3345 SBIG_UINT(pdata, 8,
3346 (uint64_t)conn->server_info->utok.uid);
3347 SBIG_UINT(pdata, 16,
3348 (uint64_t)conn->server_info->utok.gid);
3351 if (data_len >= max_data_bytes) {
3352 /* Potential overflow, skip the GIDs and SIDs. */
3354 SIVAL(pdata, 24, 0); /* num_groups */
3355 SIVAL(pdata, 28, 0); /* num_sids */
3356 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3357 SIVAL(pdata, 36, 0); /* reserved */
3359 data_len = 40;
3360 break;
3363 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3364 SIVAL(pdata, 28, conn->server_info->num_sids);
3366 /* We walk the SID list twice, but this call is fairly
3367 * infrequent, and I don't expect that it's performance
3368 * sensitive -- jpeach
3370 for (i = 0, sid_bytes = 0;
3371 i < conn->server_info->ptok->num_sids; ++i) {
3372 sid_bytes += ndr_size_dom_sid(
3373 &conn->server_info->ptok->user_sids[i],
3374 NULL,
3378 /* SID list byte count */
3379 SIVAL(pdata, 32, sid_bytes);
3381 /* 4 bytes pad/reserved - must be zero */
3382 SIVAL(pdata, 36, 0);
3383 data_len = 40;
3385 /* GID list */
3386 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3387 SBIG_UINT(pdata, data_len,
3388 (uint64_t)conn->server_info->utok.groups[i]);
3389 data_len += 8;
3392 /* SID list */
3393 for (i = 0;
3394 i < conn->server_info->ptok->num_sids; ++i) {
3395 int sid_len = ndr_size_dom_sid(
3396 &conn->server_info->ptok->user_sids[i],
3397 NULL,
3400 sid_linearize(pdata + data_len, sid_len,
3401 &conn->server_info->ptok->user_sids[i]);
3402 data_len += sid_len;
3405 break;
3408 case SMB_MAC_QUERY_FS_INFO:
3410 * Thursby MAC extension... ONLY on NTFS filesystems
3411 * once we do streams then we don't need this
3413 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3414 data_len = 88;
3415 SIVAL(pdata,84,0x100); /* Don't support mac... */
3416 break;
3418 /* drop through */
3419 default:
3420 return NT_STATUS_INVALID_LEVEL;
3423 *ret_data_len = data_len;
3424 return NT_STATUS_OK;
3427 /****************************************************************************
3428 Reply to a TRANS2_QFSINFO (query filesystem info).
3429 ****************************************************************************/
3431 static void call_trans2qfsinfo(connection_struct *conn,
3432 struct smb_request *req,
3433 char **pparams, int total_params,
3434 char **ppdata, int total_data,
3435 unsigned int max_data_bytes)
3437 char *params = *pparams;
3438 uint16_t info_level;
3439 int data_len = 0;
3440 NTSTATUS status;
3442 if (total_params < 2) {
3443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3444 return;
3447 info_level = SVAL(params,0);
3449 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3450 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3451 DEBUG(0,("call_trans2qfsinfo: encryption required "
3452 "and info level 0x%x sent.\n",
3453 (unsigned int)info_level));
3454 exit_server_cleanly("encryption required "
3455 "on connection");
3456 return;
3460 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3462 status = smbd_do_qfsinfo(conn, req,
3463 info_level,
3464 req->flags2,
3465 max_data_bytes,
3466 ppdata, &data_len);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 reply_nterror(req, status);
3469 return;
3472 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3473 max_data_bytes);
3475 DEBUG( 4, ( "%s info_level = %d\n",
3476 smb_fn_name(req->cmd), info_level) );
3478 return;
3481 /****************************************************************************
3482 Reply to a TRANS2_SETFSINFO (set filesystem info).
3483 ****************************************************************************/
3485 static void call_trans2setfsinfo(connection_struct *conn,
3486 struct smb_request *req,
3487 char **pparams, int total_params,
3488 char **ppdata, int total_data,
3489 unsigned int max_data_bytes)
3491 char *pdata = *ppdata;
3492 char *params = *pparams;
3493 uint16 info_level;
3495 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3497 /* */
3498 if (total_params < 4) {
3499 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3500 total_params));
3501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3502 return;
3505 info_level = SVAL(params,2);
3507 if (IS_IPC(conn)) {
3508 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3509 info_level != SMB_SET_CIFS_UNIX_INFO) {
3510 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3511 "info level (0x%x) on IPC$.\n",
3512 (unsigned int)info_level));
3513 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3514 return;
3518 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3519 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3520 DEBUG(0,("call_trans2setfsinfo: encryption required "
3521 "and info level 0x%x sent.\n",
3522 (unsigned int)info_level));
3523 exit_server_cleanly("encryption required "
3524 "on connection");
3525 return;
3529 switch(info_level) {
3530 case SMB_SET_CIFS_UNIX_INFO:
3532 uint16 client_unix_major;
3533 uint16 client_unix_minor;
3534 uint32 client_unix_cap_low;
3535 uint32 client_unix_cap_high;
3537 if (!lp_unix_extensions()) {
3538 reply_nterror(req,
3539 NT_STATUS_INVALID_LEVEL);
3540 return;
3543 /* There should be 12 bytes of capabilities set. */
3544 if (total_data < 8) {
3545 reply_nterror(
3546 req,
3547 NT_STATUS_INVALID_PARAMETER);
3548 return;
3550 client_unix_major = SVAL(pdata,0);
3551 client_unix_minor = SVAL(pdata,2);
3552 client_unix_cap_low = IVAL(pdata,4);
3553 client_unix_cap_high = IVAL(pdata,8);
3554 /* Just print these values for now. */
3555 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3556 cap_low = 0x%x, cap_high = 0x%x\n",
3557 (unsigned int)client_unix_major,
3558 (unsigned int)client_unix_minor,
3559 (unsigned int)client_unix_cap_low,
3560 (unsigned int)client_unix_cap_high ));
3562 /* Here is where we must switch to posix pathname processing... */
3563 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3564 lp_set_posix_pathnames();
3565 mangle_change_to_posix();
3568 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3569 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3570 /* Client that knows how to do posix locks,
3571 * but not posix open/mkdir operations. Set a
3572 * default type for read/write checks. */
3574 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3577 break;
3580 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3582 NTSTATUS status;
3583 size_t param_len = 0;
3584 size_t data_len = total_data;
3586 if (!lp_unix_extensions()) {
3587 reply_nterror(
3588 req,
3589 NT_STATUS_INVALID_LEVEL);
3590 return;
3593 if (lp_smb_encrypt(SNUM(conn)) == false) {
3594 reply_nterror(
3595 req,
3596 NT_STATUS_NOT_SUPPORTED);
3597 return;
3600 DEBUG( 4,("call_trans2setfsinfo: "
3601 "request transport encryption.\n"));
3603 status = srv_request_encryption_setup(conn,
3604 (unsigned char **)ppdata,
3605 &data_len,
3606 (unsigned char **)pparams,
3607 &param_len);
3609 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3610 !NT_STATUS_IS_OK(status)) {
3611 reply_nterror(req, status);
3612 return;
3615 send_trans2_replies(conn, req,
3616 *pparams,
3617 param_len,
3618 *ppdata,
3619 data_len,
3620 max_data_bytes);
3622 if (NT_STATUS_IS_OK(status)) {
3623 /* Server-side transport
3624 * encryption is now *on*. */
3625 status = srv_encryption_start(conn);
3626 if (!NT_STATUS_IS_OK(status)) {
3627 exit_server_cleanly(
3628 "Failure in setting "
3629 "up encrypted transport");
3632 return;
3635 case SMB_FS_QUOTA_INFORMATION:
3637 files_struct *fsp = NULL;
3638 SMB_NTQUOTA_STRUCT quotas;
3640 ZERO_STRUCT(quotas);
3642 /* access check */
3643 if (((conn->server_info->utok.uid != sec_initial_uid()) && !conn->admin_user)
3644 ||!CAN_WRITE(conn)) {
3645 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3646 lp_servicename(SNUM(conn)),
3647 conn->server_info->unix_name));
3648 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3649 return;
3652 /* note: normaly there're 48 bytes,
3653 * but we didn't use the last 6 bytes for now
3654 * --metze
3656 fsp = file_fsp(req, SVAL(params,0));
3658 if (!check_fsp_ntquota_handle(conn, req,
3659 fsp)) {
3660 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3661 reply_nterror(
3662 req, NT_STATUS_INVALID_HANDLE);
3663 return;
3666 if (total_data < 42) {
3667 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3668 total_data));
3669 reply_nterror(
3670 req,
3671 NT_STATUS_INVALID_PARAMETER);
3672 return;
3675 /* unknown_1 24 NULL bytes in pdata*/
3677 /* the soft quotas 8 bytes (uint64_t)*/
3678 quotas.softlim = (uint64_t)IVAL(pdata,24);
3679 #ifdef LARGE_SMB_OFF_T
3680 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3681 #else /* LARGE_SMB_OFF_T */
3682 if ((IVAL(pdata,28) != 0)&&
3683 ((quotas.softlim != 0xFFFFFFFF)||
3684 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3685 /* more than 32 bits? */
3686 reply_nterror(
3687 req,
3688 NT_STATUS_INVALID_PARAMETER);
3689 return;
3691 #endif /* LARGE_SMB_OFF_T */
3693 /* the hard quotas 8 bytes (uint64_t)*/
3694 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3695 #ifdef LARGE_SMB_OFF_T
3696 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3697 #else /* LARGE_SMB_OFF_T */
3698 if ((IVAL(pdata,36) != 0)&&
3699 ((quotas.hardlim != 0xFFFFFFFF)||
3700 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3701 /* more than 32 bits? */
3702 reply_nterror(
3703 req,
3704 NT_STATUS_INVALID_PARAMETER);
3705 return;
3707 #endif /* LARGE_SMB_OFF_T */
3709 /* quota_flags 2 bytes **/
3710 quotas.qflags = SVAL(pdata,40);
3712 /* unknown_2 6 NULL bytes follow*/
3714 /* now set the quotas */
3715 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3716 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3717 reply_nterror(req, map_nt_error_from_unix(errno));
3718 return;
3721 break;
3723 default:
3724 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3725 info_level));
3726 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3727 return;
3728 break;
3732 * sending this reply works fine,
3733 * but I'm not sure it's the same
3734 * like windows do...
3735 * --metze
3737 reply_outbuf(req, 10, 0);
3740 #if defined(HAVE_POSIX_ACLS)
3741 /****************************************************************************
3742 Utility function to count the number of entries in a POSIX acl.
3743 ****************************************************************************/
3745 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3747 unsigned int ace_count = 0;
3748 int entry_id = SMB_ACL_FIRST_ENTRY;
3749 SMB_ACL_ENTRY_T entry;
3751 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3752 /* get_next... */
3753 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3754 entry_id = SMB_ACL_NEXT_ENTRY;
3756 ace_count++;
3758 return ace_count;
3761 /****************************************************************************
3762 Utility function to marshall a POSIX acl into wire format.
3763 ****************************************************************************/
3765 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3767 int entry_id = SMB_ACL_FIRST_ENTRY;
3768 SMB_ACL_ENTRY_T entry;
3770 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3771 SMB_ACL_TAG_T tagtype;
3772 SMB_ACL_PERMSET_T permset;
3773 unsigned char perms = 0;
3774 unsigned int own_grp;
3776 /* get_next... */
3777 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3778 entry_id = SMB_ACL_NEXT_ENTRY;
3781 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3782 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3783 return False;
3786 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3787 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3788 return False;
3791 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3792 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3793 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3795 SCVAL(pdata,1,perms);
3797 switch (tagtype) {
3798 case SMB_ACL_USER_OBJ:
3799 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3800 own_grp = (unsigned int)pst->st_ex_uid;
3801 SIVAL(pdata,2,own_grp);
3802 SIVAL(pdata,6,0);
3803 break;
3804 case SMB_ACL_USER:
3806 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3807 if (!puid) {
3808 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3809 return False;
3811 own_grp = (unsigned int)*puid;
3812 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3813 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3814 SIVAL(pdata,2,own_grp);
3815 SIVAL(pdata,6,0);
3816 break;
3818 case SMB_ACL_GROUP_OBJ:
3819 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3820 own_grp = (unsigned int)pst->st_ex_gid;
3821 SIVAL(pdata,2,own_grp);
3822 SIVAL(pdata,6,0);
3823 break;
3824 case SMB_ACL_GROUP:
3826 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3827 if (!pgid) {
3828 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3829 return False;
3831 own_grp = (unsigned int)*pgid;
3832 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3833 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3834 SIVAL(pdata,2,own_grp);
3835 SIVAL(pdata,6,0);
3836 break;
3838 case SMB_ACL_MASK:
3839 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3840 SIVAL(pdata,2,0xFFFFFFFF);
3841 SIVAL(pdata,6,0xFFFFFFFF);
3842 break;
3843 case SMB_ACL_OTHER:
3844 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3845 SIVAL(pdata,2,0xFFFFFFFF);
3846 SIVAL(pdata,6,0xFFFFFFFF);
3847 break;
3848 default:
3849 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3850 return False;
3852 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3855 return True;
3857 #endif
3859 /****************************************************************************
3860 Store the FILE_UNIX_BASIC info.
3861 ****************************************************************************/
3863 static char *store_file_unix_basic(connection_struct *conn,
3864 char *pdata,
3865 files_struct *fsp,
3866 const SMB_STRUCT_STAT *psbuf)
3868 uint64_t file_index = get_FileIndex(conn, psbuf);
3870 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3871 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3873 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3874 pdata += 8;
3876 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3877 pdata += 8;
3879 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3880 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3881 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3882 pdata += 24;
3884 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3885 SIVAL(pdata,4,0);
3886 pdata += 8;
3888 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3889 SIVAL(pdata,4,0);
3890 pdata += 8;
3892 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3893 pdata += 4;
3895 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3896 SIVAL(pdata,4,0);
3897 pdata += 8;
3899 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3900 SIVAL(pdata,4,0);
3901 pdata += 8;
3903 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3904 pdata += 8;
3906 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3907 SIVAL(pdata,4,0);
3908 pdata += 8;
3910 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3911 SIVAL(pdata,4,0);
3912 pdata += 8;
3914 return pdata;
3917 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3918 * the chflags(2) (or equivalent) flags.
3920 * XXX: this really should be behind the VFS interface. To do this, we would
3921 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3922 * Each VFS module could then implement its own mapping as appropriate for the
3923 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3925 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3926 info2_flags_map[] =
3928 #ifdef UF_NODUMP
3929 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3930 #endif
3932 #ifdef UF_IMMUTABLE
3933 { UF_IMMUTABLE, EXT_IMMUTABLE },
3934 #endif
3936 #ifdef UF_APPEND
3937 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3938 #endif
3940 #ifdef UF_HIDDEN
3941 { UF_HIDDEN, EXT_HIDDEN },
3942 #endif
3944 /* Do not remove. We need to guarantee that this array has at least one
3945 * entry to build on HP-UX.
3947 { 0, 0 }
3951 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3952 uint32 *smb_fflags, uint32 *smb_fmask)
3954 int i;
3956 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3957 *smb_fmask |= info2_flags_map[i].smb_fflag;
3958 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3959 *smb_fflags |= info2_flags_map[i].smb_fflag;
3964 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3965 const uint32 smb_fflags,
3966 const uint32 smb_fmask,
3967 int *stat_fflags)
3969 uint32 max_fmask = 0;
3970 int i;
3972 *stat_fflags = psbuf->st_ex_flags;
3974 /* For each flags requested in smb_fmask, check the state of the
3975 * corresponding flag in smb_fflags and set or clear the matching
3976 * stat flag.
3979 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3980 max_fmask |= info2_flags_map[i].smb_fflag;
3981 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3982 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3983 *stat_fflags |= info2_flags_map[i].stat_fflag;
3984 } else {
3985 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3990 /* If smb_fmask is asking to set any bits that are not supported by
3991 * our flag mappings, we should fail.
3993 if ((smb_fmask & max_fmask) != smb_fmask) {
3994 return False;
3997 return True;
4001 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4002 * of file flags and birth (create) time.
4004 static char *store_file_unix_basic_info2(connection_struct *conn,
4005 char *pdata,
4006 files_struct *fsp,
4007 const SMB_STRUCT_STAT *psbuf)
4009 uint32 file_flags = 0;
4010 uint32 flags_mask = 0;
4012 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4014 /* Create (birth) time 64 bit */
4015 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4016 pdata += 8;
4018 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4019 SIVAL(pdata, 0, file_flags); /* flags */
4020 SIVAL(pdata, 4, flags_mask); /* mask */
4021 pdata += 8;
4023 return pdata;
4026 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4027 const struct stream_struct *streams,
4028 char *data,
4029 unsigned int max_data_bytes,
4030 unsigned int *data_size)
4032 unsigned int i;
4033 unsigned int ofs = 0;
4035 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4036 unsigned int next_offset;
4037 size_t namelen;
4038 smb_ucs2_t *namebuf;
4040 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4041 streams[i].name, &namelen) ||
4042 namelen <= 2)
4044 return NT_STATUS_INVALID_PARAMETER;
4048 * name_buf is now null-terminated, we need to marshall as not
4049 * terminated
4052 namelen -= 2;
4054 SIVAL(data, ofs+4, namelen);
4055 SOFF_T(data, ofs+8, streams[i].size);
4056 SOFF_T(data, ofs+16, streams[i].alloc_size);
4057 memcpy(data+ofs+24, namebuf, namelen);
4058 TALLOC_FREE(namebuf);
4060 next_offset = ofs + 24 + namelen;
4062 if (i == num_streams-1) {
4063 SIVAL(data, ofs, 0);
4065 else {
4066 unsigned int align = ndr_align_size(next_offset, 8);
4068 memset(data+next_offset, 0, align);
4069 next_offset += align;
4071 SIVAL(data, ofs, next_offset - ofs);
4072 ofs = next_offset;
4075 ofs = next_offset;
4078 *data_size = ofs;
4080 return NT_STATUS_OK;
4083 /****************************************************************************
4084 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4085 ****************************************************************************/
4087 static void call_trans2qpipeinfo(connection_struct *conn,
4088 struct smb_request *req,
4089 unsigned int tran_call,
4090 char **pparams, int total_params,
4091 char **ppdata, int total_data,
4092 unsigned int max_data_bytes)
4094 char *params = *pparams;
4095 char *pdata = *ppdata;
4096 unsigned int data_size = 0;
4097 unsigned int param_size = 2;
4098 uint16 info_level;
4099 files_struct *fsp;
4101 if (!params) {
4102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4103 return;
4106 if (total_params < 4) {
4107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4108 return;
4111 fsp = file_fsp(req, SVAL(params,0));
4112 if (!fsp_is_np(fsp)) {
4113 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4114 return;
4117 info_level = SVAL(params,2);
4119 *pparams = (char *)SMB_REALLOC(*pparams,2);
4120 if (*pparams == NULL) {
4121 reply_nterror(req, NT_STATUS_NO_MEMORY);
4122 return;
4124 params = *pparams;
4125 SSVAL(params,0,0);
4126 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4127 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4128 if (*ppdata == NULL ) {
4129 reply_nterror(req, NT_STATUS_NO_MEMORY);
4130 return;
4132 pdata = *ppdata;
4134 switch (info_level) {
4135 case SMB_FILE_STANDARD_INFORMATION:
4136 memset(pdata,0,24);
4137 SOFF_T(pdata,0,4096LL);
4138 SIVAL(pdata,16,1);
4139 SIVAL(pdata,20,1);
4140 data_size = 24;
4141 break;
4143 default:
4144 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4145 return;
4148 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4149 max_data_bytes);
4151 return;
4154 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4155 TALLOC_CTX *mem_ctx,
4156 uint16_t info_level,
4157 files_struct *fsp,
4158 struct smb_filename *smb_fname,
4159 bool delete_pending,
4160 struct timespec write_time_ts,
4161 bool ms_dfs_link,
4162 struct ea_list *ea_list,
4163 int lock_data_count,
4164 char *lock_data,
4165 uint16_t flags2,
4166 unsigned int max_data_bytes,
4167 char **ppdata,
4168 unsigned int *pdata_size)
4170 char *pdata = *ppdata;
4171 char *dstart, *dend;
4172 unsigned int data_size;
4173 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4174 time_t create_time, mtime, atime, c_time;
4175 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4176 char *p;
4177 char *base_name;
4178 char *dos_fname;
4179 int mode;
4180 int nlink;
4181 NTSTATUS status;
4182 uint64_t file_size = 0;
4183 uint64_t pos = 0;
4184 uint64_t allocation_size = 0;
4185 uint64_t file_index = 0;
4186 uint32_t access_mask = 0;
4188 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4189 return NT_STATUS_INVALID_LEVEL;
4192 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4193 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4194 info_level, max_data_bytes));
4196 if (ms_dfs_link) {
4197 mode = dos_mode_msdfs(conn, smb_fname);
4198 } else {
4199 mode = dos_mode(conn, smb_fname);
4202 nlink = psbuf->st_ex_nlink;
4204 if (nlink && (mode&aDIR)) {
4205 nlink = 1;
4208 if ((nlink > 0) && delete_pending) {
4209 nlink -= 1;
4212 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4213 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4214 if (*ppdata == NULL) {
4215 return NT_STATUS_NO_MEMORY;
4217 pdata = *ppdata;
4218 dstart = pdata;
4219 dend = dstart + data_size - 1;
4221 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4222 update_stat_ex_mtime(psbuf, write_time_ts);
4225 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4226 mtime_ts = psbuf->st_ex_mtime;
4227 atime_ts = psbuf->st_ex_atime;
4228 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4230 if (lp_dos_filetime_resolution(SNUM(conn))) {
4231 dos_filetime_timespec(&create_time_ts);
4232 dos_filetime_timespec(&mtime_ts);
4233 dos_filetime_timespec(&atime_ts);
4234 dos_filetime_timespec(&ctime_ts);
4237 create_time = convert_timespec_to_time_t(create_time_ts);
4238 mtime = convert_timespec_to_time_t(mtime_ts);
4239 atime = convert_timespec_to_time_t(atime_ts);
4240 c_time = convert_timespec_to_time_t(ctime_ts);
4242 p = strrchr_m(smb_fname->base_name,'/');
4243 if (!p)
4244 base_name = smb_fname->base_name;
4245 else
4246 base_name = p+1;
4248 /* NT expects the name to be in an exact form of the *full*
4249 filename. See the trans2 torture test */
4250 if (ISDOT(base_name)) {
4251 dos_fname = talloc_strdup(mem_ctx, "\\");
4252 if (!dos_fname) {
4253 return NT_STATUS_NO_MEMORY;
4255 } else {
4256 dos_fname = talloc_asprintf(mem_ctx,
4257 "\\%s",
4258 smb_fname->base_name);
4259 if (!dos_fname) {
4260 return NT_STATUS_NO_MEMORY;
4262 if (is_ntfs_stream_smb_fname(smb_fname)) {
4263 dos_fname = talloc_asprintf(dos_fname, "%s",
4264 smb_fname->stream_name);
4265 if (!dos_fname) {
4266 return NT_STATUS_NO_MEMORY;
4270 string_replace(dos_fname, '/', '\\');
4273 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4275 if (!fsp) {
4276 /* Do we have this path open ? */
4277 files_struct *fsp1;
4278 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4279 fsp1 = file_find_di_first(fileid);
4280 if (fsp1 && fsp1->initial_allocation_size) {
4281 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4285 if (!(mode & aDIR)) {
4286 file_size = get_file_size_stat(psbuf);
4289 if (fsp) {
4290 pos = fsp->fh->position_information;
4293 if (fsp) {
4294 access_mask = fsp->access_mask;
4295 } else {
4296 /* GENERIC_EXECUTE mapping from Windows */
4297 access_mask = 0x12019F;
4300 /* This should be an index number - looks like
4301 dev/ino to me :-)
4303 I think this causes us to fail the IFSKIT
4304 BasicFileInformationTest. -tpot */
4305 file_index = get_FileIndex(conn, psbuf);
4307 switch (info_level) {
4308 case SMB_INFO_STANDARD:
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4310 data_size = 22;
4311 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4312 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4313 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4314 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4315 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4316 SSVAL(pdata,l1_attrFile,mode);
4317 break;
4319 case SMB_INFO_QUERY_EA_SIZE:
4321 unsigned int ea_size =
4322 estimate_ea_size(conn, fsp,
4323 smb_fname->base_name);
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4325 data_size = 26;
4326 srv_put_dos_date2(pdata,0,create_time);
4327 srv_put_dos_date2(pdata,4,atime);
4328 srv_put_dos_date2(pdata,8,mtime); /* write time */
4329 SIVAL(pdata,12,(uint32)file_size);
4330 SIVAL(pdata,16,(uint32)allocation_size);
4331 SSVAL(pdata,20,mode);
4332 SIVAL(pdata,22,ea_size);
4333 break;
4336 case SMB_INFO_IS_NAME_VALID:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4338 if (fsp) {
4339 /* os/2 needs this ? really ?*/
4340 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4342 /* This is only reached for qpathinfo */
4343 data_size = 0;
4344 break;
4346 case SMB_INFO_QUERY_EAS_FROM_LIST:
4348 size_t total_ea_len = 0;
4349 struct ea_list *ea_file_list = NULL;
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4353 ea_file_list =
4354 get_ea_list_from_file(mem_ctx, conn, fsp,
4355 smb_fname->base_name,
4356 &total_ea_len);
4357 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4359 if (!ea_list || (total_ea_len > data_size)) {
4360 data_size = 4;
4361 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4362 break;
4365 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4366 break;
4369 case SMB_INFO_QUERY_ALL_EAS:
4371 /* We have data_size bytes to put EA's into. */
4372 size_t total_ea_len = 0;
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4376 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4377 smb_fname->base_name,
4378 &total_ea_len);
4379 if (!ea_list || (total_ea_len > data_size)) {
4380 data_size = 4;
4381 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4382 break;
4385 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4386 break;
4389 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4391 /* This is FileFullEaInformation - 0xF which maps to
4392 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4394 /* We have data_size bytes to put EA's into. */
4395 size_t total_ea_len = 0;
4396 struct ea_list *ea_file_list = NULL;
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4400 /*TODO: add filtering and index handling */
4402 ea_file_list =
4403 get_ea_list_from_file(mem_ctx, conn, fsp,
4404 smb_fname->base_name,
4405 &total_ea_len);
4406 if (!ea_file_list) {
4407 return NT_STATUS_NO_EAS_ON_FILE;
4410 status = fill_ea_chained_buffer(mem_ctx,
4411 pdata,
4412 data_size,
4413 &data_size,
4414 conn, ea_file_list);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 return status;
4418 break;
4421 case SMB_FILE_BASIC_INFORMATION:
4422 case SMB_QUERY_FILE_BASIC_INFO:
4424 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4426 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4427 } else {
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4429 data_size = 40;
4430 SIVAL(pdata,36,0);
4432 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4433 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4434 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4435 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4436 SIVAL(pdata,32,mode);
4438 DEBUG(5,("SMB_QFBI - "));
4439 DEBUG(5,("create: %s ", ctime(&create_time)));
4440 DEBUG(5,("access: %s ", ctime(&atime)));
4441 DEBUG(5,("write: %s ", ctime(&mtime)));
4442 DEBUG(5,("change: %s ", ctime(&c_time)));
4443 DEBUG(5,("mode: %x\n", mode));
4444 break;
4446 case SMB_FILE_STANDARD_INFORMATION:
4447 case SMB_QUERY_FILE_STANDARD_INFO:
4449 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4450 data_size = 24;
4451 SOFF_T(pdata,0,allocation_size);
4452 SOFF_T(pdata,8,file_size);
4453 SIVAL(pdata,16,nlink);
4454 SCVAL(pdata,20,delete_pending?1:0);
4455 SCVAL(pdata,21,(mode&aDIR)?1:0);
4456 SSVAL(pdata,22,0); /* Padding. */
4457 break;
4459 case SMB_FILE_EA_INFORMATION:
4460 case SMB_QUERY_FILE_EA_INFO:
4462 unsigned int ea_size =
4463 estimate_ea_size(conn, fsp, smb_fname->base_name);
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4465 data_size = 4;
4466 SIVAL(pdata,0,ea_size);
4467 break;
4470 /* Get the 8.3 name - used if NT SMB was negotiated. */
4471 case SMB_QUERY_FILE_ALT_NAME_INFO:
4472 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4474 int len;
4475 char mangled_name[13];
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4477 if (!name_to_8_3(base_name,mangled_name,
4478 True,conn->params)) {
4479 return NT_STATUS_NO_MEMORY;
4481 len = srvstr_push(dstart, flags2,
4482 pdata+4, mangled_name,
4483 PTR_DIFF(dend, pdata+4),
4484 STR_UNICODE);
4485 data_size = 4 + len;
4486 SIVAL(pdata,0,len);
4487 break;
4490 case SMB_QUERY_FILE_NAME_INFO:
4492 int len;
4494 this must be *exactly* right for ACLs on mapped drives to work
4496 len = srvstr_push(dstart, flags2,
4497 pdata+4, dos_fname,
4498 PTR_DIFF(dend, pdata+4),
4499 STR_UNICODE);
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4501 data_size = 4 + len;
4502 SIVAL(pdata,0,len);
4503 break;
4506 case SMB_FILE_ALLOCATION_INFORMATION:
4507 case SMB_QUERY_FILE_ALLOCATION_INFO:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4509 data_size = 8;
4510 SOFF_T(pdata,0,allocation_size);
4511 break;
4513 case SMB_FILE_END_OF_FILE_INFORMATION:
4514 case SMB_QUERY_FILE_END_OF_FILEINFO:
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4516 data_size = 8;
4517 SOFF_T(pdata,0,file_size);
4518 break;
4520 case SMB_QUERY_FILE_ALL_INFO:
4521 case SMB_FILE_ALL_INFORMATION:
4523 int len;
4524 unsigned int ea_size =
4525 estimate_ea_size(conn, fsp, smb_fname->base_name);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4527 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4528 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4529 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4530 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4531 SIVAL(pdata,32,mode);
4532 SIVAL(pdata,36,0); /* padding. */
4533 pdata += 40;
4534 SOFF_T(pdata,0,allocation_size);
4535 SOFF_T(pdata,8,file_size);
4536 SIVAL(pdata,16,nlink);
4537 SCVAL(pdata,20,delete_pending);
4538 SCVAL(pdata,21,(mode&aDIR)?1:0);
4539 SSVAL(pdata,22,0);
4540 pdata += 24;
4541 SIVAL(pdata,0,ea_size);
4542 pdata += 4; /* EA info */
4543 len = srvstr_push(dstart, flags2,
4544 pdata+4, dos_fname,
4545 PTR_DIFF(dend, pdata+4),
4546 STR_UNICODE);
4547 SIVAL(pdata,0,len);
4548 pdata += 4 + len;
4549 data_size = PTR_DIFF(pdata,(*ppdata));
4550 break;
4553 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4555 int len;
4556 unsigned int ea_size =
4557 estimate_ea_size(conn, fsp, smb_fname->base_name);
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4559 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4560 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4561 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4562 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4563 SIVAL(pdata, 0x20, mode);
4564 SIVAL(pdata, 0x24, 0); /* padding. */
4565 SBVAL(pdata, 0x28, allocation_size);
4566 SBVAL(pdata, 0x30, file_size);
4567 SIVAL(pdata, 0x38, nlink);
4568 SCVAL(pdata, 0x3C, delete_pending);
4569 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4570 SSVAL(pdata, 0x3E, 0); /* padding */
4571 SBVAL(pdata, 0x40, file_index);
4572 SIVAL(pdata, 0x48, ea_size);
4573 SIVAL(pdata, 0x4C, access_mask);
4574 SBVAL(pdata, 0x50, pos);
4575 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4576 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4578 pdata += 0x60;
4580 len = srvstr_push(dstart, flags2,
4581 pdata+4, dos_fname,
4582 PTR_DIFF(dend, pdata+4),
4583 STR_UNICODE);
4584 SIVAL(pdata,0,len);
4585 pdata += 4 + len;
4586 data_size = PTR_DIFF(pdata,(*ppdata));
4587 break;
4589 case SMB_FILE_INTERNAL_INFORMATION:
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4592 SBVAL(pdata, 0, file_index);
4593 data_size = 8;
4594 break;
4596 case SMB_FILE_ACCESS_INFORMATION:
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4598 SIVAL(pdata, 0, access_mask);
4599 data_size = 4;
4600 break;
4602 case SMB_FILE_NAME_INFORMATION:
4603 /* Pathname with leading '\'. */
4605 size_t byte_len;
4606 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4608 SIVAL(pdata,0,byte_len);
4609 data_size = 4 + byte_len;
4610 break;
4613 case SMB_FILE_DISPOSITION_INFORMATION:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4615 data_size = 1;
4616 SCVAL(pdata,0,delete_pending);
4617 break;
4619 case SMB_FILE_POSITION_INFORMATION:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4621 data_size = 8;
4622 SOFF_T(pdata,0,pos);
4623 break;
4625 case SMB_FILE_MODE_INFORMATION:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4627 SIVAL(pdata,0,mode);
4628 data_size = 4;
4629 break;
4631 case SMB_FILE_ALIGNMENT_INFORMATION:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4633 SIVAL(pdata,0,0); /* No alignment needed. */
4634 data_size = 4;
4635 break;
4638 * NT4 server just returns "invalid query" to this - if we try
4639 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4640 * want this. JRA.
4642 /* The first statement above is false - verified using Thursby
4643 * client against NT4 -- gcolley.
4645 case SMB_QUERY_FILE_STREAM_INFO:
4646 case SMB_FILE_STREAM_INFORMATION: {
4647 unsigned int num_streams;
4648 struct stream_struct *streams;
4650 DEBUG(10,("smbd_do_qfilepathinfo: "
4651 "SMB_FILE_STREAM_INFORMATION\n"));
4653 if (is_ntfs_stream_smb_fname(smb_fname)) {
4654 return NT_STATUS_INVALID_PARAMETER;
4657 status = SMB_VFS_STREAMINFO(
4658 conn, fsp, smb_fname->base_name, talloc_tos(),
4659 &num_streams, &streams);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 DEBUG(10, ("could not get stream info: %s\n",
4663 nt_errstr(status)));
4664 return status;
4667 status = marshall_stream_info(num_streams, streams,
4668 pdata, max_data_bytes,
4669 &data_size);
4671 if (!NT_STATUS_IS_OK(status)) {
4672 DEBUG(10, ("marshall_stream_info failed: %s\n",
4673 nt_errstr(status)));
4674 return status;
4677 TALLOC_FREE(streams);
4679 break;
4681 case SMB_QUERY_COMPRESSION_INFO:
4682 case SMB_FILE_COMPRESSION_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4684 SOFF_T(pdata,0,file_size);
4685 SIVAL(pdata,8,0); /* ??? */
4686 SIVAL(pdata,12,0); /* ??? */
4687 data_size = 16;
4688 break;
4690 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4692 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4693 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4694 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4695 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4696 SOFF_T(pdata,32,allocation_size);
4697 SOFF_T(pdata,40,file_size);
4698 SIVAL(pdata,48,mode);
4699 SIVAL(pdata,52,0); /* ??? */
4700 data_size = 56;
4701 break;
4703 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4705 SIVAL(pdata,0,mode);
4706 SIVAL(pdata,4,0);
4707 data_size = 8;
4708 break;
4711 * CIFS UNIX Extensions.
4714 case SMB_QUERY_FILE_UNIX_BASIC:
4716 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4717 data_size = PTR_DIFF(pdata,(*ppdata));
4720 int i;
4721 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4723 for (i=0; i<100; i++)
4724 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4725 DEBUG(4,("\n"));
4728 break;
4730 case SMB_QUERY_FILE_UNIX_INFO2:
4732 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4733 data_size = PTR_DIFF(pdata,(*ppdata));
4736 int i;
4737 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4739 for (i=0; i<100; i++)
4740 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4741 DEBUG(4,("\n"));
4744 break;
4746 case SMB_QUERY_FILE_UNIX_LINK:
4748 int len;
4749 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4751 if (!buffer) {
4752 return NT_STATUS_NO_MEMORY;
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4756 #ifdef S_ISLNK
4757 if(!S_ISLNK(psbuf->st_ex_mode)) {
4758 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4760 #else
4761 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4762 #endif
4763 len = SMB_VFS_READLINK(conn,
4764 smb_fname->base_name,
4765 buffer, PATH_MAX);
4766 if (len == -1) {
4767 return map_nt_error_from_unix(errno);
4769 buffer[len] = 0;
4770 len = srvstr_push(dstart, flags2,
4771 pdata, buffer,
4772 PTR_DIFF(dend, pdata),
4773 STR_TERMINATE);
4774 pdata += len;
4775 data_size = PTR_DIFF(pdata,(*ppdata));
4777 break;
4780 #if defined(HAVE_POSIX_ACLS)
4781 case SMB_QUERY_POSIX_ACL:
4783 SMB_ACL_T file_acl = NULL;
4784 SMB_ACL_T def_acl = NULL;
4785 uint16 num_file_acls = 0;
4786 uint16 num_def_acls = 0;
4788 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4789 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4790 } else {
4791 file_acl =
4792 SMB_VFS_SYS_ACL_GET_FILE(conn,
4793 smb_fname->base_name,
4794 SMB_ACL_TYPE_ACCESS);
4797 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4798 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4799 "not implemented on "
4800 "filesystem containing %s\n",
4801 smb_fname->base_name));
4802 return NT_STATUS_NOT_IMPLEMENTED;
4805 if (S_ISDIR(psbuf->st_ex_mode)) {
4806 if (fsp && fsp->is_directory) {
4807 def_acl =
4808 SMB_VFS_SYS_ACL_GET_FILE(
4809 conn,
4810 fsp->fsp_name->base_name,
4811 SMB_ACL_TYPE_DEFAULT);
4812 } else {
4813 def_acl =
4814 SMB_VFS_SYS_ACL_GET_FILE(
4815 conn,
4816 smb_fname->base_name,
4817 SMB_ACL_TYPE_DEFAULT);
4819 def_acl = free_empty_sys_acl(conn, def_acl);
4822 num_file_acls = count_acl_entries(conn, file_acl);
4823 num_def_acls = count_acl_entries(conn, def_acl);
4825 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4826 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4827 data_size,
4828 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4829 SMB_POSIX_ACL_HEADER_SIZE) ));
4830 if (file_acl) {
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4833 if (def_acl) {
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4836 return NT_STATUS_BUFFER_TOO_SMALL;
4839 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4840 SSVAL(pdata,2,num_file_acls);
4841 SSVAL(pdata,4,num_def_acls);
4842 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4843 if (file_acl) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4846 if (def_acl) {
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4849 return NT_STATUS_INTERNAL_ERROR;
4851 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4852 if (file_acl) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4855 if (def_acl) {
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4858 return NT_STATUS_INTERNAL_ERROR;
4861 if (file_acl) {
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4864 if (def_acl) {
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4867 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4868 break;
4870 #endif
4873 case SMB_QUERY_POSIX_LOCK:
4875 uint64_t count;
4876 uint64_t offset;
4877 uint32 lock_pid;
4878 enum brl_type lock_type;
4880 /* We need an open file with a real fd for this. */
4881 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4882 return NT_STATUS_INVALID_LEVEL;
4885 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4886 return NT_STATUS_INVALID_PARAMETER;
4889 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4890 case POSIX_LOCK_TYPE_READ:
4891 lock_type = READ_LOCK;
4892 break;
4893 case POSIX_LOCK_TYPE_WRITE:
4894 lock_type = WRITE_LOCK;
4895 break;
4896 case POSIX_LOCK_TYPE_UNLOCK:
4897 default:
4898 /* There's no point in asking for an unlock... */
4899 return NT_STATUS_INVALID_PARAMETER;
4902 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4903 #if defined(HAVE_LONGLONG)
4904 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4905 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4906 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4907 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4908 #else /* HAVE_LONGLONG */
4909 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4910 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4911 #endif /* HAVE_LONGLONG */
4913 status = query_lock(fsp,
4914 &lock_pid,
4915 &count,
4916 &offset,
4917 &lock_type,
4918 POSIX_LOCK);
4920 if (ERROR_WAS_LOCK_DENIED(status)) {
4921 /* Here we need to report who has it locked... */
4922 data_size = POSIX_LOCK_DATA_SIZE;
4924 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4925 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4926 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4927 #if defined(HAVE_LONGLONG)
4928 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4929 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4930 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4931 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4932 #else /* HAVE_LONGLONG */
4933 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4934 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4935 #endif /* HAVE_LONGLONG */
4937 } else if (NT_STATUS_IS_OK(status)) {
4938 /* For success we just return a copy of what we sent
4939 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4940 data_size = POSIX_LOCK_DATA_SIZE;
4941 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4942 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4943 } else {
4944 return status;
4946 break;
4949 default:
4950 return NT_STATUS_INVALID_LEVEL;
4953 *pdata_size = data_size;
4954 return NT_STATUS_OK;
4957 /****************************************************************************
4958 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4959 file name or file id).
4960 ****************************************************************************/
4962 static void call_trans2qfilepathinfo(connection_struct *conn,
4963 struct smb_request *req,
4964 unsigned int tran_call,
4965 char **pparams, int total_params,
4966 char **ppdata, int total_data,
4967 unsigned int max_data_bytes)
4969 char *params = *pparams;
4970 char *pdata = *ppdata;
4971 uint16 info_level;
4972 unsigned int data_size = 0;
4973 unsigned int param_size = 2;
4974 struct smb_filename *smb_fname = NULL;
4975 bool delete_pending = False;
4976 struct timespec write_time_ts;
4977 files_struct *fsp = NULL;
4978 struct file_id fileid;
4979 struct ea_list *ea_list = NULL;
4980 int lock_data_count = 0;
4981 char *lock_data = NULL;
4982 bool ms_dfs_link = false;
4983 NTSTATUS status = NT_STATUS_OK;
4985 if (!params) {
4986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987 return;
4990 ZERO_STRUCT(write_time_ts);
4992 if (tran_call == TRANSACT2_QFILEINFO) {
4993 if (total_params < 4) {
4994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4995 return;
4998 if (IS_IPC(conn)) {
4999 call_trans2qpipeinfo(conn, req, tran_call,
5000 pparams, total_params,
5001 ppdata, total_data,
5002 max_data_bytes);
5003 return;
5006 fsp = file_fsp(req, SVAL(params,0));
5007 info_level = SVAL(params,2);
5009 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5011 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5012 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5013 return;
5016 /* Initial check for valid fsp ptr. */
5017 if (!check_fsp_open(conn, req, fsp)) {
5018 return;
5021 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5022 &smb_fname);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 reply_nterror(req, status);
5025 return;
5028 if(fsp->fake_file_handle) {
5030 * This is actually for the QUOTA_FAKE_FILE --metze
5033 /* We know this name is ok, it's already passed the checks. */
5035 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5037 * This is actually a QFILEINFO on a directory
5038 * handle (returned from an NT SMB). NT5.0 seems
5039 * to do this call. JRA.
5042 if (INFO_LEVEL_IS_UNIX(info_level)) {
5043 /* Always do lstat for UNIX calls. */
5044 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5045 DEBUG(3,("call_trans2qfilepathinfo: "
5046 "SMB_VFS_LSTAT of %s failed "
5047 "(%s)\n",
5048 smb_fname_str_dbg(smb_fname),
5049 strerror(errno)));
5050 reply_nterror(req,
5051 map_nt_error_from_unix(errno));
5052 return;
5054 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5055 DEBUG(3,("call_trans2qfilepathinfo: "
5056 "SMB_VFS_STAT of %s failed (%s)\n",
5057 smb_fname_str_dbg(smb_fname),
5058 strerror(errno)));
5059 reply_nterror(req,
5060 map_nt_error_from_unix(errno));
5061 return;
5064 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5065 get_file_infos(fileid, &delete_pending, &write_time_ts);
5066 } else {
5068 * Original code - this is an open file.
5070 if (!check_fsp(conn, req, fsp)) {
5071 return;
5074 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5075 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5076 fsp->fnum, strerror(errno)));
5077 reply_nterror(req,
5078 map_nt_error_from_unix(errno));
5079 return;
5081 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5082 get_file_infos(fileid, &delete_pending, &write_time_ts);
5085 } else {
5086 char *fname = NULL;
5087 uint32_t ucf_flags = 0;
5089 /* qpathinfo */
5090 if (total_params < 7) {
5091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5092 return;
5095 info_level = SVAL(params,0);
5097 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5099 if (INFO_LEVEL_IS_UNIX(info_level)) {
5100 if (!lp_unix_extensions()) {
5101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5102 return;
5104 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5105 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5106 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5107 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5111 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5112 total_params - 6,
5113 STR_TERMINATE, &status);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 reply_nterror(req, status);
5116 return;
5119 status = filename_convert(req,
5120 conn,
5121 req->flags2 & FLAGS2_DFS_PATHNAMES,
5122 fname,
5123 ucf_flags,
5124 NULL,
5125 &smb_fname);
5126 if (!NT_STATUS_IS_OK(status)) {
5127 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5128 reply_botherror(req,
5129 NT_STATUS_PATH_NOT_COVERED,
5130 ERRSRV, ERRbadpath);
5131 return;
5133 reply_nterror(req, status);
5134 return;
5137 /* If this is a stream, check if there is a delete_pending. */
5138 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5139 && is_ntfs_stream_smb_fname(smb_fname)) {
5140 struct smb_filename *smb_fname_base = NULL;
5142 /* Create an smb_filename with stream_name == NULL. */
5143 status =
5144 create_synthetic_smb_fname(talloc_tos(),
5145 smb_fname->base_name,
5146 NULL, NULL,
5147 &smb_fname_base);
5148 if (!NT_STATUS_IS_OK(status)) {
5149 reply_nterror(req, status);
5150 return;
5153 if (INFO_LEVEL_IS_UNIX(info_level)) {
5154 /* Always do lstat for UNIX calls. */
5155 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5156 DEBUG(3,("call_trans2qfilepathinfo: "
5157 "SMB_VFS_LSTAT of %s failed "
5158 "(%s)\n",
5159 smb_fname_str_dbg(smb_fname_base),
5160 strerror(errno)));
5161 TALLOC_FREE(smb_fname_base);
5162 reply_nterror(req,
5163 map_nt_error_from_unix(errno));
5164 return;
5166 } else {
5167 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5168 DEBUG(3,("call_trans2qfilepathinfo: "
5169 "fileinfo of %s failed "
5170 "(%s)\n",
5171 smb_fname_str_dbg(smb_fname_base),
5172 strerror(errno)));
5173 TALLOC_FREE(smb_fname_base);
5174 reply_nterror(req,
5175 map_nt_error_from_unix(errno));
5176 return;
5180 fileid = vfs_file_id_from_sbuf(conn,
5181 &smb_fname_base->st);
5182 TALLOC_FREE(smb_fname_base);
5183 get_file_infos(fileid, &delete_pending, NULL);
5184 if (delete_pending) {
5185 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5186 return;
5190 if (INFO_LEVEL_IS_UNIX(info_level)) {
5191 /* Always do lstat for UNIX calls. */
5192 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5193 DEBUG(3,("call_trans2qfilepathinfo: "
5194 "SMB_VFS_LSTAT of %s failed (%s)\n",
5195 smb_fname_str_dbg(smb_fname),
5196 strerror(errno)));
5197 reply_nterror(req,
5198 map_nt_error_from_unix(errno));
5199 return;
5202 } else if (!VALID_STAT(smb_fname->st) &&
5203 SMB_VFS_STAT(conn, smb_fname) &&
5204 (info_level != SMB_INFO_IS_NAME_VALID)) {
5205 ms_dfs_link = check_msdfs_link(conn,
5206 smb_fname->base_name,
5207 &smb_fname->st);
5209 if (!ms_dfs_link) {
5210 DEBUG(3,("call_trans2qfilepathinfo: "
5211 "SMB_VFS_STAT of %s failed (%s)\n",
5212 smb_fname_str_dbg(smb_fname),
5213 strerror(errno)));
5214 reply_nterror(req,
5215 map_nt_error_from_unix(errno));
5216 return;
5220 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5221 get_file_infos(fileid, &delete_pending, &write_time_ts);
5222 if (delete_pending) {
5223 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5224 return;
5228 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5229 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5230 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5232 /* Pull out any data sent here before we realloc. */
5233 switch (info_level) {
5234 case SMB_INFO_QUERY_EAS_FROM_LIST:
5236 /* Pull any EA list from the data portion. */
5237 uint32 ea_size;
5239 if (total_data < 4) {
5240 reply_nterror(
5241 req, NT_STATUS_INVALID_PARAMETER);
5242 return;
5244 ea_size = IVAL(pdata,0);
5246 if (total_data > 0 && ea_size != total_data) {
5247 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5248 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5249 reply_nterror(
5250 req, NT_STATUS_INVALID_PARAMETER);
5251 return;
5254 if (!lp_ea_support(SNUM(conn))) {
5255 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5256 return;
5259 /* Pull out the list of names. */
5260 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5261 if (!ea_list) {
5262 reply_nterror(
5263 req, NT_STATUS_INVALID_PARAMETER);
5264 return;
5266 break;
5269 case SMB_QUERY_POSIX_LOCK:
5271 if (fsp == NULL || fsp->fh->fd == -1) {
5272 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5273 return;
5276 if (total_data != POSIX_LOCK_DATA_SIZE) {
5277 reply_nterror(
5278 req, NT_STATUS_INVALID_PARAMETER);
5279 return;
5282 /* Copy the lock range data. */
5283 lock_data = (char *)TALLOC_MEMDUP(
5284 req, pdata, total_data);
5285 if (!lock_data) {
5286 reply_nterror(req, NT_STATUS_NO_MEMORY);
5287 return;
5289 lock_data_count = total_data;
5291 default:
5292 break;
5295 *pparams = (char *)SMB_REALLOC(*pparams,2);
5296 if (*pparams == NULL) {
5297 reply_nterror(req, NT_STATUS_NO_MEMORY);
5298 return;
5300 params = *pparams;
5301 SSVAL(params,0,0);
5304 * draft-leach-cifs-v1-spec-02.txt
5305 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5306 * says:
5308 * The requested information is placed in the Data portion of the
5309 * transaction response. For the information levels greater than 0x100,
5310 * the transaction response has 1 parameter word which should be
5311 * ignored by the client.
5313 * However Windows only follows this rule for the IS_NAME_VALID call.
5315 switch (info_level) {
5316 case SMB_INFO_IS_NAME_VALID:
5317 param_size = 0;
5318 break;
5321 if ((info_level & 0xFF00) == 0xFF00) {
5323 * We use levels that start with 0xFF00
5324 * internally to represent SMB2 specific levels
5326 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5327 return;
5330 status = smbd_do_qfilepathinfo(conn, req, info_level,
5331 fsp, smb_fname,
5332 delete_pending, write_time_ts,
5333 ms_dfs_link, ea_list,
5334 lock_data_count, lock_data,
5335 req->flags2, max_data_bytes,
5336 ppdata, &data_size);
5337 if (!NT_STATUS_IS_OK(status)) {
5338 reply_nterror(req, status);
5339 return;
5342 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5343 max_data_bytes);
5345 return;
5348 /****************************************************************************
5349 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5350 code.
5351 ****************************************************************************/
5353 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5354 connection_struct *conn,
5355 const struct smb_filename *smb_fname_old,
5356 const struct smb_filename *smb_fname_new)
5358 NTSTATUS status = NT_STATUS_OK;
5360 /* source must already exist. */
5361 if (!VALID_STAT(smb_fname_old->st)) {
5362 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5365 /* Disallow if newname already exists. */
5366 if (VALID_STAT(smb_fname_new->st)) {
5367 return NT_STATUS_OBJECT_NAME_COLLISION;
5370 /* No links from a directory. */
5371 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5372 return NT_STATUS_FILE_IS_A_DIRECTORY;
5375 /* Setting a hardlink to/from a stream isn't currently supported. */
5376 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5377 is_ntfs_stream_smb_fname(smb_fname_new)) {
5378 return NT_STATUS_INVALID_PARAMETER;
5381 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5382 smb_fname_old->base_name, smb_fname_new->base_name));
5384 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5385 smb_fname_new->base_name) != 0) {
5386 status = map_nt_error_from_unix(errno);
5387 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5388 nt_errstr(status), smb_fname_old->base_name,
5389 smb_fname_new->base_name));
5391 return status;
5394 /****************************************************************************
5395 Deal with setting the time from any of the setfilepathinfo functions.
5396 ****************************************************************************/
5398 NTSTATUS smb_set_file_time(connection_struct *conn,
5399 files_struct *fsp,
5400 const struct smb_filename *smb_fname,
5401 struct smb_file_time *ft,
5402 bool setting_write_time)
5404 struct smb_filename smb_fname_base;
5405 uint32 action =
5406 FILE_NOTIFY_CHANGE_LAST_ACCESS
5407 |FILE_NOTIFY_CHANGE_LAST_WRITE
5408 |FILE_NOTIFY_CHANGE_CREATION;
5410 if (!VALID_STAT(smb_fname->st)) {
5411 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5414 /* get some defaults (no modifications) if any info is zero or -1. */
5415 if (null_timespec(ft->create_time)) {
5416 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5419 if (null_timespec(ft->atime)) {
5420 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5423 if (null_timespec(ft->mtime)) {
5424 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5427 if (!setting_write_time) {
5428 /* ft->mtime comes from change time, not write time. */
5429 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5432 /* Ensure the resolution is the correct for
5433 * what we can store on this filesystem. */
5435 round_timespec(conn->ts_res, &ft->create_time);
5436 round_timespec(conn->ts_res, &ft->ctime);
5437 round_timespec(conn->ts_res, &ft->atime);
5438 round_timespec(conn->ts_res, &ft->mtime);
5440 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5442 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5443 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5444 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5445 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5446 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5447 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5449 if (setting_write_time) {
5451 * This was a Windows setfileinfo on an open file.
5452 * NT does this a lot. We also need to
5453 * set the time here, as it can be read by
5454 * FindFirst/FindNext and with the patch for bug #2045
5455 * in smbd/fileio.c it ensures that this timestamp is
5456 * kept sticky even after a write. We save the request
5457 * away and will set it on file close and after a write. JRA.
5460 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5461 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5463 if (fsp != NULL) {
5464 if (fsp->base_fsp) {
5465 set_sticky_write_time_fsp(fsp->base_fsp,
5466 ft->mtime);
5467 } else {
5468 set_sticky_write_time_fsp(fsp, ft->mtime);
5470 } else {
5471 set_sticky_write_time_path(
5472 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5473 ft->mtime);
5477 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5479 /* Always call ntimes on the base, even if a stream was passed in. */
5480 smb_fname_base = *smb_fname;
5481 smb_fname_base.stream_name = NULL;
5483 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5484 return map_nt_error_from_unix(errno);
5487 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5488 smb_fname->base_name);
5489 return NT_STATUS_OK;
5492 /****************************************************************************
5493 Deal with setting the dosmode from any of the setfilepathinfo functions.
5494 ****************************************************************************/
5496 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5497 const struct smb_filename *smb_fname,
5498 uint32 dosmode)
5500 struct smb_filename *smb_fname_base = NULL;
5501 NTSTATUS status;
5503 if (!VALID_STAT(smb_fname->st)) {
5504 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5507 /* Always operate on the base_name, even if a stream was passed in. */
5508 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5509 NULL, &smb_fname->st,
5510 &smb_fname_base);
5511 if (!NT_STATUS_IS_OK(status)) {
5512 return status;
5515 if (dosmode) {
5516 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5517 dosmode |= aDIR;
5518 } else {
5519 dosmode &= ~aDIR;
5523 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5525 /* check the mode isn't different, before changing it */
5526 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5527 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5528 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5529 (unsigned int)dosmode));
5531 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5532 false)) {
5533 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5534 "%s failed (%s)\n",
5535 smb_fname_str_dbg(smb_fname_base),
5536 strerror(errno)));
5537 status = map_nt_error_from_unix(errno);
5538 goto out;
5541 status = NT_STATUS_OK;
5542 out:
5543 TALLOC_FREE(smb_fname_base);
5544 return status;
5547 /****************************************************************************
5548 Deal with setting the size from any of the setfilepathinfo functions.
5549 ****************************************************************************/
5551 static NTSTATUS smb_set_file_size(connection_struct *conn,
5552 struct smb_request *req,
5553 files_struct *fsp,
5554 const struct smb_filename *smb_fname,
5555 const SMB_STRUCT_STAT *psbuf,
5556 SMB_OFF_T size,
5557 bool fail_after_createfile)
5559 NTSTATUS status = NT_STATUS_OK;
5560 struct smb_filename *smb_fname_tmp = NULL;
5561 files_struct *new_fsp = NULL;
5563 if (!VALID_STAT(*psbuf)) {
5564 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5567 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5569 if (size == get_file_size_stat(psbuf)) {
5570 return NT_STATUS_OK;
5573 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5574 smb_fname_str_dbg(smb_fname), (double)size));
5576 if (fsp && fsp->fh->fd != -1) {
5577 /* Handle based call. */
5578 if (vfs_set_filelen(fsp, size) == -1) {
5579 return map_nt_error_from_unix(errno);
5581 trigger_write_time_update_immediate(fsp);
5582 return NT_STATUS_OK;
5585 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5586 if (!NT_STATUS_IS_OK(status)) {
5587 return status;
5590 smb_fname_tmp->st = *psbuf;
5592 status = SMB_VFS_CREATE_FILE(
5593 conn, /* conn */
5594 req, /* req */
5595 0, /* root_dir_fid */
5596 smb_fname_tmp, /* fname */
5597 FILE_WRITE_ATTRIBUTES, /* access_mask */
5598 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5599 FILE_SHARE_DELETE),
5600 FILE_OPEN, /* create_disposition*/
5601 0, /* create_options */
5602 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5603 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5604 0, /* allocation_size */
5605 NULL, /* sd */
5606 NULL, /* ea_list */
5607 &new_fsp, /* result */
5608 NULL); /* pinfo */
5610 TALLOC_FREE(smb_fname_tmp);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 /* NB. We check for open_was_deferred in the caller. */
5614 return status;
5617 /* See RAW-SFILEINFO-END-OF-FILE */
5618 if (fail_after_createfile) {
5619 close_file(req, new_fsp,NORMAL_CLOSE);
5620 return NT_STATUS_INVALID_LEVEL;
5623 if (vfs_set_filelen(new_fsp, size) == -1) {
5624 status = map_nt_error_from_unix(errno);
5625 close_file(req, new_fsp,NORMAL_CLOSE);
5626 return status;
5629 trigger_write_time_update_immediate(new_fsp);
5630 close_file(req, new_fsp,NORMAL_CLOSE);
5631 return NT_STATUS_OK;
5634 /****************************************************************************
5635 Deal with SMB_INFO_SET_EA.
5636 ****************************************************************************/
5638 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5639 const char *pdata,
5640 int total_data,
5641 files_struct *fsp,
5642 const struct smb_filename *smb_fname)
5644 struct ea_list *ea_list = NULL;
5645 TALLOC_CTX *ctx = NULL;
5646 NTSTATUS status = NT_STATUS_OK;
5648 if (total_data < 10) {
5650 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5651 length. They seem to have no effect. Bug #3212. JRA */
5653 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5654 /* We're done. We only get EA info in this call. */
5655 return NT_STATUS_OK;
5658 return NT_STATUS_INVALID_PARAMETER;
5661 if (IVAL(pdata,0) > total_data) {
5662 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5663 IVAL(pdata,0), (unsigned int)total_data));
5664 return NT_STATUS_INVALID_PARAMETER;
5667 ctx = talloc_tos();
5668 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5669 if (!ea_list) {
5670 return NT_STATUS_INVALID_PARAMETER;
5672 status = set_ea(conn, fsp, smb_fname, ea_list);
5674 return status;
5677 /****************************************************************************
5678 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5679 ****************************************************************************/
5681 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5682 const char *pdata,
5683 int total_data,
5684 files_struct *fsp)
5686 struct ea_list *ea_list = NULL;
5687 NTSTATUS status;
5689 if (!fsp) {
5690 return NT_STATUS_INVALID_HANDLE;
5693 if (!lp_ea_support(SNUM(conn))) {
5694 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5695 "EA's not supported.\n",
5696 (unsigned int)total_data));
5697 return NT_STATUS_EAS_NOT_SUPPORTED;
5700 if (total_data < 10) {
5701 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5702 "too small.\n",
5703 (unsigned int)total_data));
5704 return NT_STATUS_INVALID_PARAMETER;
5707 ea_list = read_nttrans_ea_list(talloc_tos(),
5708 pdata,
5709 total_data);
5711 if (!ea_list) {
5712 return NT_STATUS_INVALID_PARAMETER;
5714 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5716 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5717 smb_fname_str_dbg(fsp->fsp_name),
5718 nt_errstr(status) ));
5720 return status;
5724 /****************************************************************************
5725 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5726 ****************************************************************************/
5728 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5729 const char *pdata,
5730 int total_data,
5731 files_struct *fsp,
5732 struct smb_filename *smb_fname)
5734 NTSTATUS status = NT_STATUS_OK;
5735 bool delete_on_close;
5736 uint32 dosmode = 0;
5738 if (total_data < 1) {
5739 return NT_STATUS_INVALID_PARAMETER;
5742 if (fsp == NULL) {
5743 return NT_STATUS_INVALID_HANDLE;
5746 delete_on_close = (CVAL(pdata,0) ? True : False);
5747 dosmode = dos_mode(conn, smb_fname);
5749 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5750 "delete_on_close = %u\n",
5751 smb_fname_str_dbg(smb_fname),
5752 (unsigned int)dosmode,
5753 (unsigned int)delete_on_close ));
5755 if (delete_on_close) {
5756 status = can_set_delete_on_close(fsp, dosmode);
5757 if (!NT_STATUS_IS_OK(status)) {
5758 return status;
5762 /* The set is across all open files on this dev/inode pair. */
5763 if (!set_delete_on_close(fsp, delete_on_close,
5764 &conn->server_info->utok)) {
5765 return NT_STATUS_ACCESS_DENIED;
5767 return NT_STATUS_OK;
5770 /****************************************************************************
5771 Deal with SMB_FILE_POSITION_INFORMATION.
5772 ****************************************************************************/
5774 static NTSTATUS smb_file_position_information(connection_struct *conn,
5775 const char *pdata,
5776 int total_data,
5777 files_struct *fsp)
5779 uint64_t position_information;
5781 if (total_data < 8) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 if (fsp == NULL) {
5786 /* Ignore on pathname based set. */
5787 return NT_STATUS_OK;
5790 position_information = (uint64_t)IVAL(pdata,0);
5791 #ifdef LARGE_SMB_OFF_T
5792 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5793 #else /* LARGE_SMB_OFF_T */
5794 if (IVAL(pdata,4) != 0) {
5795 /* more than 32 bits? */
5796 return NT_STATUS_INVALID_PARAMETER;
5798 #endif /* LARGE_SMB_OFF_T */
5800 DEBUG(10,("smb_file_position_information: Set file position "
5801 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5802 (double)position_information));
5803 fsp->fh->position_information = position_information;
5804 return NT_STATUS_OK;
5807 /****************************************************************************
5808 Deal with SMB_FILE_MODE_INFORMATION.
5809 ****************************************************************************/
5811 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5812 const char *pdata,
5813 int total_data)
5815 uint32 mode;
5817 if (total_data < 4) {
5818 return NT_STATUS_INVALID_PARAMETER;
5820 mode = IVAL(pdata,0);
5821 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5822 return NT_STATUS_INVALID_PARAMETER;
5824 return NT_STATUS_OK;
5827 /****************************************************************************
5828 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5829 ****************************************************************************/
5831 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5832 struct smb_request *req,
5833 const char *pdata,
5834 int total_data,
5835 const struct smb_filename *smb_fname)
5837 char *link_target = NULL;
5838 const char *newname = smb_fname->base_name;
5839 TALLOC_CTX *ctx = talloc_tos();
5841 /* Set a symbolic link. */
5842 /* Don't allow this if follow links is false. */
5844 if (total_data == 0) {
5845 return NT_STATUS_INVALID_PARAMETER;
5848 if (!lp_symlinks(SNUM(conn))) {
5849 return NT_STATUS_ACCESS_DENIED;
5852 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5853 total_data, STR_TERMINATE);
5855 if (!link_target) {
5856 return NT_STATUS_INVALID_PARAMETER;
5859 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5860 newname, link_target ));
5862 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5863 return map_nt_error_from_unix(errno);
5866 return NT_STATUS_OK;
5869 /****************************************************************************
5870 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5871 ****************************************************************************/
5873 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5874 struct smb_request *req,
5875 const char *pdata, int total_data,
5876 const struct smb_filename *smb_fname_new)
5878 char *oldname = NULL;
5879 struct smb_filename *smb_fname_old = NULL;
5880 TALLOC_CTX *ctx = talloc_tos();
5881 NTSTATUS status = NT_STATUS_OK;
5883 /* Set a hard link. */
5884 if (total_data == 0) {
5885 return NT_STATUS_INVALID_PARAMETER;
5888 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5889 total_data, STR_TERMINATE, &status);
5890 if (!NT_STATUS_IS_OK(status)) {
5891 return status;
5894 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5895 smb_fname_str_dbg(smb_fname_new), oldname));
5897 status = filename_convert(ctx,
5898 conn,
5899 req->flags2 & FLAGS2_DFS_PATHNAMES,
5900 oldname,
5902 NULL,
5903 &smb_fname_old);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 return status;
5908 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5911 /****************************************************************************
5912 Deal with SMB_FILE_RENAME_INFORMATION.
5913 ****************************************************************************/
5915 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5916 struct smb_request *req,
5917 const char *pdata,
5918 int total_data,
5919 files_struct *fsp,
5920 struct smb_filename *smb_fname_src)
5922 bool overwrite;
5923 uint32 root_fid;
5924 uint32 len;
5925 char *newname = NULL;
5926 struct smb_filename *smb_fname_dst = NULL;
5927 bool dest_has_wcard = False;
5928 NTSTATUS status = NT_STATUS_OK;
5929 char *p;
5930 TALLOC_CTX *ctx = talloc_tos();
5932 if (total_data < 13) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 overwrite = (CVAL(pdata,0) ? True : False);
5937 root_fid = IVAL(pdata,4);
5938 len = IVAL(pdata,8);
5940 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5941 return NT_STATUS_INVALID_PARAMETER;
5944 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5945 len, 0, &status,
5946 &dest_has_wcard);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return status;
5951 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5952 newname));
5954 status = resolve_dfspath_wcard(ctx, conn,
5955 req->flags2 & FLAGS2_DFS_PATHNAMES,
5956 newname,
5957 true,
5958 &newname,
5959 &dest_has_wcard);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 return status;
5964 /* Check the new name has no '/' characters. */
5965 if (strchr_m(newname, '/')) {
5966 return NT_STATUS_NOT_SUPPORTED;
5969 if (fsp && fsp->base_fsp) {
5970 /* newname must be a stream name. */
5971 if (newname[0] != ':') {
5972 return NT_STATUS_NOT_SUPPORTED;
5975 /* Create an smb_fname to call rename_internals_fsp() with. */
5976 status = create_synthetic_smb_fname(talloc_tos(),
5977 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5978 &smb_fname_dst);
5979 if (!NT_STATUS_IS_OK(status)) {
5980 goto out;
5984 * Set the original last component, since
5985 * rename_internals_fsp() requires it.
5987 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5988 newname);
5989 if (smb_fname_dst->original_lcomp == NULL) {
5990 status = NT_STATUS_NO_MEMORY;
5991 goto out;
5994 } else {
5996 * Build up an smb_fname_dst based on the filename passed in.
5997 * We basically just strip off the last component, and put on
5998 * the newname instead.
6000 char *base_name = NULL;
6002 /* newname must *not* be a stream name. */
6003 if (newname[0] == ':') {
6004 return NT_STATUS_NOT_SUPPORTED;
6008 * Strip off the last component (filename) of the path passed
6009 * in.
6011 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6012 if (!base_name) {
6013 return NT_STATUS_NO_MEMORY;
6015 p = strrchr_m(base_name, '/');
6016 if (p) {
6017 p[1] = '\0';
6018 } else {
6019 base_name = talloc_strdup(ctx, "./");
6020 if (!base_name) {
6021 return NT_STATUS_NO_MEMORY;
6024 /* Append the new name. */
6025 base_name = talloc_asprintf_append(base_name,
6026 "%s",
6027 newname);
6028 if (!base_name) {
6029 return NT_STATUS_NO_MEMORY;
6032 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6033 (UCF_SAVE_LCOMP |
6034 (dest_has_wcard ?
6035 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6036 0)));
6038 /* If an error we expect this to be
6039 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6041 if (!NT_STATUS_IS_OK(status)) {
6042 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6043 status)) {
6044 goto out;
6046 /* Create an smb_fname to call rename_internals_fsp() */
6047 status = create_synthetic_smb_fname(ctx,
6048 base_name, NULL,
6049 NULL,
6050 &smb_fname_dst);
6051 if (!NT_STATUS_IS_OK(status)) {
6052 goto out;
6057 if (fsp) {
6058 DEBUG(10,("smb_file_rename_information: "
6059 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6060 fsp->fnum, fsp_str_dbg(fsp),
6061 smb_fname_str_dbg(smb_fname_dst)));
6062 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6063 overwrite);
6064 } else {
6065 DEBUG(10,("smb_file_rename_information: "
6066 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6067 smb_fname_str_dbg(smb_fname_src),
6068 smb_fname_str_dbg(smb_fname_dst)));
6069 status = rename_internals(ctx, conn, req, smb_fname_src,
6070 smb_fname_dst, 0, overwrite, false,
6071 dest_has_wcard,
6072 FILE_WRITE_ATTRIBUTES);
6074 out:
6075 TALLOC_FREE(smb_fname_dst);
6076 return status;
6079 /****************************************************************************
6080 Deal with SMB_SET_POSIX_ACL.
6081 ****************************************************************************/
6083 #if defined(HAVE_POSIX_ACLS)
6084 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6085 const char *pdata,
6086 int total_data,
6087 files_struct *fsp,
6088 const struct smb_filename *smb_fname)
6090 uint16 posix_acl_version;
6091 uint16 num_file_acls;
6092 uint16 num_def_acls;
6093 bool valid_file_acls = True;
6094 bool valid_def_acls = True;
6096 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6097 return NT_STATUS_INVALID_PARAMETER;
6099 posix_acl_version = SVAL(pdata,0);
6100 num_file_acls = SVAL(pdata,2);
6101 num_def_acls = SVAL(pdata,4);
6103 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6104 valid_file_acls = False;
6105 num_file_acls = 0;
6108 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6109 valid_def_acls = False;
6110 num_def_acls = 0;
6113 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6114 return NT_STATUS_INVALID_PARAMETER;
6117 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6118 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6119 return NT_STATUS_INVALID_PARAMETER;
6122 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6123 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6124 (unsigned int)num_file_acls,
6125 (unsigned int)num_def_acls));
6127 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6128 smb_fname->base_name, num_file_acls,
6129 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6130 return map_nt_error_from_unix(errno);
6133 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6134 smb_fname->base_name, &smb_fname->st, num_def_acls,
6135 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6136 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6137 return map_nt_error_from_unix(errno);
6139 return NT_STATUS_OK;
6141 #endif
6143 /****************************************************************************
6144 Deal with SMB_SET_POSIX_LOCK.
6145 ****************************************************************************/
6147 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6148 struct smb_request *req,
6149 const char *pdata,
6150 int total_data,
6151 files_struct *fsp)
6153 uint64_t count;
6154 uint64_t offset;
6155 uint32 lock_pid;
6156 bool blocking_lock = False;
6157 enum brl_type lock_type;
6159 NTSTATUS status = NT_STATUS_OK;
6161 if (fsp == NULL || fsp->fh->fd == -1) {
6162 return NT_STATUS_INVALID_HANDLE;
6165 if (total_data != POSIX_LOCK_DATA_SIZE) {
6166 return NT_STATUS_INVALID_PARAMETER;
6169 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6170 case POSIX_LOCK_TYPE_READ:
6171 lock_type = READ_LOCK;
6172 break;
6173 case POSIX_LOCK_TYPE_WRITE:
6174 /* Return the right POSIX-mappable error code for files opened read-only. */
6175 if (!fsp->can_write) {
6176 return NT_STATUS_INVALID_HANDLE;
6178 lock_type = WRITE_LOCK;
6179 break;
6180 case POSIX_LOCK_TYPE_UNLOCK:
6181 lock_type = UNLOCK_LOCK;
6182 break;
6183 default:
6184 return NT_STATUS_INVALID_PARAMETER;
6187 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6188 blocking_lock = False;
6189 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6190 blocking_lock = True;
6191 } else {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 if (!lp_blocking_locks(SNUM(conn))) {
6196 blocking_lock = False;
6199 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6200 #if defined(HAVE_LONGLONG)
6201 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6202 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6203 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6204 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6205 #else /* HAVE_LONGLONG */
6206 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6207 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6208 #endif /* HAVE_LONGLONG */
6210 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6211 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6212 fsp_str_dbg(fsp),
6213 (unsigned int)lock_type,
6214 (unsigned int)lock_pid,
6215 (double)count,
6216 (double)offset ));
6218 if (lock_type == UNLOCK_LOCK) {
6219 status = do_unlock(smbd_messaging_context(),
6220 fsp,
6221 lock_pid,
6222 count,
6223 offset,
6224 POSIX_LOCK);
6225 } else {
6226 uint32 block_smbpid;
6228 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6229 fsp,
6230 lock_pid,
6231 count,
6232 offset,
6233 lock_type,
6234 POSIX_LOCK,
6235 blocking_lock,
6236 &status,
6237 &block_smbpid,
6238 NULL);
6240 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6242 * A blocking lock was requested. Package up
6243 * this smb into a queued request and push it
6244 * onto the blocking lock queue.
6246 if(push_blocking_lock_request(br_lck,
6247 req,
6248 fsp,
6249 -1, /* infinite timeout. */
6251 lock_pid,
6252 lock_type,
6253 POSIX_LOCK,
6254 offset,
6255 count,
6256 block_smbpid)) {
6257 TALLOC_FREE(br_lck);
6258 return status;
6261 TALLOC_FREE(br_lck);
6264 return status;
6267 /****************************************************************************
6268 Deal with SMB_SET_FILE_BASIC_INFO.
6269 ****************************************************************************/
6271 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6272 const char *pdata,
6273 int total_data,
6274 files_struct *fsp,
6275 const struct smb_filename *smb_fname)
6277 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6278 struct smb_file_time ft;
6279 uint32 dosmode = 0;
6280 NTSTATUS status = NT_STATUS_OK;
6282 ZERO_STRUCT(ft);
6284 if (total_data < 36) {
6285 return NT_STATUS_INVALID_PARAMETER;
6288 /* Set the attributes */
6289 dosmode = IVAL(pdata,32);
6290 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6291 if (!NT_STATUS_IS_OK(status)) {
6292 return status;
6295 /* create time */
6296 ft.create_time = interpret_long_date(pdata);
6298 /* access time */
6299 ft.atime = interpret_long_date(pdata+8);
6301 /* write time. */
6302 ft.mtime = interpret_long_date(pdata+16);
6304 /* change time. */
6305 ft.ctime = interpret_long_date(pdata+24);
6307 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6308 smb_fname_str_dbg(smb_fname)));
6310 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6311 true);
6314 /****************************************************************************
6315 Deal with SMB_INFO_STANDARD.
6316 ****************************************************************************/
6318 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6319 const char *pdata,
6320 int total_data,
6321 files_struct *fsp,
6322 const struct smb_filename *smb_fname)
6324 struct smb_file_time ft;
6326 ZERO_STRUCT(ft);
6328 if (total_data < 12) {
6329 return NT_STATUS_INVALID_PARAMETER;
6332 /* create time */
6333 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6334 /* access time */
6335 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6336 /* write time */
6337 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6339 DEBUG(10,("smb_set_info_standard: file %s\n",
6340 smb_fname_str_dbg(smb_fname)));
6342 return smb_set_file_time(conn,
6343 fsp,
6344 smb_fname,
6345 &ft,
6346 true);
6349 /****************************************************************************
6350 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6351 ****************************************************************************/
6353 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6354 struct smb_request *req,
6355 const char *pdata,
6356 int total_data,
6357 files_struct *fsp,
6358 struct smb_filename *smb_fname)
6360 uint64_t allocation_size = 0;
6361 NTSTATUS status = NT_STATUS_OK;
6362 files_struct *new_fsp = NULL;
6364 if (!VALID_STAT(smb_fname->st)) {
6365 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6368 if (total_data < 8) {
6369 return NT_STATUS_INVALID_PARAMETER;
6372 allocation_size = (uint64_t)IVAL(pdata,0);
6373 #ifdef LARGE_SMB_OFF_T
6374 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6375 #else /* LARGE_SMB_OFF_T */
6376 if (IVAL(pdata,4) != 0) {
6377 /* more than 32 bits? */
6378 return NT_STATUS_INVALID_PARAMETER;
6380 #endif /* LARGE_SMB_OFF_T */
6382 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6383 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6384 (double)allocation_size));
6386 if (allocation_size) {
6387 allocation_size = smb_roundup(conn, allocation_size);
6390 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6391 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6392 (double)allocation_size));
6394 if (fsp && fsp->fh->fd != -1) {
6395 /* Open file handle. */
6396 /* Only change if needed. */
6397 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6398 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6399 return map_nt_error_from_unix(errno);
6402 /* But always update the time. */
6404 * This is equivalent to a write. Ensure it's seen immediately
6405 * if there are no pending writes.
6407 trigger_write_time_update_immediate(fsp);
6408 return NT_STATUS_OK;
6411 /* Pathname or stat or directory file. */
6412 status = SMB_VFS_CREATE_FILE(
6413 conn, /* conn */
6414 req, /* req */
6415 0, /* root_dir_fid */
6416 smb_fname, /* fname */
6417 FILE_WRITE_DATA, /* access_mask */
6418 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6419 FILE_SHARE_DELETE),
6420 FILE_OPEN, /* create_disposition*/
6421 0, /* create_options */
6422 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6423 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6424 0, /* allocation_size */
6425 NULL, /* sd */
6426 NULL, /* ea_list */
6427 &new_fsp, /* result */
6428 NULL); /* pinfo */
6430 if (!NT_STATUS_IS_OK(status)) {
6431 /* NB. We check for open_was_deferred in the caller. */
6432 return status;
6435 /* Only change if needed. */
6436 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6437 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6438 status = map_nt_error_from_unix(errno);
6439 close_file(req, new_fsp, NORMAL_CLOSE);
6440 return status;
6444 /* Changing the allocation size should set the last mod time. */
6446 * This is equivalent to a write. Ensure it's seen immediately
6447 * if there are no pending writes.
6449 trigger_write_time_update_immediate(new_fsp);
6451 close_file(req, new_fsp, NORMAL_CLOSE);
6452 return NT_STATUS_OK;
6455 /****************************************************************************
6456 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6457 ****************************************************************************/
6459 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6460 struct smb_request *req,
6461 const char *pdata,
6462 int total_data,
6463 files_struct *fsp,
6464 const struct smb_filename *smb_fname,
6465 bool fail_after_createfile)
6467 SMB_OFF_T size;
6469 if (total_data < 8) {
6470 return NT_STATUS_INVALID_PARAMETER;
6473 size = IVAL(pdata,0);
6474 #ifdef LARGE_SMB_OFF_T
6475 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6476 #else /* LARGE_SMB_OFF_T */
6477 if (IVAL(pdata,4) != 0) {
6478 /* more than 32 bits? */
6479 return NT_STATUS_INVALID_PARAMETER;
6481 #endif /* LARGE_SMB_OFF_T */
6482 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6483 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6484 (double)size));
6486 return smb_set_file_size(conn, req,
6487 fsp,
6488 smb_fname,
6489 &smb_fname->st,
6490 size,
6491 fail_after_createfile);
6494 /****************************************************************************
6495 Allow a UNIX info mknod.
6496 ****************************************************************************/
6498 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6499 const char *pdata,
6500 int total_data,
6501 const struct smb_filename *smb_fname)
6503 uint32 file_type = IVAL(pdata,56);
6504 #if defined(HAVE_MAKEDEV)
6505 uint32 dev_major = IVAL(pdata,60);
6506 uint32 dev_minor = IVAL(pdata,68);
6507 #endif
6508 SMB_DEV_T dev = (SMB_DEV_T)0;
6509 uint32 raw_unixmode = IVAL(pdata,84);
6510 NTSTATUS status;
6511 mode_t unixmode;
6513 if (total_data < 100) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6518 PERM_NEW_FILE, &unixmode);
6519 if (!NT_STATUS_IS_OK(status)) {
6520 return status;
6523 #if defined(HAVE_MAKEDEV)
6524 dev = makedev(dev_major, dev_minor);
6525 #endif
6527 switch (file_type) {
6528 #if defined(S_IFIFO)
6529 case UNIX_TYPE_FIFO:
6530 unixmode |= S_IFIFO;
6531 break;
6532 #endif
6533 #if defined(S_IFSOCK)
6534 case UNIX_TYPE_SOCKET:
6535 unixmode |= S_IFSOCK;
6536 break;
6537 #endif
6538 #if defined(S_IFCHR)
6539 case UNIX_TYPE_CHARDEV:
6540 unixmode |= S_IFCHR;
6541 break;
6542 #endif
6543 #if defined(S_IFBLK)
6544 case UNIX_TYPE_BLKDEV:
6545 unixmode |= S_IFBLK;
6546 break;
6547 #endif
6548 default:
6549 return NT_STATUS_INVALID_PARAMETER;
6552 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6553 "%.0f mode 0%o for file %s\n", (double)dev,
6554 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6556 /* Ok - do the mknod. */
6557 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6558 return map_nt_error_from_unix(errno);
6561 /* If any of the other "set" calls fail we
6562 * don't want to end up with a half-constructed mknod.
6565 if (lp_inherit_perms(SNUM(conn))) {
6566 char *parent;
6567 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6568 &parent, NULL)) {
6569 return NT_STATUS_NO_MEMORY;
6571 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6572 unixmode);
6573 TALLOC_FREE(parent);
6576 return NT_STATUS_OK;
6579 /****************************************************************************
6580 Deal with SMB_SET_FILE_UNIX_BASIC.
6581 ****************************************************************************/
6583 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6584 struct smb_request *req,
6585 const char *pdata,
6586 int total_data,
6587 files_struct *fsp,
6588 const struct smb_filename *smb_fname)
6590 struct smb_file_time ft;
6591 uint32 raw_unixmode;
6592 mode_t unixmode;
6593 SMB_OFF_T size = 0;
6594 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6595 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6596 NTSTATUS status = NT_STATUS_OK;
6597 bool delete_on_fail = False;
6598 enum perm_type ptype;
6599 files_struct *all_fsps = NULL;
6600 bool modify_mtime = true;
6601 struct file_id id;
6602 struct smb_filename *smb_fname_tmp = NULL;
6603 SMB_STRUCT_STAT sbuf;
6605 ZERO_STRUCT(ft);
6607 if (total_data < 100) {
6608 return NT_STATUS_INVALID_PARAMETER;
6611 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6612 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6613 size=IVAL(pdata,0); /* first 8 Bytes are size */
6614 #ifdef LARGE_SMB_OFF_T
6615 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6616 #else /* LARGE_SMB_OFF_T */
6617 if (IVAL(pdata,4) != 0) {
6618 /* more than 32 bits? */
6619 return NT_STATUS_INVALID_PARAMETER;
6621 #endif /* LARGE_SMB_OFF_T */
6624 ft.atime = interpret_long_date(pdata+24); /* access_time */
6625 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6626 set_owner = (uid_t)IVAL(pdata,40);
6627 set_grp = (gid_t)IVAL(pdata,48);
6628 raw_unixmode = IVAL(pdata,84);
6630 if (VALID_STAT(smb_fname->st)) {
6631 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6632 ptype = PERM_EXISTING_DIR;
6633 } else {
6634 ptype = PERM_EXISTING_FILE;
6636 } else {
6637 ptype = PERM_NEW_FILE;
6640 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6641 ptype, &unixmode);
6642 if (!NT_STATUS_IS_OK(status)) {
6643 return status;
6646 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6647 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6648 smb_fname_str_dbg(smb_fname), (double)size,
6649 (unsigned int)set_owner, (unsigned int)set_grp,
6650 (int)raw_unixmode));
6652 sbuf = smb_fname->st;
6654 if (!VALID_STAT(sbuf)) {
6656 * The only valid use of this is to create character and block
6657 * devices, and named pipes. This is deprecated (IMHO) and
6658 * a new info level should be used for mknod. JRA.
6661 status = smb_unix_mknod(conn,
6662 pdata,
6663 total_data,
6664 smb_fname);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 return status;
6669 status = copy_smb_filename(talloc_tos(), smb_fname,
6670 &smb_fname_tmp);
6671 if (!NT_STATUS_IS_OK(status)) {
6672 return status;
6675 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6676 status = map_nt_error_from_unix(errno);
6677 TALLOC_FREE(smb_fname_tmp);
6678 SMB_VFS_UNLINK(conn, smb_fname);
6679 return status;
6682 sbuf = smb_fname_tmp->st;
6683 smb_fname = smb_fname_tmp;
6685 /* Ensure we don't try and change anything else. */
6686 raw_unixmode = SMB_MODE_NO_CHANGE;
6687 size = get_file_size_stat(&sbuf);
6688 ft.atime = sbuf.st_ex_atime;
6689 ft.mtime = sbuf.st_ex_mtime;
6691 * We continue here as we might want to change the
6692 * owner uid/gid.
6694 delete_on_fail = True;
6697 #if 1
6698 /* Horrible backwards compatibility hack as an old server bug
6699 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6700 * */
6702 if (!size) {
6703 size = get_file_size_stat(&sbuf);
6705 #endif
6708 * Deal with the UNIX specific mode set.
6711 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6712 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6713 "setting mode 0%o for file %s\n",
6714 (unsigned int)unixmode,
6715 smb_fname_str_dbg(smb_fname)));
6716 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6717 return map_nt_error_from_unix(errno);
6722 * Deal with the UNIX specific uid set.
6725 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6726 (sbuf.st_ex_uid != set_owner)) {
6727 int ret;
6729 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6730 "changing owner %u for path %s\n",
6731 (unsigned int)set_owner,
6732 smb_fname_str_dbg(smb_fname)));
6734 if (S_ISLNK(sbuf.st_ex_mode)) {
6735 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6736 set_owner, (gid_t)-1);
6737 } else {
6738 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6739 set_owner, (gid_t)-1);
6742 if (ret != 0) {
6743 status = map_nt_error_from_unix(errno);
6744 if (delete_on_fail) {
6745 SMB_VFS_UNLINK(conn, smb_fname);
6747 return status;
6752 * Deal with the UNIX specific gid set.
6755 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6756 (sbuf.st_ex_gid != set_grp)) {
6757 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6758 "changing group %u for file %s\n",
6759 (unsigned int)set_owner,
6760 smb_fname_str_dbg(smb_fname)));
6761 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6762 set_grp) != 0) {
6763 status = map_nt_error_from_unix(errno);
6764 if (delete_on_fail) {
6765 SMB_VFS_UNLINK(conn, smb_fname);
6767 return status;
6771 /* Deal with any size changes. */
6773 status = smb_set_file_size(conn, req,
6774 fsp,
6775 smb_fname,
6776 &sbuf,
6777 size,
6778 false);
6779 if (!NT_STATUS_IS_OK(status)) {
6780 return status;
6783 /* Deal with any time changes. */
6784 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6785 /* No change, don't cancel anything. */
6786 return status;
6789 id = vfs_file_id_from_sbuf(conn, &sbuf);
6790 for(all_fsps = file_find_di_first(id); all_fsps;
6791 all_fsps = file_find_di_next(all_fsps)) {
6793 * We're setting the time explicitly for UNIX.
6794 * Cancel any pending changes over all handles.
6796 all_fsps->update_write_time_on_close = false;
6797 TALLOC_FREE(all_fsps->update_write_time_event);
6801 * Override the "setting_write_time"
6802 * parameter here as it almost does what
6803 * we need. Just remember if we modified
6804 * mtime and send the notify ourselves.
6806 if (null_timespec(ft.mtime)) {
6807 modify_mtime = false;
6810 status = smb_set_file_time(conn,
6811 fsp,
6812 smb_fname,
6813 &ft,
6814 false);
6815 if (modify_mtime) {
6816 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6817 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6819 return status;
6822 /****************************************************************************
6823 Deal with SMB_SET_FILE_UNIX_INFO2.
6824 ****************************************************************************/
6826 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6827 struct smb_request *req,
6828 const char *pdata,
6829 int total_data,
6830 files_struct *fsp,
6831 const struct smb_filename *smb_fname)
6833 NTSTATUS status;
6834 uint32 smb_fflags;
6835 uint32 smb_fmask;
6837 if (total_data < 116) {
6838 return NT_STATUS_INVALID_PARAMETER;
6841 /* Start by setting all the fields that are common between UNIX_BASIC
6842 * and UNIX_INFO2.
6844 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6845 fsp, smb_fname);
6846 if (!NT_STATUS_IS_OK(status)) {
6847 return status;
6850 smb_fflags = IVAL(pdata, 108);
6851 smb_fmask = IVAL(pdata, 112);
6853 /* NB: We should only attempt to alter the file flags if the client
6854 * sends a non-zero mask.
6856 if (smb_fmask != 0) {
6857 int stat_fflags = 0;
6859 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6860 smb_fmask, &stat_fflags)) {
6861 /* Client asked to alter a flag we don't understand. */
6862 return NT_STATUS_INVALID_PARAMETER;
6865 if (fsp && fsp->fh->fd != -1) {
6866 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6867 return NT_STATUS_NOT_SUPPORTED;
6868 } else {
6869 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6870 stat_fflags) != 0) {
6871 return map_nt_error_from_unix(errno);
6876 /* XXX: need to add support for changing the create_time here. You
6877 * can do this for paths on Darwin with setattrlist(2). The right way
6878 * to hook this up is probably by extending the VFS utimes interface.
6881 return NT_STATUS_OK;
6884 /****************************************************************************
6885 Create a directory with POSIX semantics.
6886 ****************************************************************************/
6888 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6889 struct smb_request *req,
6890 char **ppdata,
6891 int total_data,
6892 struct smb_filename *smb_fname,
6893 int *pdata_return_size)
6895 NTSTATUS status = NT_STATUS_OK;
6896 uint32 raw_unixmode = 0;
6897 uint32 mod_unixmode = 0;
6898 mode_t unixmode = (mode_t)0;
6899 files_struct *fsp = NULL;
6900 uint16 info_level_return = 0;
6901 int info;
6902 char *pdata = *ppdata;
6904 if (total_data < 18) {
6905 return NT_STATUS_INVALID_PARAMETER;
6908 raw_unixmode = IVAL(pdata,8);
6909 /* Next 4 bytes are not yet defined. */
6911 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6912 PERM_NEW_DIR, &unixmode);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 return status;
6917 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6919 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6920 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6922 status = SMB_VFS_CREATE_FILE(
6923 conn, /* conn */
6924 req, /* req */
6925 0, /* root_dir_fid */
6926 smb_fname, /* fname */
6927 FILE_READ_ATTRIBUTES, /* access_mask */
6928 FILE_SHARE_NONE, /* share_access */
6929 FILE_CREATE, /* create_disposition*/
6930 FILE_DIRECTORY_FILE, /* create_options */
6931 mod_unixmode, /* file_attributes */
6932 0, /* oplock_request */
6933 0, /* allocation_size */
6934 NULL, /* sd */
6935 NULL, /* ea_list */
6936 &fsp, /* result */
6937 &info); /* pinfo */
6939 if (NT_STATUS_IS_OK(status)) {
6940 close_file(req, fsp, NORMAL_CLOSE);
6943 info_level_return = SVAL(pdata,16);
6945 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6946 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6947 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6948 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6949 } else {
6950 *pdata_return_size = 12;
6953 /* Realloc the data size */
6954 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6955 if (*ppdata == NULL) {
6956 *pdata_return_size = 0;
6957 return NT_STATUS_NO_MEMORY;
6959 pdata = *ppdata;
6961 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6962 SSVAL(pdata,2,0); /* No fnum. */
6963 SIVAL(pdata,4,info); /* Was directory created. */
6965 switch (info_level_return) {
6966 case SMB_QUERY_FILE_UNIX_BASIC:
6967 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6968 SSVAL(pdata,10,0); /* Padding. */
6969 store_file_unix_basic(conn, pdata + 12, fsp,
6970 &smb_fname->st);
6971 break;
6972 case SMB_QUERY_FILE_UNIX_INFO2:
6973 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6974 SSVAL(pdata,10,0); /* Padding. */
6975 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6976 &smb_fname->st);
6977 break;
6978 default:
6979 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6980 SSVAL(pdata,10,0); /* Padding. */
6981 break;
6984 return status;
6987 /****************************************************************************
6988 Open/Create a file with POSIX semantics.
6989 ****************************************************************************/
6991 static NTSTATUS smb_posix_open(connection_struct *conn,
6992 struct smb_request *req,
6993 char **ppdata,
6994 int total_data,
6995 struct smb_filename *smb_fname,
6996 int *pdata_return_size)
6998 bool extended_oplock_granted = False;
6999 char *pdata = *ppdata;
7000 uint32 flags = 0;
7001 uint32 wire_open_mode = 0;
7002 uint32 raw_unixmode = 0;
7003 uint32 mod_unixmode = 0;
7004 uint32 create_disp = 0;
7005 uint32 access_mask = 0;
7006 uint32 create_options = 0;
7007 NTSTATUS status = NT_STATUS_OK;
7008 mode_t unixmode = (mode_t)0;
7009 files_struct *fsp = NULL;
7010 int oplock_request = 0;
7011 int info = 0;
7012 uint16 info_level_return = 0;
7014 if (total_data < 18) {
7015 return NT_STATUS_INVALID_PARAMETER;
7018 flags = IVAL(pdata,0);
7019 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7020 if (oplock_request) {
7021 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7024 wire_open_mode = IVAL(pdata,4);
7026 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7027 return smb_posix_mkdir(conn, req,
7028 ppdata,
7029 total_data,
7030 smb_fname,
7031 pdata_return_size);
7034 switch (wire_open_mode & SMB_ACCMODE) {
7035 case SMB_O_RDONLY:
7036 access_mask = FILE_READ_DATA;
7037 break;
7038 case SMB_O_WRONLY:
7039 access_mask = FILE_WRITE_DATA;
7040 break;
7041 case SMB_O_RDWR:
7042 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7043 break;
7044 default:
7045 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7046 (unsigned int)wire_open_mode ));
7047 return NT_STATUS_INVALID_PARAMETER;
7050 wire_open_mode &= ~SMB_ACCMODE;
7052 /* First take care of O_CREAT|O_EXCL interactions. */
7053 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7054 case (SMB_O_CREAT | SMB_O_EXCL):
7055 /* File exists fail. File not exist create. */
7056 create_disp = FILE_CREATE;
7057 break;
7058 case SMB_O_CREAT:
7059 /* File exists open. File not exist create. */
7060 create_disp = FILE_OPEN_IF;
7061 break;
7062 case 0:
7063 /* File exists open. File not exist fail. */
7064 create_disp = FILE_OPEN;
7065 break;
7066 case SMB_O_EXCL:
7067 /* O_EXCL on its own without O_CREAT is undefined. */
7068 default:
7069 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7070 (unsigned int)wire_open_mode ));
7071 return NT_STATUS_INVALID_PARAMETER;
7074 /* Next factor in the effects of O_TRUNC. */
7075 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7077 if (wire_open_mode & SMB_O_TRUNC) {
7078 switch (create_disp) {
7079 case FILE_CREATE:
7080 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7081 /* Leave create_disp alone as
7082 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7084 /* File exists fail. File not exist create. */
7085 break;
7086 case FILE_OPEN_IF:
7087 /* SMB_O_CREAT | SMB_O_TRUNC */
7088 /* File exists overwrite. File not exist create. */
7089 create_disp = FILE_OVERWRITE_IF;
7090 break;
7091 case FILE_OPEN:
7092 /* SMB_O_TRUNC */
7093 /* File exists overwrite. File not exist fail. */
7094 create_disp = FILE_OVERWRITE;
7095 break;
7096 default:
7097 /* Cannot get here. */
7098 smb_panic("smb_posix_open: logic error");
7099 return NT_STATUS_INVALID_PARAMETER;
7103 raw_unixmode = IVAL(pdata,8);
7104 /* Next 4 bytes are not yet defined. */
7106 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7107 (VALID_STAT(smb_fname->st) ?
7108 PERM_EXISTING_FILE : PERM_NEW_FILE),
7109 &unixmode);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 return status;
7115 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7117 if (wire_open_mode & SMB_O_SYNC) {
7118 create_options |= FILE_WRITE_THROUGH;
7120 if (wire_open_mode & SMB_O_APPEND) {
7121 access_mask |= FILE_APPEND_DATA;
7123 if (wire_open_mode & SMB_O_DIRECT) {
7124 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7127 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7128 smb_fname_str_dbg(smb_fname),
7129 (unsigned int)wire_open_mode,
7130 (unsigned int)unixmode ));
7132 status = SMB_VFS_CREATE_FILE(
7133 conn, /* conn */
7134 req, /* req */
7135 0, /* root_dir_fid */
7136 smb_fname, /* fname */
7137 access_mask, /* access_mask */
7138 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7139 FILE_SHARE_DELETE),
7140 create_disp, /* create_disposition*/
7141 FILE_NON_DIRECTORY_FILE, /* create_options */
7142 mod_unixmode, /* file_attributes */
7143 oplock_request, /* oplock_request */
7144 0, /* allocation_size */
7145 NULL, /* sd */
7146 NULL, /* ea_list */
7147 &fsp, /* result */
7148 &info); /* pinfo */
7150 if (!NT_STATUS_IS_OK(status)) {
7151 return status;
7154 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7155 extended_oplock_granted = True;
7158 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7159 extended_oplock_granted = True;
7162 info_level_return = SVAL(pdata,16);
7164 /* Allocate the correct return size. */
7166 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7167 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7168 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7169 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7170 } else {
7171 *pdata_return_size = 12;
7174 /* Realloc the data size */
7175 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7176 if (*ppdata == NULL) {
7177 close_file(req, fsp, ERROR_CLOSE);
7178 *pdata_return_size = 0;
7179 return NT_STATUS_NO_MEMORY;
7181 pdata = *ppdata;
7183 if (extended_oplock_granted) {
7184 if (flags & REQUEST_BATCH_OPLOCK) {
7185 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7186 } else {
7187 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7189 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7190 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7191 } else {
7192 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7195 SSVAL(pdata,2,fsp->fnum);
7196 SIVAL(pdata,4,info); /* Was file created etc. */
7198 switch (info_level_return) {
7199 case SMB_QUERY_FILE_UNIX_BASIC:
7200 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7201 SSVAL(pdata,10,0); /* padding. */
7202 store_file_unix_basic(conn, pdata + 12, fsp,
7203 &smb_fname->st);
7204 break;
7205 case SMB_QUERY_FILE_UNIX_INFO2:
7206 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7207 SSVAL(pdata,10,0); /* padding. */
7208 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7209 &smb_fname->st);
7210 break;
7211 default:
7212 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7213 SSVAL(pdata,10,0); /* padding. */
7214 break;
7216 return NT_STATUS_OK;
7219 /****************************************************************************
7220 Delete a file with POSIX semantics.
7221 ****************************************************************************/
7223 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7224 struct smb_request *req,
7225 const char *pdata,
7226 int total_data,
7227 struct smb_filename *smb_fname)
7229 NTSTATUS status = NT_STATUS_OK;
7230 files_struct *fsp = NULL;
7231 uint16 flags = 0;
7232 char del = 1;
7233 int info = 0;
7234 int create_options = 0;
7235 int i;
7236 struct share_mode_lock *lck = NULL;
7238 if (total_data < 2) {
7239 return NT_STATUS_INVALID_PARAMETER;
7242 flags = SVAL(pdata,0);
7244 if (!VALID_STAT(smb_fname->st)) {
7245 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7248 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7249 !VALID_STAT_OF_DIR(smb_fname->st)) {
7250 return NT_STATUS_NOT_A_DIRECTORY;
7253 DEBUG(10,("smb_posix_unlink: %s %s\n",
7254 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7255 smb_fname_str_dbg(smb_fname)));
7257 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7258 create_options |= FILE_DIRECTORY_FILE;
7261 status = SMB_VFS_CREATE_FILE(
7262 conn, /* conn */
7263 req, /* req */
7264 0, /* root_dir_fid */
7265 smb_fname, /* fname */
7266 DELETE_ACCESS, /* access_mask */
7267 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7268 FILE_SHARE_DELETE),
7269 FILE_OPEN, /* create_disposition*/
7270 create_options, /* create_options */
7271 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7272 0, /* oplock_request */
7273 0, /* allocation_size */
7274 NULL, /* sd */
7275 NULL, /* ea_list */
7276 &fsp, /* result */
7277 &info); /* pinfo */
7279 if (!NT_STATUS_IS_OK(status)) {
7280 return status;
7284 * Don't lie to client. If we can't really delete due to
7285 * non-POSIX opens return SHARING_VIOLATION.
7288 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7289 NULL);
7290 if (lck == NULL) {
7291 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7292 "lock for file %s\n", fsp_str_dbg(fsp)));
7293 close_file(req, fsp, NORMAL_CLOSE);
7294 return NT_STATUS_INVALID_PARAMETER;
7298 * See if others still have the file open. If this is the case, then
7299 * don't delete. If all opens are POSIX delete we can set the delete
7300 * on close disposition.
7302 for (i=0; i<lck->num_share_modes; i++) {
7303 struct share_mode_entry *e = &lck->share_modes[i];
7304 if (is_valid_share_mode_entry(e)) {
7305 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7306 continue;
7308 /* Fail with sharing violation. */
7309 close_file(req, fsp, NORMAL_CLOSE);
7310 TALLOC_FREE(lck);
7311 return NT_STATUS_SHARING_VIOLATION;
7316 * Set the delete on close.
7318 status = smb_set_file_disposition_info(conn,
7319 &del,
7321 fsp,
7322 smb_fname);
7324 if (!NT_STATUS_IS_OK(status)) {
7325 close_file(req, fsp, NORMAL_CLOSE);
7326 TALLOC_FREE(lck);
7327 return status;
7329 TALLOC_FREE(lck);
7330 return close_file(req, fsp, NORMAL_CLOSE);
7333 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7334 struct smb_request *req,
7335 TALLOC_CTX *mem_ctx,
7336 uint16_t info_level,
7337 files_struct *fsp,
7338 struct smb_filename *smb_fname,
7339 char **ppdata, int total_data,
7340 int *ret_data_size)
7342 char *pdata = *ppdata;
7343 NTSTATUS status = NT_STATUS_OK;
7344 int data_return_size = 0;
7346 *ret_data_size = 0;
7348 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7349 return NT_STATUS_INVALID_LEVEL;
7352 if (!CAN_WRITE(conn)) {
7353 /* Allow POSIX opens. The open path will deny
7354 * any non-readonly opens. */
7355 if (info_level != SMB_POSIX_PATH_OPEN) {
7356 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7360 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7361 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7362 fsp ? fsp->fnum : -1, info_level, total_data));
7364 switch (info_level) {
7366 case SMB_INFO_STANDARD:
7368 status = smb_set_info_standard(conn,
7369 pdata,
7370 total_data,
7371 fsp,
7372 smb_fname);
7373 break;
7376 case SMB_INFO_SET_EA:
7378 status = smb_info_set_ea(conn,
7379 pdata,
7380 total_data,
7381 fsp,
7382 smb_fname);
7383 break;
7386 case SMB_SET_FILE_BASIC_INFO:
7387 case SMB_FILE_BASIC_INFORMATION:
7389 status = smb_set_file_basic_info(conn,
7390 pdata,
7391 total_data,
7392 fsp,
7393 smb_fname);
7394 break;
7397 case SMB_FILE_ALLOCATION_INFORMATION:
7398 case SMB_SET_FILE_ALLOCATION_INFO:
7400 status = smb_set_file_allocation_info(conn, req,
7401 pdata,
7402 total_data,
7403 fsp,
7404 smb_fname);
7405 break;
7408 case SMB_FILE_END_OF_FILE_INFORMATION:
7409 case SMB_SET_FILE_END_OF_FILE_INFO:
7412 * XP/Win7 both fail after the createfile with
7413 * SMB_SET_FILE_END_OF_FILE_INFO but not
7414 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7415 * The level is known here, so pass it down
7416 * appropriately.
7418 bool should_fail =
7419 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7421 status = smb_set_file_end_of_file_info(conn, req,
7422 pdata,
7423 total_data,
7424 fsp,
7425 smb_fname,
7426 should_fail);
7427 break;
7430 case SMB_FILE_DISPOSITION_INFORMATION:
7431 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7433 #if 0
7434 /* JRA - We used to just ignore this on a path ?
7435 * Shouldn't this be invalid level on a pathname
7436 * based call ?
7438 if (tran_call != TRANSACT2_SETFILEINFO) {
7439 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7441 #endif
7442 status = smb_set_file_disposition_info(conn,
7443 pdata,
7444 total_data,
7445 fsp,
7446 smb_fname);
7447 break;
7450 case SMB_FILE_POSITION_INFORMATION:
7452 status = smb_file_position_information(conn,
7453 pdata,
7454 total_data,
7455 fsp);
7456 break;
7459 case SMB_FILE_FULL_EA_INFORMATION:
7461 status = smb_set_file_full_ea_info(conn,
7462 pdata,
7463 total_data,
7464 fsp);
7465 break;
7468 /* From tridge Samba4 :
7469 * MODE_INFORMATION in setfileinfo (I have no
7470 * idea what "mode information" on a file is - it takes a value of 0,
7471 * 2, 4 or 6. What could it be?).
7474 case SMB_FILE_MODE_INFORMATION:
7476 status = smb_file_mode_information(conn,
7477 pdata,
7478 total_data);
7479 break;
7483 * CIFS UNIX extensions.
7486 case SMB_SET_FILE_UNIX_BASIC:
7488 status = smb_set_file_unix_basic(conn, req,
7489 pdata,
7490 total_data,
7491 fsp,
7492 smb_fname);
7493 break;
7496 case SMB_SET_FILE_UNIX_INFO2:
7498 status = smb_set_file_unix_info2(conn, req,
7499 pdata,
7500 total_data,
7501 fsp,
7502 smb_fname);
7503 break;
7506 case SMB_SET_FILE_UNIX_LINK:
7508 if (fsp) {
7509 /* We must have a pathname for this. */
7510 return NT_STATUS_INVALID_LEVEL;
7512 status = smb_set_file_unix_link(conn, req, pdata,
7513 total_data, smb_fname);
7514 break;
7517 case SMB_SET_FILE_UNIX_HLINK:
7519 if (fsp) {
7520 /* We must have a pathname for this. */
7521 return NT_STATUS_INVALID_LEVEL;
7523 status = smb_set_file_unix_hlink(conn, req,
7524 pdata, total_data,
7525 smb_fname);
7526 break;
7529 case SMB_FILE_RENAME_INFORMATION:
7531 status = smb_file_rename_information(conn, req,
7532 pdata, total_data,
7533 fsp, smb_fname);
7534 break;
7537 #if defined(HAVE_POSIX_ACLS)
7538 case SMB_SET_POSIX_ACL:
7540 status = smb_set_posix_acl(conn,
7541 pdata,
7542 total_data,
7543 fsp,
7544 smb_fname);
7545 break;
7547 #endif
7549 case SMB_SET_POSIX_LOCK:
7551 if (!fsp) {
7552 return NT_STATUS_INVALID_LEVEL;
7554 status = smb_set_posix_lock(conn, req,
7555 pdata, total_data, fsp);
7556 break;
7559 case SMB_POSIX_PATH_OPEN:
7561 if (fsp) {
7562 /* We must have a pathname for this. */
7563 return NT_STATUS_INVALID_LEVEL;
7566 status = smb_posix_open(conn, req,
7567 ppdata,
7568 total_data,
7569 smb_fname,
7570 &data_return_size);
7571 break;
7574 case SMB_POSIX_PATH_UNLINK:
7576 if (fsp) {
7577 /* We must have a pathname for this. */
7578 return NT_STATUS_INVALID_LEVEL;
7581 status = smb_posix_unlink(conn, req,
7582 pdata,
7583 total_data,
7584 smb_fname);
7585 break;
7588 default:
7589 return NT_STATUS_INVALID_LEVEL;
7592 if (!NT_STATUS_IS_OK(status)) {
7593 return status;
7596 *ret_data_size = data_return_size;
7597 return NT_STATUS_OK;
7600 /****************************************************************************
7601 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7602 ****************************************************************************/
7604 static void call_trans2setfilepathinfo(connection_struct *conn,
7605 struct smb_request *req,
7606 unsigned int tran_call,
7607 char **pparams, int total_params,
7608 char **ppdata, int total_data,
7609 unsigned int max_data_bytes)
7611 char *params = *pparams;
7612 char *pdata = *ppdata;
7613 uint16 info_level;
7614 struct smb_filename *smb_fname = NULL;
7615 files_struct *fsp = NULL;
7616 NTSTATUS status = NT_STATUS_OK;
7617 int data_return_size = 0;
7619 if (!params) {
7620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7621 return;
7624 if (tran_call == TRANSACT2_SETFILEINFO) {
7625 if (total_params < 4) {
7626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7627 return;
7630 fsp = file_fsp(req, SVAL(params,0));
7631 /* Basic check for non-null fsp. */
7632 if (!check_fsp_open(conn, req, fsp)) {
7633 return;
7635 info_level = SVAL(params,2);
7637 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7638 &smb_fname);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 reply_nterror(req, status);
7641 return;
7644 if(fsp->is_directory || fsp->fh->fd == -1) {
7646 * This is actually a SETFILEINFO on a directory
7647 * handle (returned from an NT SMB). NT5.0 seems
7648 * to do this call. JRA.
7650 if (INFO_LEVEL_IS_UNIX(info_level)) {
7651 /* Always do lstat for UNIX calls. */
7652 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7653 DEBUG(3,("call_trans2setfilepathinfo: "
7654 "SMB_VFS_LSTAT of %s failed "
7655 "(%s)\n",
7656 smb_fname_str_dbg(smb_fname),
7657 strerror(errno)));
7658 reply_nterror(req, map_nt_error_from_unix(errno));
7659 return;
7661 } else {
7662 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7663 DEBUG(3,("call_trans2setfilepathinfo: "
7664 "fileinfo of %s failed (%s)\n",
7665 smb_fname_str_dbg(smb_fname),
7666 strerror(errno)));
7667 reply_nterror(req, map_nt_error_from_unix(errno));
7668 return;
7671 } else if (fsp->print_file) {
7673 * Doing a DELETE_ON_CLOSE should cancel a print job.
7675 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7676 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7678 DEBUG(3,("call_trans2setfilepathinfo: "
7679 "Cancelling print job (%s)\n",
7680 fsp_str_dbg(fsp)));
7682 SSVAL(params,0,0);
7683 send_trans2_replies(conn, req, params, 2,
7684 *ppdata, 0,
7685 max_data_bytes);
7686 return;
7687 } else {
7688 reply_nterror(req,
7689 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7690 return;
7692 } else {
7694 * Original code - this is an open file.
7696 if (!check_fsp(conn, req, fsp)) {
7697 return;
7700 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7701 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7702 "of fnum %d failed (%s)\n", fsp->fnum,
7703 strerror(errno)));
7704 reply_nterror(req, map_nt_error_from_unix(errno));
7705 return;
7708 } else {
7709 char *fname = NULL;
7710 uint32_t ucf_flags = 0;
7712 /* set path info */
7713 if (total_params < 7) {
7714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7715 return;
7718 info_level = SVAL(params,0);
7719 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7720 total_params - 6, STR_TERMINATE,
7721 &status);
7722 if (!NT_STATUS_IS_OK(status)) {
7723 reply_nterror(req, status);
7724 return;
7727 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
7728 info_level == SMB_SET_FILE_UNIX_INFO2 ||
7729 info_level == SMB_FILE_RENAME_INFORMATION ||
7730 info_level == SMB_POSIX_PATH_UNLINK) {
7731 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
7734 status = filename_convert(req, conn,
7735 req->flags2 & FLAGS2_DFS_PATHNAMES,
7736 fname,
7737 ucf_flags,
7738 NULL,
7739 &smb_fname);
7740 if (!NT_STATUS_IS_OK(status)) {
7741 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7742 reply_botherror(req,
7743 NT_STATUS_PATH_NOT_COVERED,
7744 ERRSRV, ERRbadpath);
7745 return;
7747 reply_nterror(req, status);
7748 return;
7751 if (INFO_LEVEL_IS_UNIX(info_level)) {
7753 * For CIFS UNIX extensions the target name may not exist.
7756 /* Always do lstat for UNIX calls. */
7757 SMB_VFS_LSTAT(conn, smb_fname);
7759 } else if (!VALID_STAT(smb_fname->st) &&
7760 SMB_VFS_STAT(conn, smb_fname)) {
7761 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7762 "%s failed (%s)\n",
7763 smb_fname_str_dbg(smb_fname),
7764 strerror(errno)));
7765 reply_nterror(req, map_nt_error_from_unix(errno));
7766 return;
7770 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7771 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7772 fsp ? fsp->fnum : -1, info_level,total_data));
7774 /* Realloc the parameter size */
7775 *pparams = (char *)SMB_REALLOC(*pparams,2);
7776 if (*pparams == NULL) {
7777 reply_nterror(req, NT_STATUS_NO_MEMORY);
7778 return;
7780 params = *pparams;
7782 SSVAL(params,0,0);
7784 status = smbd_do_setfilepathinfo(conn, req, req,
7785 info_level,
7786 fsp,
7787 smb_fname,
7788 ppdata, total_data,
7789 &data_return_size);
7790 if (!NT_STATUS_IS_OK(status)) {
7791 if (open_was_deferred(req->mid)) {
7792 /* We have re-scheduled this call. */
7793 return;
7795 if (blocking_lock_was_deferred(req->mid)) {
7796 /* We have re-scheduled this call. */
7797 return;
7799 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7800 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7801 ERRSRV, ERRbadpath);
7802 return;
7804 if (info_level == SMB_POSIX_PATH_OPEN) {
7805 reply_openerror(req, status);
7806 return;
7809 reply_nterror(req, status);
7810 return;
7813 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7814 max_data_bytes);
7816 return;
7819 /****************************************************************************
7820 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7821 ****************************************************************************/
7823 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7824 char **pparams, int total_params,
7825 char **ppdata, int total_data,
7826 unsigned int max_data_bytes)
7828 struct smb_filename *smb_dname = NULL;
7829 char *params = *pparams;
7830 char *pdata = *ppdata;
7831 char *directory = NULL;
7832 NTSTATUS status = NT_STATUS_OK;
7833 struct ea_list *ea_list = NULL;
7834 TALLOC_CTX *ctx = talloc_tos();
7836 if (!CAN_WRITE(conn)) {
7837 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7838 return;
7841 if (total_params < 5) {
7842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7843 return;
7846 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7847 total_params - 4, STR_TERMINATE,
7848 &status);
7849 if (!NT_STATUS_IS_OK(status)) {
7850 reply_nterror(req, status);
7851 return;
7854 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7856 status = filename_convert(ctx,
7857 conn,
7858 req->flags2 & FLAGS2_DFS_PATHNAMES,
7859 directory,
7861 NULL,
7862 &smb_dname);
7864 if (!NT_STATUS_IS_OK(status)) {
7865 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7866 reply_botherror(req,
7867 NT_STATUS_PATH_NOT_COVERED,
7868 ERRSRV, ERRbadpath);
7869 return;
7871 reply_nterror(req, status);
7872 return;
7876 * OS/2 workplace shell seems to send SET_EA requests of "null"
7877 * length (4 bytes containing IVAL 4).
7878 * They seem to have no effect. Bug #3212. JRA.
7881 if (total_data && (total_data != 4)) {
7882 /* Any data in this call is an EA list. */
7883 if (total_data < 10) {
7884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7885 goto out;
7888 if (IVAL(pdata,0) > total_data) {
7889 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7890 IVAL(pdata,0), (unsigned int)total_data));
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7892 goto out;
7895 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7896 total_data - 4);
7897 if (!ea_list) {
7898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7899 goto out;
7902 if (!lp_ea_support(SNUM(conn))) {
7903 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7904 goto out;
7907 /* If total_data == 4 Windows doesn't care what values
7908 * are placed in that field, it just ignores them.
7909 * The System i QNTC IBM SMB client puts bad values here,
7910 * so ignore them. */
7912 status = create_directory(conn, req, smb_dname);
7914 if (!NT_STATUS_IS_OK(status)) {
7915 reply_nterror(req, status);
7916 goto out;
7919 /* Try and set any given EA. */
7920 if (ea_list) {
7921 status = set_ea(conn, NULL, smb_dname, ea_list);
7922 if (!NT_STATUS_IS_OK(status)) {
7923 reply_nterror(req, status);
7924 goto out;
7928 /* Realloc the parameter and data sizes */
7929 *pparams = (char *)SMB_REALLOC(*pparams,2);
7930 if(*pparams == NULL) {
7931 reply_nterror(req, NT_STATUS_NO_MEMORY);
7932 goto out;
7934 params = *pparams;
7936 SSVAL(params,0,0);
7938 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7940 out:
7941 TALLOC_FREE(smb_dname);
7942 return;
7945 /****************************************************************************
7946 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7947 We don't actually do this - we just send a null response.
7948 ****************************************************************************/
7950 static void call_trans2findnotifyfirst(connection_struct *conn,
7951 struct smb_request *req,
7952 char **pparams, int total_params,
7953 char **ppdata, int total_data,
7954 unsigned int max_data_bytes)
7956 char *params = *pparams;
7957 uint16 info_level;
7959 if (total_params < 6) {
7960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7961 return;
7964 info_level = SVAL(params,4);
7965 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7967 switch (info_level) {
7968 case 1:
7969 case 2:
7970 break;
7971 default:
7972 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7973 return;
7976 /* Realloc the parameter and data sizes */
7977 *pparams = (char *)SMB_REALLOC(*pparams,6);
7978 if (*pparams == NULL) {
7979 reply_nterror(req, NT_STATUS_NO_MEMORY);
7980 return;
7982 params = *pparams;
7984 SSVAL(params,0,fnf_handle);
7985 SSVAL(params,2,0); /* No changes */
7986 SSVAL(params,4,0); /* No EA errors */
7988 fnf_handle++;
7990 if(fnf_handle == 0)
7991 fnf_handle = 257;
7993 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7995 return;
7998 /****************************************************************************
7999 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8000 changes). Currently this does nothing.
8001 ****************************************************************************/
8003 static void call_trans2findnotifynext(connection_struct *conn,
8004 struct smb_request *req,
8005 char **pparams, int total_params,
8006 char **ppdata, int total_data,
8007 unsigned int max_data_bytes)
8009 char *params = *pparams;
8011 DEBUG(3,("call_trans2findnotifynext\n"));
8013 /* Realloc the parameter and data sizes */
8014 *pparams = (char *)SMB_REALLOC(*pparams,4);
8015 if (*pparams == NULL) {
8016 reply_nterror(req, NT_STATUS_NO_MEMORY);
8017 return;
8019 params = *pparams;
8021 SSVAL(params,0,0); /* No changes */
8022 SSVAL(params,2,0); /* No EA errors */
8024 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8026 return;
8029 /****************************************************************************
8030 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8031 ****************************************************************************/
8033 static void call_trans2getdfsreferral(connection_struct *conn,
8034 struct smb_request *req,
8035 char **pparams, int total_params,
8036 char **ppdata, int total_data,
8037 unsigned int max_data_bytes)
8039 char *params = *pparams;
8040 char *pathname = NULL;
8041 int reply_size = 0;
8042 int max_referral_level;
8043 NTSTATUS status = NT_STATUS_OK;
8044 TALLOC_CTX *ctx = talloc_tos();
8046 DEBUG(10,("call_trans2getdfsreferral\n"));
8048 if (total_params < 3) {
8049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8050 return;
8053 max_referral_level = SVAL(params,0);
8055 if(!lp_host_msdfs()) {
8056 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8057 return;
8060 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8061 total_params - 2, STR_TERMINATE);
8062 if (!pathname) {
8063 reply_nterror(req, NT_STATUS_NOT_FOUND);
8064 return;
8066 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8067 ppdata,&status)) < 0) {
8068 reply_nterror(req, status);
8069 return;
8072 SSVAL(req->inbuf, smb_flg2,
8073 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8074 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8076 return;
8079 #define LMCAT_SPL 0x53
8080 #define LMFUNC_GETJOBID 0x60
8082 /****************************************************************************
8083 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8084 ****************************************************************************/
8086 static void call_trans2ioctl(connection_struct *conn,
8087 struct smb_request *req,
8088 char **pparams, int total_params,
8089 char **ppdata, int total_data,
8090 unsigned int max_data_bytes)
8092 char *pdata = *ppdata;
8093 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8095 /* check for an invalid fid before proceeding */
8097 if (!fsp) {
8098 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8099 return;
8102 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8103 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8104 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8105 if (*ppdata == NULL) {
8106 reply_nterror(req, NT_STATUS_NO_MEMORY);
8107 return;
8109 pdata = *ppdata;
8111 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8112 CAN ACCEPT THIS IN UNICODE. JRA. */
8114 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8115 srvstr_push(pdata, req->flags2, pdata + 2,
8116 global_myname(), 15,
8117 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8118 srvstr_push(pdata, req->flags2, pdata+18,
8119 lp_servicename(SNUM(conn)), 13,
8120 STR_ASCII|STR_TERMINATE); /* Service name */
8121 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8122 max_data_bytes);
8123 return;
8126 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8127 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8130 /****************************************************************************
8131 Reply to a SMBfindclose (stop trans2 directory search).
8132 ****************************************************************************/
8134 void reply_findclose(struct smb_request *req)
8136 int dptr_num;
8137 struct smbd_server_connection *sconn = smbd_server_conn;
8139 START_PROFILE(SMBfindclose);
8141 if (req->wct < 1) {
8142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8143 END_PROFILE(SMBfindclose);
8144 return;
8147 dptr_num = SVALS(req->vwv+0, 0);
8149 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8151 dptr_close(sconn, &dptr_num);
8153 reply_outbuf(req, 0, 0);
8155 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8157 END_PROFILE(SMBfindclose);
8158 return;
8161 /****************************************************************************
8162 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8163 ****************************************************************************/
8165 void reply_findnclose(struct smb_request *req)
8167 int dptr_num;
8169 START_PROFILE(SMBfindnclose);
8171 if (req->wct < 1) {
8172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8173 END_PROFILE(SMBfindnclose);
8174 return;
8177 dptr_num = SVAL(req->vwv+0, 0);
8179 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8181 /* We never give out valid handles for a
8182 findnotifyfirst - so any dptr_num is ok here.
8183 Just ignore it. */
8185 reply_outbuf(req, 0, 0);
8187 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8189 END_PROFILE(SMBfindnclose);
8190 return;
8193 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8194 struct trans_state *state)
8196 if (get_Protocol() >= PROTOCOL_NT1) {
8197 req->flags2 |= 0x40; /* IS_LONG_NAME */
8198 SSVAL(req->inbuf,smb_flg2,req->flags2);
8201 if (conn->encrypt_level == Required && !req->encrypted) {
8202 if (state->call != TRANSACT2_QFSINFO &&
8203 state->call != TRANSACT2_SETFSINFO) {
8204 DEBUG(0,("handle_trans2: encryption required "
8205 "with call 0x%x\n",
8206 (unsigned int)state->call));
8207 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8208 return;
8212 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8214 /* Now we must call the relevant TRANS2 function */
8215 switch(state->call) {
8216 case TRANSACT2_OPEN:
8218 START_PROFILE(Trans2_open);
8219 call_trans2open(conn, req,
8220 &state->param, state->total_param,
8221 &state->data, state->total_data,
8222 state->max_data_return);
8223 END_PROFILE(Trans2_open);
8224 break;
8227 case TRANSACT2_FINDFIRST:
8229 START_PROFILE(Trans2_findfirst);
8230 call_trans2findfirst(conn, req,
8231 &state->param, state->total_param,
8232 &state->data, state->total_data,
8233 state->max_data_return);
8234 END_PROFILE(Trans2_findfirst);
8235 break;
8238 case TRANSACT2_FINDNEXT:
8240 START_PROFILE(Trans2_findnext);
8241 call_trans2findnext(conn, req,
8242 &state->param, state->total_param,
8243 &state->data, state->total_data,
8244 state->max_data_return);
8245 END_PROFILE(Trans2_findnext);
8246 break;
8249 case TRANSACT2_QFSINFO:
8251 START_PROFILE(Trans2_qfsinfo);
8252 call_trans2qfsinfo(conn, req,
8253 &state->param, state->total_param,
8254 &state->data, state->total_data,
8255 state->max_data_return);
8256 END_PROFILE(Trans2_qfsinfo);
8257 break;
8260 case TRANSACT2_SETFSINFO:
8262 START_PROFILE(Trans2_setfsinfo);
8263 call_trans2setfsinfo(conn, req,
8264 &state->param, state->total_param,
8265 &state->data, state->total_data,
8266 state->max_data_return);
8267 END_PROFILE(Trans2_setfsinfo);
8268 break;
8271 case TRANSACT2_QPATHINFO:
8272 case TRANSACT2_QFILEINFO:
8274 START_PROFILE(Trans2_qpathinfo);
8275 call_trans2qfilepathinfo(conn, req, state->call,
8276 &state->param, state->total_param,
8277 &state->data, state->total_data,
8278 state->max_data_return);
8279 END_PROFILE(Trans2_qpathinfo);
8280 break;
8283 case TRANSACT2_SETPATHINFO:
8284 case TRANSACT2_SETFILEINFO:
8286 START_PROFILE(Trans2_setpathinfo);
8287 call_trans2setfilepathinfo(conn, req, state->call,
8288 &state->param, state->total_param,
8289 &state->data, state->total_data,
8290 state->max_data_return);
8291 END_PROFILE(Trans2_setpathinfo);
8292 break;
8295 case TRANSACT2_FINDNOTIFYFIRST:
8297 START_PROFILE(Trans2_findnotifyfirst);
8298 call_trans2findnotifyfirst(conn, req,
8299 &state->param, state->total_param,
8300 &state->data, state->total_data,
8301 state->max_data_return);
8302 END_PROFILE(Trans2_findnotifyfirst);
8303 break;
8306 case TRANSACT2_FINDNOTIFYNEXT:
8308 START_PROFILE(Trans2_findnotifynext);
8309 call_trans2findnotifynext(conn, req,
8310 &state->param, state->total_param,
8311 &state->data, state->total_data,
8312 state->max_data_return);
8313 END_PROFILE(Trans2_findnotifynext);
8314 break;
8317 case TRANSACT2_MKDIR:
8319 START_PROFILE(Trans2_mkdir);
8320 call_trans2mkdir(conn, req,
8321 &state->param, state->total_param,
8322 &state->data, state->total_data,
8323 state->max_data_return);
8324 END_PROFILE(Trans2_mkdir);
8325 break;
8328 case TRANSACT2_GET_DFS_REFERRAL:
8330 START_PROFILE(Trans2_get_dfs_referral);
8331 call_trans2getdfsreferral(conn, req,
8332 &state->param, state->total_param,
8333 &state->data, state->total_data,
8334 state->max_data_return);
8335 END_PROFILE(Trans2_get_dfs_referral);
8336 break;
8339 case TRANSACT2_IOCTL:
8341 START_PROFILE(Trans2_ioctl);
8342 call_trans2ioctl(conn, req,
8343 &state->param, state->total_param,
8344 &state->data, state->total_data,
8345 state->max_data_return);
8346 END_PROFILE(Trans2_ioctl);
8347 break;
8350 default:
8351 /* Error in request */
8352 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8353 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8357 /****************************************************************************
8358 Reply to a SMBtrans2.
8359 ****************************************************************************/
8361 void reply_trans2(struct smb_request *req)
8363 connection_struct *conn = req->conn;
8364 unsigned int dsoff;
8365 unsigned int dscnt;
8366 unsigned int psoff;
8367 unsigned int pscnt;
8368 unsigned int tran_call;
8369 struct trans_state *state;
8370 NTSTATUS result;
8372 START_PROFILE(SMBtrans2);
8374 if (req->wct < 14) {
8375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8376 END_PROFILE(SMBtrans2);
8377 return;
8380 dsoff = SVAL(req->vwv+12, 0);
8381 dscnt = SVAL(req->vwv+11, 0);
8382 psoff = SVAL(req->vwv+10, 0);
8383 pscnt = SVAL(req->vwv+9, 0);
8384 tran_call = SVAL(req->vwv+14, 0);
8386 result = allow_new_trans(conn->pending_trans, req->mid);
8387 if (!NT_STATUS_IS_OK(result)) {
8388 DEBUG(2, ("Got invalid trans2 request: %s\n",
8389 nt_errstr(result)));
8390 reply_nterror(req, result);
8391 END_PROFILE(SMBtrans2);
8392 return;
8395 if (IS_IPC(conn)) {
8396 switch (tran_call) {
8397 /* List the allowed trans2 calls on IPC$ */
8398 case TRANSACT2_OPEN:
8399 case TRANSACT2_GET_DFS_REFERRAL:
8400 case TRANSACT2_QFILEINFO:
8401 case TRANSACT2_QFSINFO:
8402 case TRANSACT2_SETFSINFO:
8403 break;
8404 default:
8405 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8406 END_PROFILE(SMBtrans2);
8407 return;
8411 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8412 DEBUG(0, ("talloc failed\n"));
8413 reply_nterror(req, NT_STATUS_NO_MEMORY);
8414 END_PROFILE(SMBtrans2);
8415 return;
8418 state->cmd = SMBtrans2;
8420 state->mid = req->mid;
8421 state->vuid = req->vuid;
8422 state->setup_count = SVAL(req->vwv+13, 0);
8423 state->setup = NULL;
8424 state->total_param = SVAL(req->vwv+0, 0);
8425 state->param = NULL;
8426 state->total_data = SVAL(req->vwv+1, 0);
8427 state->data = NULL;
8428 state->max_param_return = SVAL(req->vwv+2, 0);
8429 state->max_data_return = SVAL(req->vwv+3, 0);
8430 state->max_setup_return = SVAL(req->vwv+4, 0);
8431 state->close_on_completion = BITSETW(req->vwv+5, 0);
8432 state->one_way = BITSETW(req->vwv+5, 1);
8434 state->call = tran_call;
8436 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8437 is so as a sanity check */
8438 if (state->setup_count != 1) {
8440 * Need to have rc=0 for ioctl to get job id for OS/2.
8441 * Network printing will fail if function is not successful.
8442 * Similar function in reply.c will be used if protocol
8443 * is LANMAN1.0 instead of LM1.2X002.
8444 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8445 * outbuf doesn't have to be set(only job id is used).
8447 if ( (state->setup_count == 4)
8448 && (tran_call == TRANSACT2_IOCTL)
8449 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8450 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8451 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8452 } else {
8453 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8454 DEBUG(2,("Transaction is %d\n",tran_call));
8455 TALLOC_FREE(state);
8456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8457 END_PROFILE(SMBtrans2);
8458 return;
8462 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8463 goto bad_param;
8465 if (state->total_data) {
8467 if (trans_oob(state->total_data, 0, dscnt)
8468 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8469 goto bad_param;
8472 /* Can't use talloc here, the core routines do realloc on the
8473 * params and data. */
8474 state->data = (char *)SMB_MALLOC(state->total_data);
8475 if (state->data == NULL) {
8476 DEBUG(0,("reply_trans2: data malloc fail for %u "
8477 "bytes !\n", (unsigned int)state->total_data));
8478 TALLOC_FREE(state);
8479 reply_nterror(req, NT_STATUS_NO_MEMORY);
8480 END_PROFILE(SMBtrans2);
8481 return;
8484 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8487 if (state->total_param) {
8489 if (trans_oob(state->total_param, 0, pscnt)
8490 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8491 goto bad_param;
8494 /* Can't use talloc here, the core routines do realloc on the
8495 * params and data. */
8496 state->param = (char *)SMB_MALLOC(state->total_param);
8497 if (state->param == NULL) {
8498 DEBUG(0,("reply_trans: param malloc fail for %u "
8499 "bytes !\n", (unsigned int)state->total_param));
8500 SAFE_FREE(state->data);
8501 TALLOC_FREE(state);
8502 reply_nterror(req, NT_STATUS_NO_MEMORY);
8503 END_PROFILE(SMBtrans2);
8504 return;
8507 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8510 state->received_data = dscnt;
8511 state->received_param = pscnt;
8513 if ((state->received_param == state->total_param) &&
8514 (state->received_data == state->total_data)) {
8516 handle_trans2(conn, req, state);
8518 SAFE_FREE(state->data);
8519 SAFE_FREE(state->param);
8520 TALLOC_FREE(state);
8521 END_PROFILE(SMBtrans2);
8522 return;
8525 DLIST_ADD(conn->pending_trans, state);
8527 /* We need to send an interim response then receive the rest
8528 of the parameter/data bytes */
8529 reply_outbuf(req, 0, 0);
8530 show_msg((char *)req->outbuf);
8531 END_PROFILE(SMBtrans2);
8532 return;
8534 bad_param:
8536 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8537 SAFE_FREE(state->data);
8538 SAFE_FREE(state->param);
8539 TALLOC_FREE(state);
8540 END_PROFILE(SMBtrans2);
8541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8545 /****************************************************************************
8546 Reply to a SMBtranss2
8547 ****************************************************************************/
8549 void reply_transs2(struct smb_request *req)
8551 connection_struct *conn = req->conn;
8552 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8553 struct trans_state *state;
8555 START_PROFILE(SMBtranss2);
8557 show_msg((char *)req->inbuf);
8559 /* Windows clients expect all replies to
8560 a transact secondary (SMBtranss2 0x33)
8561 to have a command code of transact
8562 (SMBtrans2 0x32). See bug #8989
8563 and also [MS-CIFS] section 2.2.4.47.2
8564 for details.
8566 req->cmd = SMBtrans2;
8568 if (req->wct < 8) {
8569 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8570 END_PROFILE(SMBtranss2);
8571 return;
8574 for (state = conn->pending_trans; state != NULL;
8575 state = state->next) {
8576 if (state->mid == req->mid) {
8577 break;
8581 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8583 END_PROFILE(SMBtranss2);
8584 return;
8587 /* Revise state->total_param and state->total_data in case they have
8588 changed downwards */
8590 if (SVAL(req->vwv+0, 0) < state->total_param)
8591 state->total_param = SVAL(req->vwv+0, 0);
8592 if (SVAL(req->vwv+1, 0) < state->total_data)
8593 state->total_data = SVAL(req->vwv+1, 0);
8595 pcnt = SVAL(req->vwv+2, 0);
8596 poff = SVAL(req->vwv+3, 0);
8597 pdisp = SVAL(req->vwv+4, 0);
8599 dcnt = SVAL(req->vwv+5, 0);
8600 doff = SVAL(req->vwv+6, 0);
8601 ddisp = SVAL(req->vwv+7, 0);
8603 state->received_param += pcnt;
8604 state->received_data += dcnt;
8606 if ((state->received_data > state->total_data) ||
8607 (state->received_param > state->total_param))
8608 goto bad_param;
8610 if (pcnt) {
8611 if (trans_oob(state->total_param, pdisp, pcnt)
8612 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8613 goto bad_param;
8615 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8618 if (dcnt) {
8619 if (trans_oob(state->total_data, ddisp, dcnt)
8620 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8621 goto bad_param;
8623 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8626 if ((state->received_param < state->total_param) ||
8627 (state->received_data < state->total_data)) {
8628 END_PROFILE(SMBtranss2);
8629 return;
8632 handle_trans2(conn, req, state);
8634 DLIST_REMOVE(conn->pending_trans, state);
8635 SAFE_FREE(state->data);
8636 SAFE_FREE(state->param);
8637 TALLOC_FREE(state);
8639 END_PROFILE(SMBtranss2);
8640 return;
8642 bad_param:
8644 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8645 DLIST_REMOVE(conn->pending_trans, state);
8646 SAFE_FREE(state->data);
8647 SAFE_FREE(state->param);
8648 TALLOC_FREE(state);
8649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8650 END_PROFILE(SMBtranss2);
8651 return;