WHATSNEW: Start release notes for Samba 3.6.11.
[Samba.git] / source3 / smbd / trans2.c
blobbdbdbc0aee72d72f4b60a655b50c86d440e5bfe8
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
39 #include "libsmb/libsmb.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 Roundup a value to the nearest allocation roundup size boundary.
55 Only do this for Windows clients.
56 ********************************************************************/
58 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
60 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
62 /* Only roundup for Windows clients. */
63 enum remote_arch_types ra_type = get_remote_arch();
64 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
65 val = SMB_ROUNDUP(val,rval);
67 return val;
70 /********************************************************************
71 Create a 64 bit FileIndex. If the file is on the same device as
72 the root of the share, just return the 64-bit inode. If it isn't,
73 mangle as we used to do.
74 ********************************************************************/
76 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 uint64_t file_index;
79 if (conn->base_share_dev == psbuf->st_ex_dev) {
80 return (uint64_t)psbuf->st_ex_ino;
82 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
83 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
84 return file_index;
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char * const prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 SAMBA_XATTR_MARKER,
101 XATTR_NTACL_NAME,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return true;
111 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
112 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
113 return true;
115 return false;
118 /****************************************************************************
119 Get one EA value. Fill in a struct ea_struct.
120 ****************************************************************************/
122 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
123 files_struct *fsp, const char *fname,
124 const char *ea_name, struct ea_struct *pea)
126 /* Get the value of this xattr. Max size is 64k. */
127 size_t attr_size = 256;
128 char *val = NULL;
129 ssize_t sizeret;
131 again:
133 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (!val) {
135 return NT_STATUS_NO_MEMORY;
138 if (fsp && fsp->fh->fd != -1) {
139 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 } else {
141 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
144 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
145 attr_size = 65536;
146 goto again;
149 if (sizeret == -1) {
150 return map_nt_error_from_unix(errno);
153 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
154 dump_data(10, (uint8 *)val, sizeret);
156 pea->flags = 0;
157 if (strnequal(ea_name, "user.", 5)) {
158 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 } else {
160 pea->name = talloc_strdup(mem_ctx, ea_name);
162 if (pea->name == NULL) {
163 TALLOC_FREE(val);
164 return NT_STATUS_NO_MEMORY;
166 pea->value.data = (unsigned char *)val;
167 pea->value.length = (size_t)sizeret;
168 return NT_STATUS_OK;
171 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
172 files_struct *fsp, const char *fname,
173 char ***pnames, size_t *pnum_names)
175 /* Get a list of all xattrs. Max namesize is 64k. */
176 size_t ea_namelist_size = 1024;
177 char *ea_namelist = NULL;
179 char *p;
180 char **names, **tmp;
181 size_t num_names;
182 ssize_t sizeret = -1;
184 if (!lp_ea_support(SNUM(conn))) {
185 if (pnames) {
186 *pnames = NULL;
188 *pnum_names = 0;
189 return NT_STATUS_OK;
193 * TALLOC the result early to get the talloc hierarchy right.
196 names = TALLOC_ARRAY(mem_ctx, char *, 1);
197 if (names == NULL) {
198 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY;
202 while (ea_namelist_size <= 65536) {
204 ea_namelist = TALLOC_REALLOC_ARRAY(
205 names, ea_namelist, char, ea_namelist_size);
206 if (ea_namelist == NULL) {
207 DEBUG(0, ("talloc failed\n"));
208 TALLOC_FREE(names);
209 return NT_STATUS_NO_MEMORY;
212 if (fsp && fsp->fh->fd != -1) {
213 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
214 ea_namelist_size);
215 } else {
216 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 ea_namelist_size);
220 if ((sizeret == -1) && (errno == ERANGE)) {
221 ea_namelist_size *= 2;
223 else {
224 break;
228 if (sizeret == -1) {
229 TALLOC_FREE(names);
230 return map_nt_error_from_unix(errno);
233 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
234 (unsigned int)sizeret));
236 if (sizeret == 0) {
237 TALLOC_FREE(names);
238 if (pnames) {
239 *pnames = NULL;
241 *pnum_names = 0;
242 return NT_STATUS_OK;
246 * Ensure the result is 0-terminated
249 if (ea_namelist[sizeret-1] != '\0') {
250 TALLOC_FREE(names);
251 return NT_STATUS_INTERNAL_ERROR;
255 * count the names
257 num_names = 0;
259 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
260 num_names += 1;
263 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
264 if (tmp == NULL) {
265 DEBUG(0, ("talloc failed\n"));
266 TALLOC_FREE(names);
267 return NT_STATUS_NO_MEMORY;
270 names = tmp;
271 num_names = 0;
273 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
274 names[num_names++] = p;
277 if (pnames) {
278 *pnames = names;
279 } else {
280 TALLOC_FREE(names);
282 *pnum_names = num_names;
283 return NT_STATUS_OK;
286 /****************************************************************************
287 Return a linked list of the total EA's. Plus the total size
288 ****************************************************************************/
290 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
291 const char *fname, size_t *pea_total_len)
293 /* Get a list of all xattrs. Max namesize is 64k. */
294 size_t i, num_names;
295 char **names;
296 struct ea_list *ea_list_head = NULL;
297 NTSTATUS status;
299 *pea_total_len = 0;
301 if (!lp_ea_support(SNUM(conn))) {
302 return NULL;
305 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
306 &names, &num_names);
308 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
309 return NULL;
312 for (i=0; i<num_names; i++) {
313 struct ea_list *listp;
314 fstring dos_ea_name;
316 if (strnequal(names[i], "system.", 7)
317 || samba_private_attr_name(names[i]))
318 continue;
320 listp = TALLOC_P(mem_ctx, struct ea_list);
321 if (listp == NULL) {
322 return NULL;
325 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
326 fname, names[i],
327 &listp->ea))) {
328 return NULL;
331 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 *pea_total_len +=
334 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
336 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
337 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
338 (unsigned int)listp->ea.value.length));
340 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
344 /* Add on 4 for total length. */
345 if (*pea_total_len) {
346 *pea_total_len += 4;
349 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
350 (unsigned int)*pea_total_len));
352 return ea_list_head;
355 /****************************************************************************
356 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 that was filled.
358 ****************************************************************************/
360 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
361 connection_struct *conn, struct ea_list *ea_list)
363 unsigned int ret_data_size = 4;
364 char *p = pdata;
366 SMB_ASSERT(total_data_size >= 4);
368 if (!lp_ea_support(SNUM(conn))) {
369 SIVAL(pdata,4,0);
370 return 4;
373 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
374 size_t dos_namelen;
375 fstring dos_ea_name;
376 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
377 dos_namelen = strlen(dos_ea_name);
378 if (dos_namelen > 255 || dos_namelen == 0) {
379 break;
381 if (ea_list->ea.value.length > 65535) {
382 break;
384 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
385 break;
388 /* We know we have room. */
389 SCVAL(p,0,ea_list->ea.flags);
390 SCVAL(p,1,dos_namelen);
391 SSVAL(p,2,ea_list->ea.value.length);
392 fstrcpy(p+4, dos_ea_name);
393 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
395 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
396 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
399 ret_data_size = PTR_DIFF(p, pdata);
400 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
401 SIVAL(pdata,0,ret_data_size);
402 return ret_data_size;
405 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 char *pdata,
407 unsigned int total_data_size,
408 unsigned int *ret_data_size,
409 connection_struct *conn,
410 struct ea_list *ea_list)
412 uint8_t *p = (uint8_t *)pdata;
413 uint8_t *last_start = NULL;
415 *ret_data_size = 0;
417 if (!lp_ea_support(SNUM(conn))) {
418 return NT_STATUS_NO_EAS_ON_FILE;
421 for (; ea_list; ea_list = ea_list->next) {
422 size_t dos_namelen;
423 fstring dos_ea_name;
424 size_t this_size;
426 if (last_start) {
427 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
429 last_start = p;
431 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
432 dos_namelen = strlen(dos_ea_name);
433 if (dos_namelen > 255 || dos_namelen == 0) {
434 return NT_STATUS_INTERNAL_ERROR;
436 if (ea_list->ea.value.length > 65535) {
437 return NT_STATUS_INTERNAL_ERROR;
440 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
442 if (ea_list->next) {
443 size_t pad = 4 - (this_size % 4);
444 this_size += pad;
447 if (this_size > total_data_size) {
448 return NT_STATUS_INFO_LENGTH_MISMATCH;
451 /* We know we have room. */
452 SIVAL(p, 0x00, 0); /* next offset */
453 SCVAL(p, 0x04, ea_list->ea.flags);
454 SCVAL(p, 0x05, dos_namelen);
455 SSVAL(p, 0x06, ea_list->ea.value.length);
456 fstrcpy((char *)(p+0x08), dos_ea_name);
457 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
459 total_data_size -= this_size;
460 p += this_size;
463 *ret_data_size = PTR_DIFF(p, pdata);
464 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
465 return NT_STATUS_OK;
468 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
470 size_t total_ea_len = 0;
471 TALLOC_CTX *mem_ctx = NULL;
473 if (!lp_ea_support(SNUM(conn))) {
474 return 0;
476 mem_ctx = talloc_tos();
477 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
478 return total_ea_len;
481 /****************************************************************************
482 Ensure the EA name is case insensitive by matching any existing EA name.
483 ****************************************************************************/
485 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
487 size_t total_ea_len;
488 TALLOC_CTX *mem_ctx = talloc_tos();
489 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
491 for (; ea_list; ea_list = ea_list->next) {
492 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
493 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
494 &unix_ea_name[5], ea_list->ea.name));
495 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
496 break;
501 /****************************************************************************
502 Set or delete an extended attribute.
503 ****************************************************************************/
505 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
506 const struct smb_filename *smb_fname, struct ea_list *ea_list)
508 char *fname = NULL;
510 if (!lp_ea_support(SNUM(conn))) {
511 return NT_STATUS_EAS_NOT_SUPPORTED;
514 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
515 return NT_STATUS_ACCESS_DENIED;
518 /* For now setting EAs on streams isn't supported. */
519 fname = smb_fname->base_name;
521 for (;ea_list; ea_list = ea_list->next) {
522 int ret;
523 fstring unix_ea_name;
525 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
526 fstrcat(unix_ea_name, ea_list->ea.name);
528 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
530 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
532 if (samba_private_attr_name(unix_ea_name)) {
533 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
534 return NT_STATUS_ACCESS_DENIED;
537 if (ea_list->ea.value.length == 0) {
538 /* Remove the attribute. */
539 if (fsp && (fsp->fh->fd != -1)) {
540 DEBUG(10,("set_ea: deleting ea name %s on "
541 "file %s by file descriptor.\n",
542 unix_ea_name, fsp_str_dbg(fsp)));
543 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
544 } else {
545 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
546 unix_ea_name, fname));
547 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
549 #ifdef ENOATTR
550 /* Removing a non existent attribute always succeeds. */
551 if (ret == -1 && errno == ENOATTR) {
552 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
553 unix_ea_name));
554 ret = 0;
556 #endif
557 } else {
558 if (fsp && (fsp->fh->fd != -1)) {
559 DEBUG(10,("set_ea: setting ea name %s on file "
560 "%s by file descriptor.\n",
561 unix_ea_name, fsp_str_dbg(fsp)));
562 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
563 ea_list->ea.value.data, ea_list->ea.value.length, 0);
564 } else {
565 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
566 unix_ea_name, fname));
567 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
568 ea_list->ea.value.data, ea_list->ea.value.length, 0);
572 if (ret == -1) {
573 #ifdef ENOTSUP
574 if (errno == ENOTSUP) {
575 return NT_STATUS_EAS_NOT_SUPPORTED;
577 #endif
578 return map_nt_error_from_unix(errno);
582 return NT_STATUS_OK;
584 /****************************************************************************
585 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
586 ****************************************************************************/
588 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
590 struct ea_list *ea_list_head = NULL;
591 size_t converted_size, offset = 0;
593 while (offset + 2 < data_size) {
594 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
595 unsigned int namelen = CVAL(pdata,offset);
597 offset++; /* Go past the namelen byte. */
599 /* integer wrap paranioa. */
600 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
601 (offset > data_size) || (namelen > data_size) ||
602 (offset + namelen >= data_size)) {
603 break;
605 /* Ensure the name is null terminated. */
606 if (pdata[offset + namelen] != '\0') {
607 return NULL;
609 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
610 &converted_size)) {
611 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
612 "failed: %s", strerror(errno)));
614 if (!eal->ea.name) {
615 return NULL;
618 offset += (namelen + 1); /* Go past the name + terminating zero. */
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
623 return ea_list_head;
626 /****************************************************************************
627 Read one EA list entry from the buffer.
628 ****************************************************************************/
630 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
632 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
633 uint16 val_len;
634 unsigned int namelen;
635 size_t converted_size;
637 if (!eal) {
638 return NULL;
641 if (data_size < 6) {
642 return NULL;
645 eal->ea.flags = CVAL(pdata,0);
646 namelen = CVAL(pdata,1);
647 val_len = SVAL(pdata,2);
649 if (4 + namelen + 1 + val_len > data_size) {
650 return NULL;
653 /* Ensure the name is null terminated. */
654 if (pdata[namelen + 4] != '\0') {
655 return NULL;
657 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
658 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
659 strerror(errno)));
661 if (!eal->ea.name) {
662 return NULL;
665 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
666 if (!eal->ea.value.data) {
667 return NULL;
670 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
672 /* Ensure we're null terminated just in case we print the value. */
673 eal->ea.value.data[val_len] = '\0';
674 /* But don't count the null. */
675 eal->ea.value.length--;
677 if (pbytes_used) {
678 *pbytes_used = 4 + namelen + 1 + val_len;
681 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
682 dump_data(10, eal->ea.value.data, eal->ea.value.length);
684 return eal;
687 /****************************************************************************
688 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
689 ****************************************************************************/
691 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
693 struct ea_list *ea_list_head = NULL;
694 size_t offset = 0;
695 size_t bytes_used = 0;
697 while (offset < data_size) {
698 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
700 if (!eal) {
701 return NULL;
704 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
705 offset += bytes_used;
708 return ea_list_head;
711 /****************************************************************************
712 Count the total EA size needed.
713 ****************************************************************************/
715 static size_t ea_list_size(struct ea_list *ealist)
717 fstring dos_ea_name;
718 struct ea_list *listp;
719 size_t ret = 0;
721 for (listp = ealist; listp; listp = listp->next) {
722 push_ascii_fstring(dos_ea_name, listp->ea.name);
723 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
725 /* Add on 4 for total length. */
726 if (ret) {
727 ret += 4;
730 return ret;
733 /****************************************************************************
734 Return a union of EA's from a file list and a list of names.
735 The TALLOC context for the two lists *MUST* be identical as we steal
736 memory from one list to add to another. JRA.
737 ****************************************************************************/
739 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
741 struct ea_list *nlistp, *flistp;
743 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
744 for (flistp = file_list; flistp; flistp = flistp->next) {
745 if (strequal(nlistp->ea.name, flistp->ea.name)) {
746 break;
750 if (flistp) {
751 /* Copy the data from this entry. */
752 nlistp->ea.flags = flistp->ea.flags;
753 nlistp->ea.value = flistp->ea.value;
754 } else {
755 /* Null entry. */
756 nlistp->ea.flags = 0;
757 ZERO_STRUCT(nlistp->ea.value);
761 *total_ea_len = ea_list_size(name_list);
762 return name_list;
765 /****************************************************************************
766 Send the required number of replies back.
767 We assume all fields other than the data fields are
768 set correctly for the type of call.
769 HACK ! Always assumes smb_setup field is zero.
770 ****************************************************************************/
772 void send_trans2_replies(connection_struct *conn,
773 struct smb_request *req,
774 const char *params,
775 int paramsize,
776 const char *pdata,
777 int datasize,
778 int max_data_bytes)
780 /* As we are using a protocol > LANMAN1 then the max_send
781 variable must have been set in the sessetupX call.
782 This takes precedence over the max_xmit field in the
783 global struct. These different max_xmit variables should
784 be merged as this is now too confusing */
786 int data_to_send = datasize;
787 int params_to_send = paramsize;
788 int useable_space;
789 const char *pp = params;
790 const char *pd = pdata;
791 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
792 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
793 int data_alignment_offset = 0;
794 bool overflow = False;
795 struct smbd_server_connection *sconn = req->sconn;
796 int max_send = sconn->smb1.sessions.max_send;
798 /* Modify the data_to_send and datasize and set the error if
799 we're trying to send more than max_data_bytes. We still send
800 the part of the packet(s) that fit. Strange, but needed
801 for OS/2. */
803 if (max_data_bytes > 0 && datasize > max_data_bytes) {
804 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
805 max_data_bytes, datasize ));
806 datasize = data_to_send = max_data_bytes;
807 overflow = True;
810 /* If there genuinely are no parameters or data to send just send the empty packet */
812 if(params_to_send == 0 && data_to_send == 0) {
813 reply_outbuf(req, 10, 0);
814 show_msg((char *)req->outbuf);
815 if (!srv_send_smb(sconn,
816 (char *)req->outbuf,
817 true, req->seqnum+1,
818 IS_CONN_ENCRYPTED(conn),
819 &req->pcd)) {
820 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
822 TALLOC_FREE(req->outbuf);
823 return;
826 /* When sending params and data ensure that both are nicely aligned */
827 /* Only do this alignment when there is also data to send - else
828 can cause NT redirector problems. */
830 if (((params_to_send % 4) != 0) && (data_to_send != 0))
831 data_alignment_offset = 4 - (params_to_send % 4);
833 /* Space is bufsize minus Netbios over TCP header minus SMB header */
834 /* The alignment_offset is to align the param bytes on an even byte
835 boundary. NT 4.0 Beta needs this to work correctly. */
837 useable_space = max_send - (smb_size
838 + 2 * 10 /* wct */
839 + alignment_offset
840 + data_alignment_offset);
842 if (useable_space < 0) {
843 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
844 "= %d!!!", useable_space));
845 exit_server_cleanly("send_trans2_replies: Not enough space");
848 while (params_to_send || data_to_send) {
849 /* Calculate whether we will totally or partially fill this packet */
851 total_sent_thistime = params_to_send + data_to_send;
853 /* We can never send more than useable_space */
855 * Note that 'useable_space' does not include the alignment offsets,
856 * but we must include the alignment offsets in the calculation of
857 * the length of the data we send over the wire, as the alignment offsets
858 * are sent here. Fix from Marc_Jacobsen@hp.com.
861 total_sent_thistime = MIN(total_sent_thistime, useable_space);
863 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
864 + data_alignment_offset);
866 /* Set total params and data to be sent */
867 SSVAL(req->outbuf,smb_tprcnt,paramsize);
868 SSVAL(req->outbuf,smb_tdrcnt,datasize);
870 /* Calculate how many parameters and data we can fit into
871 * this packet. Parameters get precedence
874 params_sent_thistime = MIN(params_to_send,useable_space);
875 data_sent_thistime = useable_space - params_sent_thistime;
876 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
878 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
880 /* smb_proff is the offset from the start of the SMB header to the
881 parameter bytes, however the first 4 bytes of outbuf are
882 the Netbios over TCP header. Thus use smb_base() to subtract
883 them from the calculation */
885 SSVAL(req->outbuf,smb_proff,
886 ((smb_buf(req->outbuf)+alignment_offset)
887 - smb_base(req->outbuf)));
889 if(params_sent_thistime == 0)
890 SSVAL(req->outbuf,smb_prdisp,0);
891 else
892 /* Absolute displacement of param bytes sent in this packet */
893 SSVAL(req->outbuf,smb_prdisp,pp - params);
895 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
896 if(data_sent_thistime == 0) {
897 SSVAL(req->outbuf,smb_droff,0);
898 SSVAL(req->outbuf,smb_drdisp, 0);
899 } else {
900 /* The offset of the data bytes is the offset of the
901 parameter bytes plus the number of parameters being sent this time */
902 SSVAL(req->outbuf, smb_droff,
903 ((smb_buf(req->outbuf)+alignment_offset)
904 - smb_base(req->outbuf))
905 + params_sent_thistime + data_alignment_offset);
906 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
909 /* Initialize the padding for alignment */
911 if (alignment_offset != 0) {
912 memset(smb_buf(req->outbuf), 0, alignment_offset);
915 /* Copy the param bytes into the packet */
917 if(params_sent_thistime) {
918 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
919 params_sent_thistime);
922 /* Copy in the data bytes */
923 if(data_sent_thistime) {
924 if (data_alignment_offset != 0) {
925 memset((smb_buf(req->outbuf)+alignment_offset+
926 params_sent_thistime), 0,
927 data_alignment_offset);
929 memcpy(smb_buf(req->outbuf)+alignment_offset
930 +params_sent_thistime+data_alignment_offset,
931 pd,data_sent_thistime);
934 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
935 params_sent_thistime, data_sent_thistime, useable_space));
936 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
937 params_to_send, data_to_send, paramsize, datasize));
939 if (overflow) {
940 error_packet_set((char *)req->outbuf,
941 ERRDOS,ERRbufferoverflow,
942 STATUS_BUFFER_OVERFLOW,
943 __LINE__,__FILE__);
946 /* Send the packet */
947 show_msg((char *)req->outbuf);
948 if (!srv_send_smb(sconn,
949 (char *)req->outbuf,
950 true, req->seqnum+1,
951 IS_CONN_ENCRYPTED(conn),
952 &req->pcd))
953 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
955 TALLOC_FREE(req->outbuf);
957 pp += params_sent_thistime;
958 pd += data_sent_thistime;
960 params_to_send -= params_sent_thistime;
961 data_to_send -= data_sent_thistime;
963 /* Sanity check */
964 if(params_to_send < 0 || data_to_send < 0) {
965 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
966 params_to_send, data_to_send));
967 return;
971 return;
974 /****************************************************************************
975 Reply to a TRANSACT2_OPEN.
976 ****************************************************************************/
978 static void call_trans2open(connection_struct *conn,
979 struct smb_request *req,
980 char **pparams, int total_params,
981 char **ppdata, int total_data,
982 unsigned int max_data_bytes)
984 struct smb_filename *smb_fname = NULL;
985 char *params = *pparams;
986 char *pdata = *ppdata;
987 int deny_mode;
988 int32 open_attr;
989 bool oplock_request;
990 #if 0
991 bool return_additional_info;
992 int16 open_sattr;
993 time_t open_time;
994 #endif
995 int open_ofun;
996 uint32 open_size;
997 char *pname;
998 char *fname = NULL;
999 SMB_OFF_T size=0;
1000 int fattr=0,mtime=0;
1001 SMB_INO_T inode = 0;
1002 int smb_action = 0;
1003 files_struct *fsp;
1004 struct ea_list *ea_list = NULL;
1005 uint16 flags = 0;
1006 NTSTATUS status;
1007 uint32 access_mask;
1008 uint32 share_mode;
1009 uint32 create_disposition;
1010 uint32 create_options = 0;
1011 uint32_t private_flags = 0;
1012 TALLOC_CTX *ctx = talloc_tos();
1015 * Ensure we have enough parameters to perform the operation.
1018 if (total_params < 29) {
1019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1020 goto out;
1023 flags = SVAL(params, 0);
1024 deny_mode = SVAL(params, 2);
1025 open_attr = SVAL(params,6);
1026 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1027 if (oplock_request) {
1028 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1031 #if 0
1032 return_additional_info = BITSETW(params,0);
1033 open_sattr = SVAL(params, 4);
1034 open_time = make_unix_date3(params+8);
1035 #endif
1036 open_ofun = SVAL(params,12);
1037 open_size = IVAL(params,14);
1038 pname = &params[28];
1040 if (IS_IPC(conn)) {
1041 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1042 goto out;
1045 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1046 total_params - 28, STR_TERMINATE,
1047 &status);
1048 if (!NT_STATUS_IS_OK(status)) {
1049 reply_nterror(req, status);
1050 goto out;
1053 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1054 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1055 (unsigned int)open_ofun, open_size));
1057 status = filename_convert(ctx,
1058 conn,
1059 req->flags2 & FLAGS2_DFS_PATHNAMES,
1060 fname,
1062 NULL,
1063 &smb_fname);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1066 reply_botherror(req,
1067 NT_STATUS_PATH_NOT_COVERED,
1068 ERRSRV, ERRbadpath);
1069 goto out;
1071 reply_nterror(req, status);
1072 goto out;
1075 if (open_ofun == 0) {
1076 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1077 goto out;
1080 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1081 open_ofun,
1082 &access_mask, &share_mode,
1083 &create_disposition,
1084 &create_options,
1085 &private_flags)) {
1086 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1087 goto out;
1090 /* Any data in this call is an EA list. */
1091 if (total_data && (total_data != 4)) {
1092 if (total_data < 10) {
1093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 goto out;
1097 if (IVAL(pdata,0) > total_data) {
1098 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1099 IVAL(pdata,0), (unsigned int)total_data));
1100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1101 goto out;
1104 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1105 total_data - 4);
1106 if (!ea_list) {
1107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1108 goto out;
1111 if (!lp_ea_support(SNUM(conn))) {
1112 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1113 goto out;
1117 status = SMB_VFS_CREATE_FILE(
1118 conn, /* conn */
1119 req, /* req */
1120 0, /* root_dir_fid */
1121 smb_fname, /* fname */
1122 access_mask, /* access_mask */
1123 share_mode, /* share_access */
1124 create_disposition, /* create_disposition*/
1125 create_options, /* create_options */
1126 open_attr, /* file_attributes */
1127 oplock_request, /* oplock_request */
1128 open_size, /* allocation_size */
1129 private_flags,
1130 NULL, /* sd */
1131 ea_list, /* ea_list */
1132 &fsp, /* result */
1133 &smb_action); /* psbuf */
1135 if (!NT_STATUS_IS_OK(status)) {
1136 if (open_was_deferred(req->mid)) {
1137 /* We have re-scheduled this call. */
1138 goto out;
1140 reply_openerror(req, status);
1141 goto out;
1144 size = get_file_size_stat(&smb_fname->st);
1145 fattr = dos_mode(conn, smb_fname);
1146 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1147 inode = smb_fname->st.st_ex_ino;
1148 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1149 close_file(req, fsp, ERROR_CLOSE);
1150 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1151 goto out;
1154 /* Realloc the size of parameters and data we will return */
1155 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1156 if(*pparams == NULL ) {
1157 reply_nterror(req, NT_STATUS_NO_MEMORY);
1158 goto out;
1160 params = *pparams;
1162 SSVAL(params,0,fsp->fnum);
1163 SSVAL(params,2,fattr);
1164 srv_put_dos_date2(params,4, mtime);
1165 SIVAL(params,8, (uint32)size);
1166 SSVAL(params,12,deny_mode);
1167 SSVAL(params,14,0); /* open_type - file or directory. */
1168 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1170 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1171 smb_action |= EXTENDED_OPLOCK_GRANTED;
1174 SSVAL(params,18,smb_action);
1177 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1179 SIVAL(params,20,inode);
1180 SSVAL(params,24,0); /* Padding. */
1181 if (flags & 8) {
1182 uint32 ea_size = estimate_ea_size(conn, fsp,
1183 fsp->fsp_name->base_name);
1184 SIVAL(params, 26, ea_size);
1185 } else {
1186 SIVAL(params, 26, 0);
1189 /* Send the required number of replies */
1190 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1191 out:
1192 TALLOC_FREE(smb_fname);
1195 /*********************************************************
1196 Routine to check if a given string matches exactly.
1197 as a special case a mask of "." does NOT match. That
1198 is required for correct wildcard semantics
1199 Case can be significant or not.
1200 **********************************************************/
1202 static bool exact_match(bool has_wild,
1203 bool case_sensitive,
1204 const char *str,
1205 const char *mask)
1207 if (mask[0] == '.' && mask[1] == 0) {
1208 return false;
1211 if (has_wild) {
1212 return false;
1215 if (case_sensitive) {
1216 return strcmp(str,mask)==0;
1217 } else {
1218 return StrCaseCmp(str,mask) == 0;
1222 /****************************************************************************
1223 Return the filetype for UNIX extensions.
1224 ****************************************************************************/
1226 static uint32 unix_filetype(mode_t mode)
1228 if(S_ISREG(mode))
1229 return UNIX_TYPE_FILE;
1230 else if(S_ISDIR(mode))
1231 return UNIX_TYPE_DIR;
1232 #ifdef S_ISLNK
1233 else if(S_ISLNK(mode))
1234 return UNIX_TYPE_SYMLINK;
1235 #endif
1236 #ifdef S_ISCHR
1237 else if(S_ISCHR(mode))
1238 return UNIX_TYPE_CHARDEV;
1239 #endif
1240 #ifdef S_ISBLK
1241 else if(S_ISBLK(mode))
1242 return UNIX_TYPE_BLKDEV;
1243 #endif
1244 #ifdef S_ISFIFO
1245 else if(S_ISFIFO(mode))
1246 return UNIX_TYPE_FIFO;
1247 #endif
1248 #ifdef S_ISSOCK
1249 else if(S_ISSOCK(mode))
1250 return UNIX_TYPE_SOCKET;
1251 #endif
1253 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1254 return UNIX_TYPE_UNKNOWN;
1257 /****************************************************************************
1258 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1259 ****************************************************************************/
1261 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1263 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1264 const SMB_STRUCT_STAT *psbuf,
1265 uint32 perms,
1266 enum perm_type ptype,
1267 mode_t *ret_perms)
1269 mode_t ret = 0;
1271 if (perms == SMB_MODE_NO_CHANGE) {
1272 if (!VALID_STAT(*psbuf)) {
1273 return NT_STATUS_INVALID_PARAMETER;
1274 } else {
1275 *ret_perms = psbuf->st_ex_mode;
1276 return NT_STATUS_OK;
1280 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1281 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1282 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1283 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1284 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1285 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1286 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1287 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1288 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1289 #ifdef S_ISVTX
1290 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1291 #endif
1292 #ifdef S_ISGID
1293 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1294 #endif
1295 #ifdef S_ISUID
1296 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1297 #endif
1299 switch (ptype) {
1300 case PERM_NEW_FILE:
1301 /* Apply mode mask */
1302 ret &= lp_create_mask(SNUM(conn));
1303 /* Add in force bits */
1304 ret |= lp_force_create_mode(SNUM(conn));
1305 break;
1306 case PERM_NEW_DIR:
1307 ret &= lp_dir_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_dir_mode(SNUM(conn));
1310 break;
1311 case PERM_EXISTING_FILE:
1312 /* Apply mode mask */
1313 ret &= lp_security_mask(SNUM(conn));
1314 /* Add in force bits */
1315 ret |= lp_force_security_mode(SNUM(conn));
1316 break;
1317 case PERM_EXISTING_DIR:
1318 /* Apply mode mask */
1319 ret &= lp_dir_security_mask(SNUM(conn));
1320 /* Add in force bits */
1321 ret |= lp_force_dir_security_mode(SNUM(conn));
1322 break;
1325 *ret_perms = ret;
1326 return NT_STATUS_OK;
1329 /****************************************************************************
1330 Needed to show the msdfs symlinks as directories. Modifies psbuf
1331 to be a directory if it's a msdfs link.
1332 ****************************************************************************/
1334 static bool check_msdfs_link(connection_struct *conn,
1335 const char *pathname,
1336 SMB_STRUCT_STAT *psbuf)
1338 int saved_errno = errno;
1339 if(lp_host_msdfs() &&
1340 lp_msdfs_root(SNUM(conn)) &&
1341 is_msdfs_link(conn, pathname, psbuf)) {
1343 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1344 "as a directory\n",
1345 pathname));
1346 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1347 errno = saved_errno;
1348 return true;
1350 errno = saved_errno;
1351 return false;
1355 /****************************************************************************
1356 Get a level dependent lanman2 dir entry.
1357 ****************************************************************************/
1359 struct smbd_dirptr_lanman2_state {
1360 connection_struct *conn;
1361 uint32_t info_level;
1362 bool check_mangled_names;
1363 bool has_wild;
1364 bool got_exact_match;
1367 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1368 void *private_data,
1369 const char *dname,
1370 const char *mask,
1371 char **_fname)
1373 struct smbd_dirptr_lanman2_state *state =
1374 (struct smbd_dirptr_lanman2_state *)private_data;
1375 bool ok;
1376 char mangled_name[13]; /* mangled 8.3 name. */
1377 bool got_match;
1378 const char *fname;
1380 /* Mangle fname if it's an illegal name. */
1381 if (mangle_must_mangle(dname, state->conn->params)) {
1382 ok = name_to_8_3(dname, mangled_name,
1383 true, state->conn->params);
1384 if (!ok) {
1385 return false;
1387 fname = mangled_name;
1388 } else {
1389 fname = dname;
1392 got_match = exact_match(state->has_wild,
1393 state->conn->case_sensitive,
1394 fname, mask);
1395 state->got_exact_match = got_match;
1396 if (!got_match) {
1397 got_match = mask_match(fname, mask,
1398 state->conn->case_sensitive);
1401 if(!got_match && state->check_mangled_names &&
1402 !mangle_is_8_3(fname, false, state->conn->params)) {
1404 * It turns out that NT matches wildcards against
1405 * both long *and* short names. This may explain some
1406 * of the wildcard wierdness from old DOS clients
1407 * that some people have been seeing.... JRA.
1409 /* Force the mangling into 8.3. */
1410 ok = name_to_8_3(fname, mangled_name,
1411 false, state->conn->params);
1412 if (!ok) {
1413 return false;
1416 got_match = exact_match(state->has_wild,
1417 state->conn->case_sensitive,
1418 mangled_name, mask);
1419 state->got_exact_match = got_match;
1420 if (!got_match) {
1421 got_match = mask_match(mangled_name, mask,
1422 state->conn->case_sensitive);
1426 if (!got_match) {
1427 return false;
1430 *_fname = talloc_strdup(ctx, fname);
1431 if (*_fname == NULL) {
1432 return false;
1435 return true;
1438 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1439 void *private_data,
1440 struct smb_filename *smb_fname,
1441 uint32_t *_mode)
1443 struct smbd_dirptr_lanman2_state *state =
1444 (struct smbd_dirptr_lanman2_state *)private_data;
1445 bool ms_dfs_link = false;
1446 uint32_t mode = 0;
1448 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1449 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1450 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1451 "Couldn't lstat [%s] (%s)\n",
1452 smb_fname_str_dbg(smb_fname),
1453 strerror(errno)));
1454 return false;
1456 } else if (!VALID_STAT(smb_fname->st) &&
1457 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1458 /* Needed to show the msdfs symlinks as
1459 * directories */
1461 ms_dfs_link = check_msdfs_link(state->conn,
1462 smb_fname->base_name,
1463 &smb_fname->st);
1464 if (!ms_dfs_link) {
1465 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1466 "Couldn't stat [%s] (%s)\n",
1467 smb_fname_str_dbg(smb_fname),
1468 strerror(errno)));
1469 return false;
1473 if (ms_dfs_link) {
1474 mode = dos_mode_msdfs(state->conn, smb_fname);
1475 } else {
1476 mode = dos_mode(state->conn, smb_fname);
1479 *_mode = mode;
1480 return true;
1483 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1484 connection_struct *conn,
1485 uint16_t flags2,
1486 uint32_t info_level,
1487 struct ea_list *name_list,
1488 bool check_mangled_names,
1489 bool requires_resume_key,
1490 uint32_t mode,
1491 const char *fname,
1492 const struct smb_filename *smb_fname,
1493 int space_remaining,
1494 uint8_t align,
1495 bool do_pad,
1496 char *base_data,
1497 char **ppdata,
1498 char *end_data,
1499 bool *out_of_space,
1500 uint64_t *last_entry_off)
1502 char *p, *q, *pdata = *ppdata;
1503 uint32_t reskey=0;
1504 uint64_t file_size = 0;
1505 uint64_t allocation_size = 0;
1506 uint64_t file_index = 0;
1507 uint32_t len;
1508 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1509 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1510 time_t c_date = (time_t)0;
1511 char *nameptr;
1512 char *last_entry_ptr;
1513 bool was_8_3;
1514 int off;
1515 int pad = 0;
1517 *out_of_space = false;
1519 ZERO_STRUCT(mdate_ts);
1520 ZERO_STRUCT(adate_ts);
1521 ZERO_STRUCT(create_date_ts);
1522 ZERO_STRUCT(cdate_ts);
1524 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1525 file_size = get_file_size_stat(&smb_fname->st);
1527 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1529 file_index = get_FileIndex(conn, &smb_fname->st);
1531 mdate_ts = smb_fname->st.st_ex_mtime;
1532 adate_ts = smb_fname->st.st_ex_atime;
1533 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1534 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1536 if (lp_dos_filetime_resolution(SNUM(conn))) {
1537 dos_filetime_timespec(&create_date_ts);
1538 dos_filetime_timespec(&mdate_ts);
1539 dos_filetime_timespec(&adate_ts);
1540 dos_filetime_timespec(&cdate_ts);
1543 create_date = convert_timespec_to_time_t(create_date_ts);
1544 mdate = convert_timespec_to_time_t(mdate_ts);
1545 adate = convert_timespec_to_time_t(adate_ts);
1546 c_date = convert_timespec_to_time_t(cdate_ts);
1548 /* align the record */
1549 SMB_ASSERT(align >= 1);
1551 off = (int)PTR_DIFF(pdata, base_data);
1552 pad = (off + (align-1)) & ~(align-1);
1553 pad -= off;
1555 if (pad && pad > space_remaining) {
1556 *out_of_space = true;
1557 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1558 "for padding (wanted %u, had %d)\n",
1559 (unsigned int)pad,
1560 space_remaining ));
1561 return false; /* Not finished - just out of space */
1564 off += pad;
1565 /* initialize padding to 0 */
1566 if (pad) {
1567 memset(pdata, 0, pad);
1569 space_remaining -= pad;
1571 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1572 space_remaining ));
1574 pdata += pad;
1575 p = pdata;
1576 last_entry_ptr = p;
1578 pad = 0;
1579 off = 0;
1581 switch (info_level) {
1582 case SMB_FIND_INFO_STANDARD:
1583 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1584 if(requires_resume_key) {
1585 SIVAL(p,0,reskey);
1586 p += 4;
1588 srv_put_dos_date2(p,0,create_date);
1589 srv_put_dos_date2(p,4,adate);
1590 srv_put_dos_date2(p,8,mdate);
1591 SIVAL(p,12,(uint32)file_size);
1592 SIVAL(p,16,(uint32)allocation_size);
1593 SSVAL(p,20,mode);
1594 p += 23;
1595 nameptr = p;
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 p += ucs2_align(base_data, p, 0);
1599 len = srvstr_push(base_data, flags2, p,
1600 fname, PTR_DIFF(end_data, p),
1601 STR_TERMINATE);
1602 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1603 if (len > 2) {
1604 SCVAL(nameptr, -1, len - 2);
1605 } else {
1606 SCVAL(nameptr, -1, 0);
1608 } else {
1609 if (len > 1) {
1610 SCVAL(nameptr, -1, len - 1);
1611 } else {
1612 SCVAL(nameptr, -1, 0);
1615 p += len;
1616 break;
1618 case SMB_FIND_EA_SIZE:
1619 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1620 if (requires_resume_key) {
1621 SIVAL(p,0,reskey);
1622 p += 4;
1624 srv_put_dos_date2(p,0,create_date);
1625 srv_put_dos_date2(p,4,adate);
1626 srv_put_dos_date2(p,8,mdate);
1627 SIVAL(p,12,(uint32)file_size);
1628 SIVAL(p,16,(uint32)allocation_size);
1629 SSVAL(p,20,mode);
1631 unsigned int ea_size = estimate_ea_size(conn, NULL,
1632 smb_fname->base_name);
1633 SIVAL(p,22,ea_size); /* Extended attributes */
1635 p += 27;
1636 nameptr = p - 1;
1637 len = srvstr_push(base_data, flags2,
1638 p, fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE | STR_NOALIGN);
1640 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1641 if (len > 2) {
1642 len -= 2;
1643 } else {
1644 len = 0;
1646 } else {
1647 if (len > 1) {
1648 len -= 1;
1649 } else {
1650 len = 0;
1653 SCVAL(nameptr,0,len);
1654 p += len;
1655 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1656 break;
1658 case SMB_FIND_EA_LIST:
1660 struct ea_list *file_list = NULL;
1661 size_t ea_len = 0;
1663 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1664 if (!name_list) {
1665 return false;
1667 if (requires_resume_key) {
1668 SIVAL(p,0,reskey);
1669 p += 4;
1671 srv_put_dos_date2(p,0,create_date);
1672 srv_put_dos_date2(p,4,adate);
1673 srv_put_dos_date2(p,8,mdate);
1674 SIVAL(p,12,(uint32)file_size);
1675 SIVAL(p,16,(uint32)allocation_size);
1676 SSVAL(p,20,mode);
1677 p += 22; /* p now points to the EA area. */
1679 file_list = get_ea_list_from_file(ctx, conn, NULL,
1680 smb_fname->base_name,
1681 &ea_len);
1682 name_list = ea_list_union(name_list, file_list, &ea_len);
1684 /* We need to determine if this entry will fit in the space available. */
1685 /* Max string size is 255 bytes. */
1686 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1687 *out_of_space = true;
1688 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1689 "(wanted %u, had %d)\n",
1690 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1691 space_remaining ));
1692 return False; /* Not finished - just out of space */
1695 /* Push the ea_data followed by the name. */
1696 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1697 nameptr = p;
1698 len = srvstr_push(base_data, flags2,
1699 p + 1, fname, PTR_DIFF(end_data, p+1),
1700 STR_TERMINATE | STR_NOALIGN);
1701 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1702 if (len > 2) {
1703 len -= 2;
1704 } else {
1705 len = 0;
1707 } else {
1708 if (len > 1) {
1709 len -= 1;
1710 } else {
1711 len = 0;
1714 SCVAL(nameptr,0,len);
1715 p += len + 1;
1716 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1717 break;
1720 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1721 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1722 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1723 p += 4;
1724 SIVAL(p,0,reskey); p += 4;
1725 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1726 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1727 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1728 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1729 SOFF_T(p,0,file_size); p += 8;
1730 SOFF_T(p,0,allocation_size); p += 8;
1731 SIVAL(p,0,mode); p += 4;
1732 q = p; p += 4; /* q is placeholder for name length. */
1734 unsigned int ea_size = estimate_ea_size(conn, NULL,
1735 smb_fname->base_name);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1737 p += 4;
1739 /* Clear the short name buffer. This is
1740 * IMPORTANT as not doing so will trigger
1741 * a Win2k client bug. JRA.
1743 if (!was_8_3 && check_mangled_names) {
1744 char mangled_name[13]; /* mangled 8.3 name. */
1745 if (!name_to_8_3(fname,mangled_name,True,
1746 conn->params)) {
1747 /* Error - mangle failed ! */
1748 memset(mangled_name,'\0',12);
1750 mangled_name[12] = 0;
1751 len = srvstr_push(base_data, flags2,
1752 p+2, mangled_name, 24,
1753 STR_UPPER|STR_UNICODE);
1754 if (len < 24) {
1755 memset(p + 2 + len,'\0',24 - len);
1757 SSVAL(p, 0, len);
1758 } else {
1759 memset(p,'\0',26);
1761 p += 2 + 24;
1762 len = srvstr_push(base_data, flags2, p,
1763 fname, PTR_DIFF(end_data, p),
1764 STR_TERMINATE_ASCII);
1765 SIVAL(q,0,len);
1766 p += len;
1768 len = PTR_DIFF(p, pdata);
1769 pad = (len + (align-1)) & ~(align-1);
1771 * offset to the next entry, the caller
1772 * will overwrite it for the last entry
1773 * that's why we always include the padding
1775 SIVAL(pdata,0,pad);
1777 * set padding to zero
1779 if (do_pad) {
1780 memset(p, 0, pad - len);
1781 p = pdata + pad;
1782 } else {
1783 p = pdata + len;
1785 break;
1787 case SMB_FIND_FILE_DIRECTORY_INFO:
1788 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1789 p += 4;
1790 SIVAL(p,0,reskey); p += 4;
1791 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1792 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1793 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1794 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1795 SOFF_T(p,0,file_size); p += 8;
1796 SOFF_T(p,0,allocation_size); p += 8;
1797 SIVAL(p,0,mode); p += 4;
1798 len = srvstr_push(base_data, flags2,
1799 p + 4, fname, PTR_DIFF(end_data, p+4),
1800 STR_TERMINATE_ASCII);
1801 SIVAL(p,0,len);
1802 p += 4 + len;
1804 len = PTR_DIFF(p, pdata);
1805 pad = (len + (align-1)) & ~(align-1);
1807 * offset to the next entry, the caller
1808 * will overwrite it for the last entry
1809 * that's why we always include the padding
1811 SIVAL(pdata,0,pad);
1813 * set padding to zero
1815 if (do_pad) {
1816 memset(p, 0, pad - len);
1817 p = pdata + pad;
1818 } else {
1819 p = pdata + len;
1821 break;
1823 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1824 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1825 p += 4;
1826 SIVAL(p,0,reskey); p += 4;
1827 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1828 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1829 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1830 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1831 SOFF_T(p,0,file_size); p += 8;
1832 SOFF_T(p,0,allocation_size); p += 8;
1833 SIVAL(p,0,mode); p += 4;
1834 q = p; p += 4; /* q is placeholder for name length. */
1836 unsigned int ea_size = estimate_ea_size(conn, NULL,
1837 smb_fname->base_name);
1838 SIVAL(p,0,ea_size); /* Extended attributes */
1839 p +=4;
1841 len = srvstr_push(base_data, flags2, p,
1842 fname, PTR_DIFF(end_data, p),
1843 STR_TERMINATE_ASCII);
1844 SIVAL(q, 0, len);
1845 p += len;
1847 len = PTR_DIFF(p, pdata);
1848 pad = (len + (align-1)) & ~(align-1);
1850 * offset to the next entry, the caller
1851 * will overwrite it for the last entry
1852 * that's why we always include the padding
1854 SIVAL(pdata,0,pad);
1856 * set padding to zero
1858 if (do_pad) {
1859 memset(p, 0, pad - len);
1860 p = pdata + pad;
1861 } else {
1862 p = pdata + len;
1864 break;
1866 case SMB_FIND_FILE_NAMES_INFO:
1867 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1868 p += 4;
1869 SIVAL(p,0,reskey); p += 4;
1870 p += 4;
1871 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1872 acl on a dir (tridge) */
1873 len = srvstr_push(base_data, flags2, p,
1874 fname, PTR_DIFF(end_data, p),
1875 STR_TERMINATE_ASCII);
1876 SIVAL(p, -4, len);
1877 p += len;
1879 len = PTR_DIFF(p, pdata);
1880 pad = (len + (align-1)) & ~(align-1);
1882 * offset to the next entry, the caller
1883 * will overwrite it for the last entry
1884 * that's why we always include the padding
1886 SIVAL(pdata,0,pad);
1888 * set padding to zero
1890 if (do_pad) {
1891 memset(p, 0, pad - len);
1892 p = pdata + pad;
1893 } else {
1894 p = pdata + len;
1896 break;
1898 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1899 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1900 p += 4;
1901 SIVAL(p,0,reskey); p += 4;
1902 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1906 SOFF_T(p,0,file_size); p += 8;
1907 SOFF_T(p,0,allocation_size); p += 8;
1908 SIVAL(p,0,mode); p += 4;
1909 q = p; p += 4; /* q is placeholder for name length. */
1911 unsigned int ea_size = estimate_ea_size(conn, NULL,
1912 smb_fname->base_name);
1913 SIVAL(p,0,ea_size); /* Extended attributes */
1914 p +=4;
1916 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1917 SBVAL(p,0,file_index); p += 8;
1918 len = srvstr_push(base_data, flags2, p,
1919 fname, PTR_DIFF(end_data, p),
1920 STR_TERMINATE_ASCII);
1921 SIVAL(q, 0, len);
1922 p += len;
1924 len = PTR_DIFF(p, pdata);
1925 pad = (len + (align-1)) & ~(align-1);
1927 * offset to the next entry, the caller
1928 * will overwrite it for the last entry
1929 * that's why we always include the padding
1931 SIVAL(pdata,0,pad);
1933 * set padding to zero
1935 if (do_pad) {
1936 memset(p, 0, pad - len);
1937 p = pdata + pad;
1938 } else {
1939 p = pdata + len;
1941 break;
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1944 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1945 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1946 p += 4;
1947 SIVAL(p,0,reskey); p += 4;
1948 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1949 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1950 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1951 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1952 SOFF_T(p,0,file_size); p += 8;
1953 SOFF_T(p,0,allocation_size); p += 8;
1954 SIVAL(p,0,mode); p += 4;
1955 q = p; p += 4; /* q is placeholder for name length */
1957 unsigned int ea_size = estimate_ea_size(conn, NULL,
1958 smb_fname->base_name);
1959 SIVAL(p,0,ea_size); /* Extended attributes */
1960 p +=4;
1962 /* Clear the short name buffer. This is
1963 * IMPORTANT as not doing so will trigger
1964 * a Win2k client bug. JRA.
1966 if (!was_8_3 && check_mangled_names) {
1967 char mangled_name[13]; /* mangled 8.3 name. */
1968 if (!name_to_8_3(fname,mangled_name,True,
1969 conn->params)) {
1970 /* Error - mangle failed ! */
1971 memset(mangled_name,'\0',12);
1973 mangled_name[12] = 0;
1974 len = srvstr_push(base_data, flags2,
1975 p+2, mangled_name, 24,
1976 STR_UPPER|STR_UNICODE);
1977 SSVAL(p, 0, len);
1978 if (len < 24) {
1979 memset(p + 2 + len,'\0',24 - len);
1981 SSVAL(p, 0, len);
1982 } else {
1983 memset(p,'\0',26);
1985 p += 26;
1986 SSVAL(p,0,0); p += 2; /* Reserved ? */
1987 SBVAL(p,0,file_index); p += 8;
1988 len = srvstr_push(base_data, flags2, p,
1989 fname, PTR_DIFF(end_data, p),
1990 STR_TERMINATE_ASCII);
1991 SIVAL(q,0,len);
1992 p += len;
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2001 SIVAL(pdata,0,pad);
2003 * set padding to zero
2005 if (do_pad) {
2006 memset(p, 0, pad - len);
2007 p = pdata + pad;
2008 } else {
2009 p = pdata + len;
2011 break;
2013 /* CIFS UNIX Extension. */
2015 case SMB_FIND_FILE_UNIX:
2016 case SMB_FIND_FILE_UNIX_INFO2:
2017 p+= 4;
2018 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2020 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2022 if (info_level == SMB_FIND_FILE_UNIX) {
2023 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2024 p = store_file_unix_basic(conn, p,
2025 NULL, &smb_fname->st);
2026 len = srvstr_push(base_data, flags2, p,
2027 fname, PTR_DIFF(end_data, p),
2028 STR_TERMINATE);
2029 } else {
2030 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2031 p = store_file_unix_basic_info2(conn, p,
2032 NULL, &smb_fname->st);
2033 nameptr = p;
2034 p += 4;
2035 len = srvstr_push(base_data, flags2, p, fname,
2036 PTR_DIFF(end_data, p), 0);
2037 SIVAL(nameptr, 0, len);
2040 p += len;
2042 len = PTR_DIFF(p, pdata);
2043 pad = (len + (align-1)) & ~(align-1);
2045 * offset to the next entry, the caller
2046 * will overwrite it for the last entry
2047 * that's why we always include the padding
2049 SIVAL(pdata,0,pad);
2051 * set padding to zero
2053 if (do_pad) {
2054 memset(p, 0, pad - len);
2055 p = pdata + pad;
2056 } else {
2057 p = pdata + len;
2059 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2061 break;
2063 default:
2064 return false;
2067 if (PTR_DIFF(p,pdata) > space_remaining) {
2068 *out_of_space = true;
2069 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2070 "(wanted %u, had %d)\n",
2071 (unsigned int)PTR_DIFF(p,pdata),
2072 space_remaining ));
2073 return false; /* Not finished - just out of space */
2076 /* Setup the last entry pointer, as an offset from base_data */
2077 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2078 /* Advance the data pointer to the next slot */
2079 *ppdata = p;
2081 return true;
2084 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2085 connection_struct *conn,
2086 struct dptr_struct *dirptr,
2087 uint16 flags2,
2088 const char *path_mask,
2089 uint32 dirtype,
2090 int info_level,
2091 int requires_resume_key,
2092 bool dont_descend,
2093 bool ask_sharemode,
2094 uint8_t align,
2095 bool do_pad,
2096 char **ppdata,
2097 char *base_data,
2098 char *end_data,
2099 int space_remaining,
2100 bool *out_of_space,
2101 bool *got_exact_match,
2102 int *_last_entry_off,
2103 struct ea_list *name_list)
2105 const char *p;
2106 const char *mask = NULL;
2107 long prev_dirpos = 0;
2108 uint32_t mode = 0;
2109 char *fname = NULL;
2110 struct smb_filename *smb_fname = NULL;
2111 struct smbd_dirptr_lanman2_state state;
2112 bool ok;
2113 uint64_t last_entry_off = 0;
2115 ZERO_STRUCT(state);
2116 state.conn = conn;
2117 state.info_level = info_level;
2118 state.check_mangled_names = lp_manglednames(conn->params);
2119 state.has_wild = dptr_has_wild(dirptr);
2120 state.got_exact_match = false;
2122 *out_of_space = false;
2123 *got_exact_match = false;
2125 p = strrchr_m(path_mask,'/');
2126 if(p != NULL) {
2127 if(p[1] == '\0') {
2128 mask = "*.*";
2129 } else {
2130 mask = p+1;
2132 } else {
2133 mask = path_mask;
2136 ok = smbd_dirptr_get_entry(ctx,
2137 dirptr,
2138 mask,
2139 dirtype,
2140 dont_descend,
2141 ask_sharemode,
2142 smbd_dirptr_lanman2_match_fn,
2143 smbd_dirptr_lanman2_mode_fn,
2144 &state,
2145 &fname,
2146 &smb_fname,
2147 &mode,
2148 &prev_dirpos);
2149 if (!ok) {
2150 return false;
2153 *got_exact_match = state.got_exact_match;
2155 ok = smbd_marshall_dir_entry(ctx,
2156 conn,
2157 flags2,
2158 info_level,
2159 name_list,
2160 state.check_mangled_names,
2161 requires_resume_key,
2162 mode,
2163 fname,
2164 smb_fname,
2165 space_remaining,
2166 align,
2167 do_pad,
2168 base_data,
2169 ppdata,
2170 end_data,
2171 out_of_space,
2172 &last_entry_off);
2173 TALLOC_FREE(fname);
2174 TALLOC_FREE(smb_fname);
2175 if (*out_of_space) {
2176 dptr_SeekDir(dirptr, prev_dirpos);
2177 return false;
2179 if (!ok) {
2180 return false;
2183 *_last_entry_off = last_entry_off;
2184 return true;
2187 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2188 connection_struct *conn,
2189 struct dptr_struct *dirptr,
2190 uint16 flags2,
2191 const char *path_mask,
2192 uint32 dirtype,
2193 int info_level,
2194 bool requires_resume_key,
2195 bool dont_descend,
2196 bool ask_sharemode,
2197 char **ppdata,
2198 char *base_data,
2199 char *end_data,
2200 int space_remaining,
2201 bool *out_of_space,
2202 bool *got_exact_match,
2203 int *last_entry_off,
2204 struct ea_list *name_list)
2206 uint8_t align = 4;
2207 const bool do_pad = true;
2209 if (info_level >= 1 && info_level <= 3) {
2210 /* No alignment on earlier info levels. */
2211 align = 1;
2214 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2215 path_mask, dirtype, info_level,
2216 requires_resume_key, dont_descend, ask_sharemode,
2217 align, do_pad,
2218 ppdata, base_data, end_data,
2219 space_remaining,
2220 out_of_space, got_exact_match,
2221 last_entry_off, name_list);
2224 /****************************************************************************
2225 Reply to a TRANS2_FINDFIRST.
2226 ****************************************************************************/
2228 static void call_trans2findfirst(connection_struct *conn,
2229 struct smb_request *req,
2230 char **pparams, int total_params,
2231 char **ppdata, int total_data,
2232 unsigned int max_data_bytes)
2234 /* We must be careful here that we don't return more than the
2235 allowed number of data bytes. If this means returning fewer than
2236 maxentries then so be it. We assume that the redirector has
2237 enough room for the fixed number of parameter bytes it has
2238 requested. */
2239 struct smb_filename *smb_dname = NULL;
2240 char *params = *pparams;
2241 char *pdata = *ppdata;
2242 char *data_end;
2243 uint32 dirtype;
2244 int maxentries;
2245 uint16 findfirst_flags;
2246 bool close_after_first;
2247 bool close_if_end;
2248 bool requires_resume_key;
2249 int info_level;
2250 char *directory = NULL;
2251 char *mask = NULL;
2252 char *p;
2253 int last_entry_off=0;
2254 int dptr_num = -1;
2255 int numentries = 0;
2256 int i;
2257 bool finished = False;
2258 bool dont_descend = False;
2259 bool out_of_space = False;
2260 int space_remaining;
2261 bool mask_contains_wcard = False;
2262 struct ea_list *ea_list = NULL;
2263 NTSTATUS ntstatus = NT_STATUS_OK;
2264 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2265 TALLOC_CTX *ctx = talloc_tos();
2266 struct dptr_struct *dirptr = NULL;
2267 struct smbd_server_connection *sconn = req->sconn;
2268 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2270 if (total_params < 13) {
2271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2272 goto out;
2275 dirtype = SVAL(params,0);
2276 maxentries = SVAL(params,2);
2277 findfirst_flags = SVAL(params,4);
2278 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2279 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2280 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2281 info_level = SVAL(params,6);
2283 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2284 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2285 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2286 info_level, max_data_bytes));
2288 if (!maxentries) {
2289 /* W2K3 seems to treat zero as 1. */
2290 maxentries = 1;
2293 switch (info_level) {
2294 case SMB_FIND_INFO_STANDARD:
2295 case SMB_FIND_EA_SIZE:
2296 case SMB_FIND_EA_LIST:
2297 case SMB_FIND_FILE_DIRECTORY_INFO:
2298 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_NAMES_INFO:
2300 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2301 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2302 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2303 break;
2304 case SMB_FIND_FILE_UNIX:
2305 case SMB_FIND_FILE_UNIX_INFO2:
2306 /* Always use filesystem for UNIX mtime query. */
2307 ask_sharemode = false;
2308 if (!lp_unix_extensions()) {
2309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2310 goto out;
2312 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2313 break;
2314 default:
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2316 goto out;
2319 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2320 params+12, total_params - 12,
2321 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2322 if (!NT_STATUS_IS_OK(ntstatus)) {
2323 reply_nterror(req, ntstatus);
2324 goto out;
2327 ntstatus = filename_convert(ctx, conn,
2328 req->flags2 & FLAGS2_DFS_PATHNAMES,
2329 directory,
2330 ucf_flags,
2331 &mask_contains_wcard,
2332 &smb_dname);
2333 if (!NT_STATUS_IS_OK(ntstatus)) {
2334 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2335 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2336 ERRSRV, ERRbadpath);
2337 goto out;
2339 reply_nterror(req, ntstatus);
2340 goto out;
2343 mask = smb_dname->original_lcomp;
2345 directory = smb_dname->base_name;
2347 p = strrchr_m(directory,'/');
2348 if(p == NULL) {
2349 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2350 if((directory[0] == '.') && (directory[1] == '\0')) {
2351 mask = talloc_strdup(ctx,"*");
2352 if (!mask) {
2353 reply_nterror(req, NT_STATUS_NO_MEMORY);
2354 goto out;
2356 mask_contains_wcard = True;
2358 } else {
2359 *p = 0;
2362 if (p == NULL || p == directory) {
2363 /* Ensure we don't have a directory name of "". */
2364 directory = talloc_strdup(talloc_tos(), ".");
2365 if (!directory) {
2366 reply_nterror(req, NT_STATUS_NO_MEMORY);
2367 goto out;
2371 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2373 if (info_level == SMB_FIND_EA_LIST) {
2374 uint32 ea_size;
2376 if (total_data < 4) {
2377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2378 goto out;
2381 ea_size = IVAL(pdata,0);
2382 if (ea_size != total_data) {
2383 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2384 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2386 goto out;
2389 if (!lp_ea_support(SNUM(conn))) {
2390 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2391 goto out;
2394 /* Pull out the list of names. */
2395 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2396 if (!ea_list) {
2397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2398 goto out;
2402 *ppdata = (char *)SMB_REALLOC(
2403 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2404 if(*ppdata == NULL ) {
2405 reply_nterror(req, NT_STATUS_NO_MEMORY);
2406 goto out;
2408 pdata = *ppdata;
2409 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2411 /* Realloc the params space */
2412 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2413 if (*pparams == NULL) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 goto out;
2417 params = *pparams;
2419 /* Save the wildcard match and attribs we are using on this directory -
2420 needed as lanman2 assumes these are being saved between calls */
2422 ntstatus = dptr_create(conn,
2423 NULL, /* fsp */
2424 directory,
2425 False,
2426 True,
2427 req->smbpid,
2428 mask,
2429 mask_contains_wcard,
2430 dirtype,
2431 &dirptr);
2433 if (!NT_STATUS_IS_OK(ntstatus)) {
2434 reply_nterror(req, ntstatus);
2435 goto out;
2438 dptr_num = dptr_dnum(dirptr);
2439 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2441 /* Initialize per TRANS2_FIND_FIRST operation data */
2442 dptr_init_search_op(dirptr);
2444 /* We don't need to check for VOL here as this is returned by
2445 a different TRANS2 call. */
2447 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2448 directory,lp_dontdescend(SNUM(conn))));
2449 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2450 dont_descend = True;
2452 p = pdata;
2453 space_remaining = max_data_bytes;
2454 out_of_space = False;
2456 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2457 bool got_exact_match = False;
2459 /* this is a heuristic to avoid seeking the dirptr except when
2460 absolutely necessary. It allows for a filename of about 40 chars */
2461 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2462 out_of_space = True;
2463 finished = False;
2464 } else {
2465 finished = !get_lanman2_dir_entry(ctx,
2466 conn,
2467 dirptr,
2468 req->flags2,
2469 mask,dirtype,info_level,
2470 requires_resume_key,dont_descend,
2471 ask_sharemode,
2472 &p,pdata,data_end,
2473 space_remaining, &out_of_space,
2474 &got_exact_match,
2475 &last_entry_off, ea_list);
2478 if (finished && out_of_space)
2479 finished = False;
2481 if (!finished && !out_of_space)
2482 numentries++;
2485 * As an optimisation if we know we aren't looking
2486 * for a wildcard name (ie. the name matches the wildcard exactly)
2487 * then we can finish on any (first) match.
2488 * This speeds up large directory searches. JRA.
2491 if(got_exact_match)
2492 finished = True;
2494 /* Ensure space_remaining never goes -ve. */
2495 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2496 space_remaining = 0;
2497 out_of_space = true;
2498 } else {
2499 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2503 /* Check if we can close the dirptr */
2504 if(close_after_first || (finished && close_if_end)) {
2505 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2506 dptr_close(sconn, &dptr_num);
2510 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2511 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2512 * the protocol level is less than NT1. Tested with smbclient. JRA.
2513 * This should fix the OS/2 client bug #2335.
2516 if(numentries == 0) {
2517 dptr_close(sconn, &dptr_num);
2518 if (get_Protocol() < PROTOCOL_NT1) {
2519 reply_force_doserror(req, ERRDOS, ERRnofiles);
2520 goto out;
2521 } else {
2522 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2523 ERRDOS, ERRbadfile);
2524 goto out;
2528 /* At this point pdata points to numentries directory entries. */
2530 /* Set up the return parameter block */
2531 SSVAL(params,0,dptr_num);
2532 SSVAL(params,2,numentries);
2533 SSVAL(params,4,finished);
2534 SSVAL(params,6,0); /* Never an EA error */
2535 SSVAL(params,8,last_entry_off);
2537 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2538 max_data_bytes);
2540 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2541 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2542 if (!directory) {
2543 reply_nterror(req, NT_STATUS_NO_MEMORY);
2547 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2548 smb_fn_name(req->cmd),
2549 mask, directory, dirtype, numentries ) );
2552 * Force a name mangle here to ensure that the
2553 * mask as an 8.3 name is top of the mangled cache.
2554 * The reasons for this are subtle. Don't remove
2555 * this code unless you know what you are doing
2556 * (see PR#13758). JRA.
2559 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2560 char mangled_name[13];
2561 name_to_8_3(mask, mangled_name, True, conn->params);
2563 out:
2564 TALLOC_FREE(smb_dname);
2565 return;
2568 /****************************************************************************
2569 Reply to a TRANS2_FINDNEXT.
2570 ****************************************************************************/
2572 static void call_trans2findnext(connection_struct *conn,
2573 struct smb_request *req,
2574 char **pparams, int total_params,
2575 char **ppdata, int total_data,
2576 unsigned int max_data_bytes)
2578 /* We must be careful here that we don't return more than the
2579 allowed number of data bytes. If this means returning fewer than
2580 maxentries then so be it. We assume that the redirector has
2581 enough room for the fixed number of parameter bytes it has
2582 requested. */
2583 char *params = *pparams;
2584 char *pdata = *ppdata;
2585 char *data_end;
2586 int dptr_num;
2587 int maxentries;
2588 uint16 info_level;
2589 uint32 resume_key;
2590 uint16 findnext_flags;
2591 bool close_after_request;
2592 bool close_if_end;
2593 bool requires_resume_key;
2594 bool continue_bit;
2595 bool mask_contains_wcard = False;
2596 char *resume_name = NULL;
2597 const char *mask = NULL;
2598 const char *directory = NULL;
2599 char *p = NULL;
2600 uint16 dirtype;
2601 int numentries = 0;
2602 int i, last_entry_off=0;
2603 bool finished = False;
2604 bool dont_descend = False;
2605 bool out_of_space = False;
2606 int space_remaining;
2607 struct ea_list *ea_list = NULL;
2608 NTSTATUS ntstatus = NT_STATUS_OK;
2609 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2610 TALLOC_CTX *ctx = talloc_tos();
2611 struct dptr_struct *dirptr;
2612 struct smbd_server_connection *sconn = req->sconn;
2614 if (total_params < 13) {
2615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2616 return;
2619 dptr_num = SVAL(params,0);
2620 maxentries = SVAL(params,2);
2621 info_level = SVAL(params,4);
2622 resume_key = IVAL(params,6);
2623 findnext_flags = SVAL(params,10);
2624 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2625 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2626 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2627 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2629 if (!continue_bit) {
2630 /* We only need resume_name if continue_bit is zero. */
2631 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2632 params+12,
2633 total_params - 12, STR_TERMINATE, &ntstatus,
2634 &mask_contains_wcard);
2635 if (!NT_STATUS_IS_OK(ntstatus)) {
2636 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2637 complain (it thinks we're asking for the directory above the shared
2638 path or an invalid name). Catch this as the resume name is only compared, never used in
2639 a file access. JRA. */
2640 srvstr_pull_talloc(ctx, params, req->flags2,
2641 &resume_name, params+12,
2642 total_params - 12,
2643 STR_TERMINATE);
2645 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2646 reply_nterror(req, ntstatus);
2647 return;
2652 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2653 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2654 resume_key = %d resume name = %s continue=%d level = %d\n",
2655 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2656 requires_resume_key, resume_key,
2657 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2659 if (!maxentries) {
2660 /* W2K3 seems to treat zero as 1. */
2661 maxentries = 1;
2664 switch (info_level) {
2665 case SMB_FIND_INFO_STANDARD:
2666 case SMB_FIND_EA_SIZE:
2667 case SMB_FIND_EA_LIST:
2668 case SMB_FIND_FILE_DIRECTORY_INFO:
2669 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2670 case SMB_FIND_FILE_NAMES_INFO:
2671 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2672 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2673 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2674 break;
2675 case SMB_FIND_FILE_UNIX:
2676 case SMB_FIND_FILE_UNIX_INFO2:
2677 /* Always use filesystem for UNIX mtime query. */
2678 ask_sharemode = false;
2679 if (!lp_unix_extensions()) {
2680 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2681 return;
2683 break;
2684 default:
2685 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2686 return;
2689 if (info_level == SMB_FIND_EA_LIST) {
2690 uint32 ea_size;
2692 if (total_data < 4) {
2693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2694 return;
2697 ea_size = IVAL(pdata,0);
2698 if (ea_size != total_data) {
2699 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2700 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2702 return;
2705 if (!lp_ea_support(SNUM(conn))) {
2706 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2707 return;
2710 /* Pull out the list of names. */
2711 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2712 if (!ea_list) {
2713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2714 return;
2718 *ppdata = (char *)SMB_REALLOC(
2719 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2720 if(*ppdata == NULL) {
2721 reply_nterror(req, NT_STATUS_NO_MEMORY);
2722 return;
2725 pdata = *ppdata;
2726 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2728 /* Realloc the params space */
2729 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2730 if(*pparams == NULL ) {
2731 reply_nterror(req, NT_STATUS_NO_MEMORY);
2732 return;
2735 params = *pparams;
2737 /* Check that the dptr is valid */
2738 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2739 reply_nterror(req, STATUS_NO_MORE_FILES);
2740 return;
2743 directory = dptr_path(sconn, dptr_num);
2745 /* Get the wildcard mask from the dptr */
2746 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2747 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2748 reply_nterror(req, STATUS_NO_MORE_FILES);
2749 return;
2752 mask = p;
2754 /* Get the attr mask from the dptr */
2755 dirtype = dptr_attr(sconn, dptr_num);
2757 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2758 dptr_num, mask, dirtype,
2759 (long)dirptr,
2760 dptr_TellDir(dirptr)));
2762 /* Initialize per TRANS2_FIND_NEXT operation data */
2763 dptr_init_search_op(dirptr);
2765 /* We don't need to check for VOL here as this is returned by
2766 a different TRANS2 call. */
2768 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2769 directory,lp_dontdescend(SNUM(conn))));
2770 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2771 dont_descend = True;
2773 p = pdata;
2774 space_remaining = max_data_bytes;
2775 out_of_space = False;
2778 * Seek to the correct position. We no longer use the resume key but
2779 * depend on the last file name instead.
2782 if(!continue_bit && resume_name && *resume_name) {
2783 SMB_STRUCT_STAT st;
2785 long current_pos = 0;
2787 * Remember, name_to_8_3 is called by
2788 * get_lanman2_dir_entry(), so the resume name
2789 * could be mangled. Ensure we check the unmangled name.
2792 if (mangle_is_mangled(resume_name, conn->params)) {
2793 char *new_resume_name = NULL;
2794 mangle_lookup_name_from_8_3(ctx,
2795 resume_name,
2796 &new_resume_name,
2797 conn->params);
2798 if (new_resume_name) {
2799 resume_name = new_resume_name;
2804 * Fix for NT redirector problem triggered by resume key indexes
2805 * changing between directory scans. We now return a resume key of 0
2806 * and instead look for the filename to continue from (also given
2807 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2808 * findfirst/findnext (as is usual) then the directory pointer
2809 * should already be at the correct place.
2812 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2813 } /* end if resume_name && !continue_bit */
2815 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2816 bool got_exact_match = False;
2818 /* this is a heuristic to avoid seeking the dirptr except when
2819 absolutely necessary. It allows for a filename of about 40 chars */
2820 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2821 out_of_space = True;
2822 finished = False;
2823 } else {
2824 finished = !get_lanman2_dir_entry(ctx,
2825 conn,
2826 dirptr,
2827 req->flags2,
2828 mask,dirtype,info_level,
2829 requires_resume_key,dont_descend,
2830 ask_sharemode,
2831 &p,pdata,data_end,
2832 space_remaining, &out_of_space,
2833 &got_exact_match,
2834 &last_entry_off, ea_list);
2837 if (finished && out_of_space)
2838 finished = False;
2840 if (!finished && !out_of_space)
2841 numentries++;
2844 * As an optimisation if we know we aren't looking
2845 * for a wildcard name (ie. the name matches the wildcard exactly)
2846 * then we can finish on any (first) match.
2847 * This speeds up large directory searches. JRA.
2850 if(got_exact_match)
2851 finished = True;
2853 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2856 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2857 smb_fn_name(req->cmd),
2858 mask, directory, dirtype, numentries ) );
2860 /* Check if we can close the dirptr */
2861 if(close_after_request || (finished && close_if_end)) {
2862 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2863 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2866 /* Set up the return parameter block */
2867 SSVAL(params,0,numentries);
2868 SSVAL(params,2,finished);
2869 SSVAL(params,4,0); /* Never an EA error */
2870 SSVAL(params,6,last_entry_off);
2872 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2873 max_data_bytes);
2875 return;
2878 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2880 E_md4hash(lp_servicename(SNUM(conn)),objid);
2881 return objid;
2884 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2886 SMB_ASSERT(extended_info != NULL);
2888 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2889 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2890 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2891 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2892 #ifdef SAMBA_VERSION_REVISION
2893 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2894 #endif
2895 extended_info->samba_subversion = 0;
2896 #ifdef SAMBA_VERSION_RC_RELEASE
2897 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2898 #else
2899 #ifdef SAMBA_VERSION_PRE_RELEASE
2900 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2901 #endif
2902 #endif
2903 #ifdef SAMBA_VERSION_VENDOR_PATCH
2904 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2905 #endif
2906 extended_info->samba_gitcommitdate = 0;
2907 #ifdef SAMBA_VERSION_COMMIT_TIME
2908 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2909 #endif
2911 memset(extended_info->samba_version_string, 0,
2912 sizeof(extended_info->samba_version_string));
2914 snprintf (extended_info->samba_version_string,
2915 sizeof(extended_info->samba_version_string),
2916 "%s", samba_version_string());
2919 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2920 TALLOC_CTX *mem_ctx,
2921 uint16_t info_level,
2922 uint16_t flags2,
2923 unsigned int max_data_bytes,
2924 char **ppdata,
2925 int *ret_data_len)
2927 char *pdata, *end_data;
2928 int data_len = 0, len;
2929 const char *vname = volume_label(SNUM(conn));
2930 int snum = SNUM(conn);
2931 char *fstype = lp_fstype(SNUM(conn));
2932 uint32 additional_flags = 0;
2933 struct smb_filename smb_fname_dot;
2934 SMB_STRUCT_STAT st;
2936 if (IS_IPC(conn)) {
2937 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2938 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2939 "info level (0x%x) on IPC$.\n",
2940 (unsigned int)info_level));
2941 return NT_STATUS_ACCESS_DENIED;
2945 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2947 ZERO_STRUCT(smb_fname_dot);
2948 smb_fname_dot.base_name = discard_const_p(char, ".");
2950 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2951 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2952 return map_nt_error_from_unix(errno);
2955 st = smb_fname_dot.st;
2957 *ppdata = (char *)SMB_REALLOC(
2958 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2959 if (*ppdata == NULL) {
2960 return NT_STATUS_NO_MEMORY;
2963 pdata = *ppdata;
2964 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2965 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2967 switch (info_level) {
2968 case SMB_INFO_ALLOCATION:
2970 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2971 data_len = 18;
2972 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2973 return map_nt_error_from_unix(errno);
2976 block_size = lp_block_size(snum);
2977 if (bsize < block_size) {
2978 uint64_t factor = block_size/bsize;
2979 bsize = block_size;
2980 dsize /= factor;
2981 dfree /= factor;
2983 if (bsize > block_size) {
2984 uint64_t factor = bsize/block_size;
2985 bsize = block_size;
2986 dsize *= factor;
2987 dfree *= factor;
2989 bytes_per_sector = 512;
2990 sectors_per_unit = bsize/bytes_per_sector;
2992 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2993 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2994 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2996 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2997 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2998 SIVAL(pdata,l1_cUnit,dsize);
2999 SIVAL(pdata,l1_cUnitAvail,dfree);
3000 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3001 break;
3004 case SMB_INFO_VOLUME:
3005 /* Return volume name */
3007 * Add volume serial number - hash of a combination of
3008 * the called hostname and the service name.
3010 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3012 * Win2k3 and previous mess this up by sending a name length
3013 * one byte short. I believe only older clients (OS/2 Win9x) use
3014 * this call so try fixing this by adding a terminating null to
3015 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3017 len = srvstr_push(
3018 pdata, flags2,
3019 pdata+l2_vol_szVolLabel, vname,
3020 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3021 STR_NOALIGN|STR_TERMINATE);
3022 SCVAL(pdata,l2_vol_cch,len);
3023 data_len = l2_vol_szVolLabel + len;
3024 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3025 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3026 len, vname));
3027 break;
3029 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3030 case SMB_FS_ATTRIBUTE_INFORMATION:
3032 additional_flags = 0;
3033 #if defined(HAVE_SYS_QUOTAS)
3034 additional_flags |= FILE_VOLUME_QUOTAS;
3035 #endif
3037 if(lp_nt_acl_support(SNUM(conn))) {
3038 additional_flags |= FILE_PERSISTENT_ACLS;
3041 /* Capabilities are filled in at connection time through STATVFS call */
3042 additional_flags |= conn->fs_capabilities;
3043 additional_flags |= lp_parm_int(conn->params->service,
3044 "share", "fake_fscaps",
3047 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3048 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3049 additional_flags); /* FS ATTRIBUTES */
3051 SIVAL(pdata,4,255); /* Max filename component length */
3052 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3053 and will think we can't do long filenames */
3054 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3055 PTR_DIFF(end_data, pdata+12),
3056 STR_UNICODE);
3057 SIVAL(pdata,8,len);
3058 data_len = 12 + len;
3059 break;
3061 case SMB_QUERY_FS_LABEL_INFO:
3062 case SMB_FS_LABEL_INFORMATION:
3063 len = srvstr_push(pdata, flags2, pdata+4, vname,
3064 PTR_DIFF(end_data, pdata+4), 0);
3065 data_len = 4 + len;
3066 SIVAL(pdata,0,len);
3067 break;
3069 case SMB_QUERY_FS_VOLUME_INFO:
3070 case SMB_FS_VOLUME_INFORMATION:
3073 * Add volume serial number - hash of a combination of
3074 * the called hostname and the service name.
3076 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3077 (str_checksum(get_local_machine_name())<<16));
3079 /* Max label len is 32 characters. */
3080 len = srvstr_push(pdata, flags2, pdata+18, vname,
3081 PTR_DIFF(end_data, pdata+18),
3082 STR_UNICODE);
3083 SIVAL(pdata,12,len);
3084 data_len = 18+len;
3086 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3087 (int)strlen(vname),vname, lp_servicename(snum)));
3088 break;
3090 case SMB_QUERY_FS_SIZE_INFO:
3091 case SMB_FS_SIZE_INFORMATION:
3093 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3094 data_len = 24;
3095 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3096 return map_nt_error_from_unix(errno);
3098 block_size = lp_block_size(snum);
3099 if (bsize < block_size) {
3100 uint64_t factor = block_size/bsize;
3101 bsize = block_size;
3102 dsize /= factor;
3103 dfree /= factor;
3105 if (bsize > block_size) {
3106 uint64_t factor = bsize/block_size;
3107 bsize = block_size;
3108 dsize *= factor;
3109 dfree *= factor;
3111 bytes_per_sector = 512;
3112 sectors_per_unit = bsize/bytes_per_sector;
3113 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3114 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3115 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3116 SBIG_UINT(pdata,0,dsize);
3117 SBIG_UINT(pdata,8,dfree);
3118 SIVAL(pdata,16,sectors_per_unit);
3119 SIVAL(pdata,20,bytes_per_sector);
3120 break;
3123 case SMB_FS_FULL_SIZE_INFORMATION:
3125 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3126 data_len = 32;
3127 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3128 return map_nt_error_from_unix(errno);
3130 block_size = lp_block_size(snum);
3131 if (bsize < block_size) {
3132 uint64_t factor = block_size/bsize;
3133 bsize = block_size;
3134 dsize /= factor;
3135 dfree /= factor;
3137 if (bsize > block_size) {
3138 uint64_t factor = bsize/block_size;
3139 bsize = block_size;
3140 dsize *= factor;
3141 dfree *= factor;
3143 bytes_per_sector = 512;
3144 sectors_per_unit = bsize/bytes_per_sector;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3147 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3148 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3149 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3150 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3151 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3152 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3153 break;
3156 case SMB_QUERY_FS_DEVICE_INFO:
3157 case SMB_FS_DEVICE_INFORMATION:
3159 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3161 if (!CAN_WRITE(conn)) {
3162 characteristics |= FILE_READ_ONLY_DEVICE;
3164 data_len = 8;
3165 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3166 SIVAL(pdata,4,characteristics);
3167 break;
3170 #ifdef HAVE_SYS_QUOTAS
3171 case SMB_FS_QUOTA_INFORMATION:
3173 * what we have to send --metze:
3175 * Unknown1: 24 NULL bytes
3176 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3177 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3178 * Quota Flags: 2 byte :
3179 * Unknown3: 6 NULL bytes
3181 * 48 bytes total
3183 * details for Quota Flags:
3185 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3186 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3187 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3188 * 0x0001 Enable Quotas: enable quota for this fs
3192 /* we need to fake up a fsp here,
3193 * because its not send in this call
3195 files_struct fsp;
3196 SMB_NTQUOTA_STRUCT quotas;
3198 ZERO_STRUCT(fsp);
3199 ZERO_STRUCT(quotas);
3201 fsp.conn = conn;
3202 fsp.fnum = -1;
3204 /* access check */
3205 if (get_current_uid(conn) != 0) {
3206 DEBUG(0,("set_user_quota: access_denied "
3207 "service [%s] user [%s]\n",
3208 lp_servicename(SNUM(conn)),
3209 conn->session_info->unix_name));
3210 return NT_STATUS_ACCESS_DENIED;
3213 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3214 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3215 return map_nt_error_from_unix(errno);
3218 data_len = 48;
3220 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3221 lp_servicename(SNUM(conn))));
3223 /* Unknown1 24 NULL bytes*/
3224 SBIG_UINT(pdata,0,(uint64_t)0);
3225 SBIG_UINT(pdata,8,(uint64_t)0);
3226 SBIG_UINT(pdata,16,(uint64_t)0);
3228 /* Default Soft Quota 8 bytes */
3229 SBIG_UINT(pdata,24,quotas.softlim);
3231 /* Default Hard Quota 8 bytes */
3232 SBIG_UINT(pdata,32,quotas.hardlim);
3234 /* Quota flag 2 bytes */
3235 SSVAL(pdata,40,quotas.qflags);
3237 /* Unknown3 6 NULL bytes */
3238 SSVAL(pdata,42,0);
3239 SIVAL(pdata,44,0);
3241 break;
3243 #endif /* HAVE_SYS_QUOTAS */
3244 case SMB_FS_OBJECTID_INFORMATION:
3246 unsigned char objid[16];
3247 struct smb_extended_info extended_info;
3248 memcpy(pdata,create_volume_objectid(conn, objid),16);
3249 samba_extended_info_version (&extended_info);
3250 SIVAL(pdata,16,extended_info.samba_magic);
3251 SIVAL(pdata,20,extended_info.samba_version);
3252 SIVAL(pdata,24,extended_info.samba_subversion);
3253 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3254 memcpy(pdata+36,extended_info.samba_version_string,28);
3255 data_len = 64;
3256 break;
3260 * Query the version and capabilities of the CIFS UNIX extensions
3261 * in use.
3264 case SMB_QUERY_CIFS_UNIX_INFO:
3266 bool large_write = lp_min_receive_file_size() &&
3267 !srv_is_signing_active(conn->sconn);
3268 bool large_read = !srv_is_signing_active(conn->sconn);
3269 int encrypt_caps = 0;
3271 if (!lp_unix_extensions()) {
3272 return NT_STATUS_INVALID_LEVEL;
3275 switch (conn->encrypt_level) {
3276 case 0:
3277 encrypt_caps = 0;
3278 break;
3279 case 1:
3280 case Auto:
3281 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3282 break;
3283 case Required:
3284 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3285 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3286 large_write = false;
3287 large_read = false;
3288 break;
3291 data_len = 12;
3292 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3293 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3295 /* We have POSIX ACLs, pathname, encryption,
3296 * large read/write, and locking capability. */
3298 SBIG_UINT(pdata,4,((uint64_t)(
3299 CIFS_UNIX_POSIX_ACLS_CAP|
3300 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3301 CIFS_UNIX_FCNTL_LOCKS_CAP|
3302 CIFS_UNIX_EXTATTR_CAP|
3303 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3304 encrypt_caps|
3305 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3306 (large_write ?
3307 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3308 break;
3311 case SMB_QUERY_POSIX_FS_INFO:
3313 int rc;
3314 vfs_statvfs_struct svfs;
3316 if (!lp_unix_extensions()) {
3317 return NT_STATUS_INVALID_LEVEL;
3320 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3322 if (!rc) {
3323 data_len = 56;
3324 SIVAL(pdata,0,svfs.OptimalTransferSize);
3325 SIVAL(pdata,4,svfs.BlockSize);
3326 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3327 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3328 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3329 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3330 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3331 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3332 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3333 #ifdef EOPNOTSUPP
3334 } else if (rc == EOPNOTSUPP) {
3335 return NT_STATUS_INVALID_LEVEL;
3336 #endif /* EOPNOTSUPP */
3337 } else {
3338 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3339 return NT_STATUS_DOS(ERRSRV, ERRerror);
3341 break;
3344 case SMB_QUERY_POSIX_WHOAMI:
3346 uint32_t flags = 0;
3347 uint32_t sid_bytes;
3348 int i;
3350 if (!lp_unix_extensions()) {
3351 return NT_STATUS_INVALID_LEVEL;
3354 if (max_data_bytes < 40) {
3355 return NT_STATUS_BUFFER_TOO_SMALL;
3358 /* We ARE guest if global_sid_Builtin_Guests is
3359 * in our list of SIDs.
3361 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3362 conn->session_info->security_token)) {
3363 flags |= SMB_WHOAMI_GUEST;
3366 /* We are NOT guest if global_sid_Authenticated_Users
3367 * is in our list of SIDs.
3369 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3370 conn->session_info->security_token)) {
3371 flags &= ~SMB_WHOAMI_GUEST;
3374 /* NOTE: 8 bytes for UID/GID, irrespective of native
3375 * platform size. This matches
3376 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3378 data_len = 4 /* flags */
3379 + 4 /* flag mask */
3380 + 8 /* uid */
3381 + 8 /* gid */
3382 + 4 /* ngroups */
3383 + 4 /* num_sids */
3384 + 4 /* SID bytes */
3385 + 4 /* pad/reserved */
3386 + (conn->session_info->utok.ngroups * 8)
3387 /* groups list */
3388 + (conn->session_info->security_token->num_sids *
3389 SID_MAX_SIZE)
3390 /* SID list */;
3392 SIVAL(pdata, 0, flags);
3393 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3394 SBIG_UINT(pdata, 8,
3395 (uint64_t)conn->session_info->utok.uid);
3396 SBIG_UINT(pdata, 16,
3397 (uint64_t)conn->session_info->utok.gid);
3400 if (data_len >= max_data_bytes) {
3401 /* Potential overflow, skip the GIDs and SIDs. */
3403 SIVAL(pdata, 24, 0); /* num_groups */
3404 SIVAL(pdata, 28, 0); /* num_sids */
3405 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3406 SIVAL(pdata, 36, 0); /* reserved */
3408 data_len = 40;
3409 break;
3412 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3413 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3415 /* We walk the SID list twice, but this call is fairly
3416 * infrequent, and I don't expect that it's performance
3417 * sensitive -- jpeach
3419 for (i = 0, sid_bytes = 0;
3420 i < conn->session_info->security_token->num_sids; ++i) {
3421 sid_bytes += ndr_size_dom_sid(
3422 &conn->session_info->security_token->sids[i],
3426 /* SID list byte count */
3427 SIVAL(pdata, 32, sid_bytes);
3429 /* 4 bytes pad/reserved - must be zero */
3430 SIVAL(pdata, 36, 0);
3431 data_len = 40;
3433 /* GID list */
3434 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3435 SBIG_UINT(pdata, data_len,
3436 (uint64_t)conn->session_info->utok.groups[i]);
3437 data_len += 8;
3440 /* SID list */
3441 for (i = 0;
3442 i < conn->session_info->security_token->num_sids; ++i) {
3443 int sid_len = ndr_size_dom_sid(
3444 &conn->session_info->security_token->sids[i],
3447 sid_linearize(pdata + data_len, sid_len,
3448 &conn->session_info->security_token->sids[i]);
3449 data_len += sid_len;
3452 break;
3455 case SMB_MAC_QUERY_FS_INFO:
3457 * Thursby MAC extension... ONLY on NTFS filesystems
3458 * once we do streams then we don't need this
3460 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3461 data_len = 88;
3462 SIVAL(pdata,84,0x100); /* Don't support mac... */
3463 break;
3465 /* drop through */
3466 default:
3467 return NT_STATUS_INVALID_LEVEL;
3470 *ret_data_len = data_len;
3471 return NT_STATUS_OK;
3474 /****************************************************************************
3475 Reply to a TRANS2_QFSINFO (query filesystem info).
3476 ****************************************************************************/
3478 static void call_trans2qfsinfo(connection_struct *conn,
3479 struct smb_request *req,
3480 char **pparams, int total_params,
3481 char **ppdata, int total_data,
3482 unsigned int max_data_bytes)
3484 char *params = *pparams;
3485 uint16_t info_level;
3486 int data_len = 0;
3487 NTSTATUS status;
3489 if (total_params < 2) {
3490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3491 return;
3494 info_level = SVAL(params,0);
3496 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3497 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3498 DEBUG(0,("call_trans2qfsinfo: encryption required "
3499 "and info level 0x%x sent.\n",
3500 (unsigned int)info_level));
3501 exit_server_cleanly("encryption required "
3502 "on connection");
3503 return;
3507 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3509 status = smbd_do_qfsinfo(conn, req,
3510 info_level,
3511 req->flags2,
3512 max_data_bytes,
3513 ppdata, &data_len);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 reply_nterror(req, status);
3516 return;
3519 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3520 max_data_bytes);
3522 DEBUG( 4, ( "%s info_level = %d\n",
3523 smb_fn_name(req->cmd), info_level) );
3525 return;
3528 /****************************************************************************
3529 Reply to a TRANS2_SETFSINFO (set filesystem info).
3530 ****************************************************************************/
3532 static void call_trans2setfsinfo(connection_struct *conn,
3533 struct smb_request *req,
3534 char **pparams, int total_params,
3535 char **ppdata, int total_data,
3536 unsigned int max_data_bytes)
3538 char *pdata = *ppdata;
3539 char *params = *pparams;
3540 uint16 info_level;
3542 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3544 /* */
3545 if (total_params < 4) {
3546 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3547 total_params));
3548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3549 return;
3552 info_level = SVAL(params,2);
3554 if (IS_IPC(conn)) {
3555 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3556 info_level != SMB_SET_CIFS_UNIX_INFO) {
3557 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3558 "info level (0x%x) on IPC$.\n",
3559 (unsigned int)info_level));
3560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3561 return;
3565 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3566 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3567 DEBUG(0,("call_trans2setfsinfo: encryption required "
3568 "and info level 0x%x sent.\n",
3569 (unsigned int)info_level));
3570 exit_server_cleanly("encryption required "
3571 "on connection");
3572 return;
3576 switch(info_level) {
3577 case SMB_SET_CIFS_UNIX_INFO:
3579 uint16 client_unix_major;
3580 uint16 client_unix_minor;
3581 uint32 client_unix_cap_low;
3582 uint32 client_unix_cap_high;
3584 if (!lp_unix_extensions()) {
3585 reply_nterror(req,
3586 NT_STATUS_INVALID_LEVEL);
3587 return;
3590 /* There should be 12 bytes of capabilities set. */
3591 if (total_data < 8) {
3592 reply_nterror(
3593 req,
3594 NT_STATUS_INVALID_PARAMETER);
3595 return;
3597 client_unix_major = SVAL(pdata,0);
3598 client_unix_minor = SVAL(pdata,2);
3599 client_unix_cap_low = IVAL(pdata,4);
3600 client_unix_cap_high = IVAL(pdata,8);
3601 /* Just print these values for now. */
3602 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3603 cap_low = 0x%x, cap_high = 0x%x\n",
3604 (unsigned int)client_unix_major,
3605 (unsigned int)client_unix_minor,
3606 (unsigned int)client_unix_cap_low,
3607 (unsigned int)client_unix_cap_high ));
3609 /* Here is where we must switch to posix pathname processing... */
3610 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3611 lp_set_posix_pathnames();
3612 mangle_change_to_posix();
3615 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3616 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3617 /* Client that knows how to do posix locks,
3618 * but not posix open/mkdir operations. Set a
3619 * default type for read/write checks. */
3621 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3624 break;
3627 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3629 NTSTATUS status;
3630 size_t param_len = 0;
3631 size_t data_len = total_data;
3633 if (!lp_unix_extensions()) {
3634 reply_nterror(
3635 req,
3636 NT_STATUS_INVALID_LEVEL);
3637 return;
3640 if (lp_smb_encrypt(SNUM(conn)) == false) {
3641 reply_nterror(
3642 req,
3643 NT_STATUS_NOT_SUPPORTED);
3644 return;
3647 if (req->sconn->smb1.echo_handler.trusted_fde) {
3648 DEBUG( 2,("call_trans2setfsinfo: "
3649 "request transport encryption disabled"
3650 "with 'fork echo handler = yes'\n"));
3651 reply_nterror(
3652 req,
3653 NT_STATUS_NOT_SUPPORTED);
3654 return;
3657 DEBUG( 4,("call_trans2setfsinfo: "
3658 "request transport encryption.\n"));
3660 status = srv_request_encryption_setup(conn,
3661 (unsigned char **)ppdata,
3662 &data_len,
3663 (unsigned char **)pparams,
3664 &param_len);
3666 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3667 !NT_STATUS_IS_OK(status)) {
3668 reply_nterror(req, status);
3669 return;
3672 send_trans2_replies(conn, req,
3673 *pparams,
3674 param_len,
3675 *ppdata,
3676 data_len,
3677 max_data_bytes);
3679 if (NT_STATUS_IS_OK(status)) {
3680 /* Server-side transport
3681 * encryption is now *on*. */
3682 status = srv_encryption_start(conn);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 exit_server_cleanly(
3685 "Failure in setting "
3686 "up encrypted transport");
3689 return;
3692 case SMB_FS_QUOTA_INFORMATION:
3694 files_struct *fsp = NULL;
3695 SMB_NTQUOTA_STRUCT quotas;
3697 ZERO_STRUCT(quotas);
3699 /* access check */
3700 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3701 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3702 lp_servicename(SNUM(conn)),
3703 conn->session_info->unix_name));
3704 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3705 return;
3708 /* note: normaly there're 48 bytes,
3709 * but we didn't use the last 6 bytes for now
3710 * --metze
3712 fsp = file_fsp(req, SVAL(params,0));
3714 if (!check_fsp_ntquota_handle(conn, req,
3715 fsp)) {
3716 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3717 reply_nterror(
3718 req, NT_STATUS_INVALID_HANDLE);
3719 return;
3722 if (total_data < 42) {
3723 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3724 total_data));
3725 reply_nterror(
3726 req,
3727 NT_STATUS_INVALID_PARAMETER);
3728 return;
3731 /* unknown_1 24 NULL bytes in pdata*/
3733 /* the soft quotas 8 bytes (uint64_t)*/
3734 quotas.softlim = BVAL(pdata,24);
3736 /* the hard quotas 8 bytes (uint64_t)*/
3737 quotas.hardlim = BVAL(pdata,32);
3739 /* quota_flags 2 bytes **/
3740 quotas.qflags = SVAL(pdata,40);
3742 /* unknown_2 6 NULL bytes follow*/
3744 /* now set the quotas */
3745 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3746 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3747 reply_nterror(req, map_nt_error_from_unix(errno));
3748 return;
3751 break;
3753 default:
3754 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3755 info_level));
3756 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3757 return;
3758 break;
3762 * sending this reply works fine,
3763 * but I'm not sure it's the same
3764 * like windows do...
3765 * --metze
3767 reply_outbuf(req, 10, 0);
3770 #if defined(HAVE_POSIX_ACLS)
3771 /****************************************************************************
3772 Utility function to count the number of entries in a POSIX acl.
3773 ****************************************************************************/
3775 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3777 unsigned int ace_count = 0;
3778 int entry_id = SMB_ACL_FIRST_ENTRY;
3779 SMB_ACL_ENTRY_T entry;
3781 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3782 /* get_next... */
3783 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3784 entry_id = SMB_ACL_NEXT_ENTRY;
3786 ace_count++;
3788 return ace_count;
3791 /****************************************************************************
3792 Utility function to marshall a POSIX acl into wire format.
3793 ****************************************************************************/
3795 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3797 int entry_id = SMB_ACL_FIRST_ENTRY;
3798 SMB_ACL_ENTRY_T entry;
3800 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3801 SMB_ACL_TAG_T tagtype;
3802 SMB_ACL_PERMSET_T permset;
3803 unsigned char perms = 0;
3804 unsigned int own_grp;
3806 /* get_next... */
3807 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3808 entry_id = SMB_ACL_NEXT_ENTRY;
3811 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3813 return False;
3816 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3817 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3818 return False;
3821 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3822 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3823 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3825 SCVAL(pdata,1,perms);
3827 switch (tagtype) {
3828 case SMB_ACL_USER_OBJ:
3829 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3830 own_grp = (unsigned int)pst->st_ex_uid;
3831 SIVAL(pdata,2,own_grp);
3832 SIVAL(pdata,6,0);
3833 break;
3834 case SMB_ACL_USER:
3836 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3837 if (!puid) {
3838 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3839 return False;
3841 own_grp = (unsigned int)*puid;
3842 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3843 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3844 SIVAL(pdata,2,own_grp);
3845 SIVAL(pdata,6,0);
3846 break;
3848 case SMB_ACL_GROUP_OBJ:
3849 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3850 own_grp = (unsigned int)pst->st_ex_gid;
3851 SIVAL(pdata,2,own_grp);
3852 SIVAL(pdata,6,0);
3853 break;
3854 case SMB_ACL_GROUP:
3856 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3857 if (!pgid) {
3858 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3859 return False;
3861 own_grp = (unsigned int)*pgid;
3862 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3863 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3864 SIVAL(pdata,2,own_grp);
3865 SIVAL(pdata,6,0);
3866 break;
3868 case SMB_ACL_MASK:
3869 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3870 SIVAL(pdata,2,0xFFFFFFFF);
3871 SIVAL(pdata,6,0xFFFFFFFF);
3872 break;
3873 case SMB_ACL_OTHER:
3874 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3875 SIVAL(pdata,2,0xFFFFFFFF);
3876 SIVAL(pdata,6,0xFFFFFFFF);
3877 break;
3878 default:
3879 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3880 return False;
3882 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3885 return True;
3887 #endif
3889 /****************************************************************************
3890 Store the FILE_UNIX_BASIC info.
3891 ****************************************************************************/
3893 static char *store_file_unix_basic(connection_struct *conn,
3894 char *pdata,
3895 files_struct *fsp,
3896 const SMB_STRUCT_STAT *psbuf)
3898 uint64_t file_index = get_FileIndex(conn, psbuf);
3900 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3901 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3903 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3904 pdata += 8;
3906 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3907 pdata += 8;
3909 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3910 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3911 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3912 pdata += 24;
3914 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3915 SIVAL(pdata,4,0);
3916 pdata += 8;
3918 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3919 SIVAL(pdata,4,0);
3920 pdata += 8;
3922 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3923 pdata += 4;
3925 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3926 SIVAL(pdata,4,0);
3927 pdata += 8;
3929 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3930 SIVAL(pdata,4,0);
3931 pdata += 8;
3933 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3934 pdata += 8;
3936 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3937 SIVAL(pdata,4,0);
3938 pdata += 8;
3940 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3941 SIVAL(pdata,4,0);
3942 pdata += 8;
3944 return pdata;
3947 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3948 * the chflags(2) (or equivalent) flags.
3950 * XXX: this really should be behind the VFS interface. To do this, we would
3951 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3952 * Each VFS module could then implement its own mapping as appropriate for the
3953 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3955 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3956 info2_flags_map[] =
3958 #ifdef UF_NODUMP
3959 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3960 #endif
3962 #ifdef UF_IMMUTABLE
3963 { UF_IMMUTABLE, EXT_IMMUTABLE },
3964 #endif
3966 #ifdef UF_APPEND
3967 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3968 #endif
3970 #ifdef UF_HIDDEN
3971 { UF_HIDDEN, EXT_HIDDEN },
3972 #endif
3974 /* Do not remove. We need to guarantee that this array has at least one
3975 * entry to build on HP-UX.
3977 { 0, 0 }
3981 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3982 uint32 *smb_fflags, uint32 *smb_fmask)
3984 int i;
3986 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3987 *smb_fmask |= info2_flags_map[i].smb_fflag;
3988 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3989 *smb_fflags |= info2_flags_map[i].smb_fflag;
3994 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3995 const uint32 smb_fflags,
3996 const uint32 smb_fmask,
3997 int *stat_fflags)
3999 uint32 max_fmask = 0;
4000 int i;
4002 *stat_fflags = psbuf->st_ex_flags;
4004 /* For each flags requested in smb_fmask, check the state of the
4005 * corresponding flag in smb_fflags and set or clear the matching
4006 * stat flag.
4009 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4010 max_fmask |= info2_flags_map[i].smb_fflag;
4011 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4012 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4013 *stat_fflags |= info2_flags_map[i].stat_fflag;
4014 } else {
4015 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4020 /* If smb_fmask is asking to set any bits that are not supported by
4021 * our flag mappings, we should fail.
4023 if ((smb_fmask & max_fmask) != smb_fmask) {
4024 return False;
4027 return True;
4031 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4032 * of file flags and birth (create) time.
4034 static char *store_file_unix_basic_info2(connection_struct *conn,
4035 char *pdata,
4036 files_struct *fsp,
4037 const SMB_STRUCT_STAT *psbuf)
4039 uint32 file_flags = 0;
4040 uint32 flags_mask = 0;
4042 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4044 /* Create (birth) time 64 bit */
4045 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4046 pdata += 8;
4048 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4049 SIVAL(pdata, 0, file_flags); /* flags */
4050 SIVAL(pdata, 4, flags_mask); /* mask */
4051 pdata += 8;
4053 return pdata;
4056 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4057 const struct stream_struct *streams,
4058 char *data,
4059 unsigned int max_data_bytes,
4060 unsigned int *data_size)
4062 unsigned int i;
4063 unsigned int ofs = 0;
4065 for (i = 0; i < num_streams; i++) {
4066 unsigned int next_offset;
4067 size_t namelen;
4068 smb_ucs2_t *namebuf;
4070 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4071 streams[i].name, &namelen) ||
4072 namelen <= 2)
4074 return NT_STATUS_INVALID_PARAMETER;
4078 * name_buf is now null-terminated, we need to marshall as not
4079 * terminated
4082 namelen -= 2;
4085 * We cannot overflow ...
4087 if ((ofs + 24 + namelen) > max_data_bytes) {
4088 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4089 i));
4090 TALLOC_FREE(namebuf);
4091 return STATUS_BUFFER_OVERFLOW;
4094 SIVAL(data, ofs+4, namelen);
4095 SOFF_T(data, ofs+8, streams[i].size);
4096 SOFF_T(data, ofs+16, streams[i].alloc_size);
4097 memcpy(data+ofs+24, namebuf, namelen);
4098 TALLOC_FREE(namebuf);
4100 next_offset = ofs + 24 + namelen;
4102 if (i == num_streams-1) {
4103 SIVAL(data, ofs, 0);
4105 else {
4106 unsigned int align = ndr_align_size(next_offset, 8);
4108 if ((next_offset + align) > max_data_bytes) {
4109 DEBUG(10, ("refusing to overflow align "
4110 "reply at stream %u\n",
4111 i));
4112 TALLOC_FREE(namebuf);
4113 return STATUS_BUFFER_OVERFLOW;
4116 memset(data+next_offset, 0, align);
4117 next_offset += align;
4119 SIVAL(data, ofs, next_offset - ofs);
4120 ofs = next_offset;
4123 ofs = next_offset;
4126 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4128 *data_size = ofs;
4130 return NT_STATUS_OK;
4133 /****************************************************************************
4134 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4135 ****************************************************************************/
4137 static void call_trans2qpipeinfo(connection_struct *conn,
4138 struct smb_request *req,
4139 unsigned int tran_call,
4140 char **pparams, int total_params,
4141 char **ppdata, int total_data,
4142 unsigned int max_data_bytes)
4144 char *params = *pparams;
4145 char *pdata = *ppdata;
4146 unsigned int data_size = 0;
4147 unsigned int param_size = 2;
4148 uint16 info_level;
4149 files_struct *fsp;
4151 if (!params) {
4152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4153 return;
4156 if (total_params < 4) {
4157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4158 return;
4161 fsp = file_fsp(req, SVAL(params,0));
4162 if (!fsp_is_np(fsp)) {
4163 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4164 return;
4167 info_level = SVAL(params,2);
4169 *pparams = (char *)SMB_REALLOC(*pparams,2);
4170 if (*pparams == NULL) {
4171 reply_nterror(req, NT_STATUS_NO_MEMORY);
4172 return;
4174 params = *pparams;
4175 SSVAL(params,0,0);
4176 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4177 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4178 if (*ppdata == NULL ) {
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4180 return;
4182 pdata = *ppdata;
4184 switch (info_level) {
4185 case SMB_FILE_STANDARD_INFORMATION:
4186 memset(pdata,0,24);
4187 SOFF_T(pdata,0,4096LL);
4188 SIVAL(pdata,16,1);
4189 SIVAL(pdata,20,1);
4190 data_size = 24;
4191 break;
4193 default:
4194 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4195 return;
4198 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4199 max_data_bytes);
4201 return;
4204 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4205 TALLOC_CTX *mem_ctx,
4206 uint16_t info_level,
4207 files_struct *fsp,
4208 struct smb_filename *smb_fname,
4209 bool delete_pending,
4210 struct timespec write_time_ts,
4211 struct ea_list *ea_list,
4212 int lock_data_count,
4213 char *lock_data,
4214 uint16_t flags2,
4215 unsigned int max_data_bytes,
4216 char **ppdata,
4217 unsigned int *pdata_size)
4219 char *pdata = *ppdata;
4220 char *dstart, *dend;
4221 unsigned int data_size;
4222 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4223 time_t create_time, mtime, atime, c_time;
4224 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4225 char *p;
4226 char *base_name;
4227 char *dos_fname;
4228 int mode;
4229 int nlink;
4230 NTSTATUS status;
4231 uint64_t file_size = 0;
4232 uint64_t pos = 0;
4233 uint64_t allocation_size = 0;
4234 uint64_t file_index = 0;
4235 uint32_t access_mask = 0;
4237 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4238 return NT_STATUS_INVALID_LEVEL;
4241 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4242 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4243 info_level, max_data_bytes));
4245 mode = dos_mode(conn, smb_fname);
4246 nlink = psbuf->st_ex_nlink;
4248 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4249 nlink = 1;
4252 if ((nlink > 0) && delete_pending) {
4253 nlink -= 1;
4256 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4257 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4258 if (*ppdata == NULL) {
4259 return NT_STATUS_NO_MEMORY;
4261 pdata = *ppdata;
4262 dstart = pdata;
4263 dend = dstart + data_size - 1;
4265 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4266 update_stat_ex_mtime(psbuf, write_time_ts);
4269 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4270 mtime_ts = psbuf->st_ex_mtime;
4271 atime_ts = psbuf->st_ex_atime;
4272 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4274 if (lp_dos_filetime_resolution(SNUM(conn))) {
4275 dos_filetime_timespec(&create_time_ts);
4276 dos_filetime_timespec(&mtime_ts);
4277 dos_filetime_timespec(&atime_ts);
4278 dos_filetime_timespec(&ctime_ts);
4281 create_time = convert_timespec_to_time_t(create_time_ts);
4282 mtime = convert_timespec_to_time_t(mtime_ts);
4283 atime = convert_timespec_to_time_t(atime_ts);
4284 c_time = convert_timespec_to_time_t(ctime_ts);
4286 p = strrchr_m(smb_fname->base_name,'/');
4287 if (!p)
4288 base_name = smb_fname->base_name;
4289 else
4290 base_name = p+1;
4292 /* NT expects the name to be in an exact form of the *full*
4293 filename. See the trans2 torture test */
4294 if (ISDOT(base_name)) {
4295 dos_fname = talloc_strdup(mem_ctx, "\\");
4296 if (!dos_fname) {
4297 return NT_STATUS_NO_MEMORY;
4299 } else {
4300 dos_fname = talloc_asprintf(mem_ctx,
4301 "\\%s",
4302 smb_fname->base_name);
4303 if (!dos_fname) {
4304 return NT_STATUS_NO_MEMORY;
4306 if (is_ntfs_stream_smb_fname(smb_fname)) {
4307 dos_fname = talloc_asprintf(dos_fname, "%s",
4308 smb_fname->stream_name);
4309 if (!dos_fname) {
4310 return NT_STATUS_NO_MEMORY;
4314 string_replace(dos_fname, '/', '\\');
4317 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4319 if (!fsp) {
4320 /* Do we have this path open ? */
4321 files_struct *fsp1;
4322 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4323 fsp1 = file_find_di_first(conn->sconn, fileid);
4324 if (fsp1 && fsp1->initial_allocation_size) {
4325 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4329 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4330 file_size = get_file_size_stat(psbuf);
4333 if (fsp) {
4334 pos = fsp->fh->position_information;
4337 if (fsp) {
4338 access_mask = fsp->access_mask;
4339 } else {
4340 /* GENERIC_EXECUTE mapping from Windows */
4341 access_mask = 0x12019F;
4344 /* This should be an index number - looks like
4345 dev/ino to me :-)
4347 I think this causes us to fail the IFSKIT
4348 BasicFileInformationTest. -tpot */
4349 file_index = get_FileIndex(conn, psbuf);
4351 switch (info_level) {
4352 case SMB_INFO_STANDARD:
4353 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4354 data_size = 22;
4355 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4356 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4357 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4358 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4359 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4360 SSVAL(pdata,l1_attrFile,mode);
4361 break;
4363 case SMB_INFO_QUERY_EA_SIZE:
4365 unsigned int ea_size =
4366 estimate_ea_size(conn, fsp,
4367 smb_fname->base_name);
4368 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4369 data_size = 26;
4370 srv_put_dos_date2(pdata,0,create_time);
4371 srv_put_dos_date2(pdata,4,atime);
4372 srv_put_dos_date2(pdata,8,mtime); /* write time */
4373 SIVAL(pdata,12,(uint32)file_size);
4374 SIVAL(pdata,16,(uint32)allocation_size);
4375 SSVAL(pdata,20,mode);
4376 SIVAL(pdata,22,ea_size);
4377 break;
4380 case SMB_INFO_IS_NAME_VALID:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4382 if (fsp) {
4383 /* os/2 needs this ? really ?*/
4384 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4386 /* This is only reached for qpathinfo */
4387 data_size = 0;
4388 break;
4390 case SMB_INFO_QUERY_EAS_FROM_LIST:
4392 size_t total_ea_len = 0;
4393 struct ea_list *ea_file_list = NULL;
4395 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4397 ea_file_list =
4398 get_ea_list_from_file(mem_ctx, conn, fsp,
4399 smb_fname->base_name,
4400 &total_ea_len);
4401 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4403 if (!ea_list || (total_ea_len > data_size)) {
4404 data_size = 4;
4405 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4406 break;
4409 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4410 break;
4413 case SMB_INFO_QUERY_ALL_EAS:
4415 /* We have data_size bytes to put EA's into. */
4416 size_t total_ea_len = 0;
4418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4420 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4421 smb_fname->base_name,
4422 &total_ea_len);
4423 if (!ea_list || (total_ea_len > data_size)) {
4424 data_size = 4;
4425 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4426 break;
4429 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4430 break;
4433 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4435 /* This is FileFullEaInformation - 0xF which maps to
4436 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4438 /* We have data_size bytes to put EA's into. */
4439 size_t total_ea_len = 0;
4440 struct ea_list *ea_file_list = NULL;
4442 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4444 /*TODO: add filtering and index handling */
4446 ea_file_list =
4447 get_ea_list_from_file(mem_ctx, conn, fsp,
4448 smb_fname->base_name,
4449 &total_ea_len);
4450 if (!ea_file_list) {
4451 return NT_STATUS_NO_EAS_ON_FILE;
4454 status = fill_ea_chained_buffer(mem_ctx,
4455 pdata,
4456 data_size,
4457 &data_size,
4458 conn, ea_file_list);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 return status;
4462 break;
4465 case SMB_FILE_BASIC_INFORMATION:
4466 case SMB_QUERY_FILE_BASIC_INFO:
4468 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4470 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4471 } else {
4472 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4473 data_size = 40;
4474 SIVAL(pdata,36,0);
4476 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4477 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4478 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4479 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4480 SIVAL(pdata,32,mode);
4482 DEBUG(5,("SMB_QFBI - "));
4483 DEBUG(5,("create: %s ", ctime(&create_time)));
4484 DEBUG(5,("access: %s ", ctime(&atime)));
4485 DEBUG(5,("write: %s ", ctime(&mtime)));
4486 DEBUG(5,("change: %s ", ctime(&c_time)));
4487 DEBUG(5,("mode: %x\n", mode));
4488 break;
4490 case SMB_FILE_STANDARD_INFORMATION:
4491 case SMB_QUERY_FILE_STANDARD_INFO:
4493 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4494 data_size = 24;
4495 SOFF_T(pdata,0,allocation_size);
4496 SOFF_T(pdata,8,file_size);
4497 SIVAL(pdata,16,nlink);
4498 SCVAL(pdata,20,delete_pending?1:0);
4499 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4500 SSVAL(pdata,22,0); /* Padding. */
4501 break;
4503 case SMB_FILE_EA_INFORMATION:
4504 case SMB_QUERY_FILE_EA_INFO:
4506 unsigned int ea_size =
4507 estimate_ea_size(conn, fsp, smb_fname->base_name);
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4509 data_size = 4;
4510 SIVAL(pdata,0,ea_size);
4511 break;
4514 /* Get the 8.3 name - used if NT SMB was negotiated. */
4515 case SMB_QUERY_FILE_ALT_NAME_INFO:
4516 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4518 int len;
4519 char mangled_name[13];
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4521 if (!name_to_8_3(base_name,mangled_name,
4522 True,conn->params)) {
4523 return NT_STATUS_NO_MEMORY;
4525 len = srvstr_push(dstart, flags2,
4526 pdata+4, mangled_name,
4527 PTR_DIFF(dend, pdata+4),
4528 STR_UNICODE);
4529 data_size = 4 + len;
4530 SIVAL(pdata,0,len);
4531 break;
4534 case SMB_QUERY_FILE_NAME_INFO:
4536 int len;
4538 this must be *exactly* right for ACLs on mapped drives to work
4540 len = srvstr_push(dstart, flags2,
4541 pdata+4, dos_fname,
4542 PTR_DIFF(dend, pdata+4),
4543 STR_UNICODE);
4544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4545 data_size = 4 + len;
4546 SIVAL(pdata,0,len);
4547 break;
4550 case SMB_FILE_ALLOCATION_INFORMATION:
4551 case SMB_QUERY_FILE_ALLOCATION_INFO:
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4553 data_size = 8;
4554 SOFF_T(pdata,0,allocation_size);
4555 break;
4557 case SMB_FILE_END_OF_FILE_INFORMATION:
4558 case SMB_QUERY_FILE_END_OF_FILEINFO:
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4560 data_size = 8;
4561 SOFF_T(pdata,0,file_size);
4562 break;
4564 case SMB_QUERY_FILE_ALL_INFO:
4565 case SMB_FILE_ALL_INFORMATION:
4567 int len;
4568 unsigned int ea_size =
4569 estimate_ea_size(conn, fsp, smb_fname->base_name);
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4571 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4572 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4573 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4574 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4575 SIVAL(pdata,32,mode);
4576 SIVAL(pdata,36,0); /* padding. */
4577 pdata += 40;
4578 SOFF_T(pdata,0,allocation_size);
4579 SOFF_T(pdata,8,file_size);
4580 SIVAL(pdata,16,nlink);
4581 SCVAL(pdata,20,delete_pending);
4582 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4583 SSVAL(pdata,22,0);
4584 pdata += 24;
4585 SIVAL(pdata,0,ea_size);
4586 pdata += 4; /* EA info */
4587 len = srvstr_push(dstart, flags2,
4588 pdata+4, dos_fname,
4589 PTR_DIFF(dend, pdata+4),
4590 STR_UNICODE);
4591 SIVAL(pdata,0,len);
4592 pdata += 4 + len;
4593 data_size = PTR_DIFF(pdata,(*ppdata));
4594 break;
4597 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4599 int len;
4600 unsigned int ea_size =
4601 estimate_ea_size(conn, fsp, smb_fname->base_name);
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4603 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4604 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4605 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4606 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4607 SIVAL(pdata, 0x20, mode);
4608 SIVAL(pdata, 0x24, 0); /* padding. */
4609 SBVAL(pdata, 0x28, allocation_size);
4610 SBVAL(pdata, 0x30, file_size);
4611 SIVAL(pdata, 0x38, nlink);
4612 SCVAL(pdata, 0x3C, delete_pending);
4613 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4614 SSVAL(pdata, 0x3E, 0); /* padding */
4615 SBVAL(pdata, 0x40, file_index);
4616 SIVAL(pdata, 0x48, ea_size);
4617 SIVAL(pdata, 0x4C, access_mask);
4618 SBVAL(pdata, 0x50, pos);
4619 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4620 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4622 pdata += 0x60;
4624 len = srvstr_push(dstart, flags2,
4625 pdata+4, dos_fname,
4626 PTR_DIFF(dend, pdata+4),
4627 STR_UNICODE);
4628 SIVAL(pdata,0,len);
4629 pdata += 4 + len;
4630 data_size = PTR_DIFF(pdata,(*ppdata));
4631 break;
4633 case SMB_FILE_INTERNAL_INFORMATION:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4636 SBVAL(pdata, 0, file_index);
4637 data_size = 8;
4638 break;
4640 case SMB_FILE_ACCESS_INFORMATION:
4641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4642 SIVAL(pdata, 0, access_mask);
4643 data_size = 4;
4644 break;
4646 case SMB_FILE_NAME_INFORMATION:
4647 /* Pathname with leading '\'. */
4649 size_t byte_len;
4650 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4652 SIVAL(pdata,0,byte_len);
4653 data_size = 4 + byte_len;
4654 break;
4657 case SMB_FILE_DISPOSITION_INFORMATION:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4659 data_size = 1;
4660 SCVAL(pdata,0,delete_pending);
4661 break;
4663 case SMB_FILE_POSITION_INFORMATION:
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4665 data_size = 8;
4666 SOFF_T(pdata,0,pos);
4667 break;
4669 case SMB_FILE_MODE_INFORMATION:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4671 SIVAL(pdata,0,mode);
4672 data_size = 4;
4673 break;
4675 case SMB_FILE_ALIGNMENT_INFORMATION:
4676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4677 SIVAL(pdata,0,0); /* No alignment needed. */
4678 data_size = 4;
4679 break;
4682 * NT4 server just returns "invalid query" to this - if we try
4683 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4684 * want this. JRA.
4686 /* The first statement above is false - verified using Thursby
4687 * client against NT4 -- gcolley.
4689 case SMB_QUERY_FILE_STREAM_INFO:
4690 case SMB_FILE_STREAM_INFORMATION: {
4691 unsigned int num_streams = 0;
4692 struct stream_struct *streams = NULL;
4694 DEBUG(10,("smbd_do_qfilepathinfo: "
4695 "SMB_FILE_STREAM_INFORMATION\n"));
4697 if (is_ntfs_stream_smb_fname(smb_fname)) {
4698 return NT_STATUS_INVALID_PARAMETER;
4701 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4702 talloc_tos(), &num_streams, &streams);
4704 if (!NT_STATUS_IS_OK(status)) {
4705 DEBUG(10, ("could not get stream info: %s\n",
4706 nt_errstr(status)));
4707 return status;
4710 status = marshall_stream_info(num_streams, streams,
4711 pdata, max_data_bytes,
4712 &data_size);
4714 if (!NT_STATUS_IS_OK(status)) {
4715 DEBUG(10, ("marshall_stream_info failed: %s\n",
4716 nt_errstr(status)));
4717 TALLOC_FREE(streams);
4718 return status;
4721 TALLOC_FREE(streams);
4723 break;
4725 case SMB_QUERY_COMPRESSION_INFO:
4726 case SMB_FILE_COMPRESSION_INFORMATION:
4727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4728 SOFF_T(pdata,0,file_size);
4729 SIVAL(pdata,8,0); /* ??? */
4730 SIVAL(pdata,12,0); /* ??? */
4731 data_size = 16;
4732 break;
4734 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4736 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4737 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4738 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4739 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4740 SOFF_T(pdata,32,allocation_size);
4741 SOFF_T(pdata,40,file_size);
4742 SIVAL(pdata,48,mode);
4743 SIVAL(pdata,52,0); /* ??? */
4744 data_size = 56;
4745 break;
4747 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4749 SIVAL(pdata,0,mode);
4750 SIVAL(pdata,4,0);
4751 data_size = 8;
4752 break;
4755 * CIFS UNIX Extensions.
4758 case SMB_QUERY_FILE_UNIX_BASIC:
4760 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4761 data_size = PTR_DIFF(pdata,(*ppdata));
4763 DEBUG(4,("smbd_do_qfilepathinfo: "
4764 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4765 dump_data(4, (uint8_t *)(*ppdata), data_size);
4767 break;
4769 case SMB_QUERY_FILE_UNIX_INFO2:
4771 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4772 data_size = PTR_DIFF(pdata,(*ppdata));
4775 int i;
4776 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4778 for (i=0; i<100; i++)
4779 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4780 DEBUG(4,("\n"));
4783 break;
4785 case SMB_QUERY_FILE_UNIX_LINK:
4787 int len;
4788 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4790 if (!buffer) {
4791 return NT_STATUS_NO_MEMORY;
4794 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4795 #ifdef S_ISLNK
4796 if(!S_ISLNK(psbuf->st_ex_mode)) {
4797 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4799 #else
4800 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4801 #endif
4802 len = SMB_VFS_READLINK(conn,
4803 smb_fname->base_name,
4804 buffer, PATH_MAX);
4805 if (len == -1) {
4806 return map_nt_error_from_unix(errno);
4808 buffer[len] = 0;
4809 len = srvstr_push(dstart, flags2,
4810 pdata, buffer,
4811 PTR_DIFF(dend, pdata),
4812 STR_TERMINATE);
4813 pdata += len;
4814 data_size = PTR_DIFF(pdata,(*ppdata));
4816 break;
4819 #if defined(HAVE_POSIX_ACLS)
4820 case SMB_QUERY_POSIX_ACL:
4822 SMB_ACL_T file_acl = NULL;
4823 SMB_ACL_T def_acl = NULL;
4824 uint16 num_file_acls = 0;
4825 uint16 num_def_acls = 0;
4827 if (fsp && fsp->fh->fd != -1) {
4828 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4829 } else {
4830 file_acl =
4831 SMB_VFS_SYS_ACL_GET_FILE(conn,
4832 smb_fname->base_name,
4833 SMB_ACL_TYPE_ACCESS);
4836 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4837 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4838 "not implemented on "
4839 "filesystem containing %s\n",
4840 smb_fname->base_name));
4841 return NT_STATUS_NOT_IMPLEMENTED;
4844 if (S_ISDIR(psbuf->st_ex_mode)) {
4845 if (fsp && fsp->is_directory) {
4846 def_acl =
4847 SMB_VFS_SYS_ACL_GET_FILE(
4848 conn,
4849 fsp->fsp_name->base_name,
4850 SMB_ACL_TYPE_DEFAULT);
4851 } else {
4852 def_acl =
4853 SMB_VFS_SYS_ACL_GET_FILE(
4854 conn,
4855 smb_fname->base_name,
4856 SMB_ACL_TYPE_DEFAULT);
4858 def_acl = free_empty_sys_acl(conn, def_acl);
4861 num_file_acls = count_acl_entries(conn, file_acl);
4862 num_def_acls = count_acl_entries(conn, def_acl);
4864 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4865 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4866 data_size,
4867 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4868 SMB_POSIX_ACL_HEADER_SIZE) ));
4869 if (file_acl) {
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4872 if (def_acl) {
4873 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4875 return NT_STATUS_BUFFER_TOO_SMALL;
4878 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4879 SSVAL(pdata,2,num_file_acls);
4880 SSVAL(pdata,4,num_def_acls);
4881 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4882 if (file_acl) {
4883 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4885 if (def_acl) {
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4888 return NT_STATUS_INTERNAL_ERROR;
4890 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4891 if (file_acl) {
4892 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4894 if (def_acl) {
4895 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4897 return NT_STATUS_INTERNAL_ERROR;
4900 if (file_acl) {
4901 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4903 if (def_acl) {
4904 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4906 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4907 break;
4909 #endif
4912 case SMB_QUERY_POSIX_LOCK:
4914 uint64_t count;
4915 uint64_t offset;
4916 uint64_t smblctx;
4917 enum brl_type lock_type;
4919 /* We need an open file with a real fd for this. */
4920 if (!fsp || fsp->fh->fd == -1) {
4921 return NT_STATUS_INVALID_LEVEL;
4924 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4925 return NT_STATUS_INVALID_PARAMETER;
4928 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4929 case POSIX_LOCK_TYPE_READ:
4930 lock_type = READ_LOCK;
4931 break;
4932 case POSIX_LOCK_TYPE_WRITE:
4933 lock_type = WRITE_LOCK;
4934 break;
4935 case POSIX_LOCK_TYPE_UNLOCK:
4936 default:
4937 /* There's no point in asking for an unlock... */
4938 return NT_STATUS_INVALID_PARAMETER;
4941 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4942 #if defined(HAVE_LONGLONG)
4943 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4944 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4945 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4946 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4947 #else /* HAVE_LONGLONG */
4948 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4949 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4950 #endif /* HAVE_LONGLONG */
4952 status = query_lock(fsp,
4953 &smblctx,
4954 &count,
4955 &offset,
4956 &lock_type,
4957 POSIX_LOCK);
4959 if (ERROR_WAS_LOCK_DENIED(status)) {
4960 /* Here we need to report who has it locked... */
4961 data_size = POSIX_LOCK_DATA_SIZE;
4963 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4964 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4965 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4966 #if defined(HAVE_LONGLONG)
4967 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4968 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4969 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4970 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4971 #else /* HAVE_LONGLONG */
4972 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4973 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4974 #endif /* HAVE_LONGLONG */
4976 } else if (NT_STATUS_IS_OK(status)) {
4977 /* For success we just return a copy of what we sent
4978 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4979 data_size = POSIX_LOCK_DATA_SIZE;
4980 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4981 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4982 } else {
4983 return status;
4985 break;
4988 default:
4989 return NT_STATUS_INVALID_LEVEL;
4992 *pdata_size = data_size;
4993 return NT_STATUS_OK;
4996 /****************************************************************************
4997 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4998 file name or file id).
4999 ****************************************************************************/
5001 static void call_trans2qfilepathinfo(connection_struct *conn,
5002 struct smb_request *req,
5003 unsigned int tran_call,
5004 char **pparams, int total_params,
5005 char **ppdata, int total_data,
5006 unsigned int max_data_bytes)
5008 char *params = *pparams;
5009 char *pdata = *ppdata;
5010 uint16 info_level;
5011 unsigned int data_size = 0;
5012 unsigned int param_size = 2;
5013 struct smb_filename *smb_fname = NULL;
5014 bool delete_pending = False;
5015 struct timespec write_time_ts;
5016 files_struct *fsp = NULL;
5017 struct file_id fileid;
5018 struct ea_list *ea_list = NULL;
5019 int lock_data_count = 0;
5020 char *lock_data = NULL;
5021 NTSTATUS status = NT_STATUS_OK;
5023 if (!params) {
5024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5025 return;
5028 ZERO_STRUCT(write_time_ts);
5030 if (tran_call == TRANSACT2_QFILEINFO) {
5031 if (total_params < 4) {
5032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033 return;
5036 if (IS_IPC(conn)) {
5037 call_trans2qpipeinfo(conn, req, tran_call,
5038 pparams, total_params,
5039 ppdata, total_data,
5040 max_data_bytes);
5041 return;
5044 fsp = file_fsp(req, SVAL(params,0));
5045 info_level = SVAL(params,2);
5047 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5049 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5050 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5051 return;
5054 /* Initial check for valid fsp ptr. */
5055 if (!check_fsp_open(conn, req, fsp)) {
5056 return;
5059 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5060 &smb_fname);
5061 if (!NT_STATUS_IS_OK(status)) {
5062 reply_nterror(req, status);
5063 return;
5066 if(fsp->fake_file_handle) {
5068 * This is actually for the QUOTA_FAKE_FILE --metze
5071 /* We know this name is ok, it's already passed the checks. */
5073 } else if(fsp->fh->fd == -1) {
5075 * This is actually a QFILEINFO on a directory
5076 * handle (returned from an NT SMB). NT5.0 seems
5077 * to do this call. JRA.
5080 if (INFO_LEVEL_IS_UNIX(info_level)) {
5081 /* Always do lstat for UNIX calls. */
5082 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5083 DEBUG(3,("call_trans2qfilepathinfo: "
5084 "SMB_VFS_LSTAT of %s failed "
5085 "(%s)\n",
5086 smb_fname_str_dbg(smb_fname),
5087 strerror(errno)));
5088 reply_nterror(req,
5089 map_nt_error_from_unix(errno));
5090 return;
5092 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5093 DEBUG(3,("call_trans2qfilepathinfo: "
5094 "SMB_VFS_STAT of %s failed (%s)\n",
5095 smb_fname_str_dbg(smb_fname),
5096 strerror(errno)));
5097 reply_nterror(req,
5098 map_nt_error_from_unix(errno));
5099 return;
5102 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5103 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5104 } else {
5106 * Original code - this is an open file.
5108 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5109 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5110 fsp->fnum, strerror(errno)));
5111 reply_nterror(req,
5112 map_nt_error_from_unix(errno));
5113 return;
5115 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5116 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5119 } else {
5120 uint32_t name_hash;
5121 char *fname = NULL;
5122 uint32_t ucf_flags = 0;
5124 /* qpathinfo */
5125 if (total_params < 7) {
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127 return;
5130 info_level = SVAL(params,0);
5132 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5134 if (INFO_LEVEL_IS_UNIX(info_level)) {
5135 if (!lp_unix_extensions()) {
5136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5137 return;
5139 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5140 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5141 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5142 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5146 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5147 total_params - 6,
5148 STR_TERMINATE, &status);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 reply_nterror(req, status);
5151 return;
5154 status = filename_convert(req,
5155 conn,
5156 req->flags2 & FLAGS2_DFS_PATHNAMES,
5157 fname,
5158 ucf_flags,
5159 NULL,
5160 &smb_fname);
5161 if (!NT_STATUS_IS_OK(status)) {
5162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5163 reply_botherror(req,
5164 NT_STATUS_PATH_NOT_COVERED,
5165 ERRSRV, ERRbadpath);
5166 return;
5168 reply_nterror(req, status);
5169 return;
5172 /* If this is a stream, check if there is a delete_pending. */
5173 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5174 && is_ntfs_stream_smb_fname(smb_fname)) {
5175 struct smb_filename *smb_fname_base = NULL;
5177 /* Create an smb_filename with stream_name == NULL. */
5178 status =
5179 create_synthetic_smb_fname(talloc_tos(),
5180 smb_fname->base_name,
5181 NULL, NULL,
5182 &smb_fname_base);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 reply_nterror(req, status);
5185 return;
5188 if (INFO_LEVEL_IS_UNIX(info_level)) {
5189 /* Always do lstat for UNIX calls. */
5190 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5191 DEBUG(3,("call_trans2qfilepathinfo: "
5192 "SMB_VFS_LSTAT of %s failed "
5193 "(%s)\n",
5194 smb_fname_str_dbg(smb_fname_base),
5195 strerror(errno)));
5196 TALLOC_FREE(smb_fname_base);
5197 reply_nterror(req,
5198 map_nt_error_from_unix(errno));
5199 return;
5201 } else {
5202 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5203 DEBUG(3,("call_trans2qfilepathinfo: "
5204 "fileinfo of %s failed "
5205 "(%s)\n",
5206 smb_fname_str_dbg(smb_fname_base),
5207 strerror(errno)));
5208 TALLOC_FREE(smb_fname_base);
5209 reply_nterror(req,
5210 map_nt_error_from_unix(errno));
5211 return;
5215 status = file_name_hash(conn,
5216 smb_fname_str_dbg(smb_fname_base),
5217 &name_hash);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 TALLOC_FREE(smb_fname_base);
5220 reply_nterror(req, status);
5221 return;
5224 fileid = vfs_file_id_from_sbuf(conn,
5225 &smb_fname_base->st);
5226 TALLOC_FREE(smb_fname_base);
5227 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5228 if (delete_pending) {
5229 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5230 return;
5234 if (INFO_LEVEL_IS_UNIX(info_level)) {
5235 /* Always do lstat for UNIX calls. */
5236 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5237 DEBUG(3,("call_trans2qfilepathinfo: "
5238 "SMB_VFS_LSTAT of %s failed (%s)\n",
5239 smb_fname_str_dbg(smb_fname),
5240 strerror(errno)));
5241 reply_nterror(req,
5242 map_nt_error_from_unix(errno));
5243 return;
5246 } else {
5247 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5248 DEBUG(3,("call_trans2qfilepathinfo: "
5249 "SMB_VFS_STAT of %s failed (%s)\n",
5250 smb_fname_str_dbg(smb_fname),
5251 strerror(errno)));
5252 reply_nterror(req,
5253 map_nt_error_from_unix(errno));
5254 return;
5258 status = file_name_hash(conn,
5259 smb_fname_str_dbg(smb_fname),
5260 &name_hash);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 reply_nterror(req, status);
5263 return;
5266 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5267 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5268 if (delete_pending) {
5269 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5270 return;
5274 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5275 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5276 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5278 /* Pull out any data sent here before we realloc. */
5279 switch (info_level) {
5280 case SMB_INFO_QUERY_EAS_FROM_LIST:
5282 /* Pull any EA list from the data portion. */
5283 uint32 ea_size;
5285 if (total_data < 4) {
5286 reply_nterror(
5287 req, NT_STATUS_INVALID_PARAMETER);
5288 return;
5290 ea_size = IVAL(pdata,0);
5292 if (total_data > 0 && ea_size != total_data) {
5293 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5294 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5295 reply_nterror(
5296 req, NT_STATUS_INVALID_PARAMETER);
5297 return;
5300 if (!lp_ea_support(SNUM(conn))) {
5301 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5302 return;
5305 /* Pull out the list of names. */
5306 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5307 if (!ea_list) {
5308 reply_nterror(
5309 req, NT_STATUS_INVALID_PARAMETER);
5310 return;
5312 break;
5315 case SMB_QUERY_POSIX_LOCK:
5317 if (fsp == NULL || fsp->fh->fd == -1) {
5318 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5319 return;
5322 if (total_data != POSIX_LOCK_DATA_SIZE) {
5323 reply_nterror(
5324 req, NT_STATUS_INVALID_PARAMETER);
5325 return;
5328 /* Copy the lock range data. */
5329 lock_data = (char *)TALLOC_MEMDUP(
5330 req, pdata, total_data);
5331 if (!lock_data) {
5332 reply_nterror(req, NT_STATUS_NO_MEMORY);
5333 return;
5335 lock_data_count = total_data;
5337 default:
5338 break;
5341 *pparams = (char *)SMB_REALLOC(*pparams,2);
5342 if (*pparams == NULL) {
5343 reply_nterror(req, NT_STATUS_NO_MEMORY);
5344 return;
5346 params = *pparams;
5347 SSVAL(params,0,0);
5350 * draft-leach-cifs-v1-spec-02.txt
5351 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5352 * says:
5354 * The requested information is placed in the Data portion of the
5355 * transaction response. For the information levels greater than 0x100,
5356 * the transaction response has 1 parameter word which should be
5357 * ignored by the client.
5359 * However Windows only follows this rule for the IS_NAME_VALID call.
5361 switch (info_level) {
5362 case SMB_INFO_IS_NAME_VALID:
5363 param_size = 0;
5364 break;
5367 if ((info_level & 0xFF00) == 0xFF00) {
5369 * We use levels that start with 0xFF00
5370 * internally to represent SMB2 specific levels
5372 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5373 return;
5376 status = smbd_do_qfilepathinfo(conn, req, info_level,
5377 fsp, smb_fname,
5378 delete_pending, write_time_ts,
5379 ea_list,
5380 lock_data_count, lock_data,
5381 req->flags2, max_data_bytes,
5382 ppdata, &data_size);
5383 if (!NT_STATUS_IS_OK(status)) {
5384 reply_nterror(req, status);
5385 return;
5388 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5389 max_data_bytes);
5391 return;
5394 /****************************************************************************
5395 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5396 code.
5397 ****************************************************************************/
5399 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5400 connection_struct *conn,
5401 struct smb_request *req,
5402 bool overwrite_if_exists,
5403 const struct smb_filename *smb_fname_old,
5404 struct smb_filename *smb_fname_new)
5406 NTSTATUS status = NT_STATUS_OK;
5408 /* source must already exist. */
5409 if (!VALID_STAT(smb_fname_old->st)) {
5410 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5413 if (VALID_STAT(smb_fname_new->st)) {
5414 if (overwrite_if_exists) {
5415 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5416 return NT_STATUS_FILE_IS_A_DIRECTORY;
5418 status = unlink_internals(conn,
5419 req,
5420 FILE_ATTRIBUTE_NORMAL,
5421 smb_fname_new,
5422 false);
5423 if (!NT_STATUS_IS_OK(status)) {
5424 return status;
5426 } else {
5427 /* Disallow if newname already exists. */
5428 return NT_STATUS_OBJECT_NAME_COLLISION;
5432 /* No links from a directory. */
5433 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5434 return NT_STATUS_FILE_IS_A_DIRECTORY;
5437 /* Setting a hardlink to/from a stream isn't currently supported. */
5438 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5439 is_ntfs_stream_smb_fname(smb_fname_new)) {
5440 return NT_STATUS_INVALID_PARAMETER;
5443 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5444 smb_fname_old->base_name, smb_fname_new->base_name));
5446 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5447 smb_fname_new->base_name) != 0) {
5448 status = map_nt_error_from_unix(errno);
5449 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5450 nt_errstr(status), smb_fname_old->base_name,
5451 smb_fname_new->base_name));
5453 return status;
5456 /****************************************************************************
5457 Deal with setting the time from any of the setfilepathinfo functions.
5458 ****************************************************************************/
5460 NTSTATUS smb_set_file_time(connection_struct *conn,
5461 files_struct *fsp,
5462 const struct smb_filename *smb_fname,
5463 struct smb_file_time *ft,
5464 bool setting_write_time)
5466 struct smb_filename smb_fname_base;
5467 uint32 action =
5468 FILE_NOTIFY_CHANGE_LAST_ACCESS
5469 |FILE_NOTIFY_CHANGE_LAST_WRITE
5470 |FILE_NOTIFY_CHANGE_CREATION;
5472 if (!VALID_STAT(smb_fname->st)) {
5473 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5476 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5477 return NT_STATUS_ACCESS_DENIED;
5480 /* get some defaults (no modifications) if any info is zero or -1. */
5481 if (null_timespec(ft->create_time)) {
5482 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5485 if (null_timespec(ft->atime)) {
5486 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5489 if (null_timespec(ft->mtime)) {
5490 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5493 if (!setting_write_time) {
5494 /* ft->mtime comes from change time, not write time. */
5495 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5498 /* Ensure the resolution is the correct for
5499 * what we can store on this filesystem. */
5501 round_timespec(conn->ts_res, &ft->create_time);
5502 round_timespec(conn->ts_res, &ft->ctime);
5503 round_timespec(conn->ts_res, &ft->atime);
5504 round_timespec(conn->ts_res, &ft->mtime);
5506 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5507 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5508 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5509 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5510 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5511 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5512 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5513 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5515 if (setting_write_time) {
5517 * This was a Windows setfileinfo on an open file.
5518 * NT does this a lot. We also need to
5519 * set the time here, as it can be read by
5520 * FindFirst/FindNext and with the patch for bug #2045
5521 * in smbd/fileio.c it ensures that this timestamp is
5522 * kept sticky even after a write. We save the request
5523 * away and will set it on file close and after a write. JRA.
5526 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5527 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5529 if (fsp != NULL) {
5530 if (fsp->base_fsp) {
5531 set_sticky_write_time_fsp(fsp->base_fsp,
5532 ft->mtime);
5533 } else {
5534 set_sticky_write_time_fsp(fsp, ft->mtime);
5536 } else {
5537 set_sticky_write_time_path(
5538 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5539 ft->mtime);
5543 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5545 /* Always call ntimes on the base, even if a stream was passed in. */
5546 smb_fname_base = *smb_fname;
5547 smb_fname_base.stream_name = NULL;
5549 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5550 return map_nt_error_from_unix(errno);
5553 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5554 smb_fname->base_name);
5555 return NT_STATUS_OK;
5558 /****************************************************************************
5559 Deal with setting the dosmode from any of the setfilepathinfo functions.
5560 ****************************************************************************/
5562 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5563 const struct smb_filename *smb_fname,
5564 uint32 dosmode)
5566 struct smb_filename *smb_fname_base = NULL;
5567 NTSTATUS status;
5569 if (!VALID_STAT(smb_fname->st)) {
5570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5573 /* Always operate on the base_name, even if a stream was passed in. */
5574 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5575 NULL, &smb_fname->st,
5576 &smb_fname_base);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 return status;
5581 if (dosmode) {
5582 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5583 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5584 } else {
5585 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5589 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5591 /* check the mode isn't different, before changing it */
5592 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5593 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5594 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5595 (unsigned int)dosmode));
5597 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5598 false)) {
5599 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5600 "%s failed (%s)\n",
5601 smb_fname_str_dbg(smb_fname_base),
5602 strerror(errno)));
5603 status = map_nt_error_from_unix(errno);
5604 goto out;
5607 status = NT_STATUS_OK;
5608 out:
5609 TALLOC_FREE(smb_fname_base);
5610 return status;
5613 /****************************************************************************
5614 Deal with setting the size from any of the setfilepathinfo functions.
5615 ****************************************************************************/
5617 static NTSTATUS smb_set_file_size(connection_struct *conn,
5618 struct smb_request *req,
5619 files_struct *fsp,
5620 const struct smb_filename *smb_fname,
5621 const SMB_STRUCT_STAT *psbuf,
5622 SMB_OFF_T size,
5623 bool fail_after_createfile)
5625 NTSTATUS status = NT_STATUS_OK;
5626 struct smb_filename *smb_fname_tmp = NULL;
5627 files_struct *new_fsp = NULL;
5629 if (!VALID_STAT(*psbuf)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5633 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5634 return NT_STATUS_ACCESS_DENIED;
5637 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5639 if (size == get_file_size_stat(psbuf)) {
5640 return NT_STATUS_OK;
5643 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5644 smb_fname_str_dbg(smb_fname), (double)size));
5646 if (fsp && fsp->fh->fd != -1) {
5647 /* Handle based call. */
5648 if (vfs_set_filelen(fsp, size) == -1) {
5649 return map_nt_error_from_unix(errno);
5651 trigger_write_time_update_immediate(fsp);
5652 return NT_STATUS_OK;
5655 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 return status;
5660 smb_fname_tmp->st = *psbuf;
5662 status = SMB_VFS_CREATE_FILE(
5663 conn, /* conn */
5664 req, /* req */
5665 0, /* root_dir_fid */
5666 smb_fname_tmp, /* fname */
5667 FILE_WRITE_DATA, /* access_mask */
5668 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5669 FILE_SHARE_DELETE),
5670 FILE_OPEN, /* create_disposition*/
5671 0, /* create_options */
5672 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5673 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5674 0, /* allocation_size */
5675 0, /* private_flags */
5676 NULL, /* sd */
5677 NULL, /* ea_list */
5678 &new_fsp, /* result */
5679 NULL); /* pinfo */
5681 TALLOC_FREE(smb_fname_tmp);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 /* NB. We check for open_was_deferred in the caller. */
5685 return status;
5688 /* See RAW-SFILEINFO-END-OF-FILE */
5689 if (fail_after_createfile) {
5690 close_file(req, new_fsp,NORMAL_CLOSE);
5691 return NT_STATUS_INVALID_LEVEL;
5694 if (vfs_set_filelen(new_fsp, size) == -1) {
5695 status = map_nt_error_from_unix(errno);
5696 close_file(req, new_fsp,NORMAL_CLOSE);
5697 return status;
5700 trigger_write_time_update_immediate(new_fsp);
5701 close_file(req, new_fsp,NORMAL_CLOSE);
5702 return NT_STATUS_OK;
5705 /****************************************************************************
5706 Deal with SMB_INFO_SET_EA.
5707 ****************************************************************************/
5709 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5710 const char *pdata,
5711 int total_data,
5712 files_struct *fsp,
5713 const struct smb_filename *smb_fname)
5715 struct ea_list *ea_list = NULL;
5716 TALLOC_CTX *ctx = NULL;
5717 NTSTATUS status = NT_STATUS_OK;
5719 if (total_data < 10) {
5721 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5722 length. They seem to have no effect. Bug #3212. JRA */
5724 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5725 /* We're done. We only get EA info in this call. */
5726 return NT_STATUS_OK;
5729 return NT_STATUS_INVALID_PARAMETER;
5732 if (IVAL(pdata,0) > total_data) {
5733 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5734 IVAL(pdata,0), (unsigned int)total_data));
5735 return NT_STATUS_INVALID_PARAMETER;
5738 ctx = talloc_tos();
5739 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5740 if (!ea_list) {
5741 return NT_STATUS_INVALID_PARAMETER;
5744 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5745 return NT_STATUS_ACCESS_DENIED;
5748 status = set_ea(conn, fsp, smb_fname, ea_list);
5750 return status;
5753 /****************************************************************************
5754 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5755 ****************************************************************************/
5757 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5758 const char *pdata,
5759 int total_data,
5760 files_struct *fsp)
5762 struct ea_list *ea_list = NULL;
5763 NTSTATUS status;
5765 if (!fsp) {
5766 return NT_STATUS_INVALID_HANDLE;
5769 if (!lp_ea_support(SNUM(conn))) {
5770 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5771 "EA's not supported.\n",
5772 (unsigned int)total_data));
5773 return NT_STATUS_EAS_NOT_SUPPORTED;
5776 if (total_data < 10) {
5777 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5778 "too small.\n",
5779 (unsigned int)total_data));
5780 return NT_STATUS_INVALID_PARAMETER;
5783 ea_list = read_nttrans_ea_list(talloc_tos(),
5784 pdata,
5785 total_data);
5787 if (!ea_list) {
5788 return NT_STATUS_INVALID_PARAMETER;
5791 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5792 return NT_STATUS_ACCESS_DENIED;
5795 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5797 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5798 smb_fname_str_dbg(fsp->fsp_name),
5799 nt_errstr(status) ));
5801 return status;
5805 /****************************************************************************
5806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5807 ****************************************************************************/
5809 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5810 const char *pdata,
5811 int total_data,
5812 files_struct *fsp,
5813 struct smb_filename *smb_fname)
5815 NTSTATUS status = NT_STATUS_OK;
5816 bool delete_on_close;
5817 uint32 dosmode = 0;
5819 if (total_data < 1) {
5820 return NT_STATUS_INVALID_PARAMETER;
5823 if (fsp == NULL) {
5824 return NT_STATUS_INVALID_HANDLE;
5827 delete_on_close = (CVAL(pdata,0) ? True : False);
5828 dosmode = dos_mode(conn, smb_fname);
5830 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5831 "delete_on_close = %u\n",
5832 smb_fname_str_dbg(smb_fname),
5833 (unsigned int)dosmode,
5834 (unsigned int)delete_on_close ));
5836 if (delete_on_close) {
5837 status = can_set_delete_on_close(fsp, dosmode);
5838 if (!NT_STATUS_IS_OK(status)) {
5839 return status;
5843 /* The set is across all open files on this dev/inode pair. */
5844 if (!set_delete_on_close(fsp, delete_on_close,
5845 conn->session_info->security_token,
5846 &conn->session_info->utok)) {
5847 return NT_STATUS_ACCESS_DENIED;
5849 return NT_STATUS_OK;
5852 /****************************************************************************
5853 Deal with SMB_FILE_POSITION_INFORMATION.
5854 ****************************************************************************/
5856 static NTSTATUS smb_file_position_information(connection_struct *conn,
5857 const char *pdata,
5858 int total_data,
5859 files_struct *fsp)
5861 uint64_t position_information;
5863 if (total_data < 8) {
5864 return NT_STATUS_INVALID_PARAMETER;
5867 if (fsp == NULL) {
5868 /* Ignore on pathname based set. */
5869 return NT_STATUS_OK;
5872 position_information = (uint64_t)IVAL(pdata,0);
5873 #ifdef LARGE_SMB_OFF_T
5874 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5875 #else /* LARGE_SMB_OFF_T */
5876 if (IVAL(pdata,4) != 0) {
5877 /* more than 32 bits? */
5878 return NT_STATUS_INVALID_PARAMETER;
5880 #endif /* LARGE_SMB_OFF_T */
5882 DEBUG(10,("smb_file_position_information: Set file position "
5883 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5884 (double)position_information));
5885 fsp->fh->position_information = position_information;
5886 return NT_STATUS_OK;
5889 /****************************************************************************
5890 Deal with SMB_FILE_MODE_INFORMATION.
5891 ****************************************************************************/
5893 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5894 const char *pdata,
5895 int total_data)
5897 uint32 mode;
5899 if (total_data < 4) {
5900 return NT_STATUS_INVALID_PARAMETER;
5902 mode = IVAL(pdata,0);
5903 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5904 return NT_STATUS_INVALID_PARAMETER;
5906 return NT_STATUS_OK;
5909 /****************************************************************************
5910 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5911 ****************************************************************************/
5913 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5914 struct smb_request *req,
5915 const char *pdata,
5916 int total_data,
5917 const struct smb_filename *smb_fname)
5919 char *link_target = NULL;
5920 const char *newname = smb_fname->base_name;
5921 TALLOC_CTX *ctx = talloc_tos();
5923 /* Set a symbolic link. */
5924 /* Don't allow this if follow links is false. */
5926 if (total_data == 0) {
5927 return NT_STATUS_INVALID_PARAMETER;
5930 if (!lp_symlinks(SNUM(conn))) {
5931 return NT_STATUS_ACCESS_DENIED;
5934 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5935 total_data, STR_TERMINATE);
5937 if (!link_target) {
5938 return NT_STATUS_INVALID_PARAMETER;
5941 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5942 newname, link_target ));
5944 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5945 return map_nt_error_from_unix(errno);
5948 return NT_STATUS_OK;
5951 /****************************************************************************
5952 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5953 ****************************************************************************/
5955 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5956 struct smb_request *req,
5957 const char *pdata, int total_data,
5958 struct smb_filename *smb_fname_new)
5960 char *oldname = NULL;
5961 struct smb_filename *smb_fname_old = NULL;
5962 TALLOC_CTX *ctx = talloc_tos();
5963 NTSTATUS status = NT_STATUS_OK;
5965 /* Set a hard link. */
5966 if (total_data == 0) {
5967 return NT_STATUS_INVALID_PARAMETER;
5970 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5971 total_data, STR_TERMINATE, &status);
5972 if (!NT_STATUS_IS_OK(status)) {
5973 return status;
5976 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5977 smb_fname_str_dbg(smb_fname_new), oldname));
5979 status = filename_convert(ctx,
5980 conn,
5981 req->flags2 & FLAGS2_DFS_PATHNAMES,
5982 oldname,
5984 NULL,
5985 &smb_fname_old);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 return status;
5990 return hardlink_internals(ctx, conn, req, false,
5991 smb_fname_old, smb_fname_new);
5994 /****************************************************************************
5995 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5996 ****************************************************************************/
5998 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5999 struct smb_request *req,
6000 const char *pdata,
6001 int total_data,
6002 files_struct *fsp,
6003 struct smb_filename *smb_fname_src)
6005 bool overwrite;
6006 uint32_t len;
6007 char *newname = NULL;
6008 struct smb_filename *smb_fname_dst = NULL;
6009 NTSTATUS status = NT_STATUS_OK;
6010 TALLOC_CTX *ctx = talloc_tos();
6012 if (!fsp) {
6013 return NT_STATUS_INVALID_HANDLE;
6016 if (total_data < 20) {
6017 return NT_STATUS_INVALID_PARAMETER;
6020 overwrite = (CVAL(pdata,0) ? True : False);
6021 len = IVAL(pdata,16);
6023 if (len > (total_data - 20) || (len == 0)) {
6024 return NT_STATUS_INVALID_PARAMETER;
6027 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6028 &pdata[20], len, STR_TERMINATE,
6029 &status);
6030 if (!NT_STATUS_IS_OK(status)) {
6031 return status;
6034 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6035 newname));
6037 status = filename_convert(ctx,
6038 conn,
6039 req->flags2 & FLAGS2_DFS_PATHNAMES,
6040 newname,
6041 UCF_SAVE_LCOMP,
6042 NULL,
6043 &smb_fname_dst);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 return status;
6048 if (fsp->base_fsp) {
6049 /* newname must be a stream name. */
6050 if (newname[0] != ':') {
6051 return NT_STATUS_NOT_SUPPORTED;
6054 /* Create an smb_fname to call rename_internals_fsp() with. */
6055 status = create_synthetic_smb_fname(talloc_tos(),
6056 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6057 &smb_fname_dst);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 goto out;
6063 * Set the original last component, since
6064 * rename_internals_fsp() requires it.
6066 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6067 newname);
6068 if (smb_fname_dst->original_lcomp == NULL) {
6069 status = NT_STATUS_NO_MEMORY;
6070 goto out;
6075 DEBUG(10,("smb2_file_rename_information: "
6076 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6077 fsp->fnum, fsp_str_dbg(fsp),
6078 smb_fname_str_dbg(smb_fname_dst)));
6079 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6080 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6081 overwrite);
6083 out:
6084 TALLOC_FREE(smb_fname_dst);
6085 return status;
6088 static NTSTATUS smb_file_link_information(connection_struct *conn,
6089 struct smb_request *req,
6090 const char *pdata,
6091 int total_data,
6092 files_struct *fsp,
6093 struct smb_filename *smb_fname_src)
6095 bool overwrite;
6096 uint32_t len;
6097 char *newname = NULL;
6098 struct smb_filename *smb_fname_dst = NULL;
6099 NTSTATUS status = NT_STATUS_OK;
6100 TALLOC_CTX *ctx = talloc_tos();
6102 if (!fsp) {
6103 return NT_STATUS_INVALID_HANDLE;
6106 if (total_data < 20) {
6107 return NT_STATUS_INVALID_PARAMETER;
6110 overwrite = (CVAL(pdata,0) ? true : false);
6111 len = IVAL(pdata,16);
6113 if (len > (total_data - 20) || (len == 0)) {
6114 return NT_STATUS_INVALID_PARAMETER;
6117 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6118 &pdata[20], len, STR_TERMINATE,
6119 &status);
6120 if (!NT_STATUS_IS_OK(status)) {
6121 return status;
6124 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6125 newname));
6127 status = filename_convert(ctx,
6128 conn,
6129 req->flags2 & FLAGS2_DFS_PATHNAMES,
6130 newname,
6131 UCF_SAVE_LCOMP,
6132 NULL,
6133 &smb_fname_dst);
6134 if (!NT_STATUS_IS_OK(status)) {
6135 return status;
6138 if (fsp->base_fsp) {
6139 /* No stream names. */
6140 return NT_STATUS_NOT_SUPPORTED;
6143 DEBUG(10,("smb_file_link_information: "
6144 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6145 fsp->fnum, fsp_str_dbg(fsp),
6146 smb_fname_str_dbg(smb_fname_dst)));
6147 status = hardlink_internals(ctx,
6148 conn,
6149 req,
6150 overwrite,
6151 fsp->fsp_name,
6152 smb_fname_dst);
6154 TALLOC_FREE(smb_fname_dst);
6155 return status;
6158 /****************************************************************************
6159 Deal with SMB_FILE_RENAME_INFORMATION.
6160 ****************************************************************************/
6162 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6163 struct smb_request *req,
6164 const char *pdata,
6165 int total_data,
6166 files_struct *fsp,
6167 struct smb_filename *smb_fname_src)
6169 bool overwrite;
6170 uint32 root_fid;
6171 uint32 len;
6172 char *newname = NULL;
6173 struct smb_filename *smb_fname_dst = NULL;
6174 bool dest_has_wcard = False;
6175 NTSTATUS status = NT_STATUS_OK;
6176 char *p;
6177 TALLOC_CTX *ctx = talloc_tos();
6179 if (total_data < 13) {
6180 return NT_STATUS_INVALID_PARAMETER;
6183 overwrite = (CVAL(pdata,0) ? True : False);
6184 root_fid = IVAL(pdata,4);
6185 len = IVAL(pdata,8);
6187 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6188 return NT_STATUS_INVALID_PARAMETER;
6191 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6192 len, 0, &status,
6193 &dest_has_wcard);
6194 if (!NT_STATUS_IS_OK(status)) {
6195 return status;
6198 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6199 newname));
6201 status = resolve_dfspath_wcard(ctx, conn,
6202 req->flags2 & FLAGS2_DFS_PATHNAMES,
6203 newname,
6204 true,
6205 &newname,
6206 &dest_has_wcard);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 return status;
6211 /* Check the new name has no '/' characters. */
6212 if (strchr_m(newname, '/')) {
6213 return NT_STATUS_NOT_SUPPORTED;
6216 if (fsp && fsp->base_fsp) {
6217 /* newname must be a stream name. */
6218 if (newname[0] != ':') {
6219 return NT_STATUS_NOT_SUPPORTED;
6222 /* Create an smb_fname to call rename_internals_fsp() with. */
6223 status = create_synthetic_smb_fname(talloc_tos(),
6224 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6225 &smb_fname_dst);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 goto out;
6231 * Set the original last component, since
6232 * rename_internals_fsp() requires it.
6234 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6235 newname);
6236 if (smb_fname_dst->original_lcomp == NULL) {
6237 status = NT_STATUS_NO_MEMORY;
6238 goto out;
6241 } else {
6243 * Build up an smb_fname_dst based on the filename passed in.
6244 * We basically just strip off the last component, and put on
6245 * the newname instead.
6247 char *base_name = NULL;
6249 /* newname must *not* be a stream name. */
6250 if (newname[0] == ':') {
6251 return NT_STATUS_NOT_SUPPORTED;
6255 * Strip off the last component (filename) of the path passed
6256 * in.
6258 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6259 if (!base_name) {
6260 return NT_STATUS_NO_MEMORY;
6262 p = strrchr_m(base_name, '/');
6263 if (p) {
6264 p[1] = '\0';
6265 } else {
6266 base_name = talloc_strdup(ctx, "");
6267 if (!base_name) {
6268 return NT_STATUS_NO_MEMORY;
6271 /* Append the new name. */
6272 base_name = talloc_asprintf_append(base_name,
6273 "%s",
6274 newname);
6275 if (!base_name) {
6276 return NT_STATUS_NO_MEMORY;
6279 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6280 (UCF_SAVE_LCOMP |
6281 (dest_has_wcard ?
6282 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6283 0)));
6285 /* If an error we expect this to be
6286 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6288 if (!NT_STATUS_IS_OK(status)) {
6289 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6290 status)) {
6291 goto out;
6293 /* Create an smb_fname to call rename_internals_fsp() */
6294 status = create_synthetic_smb_fname(ctx,
6295 base_name, NULL,
6296 NULL,
6297 &smb_fname_dst);
6298 if (!NT_STATUS_IS_OK(status)) {
6299 goto out;
6304 if (fsp) {
6305 DEBUG(10,("smb_file_rename_information: "
6306 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6307 fsp->fnum, fsp_str_dbg(fsp),
6308 smb_fname_str_dbg(smb_fname_dst)));
6309 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6310 overwrite);
6311 } else {
6312 DEBUG(10,("smb_file_rename_information: "
6313 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6314 smb_fname_str_dbg(smb_fname_src),
6315 smb_fname_str_dbg(smb_fname_dst)));
6316 status = rename_internals(ctx, conn, req, smb_fname_src,
6317 smb_fname_dst, 0, overwrite, false,
6318 dest_has_wcard,
6319 FILE_WRITE_ATTRIBUTES);
6321 out:
6322 TALLOC_FREE(smb_fname_dst);
6323 return status;
6326 /****************************************************************************
6327 Deal with SMB_SET_POSIX_ACL.
6328 ****************************************************************************/
6330 #if defined(HAVE_POSIX_ACLS)
6331 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6332 const char *pdata,
6333 int total_data,
6334 files_struct *fsp,
6335 const struct smb_filename *smb_fname)
6337 uint16 posix_acl_version;
6338 uint16 num_file_acls;
6339 uint16 num_def_acls;
6340 bool valid_file_acls = True;
6341 bool valid_def_acls = True;
6343 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6344 return NT_STATUS_INVALID_PARAMETER;
6346 posix_acl_version = SVAL(pdata,0);
6347 num_file_acls = SVAL(pdata,2);
6348 num_def_acls = SVAL(pdata,4);
6350 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6351 valid_file_acls = False;
6352 num_file_acls = 0;
6355 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6356 valid_def_acls = False;
6357 num_def_acls = 0;
6360 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6361 return NT_STATUS_INVALID_PARAMETER;
6364 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6365 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6366 return NT_STATUS_INVALID_PARAMETER;
6369 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6370 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6371 (unsigned int)num_file_acls,
6372 (unsigned int)num_def_acls));
6374 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6375 smb_fname->base_name, num_file_acls,
6376 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6377 return map_nt_error_from_unix(errno);
6380 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6381 smb_fname->base_name, &smb_fname->st, num_def_acls,
6382 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6383 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6384 return map_nt_error_from_unix(errno);
6386 return NT_STATUS_OK;
6388 #endif
6390 /****************************************************************************
6391 Deal with SMB_SET_POSIX_LOCK.
6392 ****************************************************************************/
6394 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6395 struct smb_request *req,
6396 const char *pdata,
6397 int total_data,
6398 files_struct *fsp)
6400 uint64_t count;
6401 uint64_t offset;
6402 uint64_t smblctx;
6403 bool blocking_lock = False;
6404 enum brl_type lock_type;
6406 NTSTATUS status = NT_STATUS_OK;
6408 if (fsp == NULL || fsp->fh->fd == -1) {
6409 return NT_STATUS_INVALID_HANDLE;
6412 if (total_data != POSIX_LOCK_DATA_SIZE) {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6417 case POSIX_LOCK_TYPE_READ:
6418 lock_type = READ_LOCK;
6419 break;
6420 case POSIX_LOCK_TYPE_WRITE:
6421 /* Return the right POSIX-mappable error code for files opened read-only. */
6422 if (!fsp->can_write) {
6423 return NT_STATUS_INVALID_HANDLE;
6425 lock_type = WRITE_LOCK;
6426 break;
6427 case POSIX_LOCK_TYPE_UNLOCK:
6428 lock_type = UNLOCK_LOCK;
6429 break;
6430 default:
6431 return NT_STATUS_INVALID_PARAMETER;
6434 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6435 blocking_lock = False;
6436 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6437 blocking_lock = True;
6438 } else {
6439 return NT_STATUS_INVALID_PARAMETER;
6442 if (!lp_blocking_locks(SNUM(conn))) {
6443 blocking_lock = False;
6446 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6447 #if defined(HAVE_LONGLONG)
6448 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6449 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6450 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6451 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6452 #else /* HAVE_LONGLONG */
6453 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6454 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6455 #endif /* HAVE_LONGLONG */
6457 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6458 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6459 fsp_str_dbg(fsp),
6460 (unsigned int)lock_type,
6461 (unsigned long long)smblctx,
6462 (double)count,
6463 (double)offset ));
6465 if (lock_type == UNLOCK_LOCK) {
6466 status = do_unlock(req->sconn->msg_ctx,
6467 fsp,
6468 smblctx,
6469 count,
6470 offset,
6471 POSIX_LOCK);
6472 } else {
6473 uint64_t block_smblctx;
6475 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6476 fsp,
6477 smblctx,
6478 count,
6479 offset,
6480 lock_type,
6481 POSIX_LOCK,
6482 blocking_lock,
6483 &status,
6484 &block_smblctx,
6485 NULL);
6487 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6489 * A blocking lock was requested. Package up
6490 * this smb into a queued request and push it
6491 * onto the blocking lock queue.
6493 if(push_blocking_lock_request(br_lck,
6494 req,
6495 fsp,
6496 -1, /* infinite timeout. */
6498 smblctx,
6499 lock_type,
6500 POSIX_LOCK,
6501 offset,
6502 count,
6503 block_smblctx)) {
6504 TALLOC_FREE(br_lck);
6505 return status;
6508 TALLOC_FREE(br_lck);
6511 return status;
6514 /****************************************************************************
6515 Deal with SMB_SET_FILE_BASIC_INFO.
6516 ****************************************************************************/
6518 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6519 const char *pdata,
6520 int total_data,
6521 files_struct *fsp,
6522 const struct smb_filename *smb_fname)
6524 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6525 struct smb_file_time ft;
6526 uint32 dosmode = 0;
6527 NTSTATUS status = NT_STATUS_OK;
6529 ZERO_STRUCT(ft);
6531 if (total_data < 36) {
6532 return NT_STATUS_INVALID_PARAMETER;
6535 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6536 return NT_STATUS_ACCESS_DENIED;
6539 /* Set the attributes */
6540 dosmode = IVAL(pdata,32);
6541 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6542 if (!NT_STATUS_IS_OK(status)) {
6543 return status;
6546 /* create time */
6547 ft.create_time = interpret_long_date(pdata);
6549 /* access time */
6550 ft.atime = interpret_long_date(pdata+8);
6552 /* write time. */
6553 ft.mtime = interpret_long_date(pdata+16);
6555 /* change time. */
6556 ft.ctime = interpret_long_date(pdata+24);
6558 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6559 smb_fname_str_dbg(smb_fname)));
6561 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6562 true);
6565 /****************************************************************************
6566 Deal with SMB_INFO_STANDARD.
6567 ****************************************************************************/
6569 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6570 const char *pdata,
6571 int total_data,
6572 files_struct *fsp,
6573 const struct smb_filename *smb_fname)
6575 struct smb_file_time ft;
6577 ZERO_STRUCT(ft);
6579 if (total_data < 12) {
6580 return NT_STATUS_INVALID_PARAMETER;
6583 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6584 return NT_STATUS_ACCESS_DENIED;
6587 /* create time */
6588 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6589 /* access time */
6590 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6591 /* write time */
6592 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6594 DEBUG(10,("smb_set_info_standard: file %s\n",
6595 smb_fname_str_dbg(smb_fname)));
6597 return smb_set_file_time(conn,
6598 fsp,
6599 smb_fname,
6600 &ft,
6601 true);
6604 /****************************************************************************
6605 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6606 ****************************************************************************/
6608 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6609 struct smb_request *req,
6610 const char *pdata,
6611 int total_data,
6612 files_struct *fsp,
6613 struct smb_filename *smb_fname)
6615 uint64_t allocation_size = 0;
6616 NTSTATUS status = NT_STATUS_OK;
6617 files_struct *new_fsp = NULL;
6619 if (!VALID_STAT(smb_fname->st)) {
6620 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6623 if (total_data < 8) {
6624 return NT_STATUS_INVALID_PARAMETER;
6627 allocation_size = (uint64_t)IVAL(pdata,0);
6628 #ifdef LARGE_SMB_OFF_T
6629 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6630 #else /* LARGE_SMB_OFF_T */
6631 if (IVAL(pdata,4) != 0) {
6632 /* more than 32 bits? */
6633 return NT_STATUS_INVALID_PARAMETER;
6635 #endif /* LARGE_SMB_OFF_T */
6637 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6638 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6639 (double)allocation_size));
6641 if (allocation_size) {
6642 allocation_size = smb_roundup(conn, allocation_size);
6645 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6646 return NT_STATUS_ACCESS_DENIED;
6649 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6650 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6651 (double)allocation_size));
6653 if (fsp && fsp->fh->fd != -1) {
6654 /* Open file handle. */
6655 /* Only change if needed. */
6656 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6657 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6658 return map_nt_error_from_unix(errno);
6661 /* But always update the time. */
6663 * This is equivalent to a write. Ensure it's seen immediately
6664 * if there are no pending writes.
6666 trigger_write_time_update_immediate(fsp);
6667 return NT_STATUS_OK;
6670 /* Pathname or stat or directory file. */
6671 status = SMB_VFS_CREATE_FILE(
6672 conn, /* conn */
6673 req, /* req */
6674 0, /* root_dir_fid */
6675 smb_fname, /* fname */
6676 FILE_WRITE_DATA, /* access_mask */
6677 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6678 FILE_SHARE_DELETE),
6679 FILE_OPEN, /* create_disposition*/
6680 0, /* create_options */
6681 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6682 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6683 0, /* allocation_size */
6684 0, /* private_flags */
6685 NULL, /* sd */
6686 NULL, /* ea_list */
6687 &new_fsp, /* result */
6688 NULL); /* pinfo */
6690 if (!NT_STATUS_IS_OK(status)) {
6691 /* NB. We check for open_was_deferred in the caller. */
6692 return status;
6695 /* Only change if needed. */
6696 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6697 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6698 status = map_nt_error_from_unix(errno);
6699 close_file(req, new_fsp, NORMAL_CLOSE);
6700 return status;
6704 /* Changing the allocation size should set the last mod time. */
6706 * This is equivalent to a write. Ensure it's seen immediately
6707 * if there are no pending writes.
6709 trigger_write_time_update_immediate(new_fsp);
6711 close_file(req, new_fsp, NORMAL_CLOSE);
6712 return NT_STATUS_OK;
6715 /****************************************************************************
6716 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6717 ****************************************************************************/
6719 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6720 struct smb_request *req,
6721 const char *pdata,
6722 int total_data,
6723 files_struct *fsp,
6724 const struct smb_filename *smb_fname,
6725 bool fail_after_createfile)
6727 SMB_OFF_T size;
6729 if (total_data < 8) {
6730 return NT_STATUS_INVALID_PARAMETER;
6733 size = IVAL(pdata,0);
6734 #ifdef LARGE_SMB_OFF_T
6735 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6736 #else /* LARGE_SMB_OFF_T */
6737 if (IVAL(pdata,4) != 0) {
6738 /* more than 32 bits? */
6739 return NT_STATUS_INVALID_PARAMETER;
6741 #endif /* LARGE_SMB_OFF_T */
6742 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6743 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6744 (double)size));
6746 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6747 return NT_STATUS_ACCESS_DENIED;
6750 return smb_set_file_size(conn, req,
6751 fsp,
6752 smb_fname,
6753 &smb_fname->st,
6754 size,
6755 fail_after_createfile);
6758 /****************************************************************************
6759 Allow a UNIX info mknod.
6760 ****************************************************************************/
6762 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6763 const char *pdata,
6764 int total_data,
6765 const struct smb_filename *smb_fname)
6767 uint32 file_type = IVAL(pdata,56);
6768 #if defined(HAVE_MAKEDEV)
6769 uint32 dev_major = IVAL(pdata,60);
6770 uint32 dev_minor = IVAL(pdata,68);
6771 #endif
6772 SMB_DEV_T dev = (SMB_DEV_T)0;
6773 uint32 raw_unixmode = IVAL(pdata,84);
6774 NTSTATUS status;
6775 mode_t unixmode;
6777 if (total_data < 100) {
6778 return NT_STATUS_INVALID_PARAMETER;
6781 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6782 PERM_NEW_FILE, &unixmode);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 return status;
6787 #if defined(HAVE_MAKEDEV)
6788 dev = makedev(dev_major, dev_minor);
6789 #endif
6791 switch (file_type) {
6792 #if defined(S_IFIFO)
6793 case UNIX_TYPE_FIFO:
6794 unixmode |= S_IFIFO;
6795 break;
6796 #endif
6797 #if defined(S_IFSOCK)
6798 case UNIX_TYPE_SOCKET:
6799 unixmode |= S_IFSOCK;
6800 break;
6801 #endif
6802 #if defined(S_IFCHR)
6803 case UNIX_TYPE_CHARDEV:
6804 unixmode |= S_IFCHR;
6805 break;
6806 #endif
6807 #if defined(S_IFBLK)
6808 case UNIX_TYPE_BLKDEV:
6809 unixmode |= S_IFBLK;
6810 break;
6811 #endif
6812 default:
6813 return NT_STATUS_INVALID_PARAMETER;
6816 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6817 "%.0f mode 0%o for file %s\n", (double)dev,
6818 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6820 /* Ok - do the mknod. */
6821 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6822 return map_nt_error_from_unix(errno);
6825 /* If any of the other "set" calls fail we
6826 * don't want to end up with a half-constructed mknod.
6829 if (lp_inherit_perms(SNUM(conn))) {
6830 char *parent;
6831 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6832 &parent, NULL)) {
6833 return NT_STATUS_NO_MEMORY;
6835 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6836 unixmode);
6837 TALLOC_FREE(parent);
6840 return NT_STATUS_OK;
6843 /****************************************************************************
6844 Deal with SMB_SET_FILE_UNIX_BASIC.
6845 ****************************************************************************/
6847 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6848 struct smb_request *req,
6849 const char *pdata,
6850 int total_data,
6851 files_struct *fsp,
6852 const struct smb_filename *smb_fname)
6854 struct smb_file_time ft;
6855 uint32 raw_unixmode;
6856 mode_t unixmode;
6857 SMB_OFF_T size = 0;
6858 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6859 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6860 NTSTATUS status = NT_STATUS_OK;
6861 bool delete_on_fail = False;
6862 enum perm_type ptype;
6863 files_struct *all_fsps = NULL;
6864 bool modify_mtime = true;
6865 struct file_id id;
6866 struct smb_filename *smb_fname_tmp = NULL;
6867 SMB_STRUCT_STAT sbuf;
6869 ZERO_STRUCT(ft);
6871 if (total_data < 100) {
6872 return NT_STATUS_INVALID_PARAMETER;
6875 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6876 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6877 size=IVAL(pdata,0); /* first 8 Bytes are size */
6878 #ifdef LARGE_SMB_OFF_T
6879 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6880 #else /* LARGE_SMB_OFF_T */
6881 if (IVAL(pdata,4) != 0) {
6882 /* more than 32 bits? */
6883 return NT_STATUS_INVALID_PARAMETER;
6885 #endif /* LARGE_SMB_OFF_T */
6888 ft.atime = interpret_long_date(pdata+24); /* access_time */
6889 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6890 set_owner = (uid_t)IVAL(pdata,40);
6891 set_grp = (gid_t)IVAL(pdata,48);
6892 raw_unixmode = IVAL(pdata,84);
6894 if (VALID_STAT(smb_fname->st)) {
6895 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6896 ptype = PERM_EXISTING_DIR;
6897 } else {
6898 ptype = PERM_EXISTING_FILE;
6900 } else {
6901 ptype = PERM_NEW_FILE;
6904 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6905 ptype, &unixmode);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 return status;
6910 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6911 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6912 smb_fname_str_dbg(smb_fname), (double)size,
6913 (unsigned int)set_owner, (unsigned int)set_grp,
6914 (int)raw_unixmode));
6916 sbuf = smb_fname->st;
6918 if (!VALID_STAT(sbuf)) {
6920 * The only valid use of this is to create character and block
6921 * devices, and named pipes. This is deprecated (IMHO) and
6922 * a new info level should be used for mknod. JRA.
6925 status = smb_unix_mknod(conn,
6926 pdata,
6927 total_data,
6928 smb_fname);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 return status;
6933 status = copy_smb_filename(talloc_tos(), smb_fname,
6934 &smb_fname_tmp);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 return status;
6939 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6940 status = map_nt_error_from_unix(errno);
6941 TALLOC_FREE(smb_fname_tmp);
6942 SMB_VFS_UNLINK(conn, smb_fname);
6943 return status;
6946 sbuf = smb_fname_tmp->st;
6947 smb_fname = smb_fname_tmp;
6949 /* Ensure we don't try and change anything else. */
6950 raw_unixmode = SMB_MODE_NO_CHANGE;
6951 size = get_file_size_stat(&sbuf);
6952 ft.atime = sbuf.st_ex_atime;
6953 ft.mtime = sbuf.st_ex_mtime;
6955 * We continue here as we might want to change the
6956 * owner uid/gid.
6958 delete_on_fail = True;
6961 #if 1
6962 /* Horrible backwards compatibility hack as an old server bug
6963 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6964 * */
6966 if (!size) {
6967 size = get_file_size_stat(&sbuf);
6969 #endif
6972 * Deal with the UNIX specific mode set.
6975 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6976 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6977 "setting mode 0%o for file %s\n",
6978 (unsigned int)unixmode,
6979 smb_fname_str_dbg(smb_fname)));
6980 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6981 return map_nt_error_from_unix(errno);
6986 * Deal with the UNIX specific uid set.
6989 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6990 (sbuf.st_ex_uid != set_owner)) {
6991 int ret;
6993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6994 "changing owner %u for path %s\n",
6995 (unsigned int)set_owner,
6996 smb_fname_str_dbg(smb_fname)));
6998 if (S_ISLNK(sbuf.st_ex_mode)) {
6999 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7000 set_owner, (gid_t)-1);
7001 } else {
7002 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7003 set_owner, (gid_t)-1);
7006 if (ret != 0) {
7007 status = map_nt_error_from_unix(errno);
7008 if (delete_on_fail) {
7009 SMB_VFS_UNLINK(conn, smb_fname);
7011 return status;
7016 * Deal with the UNIX specific gid set.
7019 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7020 (sbuf.st_ex_gid != set_grp)) {
7021 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7022 "changing group %u for file %s\n",
7023 (unsigned int)set_owner,
7024 smb_fname_str_dbg(smb_fname)));
7025 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7026 set_grp) != 0) {
7027 status = map_nt_error_from_unix(errno);
7028 if (delete_on_fail) {
7029 SMB_VFS_UNLINK(conn, smb_fname);
7031 return status;
7035 /* Deal with any size changes. */
7037 status = smb_set_file_size(conn, req,
7038 fsp,
7039 smb_fname,
7040 &sbuf,
7041 size,
7042 false);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 return status;
7047 /* Deal with any time changes. */
7048 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7049 /* No change, don't cancel anything. */
7050 return status;
7053 id = vfs_file_id_from_sbuf(conn, &sbuf);
7054 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7055 all_fsps = file_find_di_next(all_fsps)) {
7057 * We're setting the time explicitly for UNIX.
7058 * Cancel any pending changes over all handles.
7060 all_fsps->update_write_time_on_close = false;
7061 TALLOC_FREE(all_fsps->update_write_time_event);
7065 * Override the "setting_write_time"
7066 * parameter here as it almost does what
7067 * we need. Just remember if we modified
7068 * mtime and send the notify ourselves.
7070 if (null_timespec(ft.mtime)) {
7071 modify_mtime = false;
7074 status = smb_set_file_time(conn,
7075 fsp,
7076 smb_fname,
7077 &ft,
7078 false);
7079 if (modify_mtime) {
7080 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7081 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7083 return status;
7086 /****************************************************************************
7087 Deal with SMB_SET_FILE_UNIX_INFO2.
7088 ****************************************************************************/
7090 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7091 struct smb_request *req,
7092 const char *pdata,
7093 int total_data,
7094 files_struct *fsp,
7095 const struct smb_filename *smb_fname)
7097 NTSTATUS status;
7098 uint32 smb_fflags;
7099 uint32 smb_fmask;
7101 if (total_data < 116) {
7102 return NT_STATUS_INVALID_PARAMETER;
7105 /* Start by setting all the fields that are common between UNIX_BASIC
7106 * and UNIX_INFO2.
7108 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7109 fsp, smb_fname);
7110 if (!NT_STATUS_IS_OK(status)) {
7111 return status;
7114 smb_fflags = IVAL(pdata, 108);
7115 smb_fmask = IVAL(pdata, 112);
7117 /* NB: We should only attempt to alter the file flags if the client
7118 * sends a non-zero mask.
7120 if (smb_fmask != 0) {
7121 int stat_fflags = 0;
7123 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7124 smb_fmask, &stat_fflags)) {
7125 /* Client asked to alter a flag we don't understand. */
7126 return NT_STATUS_INVALID_PARAMETER;
7129 if (fsp && fsp->fh->fd != -1) {
7130 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7131 return NT_STATUS_NOT_SUPPORTED;
7132 } else {
7133 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7134 stat_fflags) != 0) {
7135 return map_nt_error_from_unix(errno);
7140 /* XXX: need to add support for changing the create_time here. You
7141 * can do this for paths on Darwin with setattrlist(2). The right way
7142 * to hook this up is probably by extending the VFS utimes interface.
7145 return NT_STATUS_OK;
7148 /****************************************************************************
7149 Create a directory with POSIX semantics.
7150 ****************************************************************************/
7152 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7153 struct smb_request *req,
7154 char **ppdata,
7155 int total_data,
7156 struct smb_filename *smb_fname,
7157 int *pdata_return_size)
7159 NTSTATUS status = NT_STATUS_OK;
7160 uint32 raw_unixmode = 0;
7161 uint32 mod_unixmode = 0;
7162 mode_t unixmode = (mode_t)0;
7163 files_struct *fsp = NULL;
7164 uint16 info_level_return = 0;
7165 int info;
7166 char *pdata = *ppdata;
7168 if (total_data < 18) {
7169 return NT_STATUS_INVALID_PARAMETER;
7172 raw_unixmode = IVAL(pdata,8);
7173 /* Next 4 bytes are not yet defined. */
7175 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7176 PERM_NEW_DIR, &unixmode);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 return status;
7181 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7183 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7184 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7186 status = SMB_VFS_CREATE_FILE(
7187 conn, /* conn */
7188 req, /* req */
7189 0, /* root_dir_fid */
7190 smb_fname, /* fname */
7191 FILE_READ_ATTRIBUTES, /* access_mask */
7192 FILE_SHARE_NONE, /* share_access */
7193 FILE_CREATE, /* create_disposition*/
7194 FILE_DIRECTORY_FILE, /* create_options */
7195 mod_unixmode, /* file_attributes */
7196 0, /* oplock_request */
7197 0, /* allocation_size */
7198 0, /* private_flags */
7199 NULL, /* sd */
7200 NULL, /* ea_list */
7201 &fsp, /* result */
7202 &info); /* pinfo */
7204 if (NT_STATUS_IS_OK(status)) {
7205 close_file(req, fsp, NORMAL_CLOSE);
7208 info_level_return = SVAL(pdata,16);
7210 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7211 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7212 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7213 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7214 } else {
7215 *pdata_return_size = 12;
7218 /* Realloc the data size */
7219 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7220 if (*ppdata == NULL) {
7221 *pdata_return_size = 0;
7222 return NT_STATUS_NO_MEMORY;
7224 pdata = *ppdata;
7226 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7227 SSVAL(pdata,2,0); /* No fnum. */
7228 SIVAL(pdata,4,info); /* Was directory created. */
7230 switch (info_level_return) {
7231 case SMB_QUERY_FILE_UNIX_BASIC:
7232 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7233 SSVAL(pdata,10,0); /* Padding. */
7234 store_file_unix_basic(conn, pdata + 12, fsp,
7235 &smb_fname->st);
7236 break;
7237 case SMB_QUERY_FILE_UNIX_INFO2:
7238 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7239 SSVAL(pdata,10,0); /* Padding. */
7240 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7241 &smb_fname->st);
7242 break;
7243 default:
7244 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7245 SSVAL(pdata,10,0); /* Padding. */
7246 break;
7249 return status;
7252 /****************************************************************************
7253 Open/Create a file with POSIX semantics.
7254 ****************************************************************************/
7256 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7257 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7259 static NTSTATUS smb_posix_open(connection_struct *conn,
7260 struct smb_request *req,
7261 char **ppdata,
7262 int total_data,
7263 struct smb_filename *smb_fname,
7264 int *pdata_return_size)
7266 bool extended_oplock_granted = False;
7267 char *pdata = *ppdata;
7268 uint32 flags = 0;
7269 uint32 wire_open_mode = 0;
7270 uint32 raw_unixmode = 0;
7271 uint32 mod_unixmode = 0;
7272 uint32 create_disp = 0;
7273 uint32 access_mask = 0;
7274 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7275 NTSTATUS status = NT_STATUS_OK;
7276 mode_t unixmode = (mode_t)0;
7277 files_struct *fsp = NULL;
7278 int oplock_request = 0;
7279 int info = 0;
7280 uint16 info_level_return = 0;
7282 if (total_data < 18) {
7283 return NT_STATUS_INVALID_PARAMETER;
7286 flags = IVAL(pdata,0);
7287 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7288 if (oplock_request) {
7289 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7292 wire_open_mode = IVAL(pdata,4);
7294 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7295 return smb_posix_mkdir(conn, req,
7296 ppdata,
7297 total_data,
7298 smb_fname,
7299 pdata_return_size);
7302 switch (wire_open_mode & SMB_ACCMODE) {
7303 case SMB_O_RDONLY:
7304 access_mask = SMB_O_RDONLY_MAPPING;
7305 break;
7306 case SMB_O_WRONLY:
7307 access_mask = SMB_O_WRONLY_MAPPING;
7308 break;
7309 case SMB_O_RDWR:
7310 access_mask = (SMB_O_RDONLY_MAPPING|
7311 SMB_O_WRONLY_MAPPING);
7312 break;
7313 default:
7314 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7315 (unsigned int)wire_open_mode ));
7316 return NT_STATUS_INVALID_PARAMETER;
7319 wire_open_mode &= ~SMB_ACCMODE;
7321 /* First take care of O_CREAT|O_EXCL interactions. */
7322 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7323 case (SMB_O_CREAT | SMB_O_EXCL):
7324 /* File exists fail. File not exist create. */
7325 create_disp = FILE_CREATE;
7326 break;
7327 case SMB_O_CREAT:
7328 /* File exists open. File not exist create. */
7329 create_disp = FILE_OPEN_IF;
7330 break;
7331 case 0:
7332 /* File exists open. File not exist fail. */
7333 create_disp = FILE_OPEN;
7334 break;
7335 case SMB_O_EXCL:
7336 /* O_EXCL on its own without O_CREAT is undefined. */
7337 default:
7338 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7339 (unsigned int)wire_open_mode ));
7340 return NT_STATUS_INVALID_PARAMETER;
7343 /* Next factor in the effects of O_TRUNC. */
7344 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7346 if (wire_open_mode & SMB_O_TRUNC) {
7347 switch (create_disp) {
7348 case FILE_CREATE:
7349 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7350 /* Leave create_disp alone as
7351 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7353 /* File exists fail. File not exist create. */
7354 break;
7355 case FILE_OPEN_IF:
7356 /* SMB_O_CREAT | SMB_O_TRUNC */
7357 /* File exists overwrite. File not exist create. */
7358 create_disp = FILE_OVERWRITE_IF;
7359 break;
7360 case FILE_OPEN:
7361 /* SMB_O_TRUNC */
7362 /* File exists overwrite. File not exist fail. */
7363 create_disp = FILE_OVERWRITE;
7364 break;
7365 default:
7366 /* Cannot get here. */
7367 smb_panic("smb_posix_open: logic error");
7368 return NT_STATUS_INVALID_PARAMETER;
7372 raw_unixmode = IVAL(pdata,8);
7373 /* Next 4 bytes are not yet defined. */
7375 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7376 (VALID_STAT(smb_fname->st) ?
7377 PERM_EXISTING_FILE : PERM_NEW_FILE),
7378 &unixmode);
7380 if (!NT_STATUS_IS_OK(status)) {
7381 return status;
7384 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7386 if (wire_open_mode & SMB_O_SYNC) {
7387 create_options |= FILE_WRITE_THROUGH;
7389 if (wire_open_mode & SMB_O_APPEND) {
7390 access_mask |= FILE_APPEND_DATA;
7392 if (wire_open_mode & SMB_O_DIRECT) {
7393 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7396 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7397 VALID_STAT_OF_DIR(smb_fname->st)) {
7398 if (access_mask != SMB_O_RDONLY_MAPPING) {
7399 return NT_STATUS_FILE_IS_A_DIRECTORY;
7401 create_options &= ~FILE_NON_DIRECTORY_FILE;
7402 create_options |= FILE_DIRECTORY_FILE;
7405 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7406 smb_fname_str_dbg(smb_fname),
7407 (unsigned int)wire_open_mode,
7408 (unsigned int)unixmode ));
7410 status = SMB_VFS_CREATE_FILE(
7411 conn, /* conn */
7412 req, /* req */
7413 0, /* root_dir_fid */
7414 smb_fname, /* fname */
7415 access_mask, /* access_mask */
7416 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7417 FILE_SHARE_DELETE),
7418 create_disp, /* create_disposition*/
7419 create_options, /* create_options */
7420 mod_unixmode, /* file_attributes */
7421 oplock_request, /* oplock_request */
7422 0, /* allocation_size */
7423 0, /* private_flags */
7424 NULL, /* sd */
7425 NULL, /* ea_list */
7426 &fsp, /* result */
7427 &info); /* pinfo */
7429 if (!NT_STATUS_IS_OK(status)) {
7430 return status;
7433 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7434 extended_oplock_granted = True;
7437 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7438 extended_oplock_granted = True;
7441 info_level_return = SVAL(pdata,16);
7443 /* Allocate the correct return size. */
7445 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7446 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7447 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7448 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7449 } else {
7450 *pdata_return_size = 12;
7453 /* Realloc the data size */
7454 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7455 if (*ppdata == NULL) {
7456 close_file(req, fsp, ERROR_CLOSE);
7457 *pdata_return_size = 0;
7458 return NT_STATUS_NO_MEMORY;
7460 pdata = *ppdata;
7462 if (extended_oplock_granted) {
7463 if (flags & REQUEST_BATCH_OPLOCK) {
7464 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7465 } else {
7466 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7468 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7469 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7470 } else {
7471 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7474 SSVAL(pdata,2,fsp->fnum);
7475 SIVAL(pdata,4,info); /* Was file created etc. */
7477 switch (info_level_return) {
7478 case SMB_QUERY_FILE_UNIX_BASIC:
7479 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7480 SSVAL(pdata,10,0); /* padding. */
7481 store_file_unix_basic(conn, pdata + 12, fsp,
7482 &smb_fname->st);
7483 break;
7484 case SMB_QUERY_FILE_UNIX_INFO2:
7485 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7486 SSVAL(pdata,10,0); /* padding. */
7487 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7488 &smb_fname->st);
7489 break;
7490 default:
7491 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7492 SSVAL(pdata,10,0); /* padding. */
7493 break;
7495 return NT_STATUS_OK;
7498 /****************************************************************************
7499 Delete a file with POSIX semantics.
7500 ****************************************************************************/
7502 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7503 struct smb_request *req,
7504 const char *pdata,
7505 int total_data,
7506 struct smb_filename *smb_fname)
7508 NTSTATUS status = NT_STATUS_OK;
7509 files_struct *fsp = NULL;
7510 uint16 flags = 0;
7511 char del = 1;
7512 int info = 0;
7513 int create_options = 0;
7514 int i;
7515 struct share_mode_lock *lck = NULL;
7517 if (total_data < 2) {
7518 return NT_STATUS_INVALID_PARAMETER;
7521 flags = SVAL(pdata,0);
7523 if (!VALID_STAT(smb_fname->st)) {
7524 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7527 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7528 !VALID_STAT_OF_DIR(smb_fname->st)) {
7529 return NT_STATUS_NOT_A_DIRECTORY;
7532 DEBUG(10,("smb_posix_unlink: %s %s\n",
7533 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7534 smb_fname_str_dbg(smb_fname)));
7536 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7537 create_options |= FILE_DIRECTORY_FILE;
7540 status = SMB_VFS_CREATE_FILE(
7541 conn, /* conn */
7542 req, /* req */
7543 0, /* root_dir_fid */
7544 smb_fname, /* fname */
7545 DELETE_ACCESS, /* access_mask */
7546 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7547 FILE_SHARE_DELETE),
7548 FILE_OPEN, /* create_disposition*/
7549 create_options, /* create_options */
7550 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7551 0, /* oplock_request */
7552 0, /* allocation_size */
7553 0, /* private_flags */
7554 NULL, /* sd */
7555 NULL, /* ea_list */
7556 &fsp, /* result */
7557 &info); /* pinfo */
7559 if (!NT_STATUS_IS_OK(status)) {
7560 return status;
7564 * Don't lie to client. If we can't really delete due to
7565 * non-POSIX opens return SHARING_VIOLATION.
7568 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7569 NULL);
7570 if (lck == NULL) {
7571 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7572 "lock for file %s\n", fsp_str_dbg(fsp)));
7573 close_file(req, fsp, NORMAL_CLOSE);
7574 return NT_STATUS_INVALID_PARAMETER;
7578 * See if others still have the file open. If this is the case, then
7579 * don't delete. If all opens are POSIX delete we can set the delete
7580 * on close disposition.
7582 for (i=0; i<lck->num_share_modes; i++) {
7583 struct share_mode_entry *e = &lck->share_modes[i];
7584 if (is_valid_share_mode_entry(e)) {
7585 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7586 continue;
7588 /* Fail with sharing violation. */
7589 close_file(req, fsp, NORMAL_CLOSE);
7590 TALLOC_FREE(lck);
7591 return NT_STATUS_SHARING_VIOLATION;
7596 * Set the delete on close.
7598 status = smb_set_file_disposition_info(conn,
7599 &del,
7601 fsp,
7602 smb_fname);
7604 if (!NT_STATUS_IS_OK(status)) {
7605 close_file(req, fsp, NORMAL_CLOSE);
7606 TALLOC_FREE(lck);
7607 return status;
7609 TALLOC_FREE(lck);
7610 return close_file(req, fsp, NORMAL_CLOSE);
7613 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7614 struct smb_request *req,
7615 TALLOC_CTX *mem_ctx,
7616 uint16_t info_level,
7617 files_struct *fsp,
7618 struct smb_filename *smb_fname,
7619 char **ppdata, int total_data,
7620 int *ret_data_size)
7622 char *pdata = *ppdata;
7623 NTSTATUS status = NT_STATUS_OK;
7624 int data_return_size = 0;
7626 *ret_data_size = 0;
7628 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7629 return NT_STATUS_INVALID_LEVEL;
7632 if (!CAN_WRITE(conn)) {
7633 /* Allow POSIX opens. The open path will deny
7634 * any non-readonly opens. */
7635 if (info_level != SMB_POSIX_PATH_OPEN) {
7636 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7640 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7641 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7642 fsp ? fsp->fnum : -1, info_level, total_data));
7644 switch (info_level) {
7646 case SMB_INFO_STANDARD:
7648 status = smb_set_info_standard(conn,
7649 pdata,
7650 total_data,
7651 fsp,
7652 smb_fname);
7653 break;
7656 case SMB_INFO_SET_EA:
7658 status = smb_info_set_ea(conn,
7659 pdata,
7660 total_data,
7661 fsp,
7662 smb_fname);
7663 break;
7666 case SMB_SET_FILE_BASIC_INFO:
7667 case SMB_FILE_BASIC_INFORMATION:
7669 status = smb_set_file_basic_info(conn,
7670 pdata,
7671 total_data,
7672 fsp,
7673 smb_fname);
7674 break;
7677 case SMB_FILE_ALLOCATION_INFORMATION:
7678 case SMB_SET_FILE_ALLOCATION_INFO:
7680 status = smb_set_file_allocation_info(conn, req,
7681 pdata,
7682 total_data,
7683 fsp,
7684 smb_fname);
7685 break;
7688 case SMB_FILE_END_OF_FILE_INFORMATION:
7689 case SMB_SET_FILE_END_OF_FILE_INFO:
7692 * XP/Win7 both fail after the createfile with
7693 * SMB_SET_FILE_END_OF_FILE_INFO but not
7694 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7695 * The level is known here, so pass it down
7696 * appropriately.
7698 bool should_fail =
7699 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7701 status = smb_set_file_end_of_file_info(conn, req,
7702 pdata,
7703 total_data,
7704 fsp,
7705 smb_fname,
7706 should_fail);
7707 break;
7710 case SMB_FILE_DISPOSITION_INFORMATION:
7711 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7713 #if 0
7714 /* JRA - We used to just ignore this on a path ?
7715 * Shouldn't this be invalid level on a pathname
7716 * based call ?
7718 if (tran_call != TRANSACT2_SETFILEINFO) {
7719 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7721 #endif
7722 status = smb_set_file_disposition_info(conn,
7723 pdata,
7724 total_data,
7725 fsp,
7726 smb_fname);
7727 break;
7730 case SMB_FILE_POSITION_INFORMATION:
7732 status = smb_file_position_information(conn,
7733 pdata,
7734 total_data,
7735 fsp);
7736 break;
7739 case SMB_FILE_FULL_EA_INFORMATION:
7741 status = smb_set_file_full_ea_info(conn,
7742 pdata,
7743 total_data,
7744 fsp);
7745 break;
7748 /* From tridge Samba4 :
7749 * MODE_INFORMATION in setfileinfo (I have no
7750 * idea what "mode information" on a file is - it takes a value of 0,
7751 * 2, 4 or 6. What could it be?).
7754 case SMB_FILE_MODE_INFORMATION:
7756 status = smb_file_mode_information(conn,
7757 pdata,
7758 total_data);
7759 break;
7763 * CIFS UNIX extensions.
7766 case SMB_SET_FILE_UNIX_BASIC:
7768 status = smb_set_file_unix_basic(conn, req,
7769 pdata,
7770 total_data,
7771 fsp,
7772 smb_fname);
7773 break;
7776 case SMB_SET_FILE_UNIX_INFO2:
7778 status = smb_set_file_unix_info2(conn, req,
7779 pdata,
7780 total_data,
7781 fsp,
7782 smb_fname);
7783 break;
7786 case SMB_SET_FILE_UNIX_LINK:
7788 if (fsp) {
7789 /* We must have a pathname for this. */
7790 return NT_STATUS_INVALID_LEVEL;
7792 status = smb_set_file_unix_link(conn, req, pdata,
7793 total_data, smb_fname);
7794 break;
7797 case SMB_SET_FILE_UNIX_HLINK:
7799 if (fsp) {
7800 /* We must have a pathname for this. */
7801 return NT_STATUS_INVALID_LEVEL;
7803 status = smb_set_file_unix_hlink(conn, req,
7804 pdata, total_data,
7805 smb_fname);
7806 break;
7809 case SMB_FILE_RENAME_INFORMATION:
7811 status = smb_file_rename_information(conn, req,
7812 pdata, total_data,
7813 fsp, smb_fname);
7814 break;
7817 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7819 /* SMB2 rename information. */
7820 status = smb2_file_rename_information(conn, req,
7821 pdata, total_data,
7822 fsp, smb_fname);
7823 break;
7826 case SMB_FILE_LINK_INFORMATION:
7828 status = smb_file_link_information(conn, req,
7829 pdata, total_data,
7830 fsp, smb_fname);
7831 break;
7834 #if defined(HAVE_POSIX_ACLS)
7835 case SMB_SET_POSIX_ACL:
7837 status = smb_set_posix_acl(conn,
7838 pdata,
7839 total_data,
7840 fsp,
7841 smb_fname);
7842 break;
7844 #endif
7846 case SMB_SET_POSIX_LOCK:
7848 if (!fsp) {
7849 return NT_STATUS_INVALID_LEVEL;
7851 status = smb_set_posix_lock(conn, req,
7852 pdata, total_data, fsp);
7853 break;
7856 case SMB_POSIX_PATH_OPEN:
7858 if (fsp) {
7859 /* We must have a pathname for this. */
7860 return NT_STATUS_INVALID_LEVEL;
7863 status = smb_posix_open(conn, req,
7864 ppdata,
7865 total_data,
7866 smb_fname,
7867 &data_return_size);
7868 break;
7871 case SMB_POSIX_PATH_UNLINK:
7873 if (fsp) {
7874 /* We must have a pathname for this. */
7875 return NT_STATUS_INVALID_LEVEL;
7878 status = smb_posix_unlink(conn, req,
7879 pdata,
7880 total_data,
7881 smb_fname);
7882 break;
7885 default:
7886 return NT_STATUS_INVALID_LEVEL;
7889 if (!NT_STATUS_IS_OK(status)) {
7890 return status;
7893 *ret_data_size = data_return_size;
7894 return NT_STATUS_OK;
7897 /****************************************************************************
7898 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7899 ****************************************************************************/
7901 static void call_trans2setfilepathinfo(connection_struct *conn,
7902 struct smb_request *req,
7903 unsigned int tran_call,
7904 char **pparams, int total_params,
7905 char **ppdata, int total_data,
7906 unsigned int max_data_bytes)
7908 char *params = *pparams;
7909 char *pdata = *ppdata;
7910 uint16 info_level;
7911 struct smb_filename *smb_fname = NULL;
7912 files_struct *fsp = NULL;
7913 NTSTATUS status = NT_STATUS_OK;
7914 int data_return_size = 0;
7916 if (!params) {
7917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7918 return;
7921 if (tran_call == TRANSACT2_SETFILEINFO) {
7922 if (total_params < 4) {
7923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7924 return;
7927 fsp = file_fsp(req, SVAL(params,0));
7928 /* Basic check for non-null fsp. */
7929 if (!check_fsp_open(conn, req, fsp)) {
7930 return;
7932 info_level = SVAL(params,2);
7934 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7935 &smb_fname);
7936 if (!NT_STATUS_IS_OK(status)) {
7937 reply_nterror(req, status);
7938 return;
7941 if(fsp->fh->fd == -1) {
7943 * This is actually a SETFILEINFO on a directory
7944 * handle (returned from an NT SMB). NT5.0 seems
7945 * to do this call. JRA.
7947 if (INFO_LEVEL_IS_UNIX(info_level)) {
7948 /* Always do lstat for UNIX calls. */
7949 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7950 DEBUG(3,("call_trans2setfilepathinfo: "
7951 "SMB_VFS_LSTAT of %s failed "
7952 "(%s)\n",
7953 smb_fname_str_dbg(smb_fname),
7954 strerror(errno)));
7955 reply_nterror(req, map_nt_error_from_unix(errno));
7956 return;
7958 } else {
7959 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7960 DEBUG(3,("call_trans2setfilepathinfo: "
7961 "fileinfo of %s failed (%s)\n",
7962 smb_fname_str_dbg(smb_fname),
7963 strerror(errno)));
7964 reply_nterror(req, map_nt_error_from_unix(errno));
7965 return;
7968 } else if (fsp->print_file) {
7970 * Doing a DELETE_ON_CLOSE should cancel a print job.
7972 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7973 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7975 DEBUG(3,("call_trans2setfilepathinfo: "
7976 "Cancelling print job (%s)\n",
7977 fsp_str_dbg(fsp)));
7979 SSVAL(params,0,0);
7980 send_trans2_replies(conn, req, params, 2,
7981 *ppdata, 0,
7982 max_data_bytes);
7983 return;
7984 } else {
7985 reply_nterror(req,
7986 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7987 return;
7989 } else {
7991 * Original code - this is an open file.
7993 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7994 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7995 "of fnum %d failed (%s)\n", fsp->fnum,
7996 strerror(errno)));
7997 reply_nterror(req, map_nt_error_from_unix(errno));
7998 return;
8001 } else {
8002 char *fname = NULL;
8003 uint32_t ucf_flags = 0;
8005 /* set path info */
8006 if (total_params < 7) {
8007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8008 return;
8011 info_level = SVAL(params,0);
8012 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8013 total_params - 6, STR_TERMINATE,
8014 &status);
8015 if (!NT_STATUS_IS_OK(status)) {
8016 reply_nterror(req, status);
8017 return;
8020 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8021 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8022 info_level == SMB_FILE_RENAME_INFORMATION ||
8023 info_level == SMB_POSIX_PATH_UNLINK) {
8024 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8027 status = filename_convert(req, conn,
8028 req->flags2 & FLAGS2_DFS_PATHNAMES,
8029 fname,
8030 ucf_flags,
8031 NULL,
8032 &smb_fname);
8033 if (!NT_STATUS_IS_OK(status)) {
8034 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8035 reply_botherror(req,
8036 NT_STATUS_PATH_NOT_COVERED,
8037 ERRSRV, ERRbadpath);
8038 return;
8040 reply_nterror(req, status);
8041 return;
8044 if (INFO_LEVEL_IS_UNIX(info_level)) {
8046 * For CIFS UNIX extensions the target name may not exist.
8049 /* Always do lstat for UNIX calls. */
8050 SMB_VFS_LSTAT(conn, smb_fname);
8052 } else if (!VALID_STAT(smb_fname->st) &&
8053 SMB_VFS_STAT(conn, smb_fname)) {
8054 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8055 "%s failed (%s)\n",
8056 smb_fname_str_dbg(smb_fname),
8057 strerror(errno)));
8058 reply_nterror(req, map_nt_error_from_unix(errno));
8059 return;
8063 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8064 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8065 fsp ? fsp->fnum : -1, info_level,total_data));
8067 /* Realloc the parameter size */
8068 *pparams = (char *)SMB_REALLOC(*pparams,2);
8069 if (*pparams == NULL) {
8070 reply_nterror(req, NT_STATUS_NO_MEMORY);
8071 return;
8073 params = *pparams;
8075 SSVAL(params,0,0);
8077 status = smbd_do_setfilepathinfo(conn, req, req,
8078 info_level,
8079 fsp,
8080 smb_fname,
8081 ppdata, total_data,
8082 &data_return_size);
8083 if (!NT_STATUS_IS_OK(status)) {
8084 if (open_was_deferred(req->mid)) {
8085 /* We have re-scheduled this call. */
8086 return;
8088 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8089 /* We have re-scheduled this call. */
8090 return;
8092 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8093 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8094 ERRSRV, ERRbadpath);
8095 return;
8097 if (info_level == SMB_POSIX_PATH_OPEN) {
8098 reply_openerror(req, status);
8099 return;
8102 reply_nterror(req, status);
8103 return;
8106 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8107 max_data_bytes);
8109 return;
8112 /****************************************************************************
8113 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8114 ****************************************************************************/
8116 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8117 char **pparams, int total_params,
8118 char **ppdata, int total_data,
8119 unsigned int max_data_bytes)
8121 struct smb_filename *smb_dname = NULL;
8122 char *params = *pparams;
8123 char *pdata = *ppdata;
8124 char *directory = NULL;
8125 NTSTATUS status = NT_STATUS_OK;
8126 struct ea_list *ea_list = NULL;
8127 TALLOC_CTX *ctx = talloc_tos();
8129 if (!CAN_WRITE(conn)) {
8130 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8131 return;
8134 if (total_params < 5) {
8135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8136 return;
8139 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8140 total_params - 4, STR_TERMINATE,
8141 &status);
8142 if (!NT_STATUS_IS_OK(status)) {
8143 reply_nterror(req, status);
8144 return;
8147 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8149 status = filename_convert(ctx,
8150 conn,
8151 req->flags2 & FLAGS2_DFS_PATHNAMES,
8152 directory,
8154 NULL,
8155 &smb_dname);
8157 if (!NT_STATUS_IS_OK(status)) {
8158 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8159 reply_botherror(req,
8160 NT_STATUS_PATH_NOT_COVERED,
8161 ERRSRV, ERRbadpath);
8162 return;
8164 reply_nterror(req, status);
8165 return;
8169 * OS/2 workplace shell seems to send SET_EA requests of "null"
8170 * length (4 bytes containing IVAL 4).
8171 * They seem to have no effect. Bug #3212. JRA.
8174 if (total_data && (total_data != 4)) {
8175 /* Any data in this call is an EA list. */
8176 if (total_data < 10) {
8177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8178 goto out;
8181 if (IVAL(pdata,0) > total_data) {
8182 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8183 IVAL(pdata,0), (unsigned int)total_data));
8184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8185 goto out;
8188 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8189 total_data - 4);
8190 if (!ea_list) {
8191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8192 goto out;
8195 if (!lp_ea_support(SNUM(conn))) {
8196 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8197 goto out;
8200 /* If total_data == 4 Windows doesn't care what values
8201 * are placed in that field, it just ignores them.
8202 * The System i QNTC IBM SMB client puts bad values here,
8203 * so ignore them. */
8205 status = create_directory(conn, req, smb_dname);
8207 if (!NT_STATUS_IS_OK(status)) {
8208 reply_nterror(req, status);
8209 goto out;
8212 /* Try and set any given EA. */
8213 if (ea_list) {
8214 status = set_ea(conn, NULL, smb_dname, ea_list);
8215 if (!NT_STATUS_IS_OK(status)) {
8216 reply_nterror(req, status);
8217 goto out;
8221 /* Realloc the parameter and data sizes */
8222 *pparams = (char *)SMB_REALLOC(*pparams,2);
8223 if(*pparams == NULL) {
8224 reply_nterror(req, NT_STATUS_NO_MEMORY);
8225 goto out;
8227 params = *pparams;
8229 SSVAL(params,0,0);
8231 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8233 out:
8234 TALLOC_FREE(smb_dname);
8235 return;
8238 /****************************************************************************
8239 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8240 We don't actually do this - we just send a null response.
8241 ****************************************************************************/
8243 static void call_trans2findnotifyfirst(connection_struct *conn,
8244 struct smb_request *req,
8245 char **pparams, int total_params,
8246 char **ppdata, int total_data,
8247 unsigned int max_data_bytes)
8249 char *params = *pparams;
8250 uint16 info_level;
8252 if (total_params < 6) {
8253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8254 return;
8257 info_level = SVAL(params,4);
8258 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8260 switch (info_level) {
8261 case 1:
8262 case 2:
8263 break;
8264 default:
8265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8266 return;
8269 /* Realloc the parameter and data sizes */
8270 *pparams = (char *)SMB_REALLOC(*pparams,6);
8271 if (*pparams == NULL) {
8272 reply_nterror(req, NT_STATUS_NO_MEMORY);
8273 return;
8275 params = *pparams;
8277 SSVAL(params,0,fnf_handle);
8278 SSVAL(params,2,0); /* No changes */
8279 SSVAL(params,4,0); /* No EA errors */
8281 fnf_handle++;
8283 if(fnf_handle == 0)
8284 fnf_handle = 257;
8286 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8288 return;
8291 /****************************************************************************
8292 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8293 changes). Currently this does nothing.
8294 ****************************************************************************/
8296 static void call_trans2findnotifynext(connection_struct *conn,
8297 struct smb_request *req,
8298 char **pparams, int total_params,
8299 char **ppdata, int total_data,
8300 unsigned int max_data_bytes)
8302 char *params = *pparams;
8304 DEBUG(3,("call_trans2findnotifynext\n"));
8306 /* Realloc the parameter and data sizes */
8307 *pparams = (char *)SMB_REALLOC(*pparams,4);
8308 if (*pparams == NULL) {
8309 reply_nterror(req, NT_STATUS_NO_MEMORY);
8310 return;
8312 params = *pparams;
8314 SSVAL(params,0,0); /* No changes */
8315 SSVAL(params,2,0); /* No EA errors */
8317 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8319 return;
8322 /****************************************************************************
8323 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8324 ****************************************************************************/
8326 static void call_trans2getdfsreferral(connection_struct *conn,
8327 struct smb_request *req,
8328 char **pparams, int total_params,
8329 char **ppdata, int total_data,
8330 unsigned int max_data_bytes)
8332 char *params = *pparams;
8333 char *pathname = NULL;
8334 int reply_size = 0;
8335 int max_referral_level;
8336 NTSTATUS status = NT_STATUS_OK;
8337 TALLOC_CTX *ctx = talloc_tos();
8339 DEBUG(10,("call_trans2getdfsreferral\n"));
8341 if (total_params < 3) {
8342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8343 return;
8346 max_referral_level = SVAL(params,0);
8348 if(!lp_host_msdfs()) {
8349 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8350 return;
8353 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8354 total_params - 2, STR_TERMINATE);
8355 if (!pathname) {
8356 reply_nterror(req, NT_STATUS_NOT_FOUND);
8357 return;
8359 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8360 ppdata,&status)) < 0) {
8361 reply_nterror(req, status);
8362 return;
8365 SSVAL(req->inbuf, smb_flg2,
8366 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8367 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8369 return;
8372 #define LMCAT_SPL 0x53
8373 #define LMFUNC_GETJOBID 0x60
8375 /****************************************************************************
8376 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8377 ****************************************************************************/
8379 static void call_trans2ioctl(connection_struct *conn,
8380 struct smb_request *req,
8381 char **pparams, int total_params,
8382 char **ppdata, int total_data,
8383 unsigned int max_data_bytes)
8385 char *pdata = *ppdata;
8386 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8388 /* check for an invalid fid before proceeding */
8390 if (!fsp) {
8391 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8392 return;
8395 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8396 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8397 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8398 if (*ppdata == NULL) {
8399 reply_nterror(req, NT_STATUS_NO_MEMORY);
8400 return;
8402 pdata = *ppdata;
8404 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8405 CAN ACCEPT THIS IN UNICODE. JRA. */
8407 /* Job number */
8408 if (fsp->print_file) {
8409 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8410 } else {
8411 SSVAL(pdata, 0, 0);
8413 srvstr_push(pdata, req->flags2, pdata + 2,
8414 global_myname(), 15,
8415 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8416 srvstr_push(pdata, req->flags2, pdata+18,
8417 lp_servicename(SNUM(conn)), 13,
8418 STR_ASCII|STR_TERMINATE); /* Service name */
8419 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8420 max_data_bytes);
8421 return;
8424 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8425 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8428 /****************************************************************************
8429 Reply to a SMBfindclose (stop trans2 directory search).
8430 ****************************************************************************/
8432 void reply_findclose(struct smb_request *req)
8434 int dptr_num;
8435 struct smbd_server_connection *sconn = req->sconn;
8437 START_PROFILE(SMBfindclose);
8439 if (req->wct < 1) {
8440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8441 END_PROFILE(SMBfindclose);
8442 return;
8445 dptr_num = SVALS(req->vwv+0, 0);
8447 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8449 dptr_close(sconn, &dptr_num);
8451 reply_outbuf(req, 0, 0);
8453 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8455 END_PROFILE(SMBfindclose);
8456 return;
8459 /****************************************************************************
8460 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8461 ****************************************************************************/
8463 void reply_findnclose(struct smb_request *req)
8465 int dptr_num;
8467 START_PROFILE(SMBfindnclose);
8469 if (req->wct < 1) {
8470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8471 END_PROFILE(SMBfindnclose);
8472 return;
8475 dptr_num = SVAL(req->vwv+0, 0);
8477 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8479 /* We never give out valid handles for a
8480 findnotifyfirst - so any dptr_num is ok here.
8481 Just ignore it. */
8483 reply_outbuf(req, 0, 0);
8485 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8487 END_PROFILE(SMBfindnclose);
8488 return;
8491 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8492 struct trans_state *state)
8494 if (get_Protocol() >= PROTOCOL_NT1) {
8495 req->flags2 |= 0x40; /* IS_LONG_NAME */
8496 SSVAL(req->inbuf,smb_flg2,req->flags2);
8499 if (conn->encrypt_level == Required && !req->encrypted) {
8500 if (state->call != TRANSACT2_QFSINFO &&
8501 state->call != TRANSACT2_SETFSINFO) {
8502 DEBUG(0,("handle_trans2: encryption required "
8503 "with call 0x%x\n",
8504 (unsigned int)state->call));
8505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8506 return;
8510 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8512 /* Now we must call the relevant TRANS2 function */
8513 switch(state->call) {
8514 case TRANSACT2_OPEN:
8516 START_PROFILE(Trans2_open);
8517 call_trans2open(conn, req,
8518 &state->param, state->total_param,
8519 &state->data, state->total_data,
8520 state->max_data_return);
8521 END_PROFILE(Trans2_open);
8522 break;
8525 case TRANSACT2_FINDFIRST:
8527 START_PROFILE(Trans2_findfirst);
8528 call_trans2findfirst(conn, req,
8529 &state->param, state->total_param,
8530 &state->data, state->total_data,
8531 state->max_data_return);
8532 END_PROFILE(Trans2_findfirst);
8533 break;
8536 case TRANSACT2_FINDNEXT:
8538 START_PROFILE(Trans2_findnext);
8539 call_trans2findnext(conn, req,
8540 &state->param, state->total_param,
8541 &state->data, state->total_data,
8542 state->max_data_return);
8543 END_PROFILE(Trans2_findnext);
8544 break;
8547 case TRANSACT2_QFSINFO:
8549 START_PROFILE(Trans2_qfsinfo);
8550 call_trans2qfsinfo(conn, req,
8551 &state->param, state->total_param,
8552 &state->data, state->total_data,
8553 state->max_data_return);
8554 END_PROFILE(Trans2_qfsinfo);
8555 break;
8558 case TRANSACT2_SETFSINFO:
8560 START_PROFILE(Trans2_setfsinfo);
8561 call_trans2setfsinfo(conn, req,
8562 &state->param, state->total_param,
8563 &state->data, state->total_data,
8564 state->max_data_return);
8565 END_PROFILE(Trans2_setfsinfo);
8566 break;
8569 case TRANSACT2_QPATHINFO:
8570 case TRANSACT2_QFILEINFO:
8572 START_PROFILE(Trans2_qpathinfo);
8573 call_trans2qfilepathinfo(conn, req, state->call,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_qpathinfo);
8578 break;
8581 case TRANSACT2_SETPATHINFO:
8582 case TRANSACT2_SETFILEINFO:
8584 START_PROFILE(Trans2_setpathinfo);
8585 call_trans2setfilepathinfo(conn, req, state->call,
8586 &state->param, state->total_param,
8587 &state->data, state->total_data,
8588 state->max_data_return);
8589 END_PROFILE(Trans2_setpathinfo);
8590 break;
8593 case TRANSACT2_FINDNOTIFYFIRST:
8595 START_PROFILE(Trans2_findnotifyfirst);
8596 call_trans2findnotifyfirst(conn, req,
8597 &state->param, state->total_param,
8598 &state->data, state->total_data,
8599 state->max_data_return);
8600 END_PROFILE(Trans2_findnotifyfirst);
8601 break;
8604 case TRANSACT2_FINDNOTIFYNEXT:
8606 START_PROFILE(Trans2_findnotifynext);
8607 call_trans2findnotifynext(conn, req,
8608 &state->param, state->total_param,
8609 &state->data, state->total_data,
8610 state->max_data_return);
8611 END_PROFILE(Trans2_findnotifynext);
8612 break;
8615 case TRANSACT2_MKDIR:
8617 START_PROFILE(Trans2_mkdir);
8618 call_trans2mkdir(conn, req,
8619 &state->param, state->total_param,
8620 &state->data, state->total_data,
8621 state->max_data_return);
8622 END_PROFILE(Trans2_mkdir);
8623 break;
8626 case TRANSACT2_GET_DFS_REFERRAL:
8628 START_PROFILE(Trans2_get_dfs_referral);
8629 call_trans2getdfsreferral(conn, req,
8630 &state->param, state->total_param,
8631 &state->data, state->total_data,
8632 state->max_data_return);
8633 END_PROFILE(Trans2_get_dfs_referral);
8634 break;
8637 case TRANSACT2_IOCTL:
8639 START_PROFILE(Trans2_ioctl);
8640 call_trans2ioctl(conn, req,
8641 &state->param, state->total_param,
8642 &state->data, state->total_data,
8643 state->max_data_return);
8644 END_PROFILE(Trans2_ioctl);
8645 break;
8648 default:
8649 /* Error in request */
8650 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8651 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8655 /****************************************************************************
8656 Reply to a SMBtrans2.
8657 ****************************************************************************/
8659 void reply_trans2(struct smb_request *req)
8661 connection_struct *conn = req->conn;
8662 unsigned int dsoff;
8663 unsigned int dscnt;
8664 unsigned int psoff;
8665 unsigned int pscnt;
8666 unsigned int tran_call;
8667 struct trans_state *state;
8668 NTSTATUS result;
8670 START_PROFILE(SMBtrans2);
8672 if (req->wct < 14) {
8673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8674 END_PROFILE(SMBtrans2);
8675 return;
8678 dsoff = SVAL(req->vwv+12, 0);
8679 dscnt = SVAL(req->vwv+11, 0);
8680 psoff = SVAL(req->vwv+10, 0);
8681 pscnt = SVAL(req->vwv+9, 0);
8682 tran_call = SVAL(req->vwv+14, 0);
8684 result = allow_new_trans(conn->pending_trans, req->mid);
8685 if (!NT_STATUS_IS_OK(result)) {
8686 DEBUG(2, ("Got invalid trans2 request: %s\n",
8687 nt_errstr(result)));
8688 reply_nterror(req, result);
8689 END_PROFILE(SMBtrans2);
8690 return;
8693 if (IS_IPC(conn)) {
8694 switch (tran_call) {
8695 /* List the allowed trans2 calls on IPC$ */
8696 case TRANSACT2_OPEN:
8697 case TRANSACT2_GET_DFS_REFERRAL:
8698 case TRANSACT2_QFILEINFO:
8699 case TRANSACT2_QFSINFO:
8700 case TRANSACT2_SETFSINFO:
8701 break;
8702 default:
8703 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8704 END_PROFILE(SMBtrans2);
8705 return;
8709 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8710 DEBUG(0, ("talloc failed\n"));
8711 reply_nterror(req, NT_STATUS_NO_MEMORY);
8712 END_PROFILE(SMBtrans2);
8713 return;
8716 state->cmd = SMBtrans2;
8718 state->mid = req->mid;
8719 state->vuid = req->vuid;
8720 state->setup_count = SVAL(req->vwv+13, 0);
8721 state->setup = NULL;
8722 state->total_param = SVAL(req->vwv+0, 0);
8723 state->param = NULL;
8724 state->total_data = SVAL(req->vwv+1, 0);
8725 state->data = NULL;
8726 state->max_param_return = SVAL(req->vwv+2, 0);
8727 state->max_data_return = SVAL(req->vwv+3, 0);
8728 state->max_setup_return = SVAL(req->vwv+4, 0);
8729 state->close_on_completion = BITSETW(req->vwv+5, 0);
8730 state->one_way = BITSETW(req->vwv+5, 1);
8732 state->call = tran_call;
8734 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8735 is so as a sanity check */
8736 if (state->setup_count != 1) {
8738 * Need to have rc=0 for ioctl to get job id for OS/2.
8739 * Network printing will fail if function is not successful.
8740 * Similar function in reply.c will be used if protocol
8741 * is LANMAN1.0 instead of LM1.2X002.
8742 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8743 * outbuf doesn't have to be set(only job id is used).
8745 if ( (state->setup_count == 4)
8746 && (tran_call == TRANSACT2_IOCTL)
8747 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8748 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8749 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8750 } else {
8751 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8752 DEBUG(2,("Transaction is %d\n",tran_call));
8753 TALLOC_FREE(state);
8754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8755 END_PROFILE(SMBtrans2);
8756 return;
8760 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8761 goto bad_param;
8763 if (state->total_data) {
8765 if (trans_oob(state->total_data, 0, dscnt)
8766 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8767 goto bad_param;
8770 /* Can't use talloc here, the core routines do realloc on the
8771 * params and data. */
8772 state->data = (char *)SMB_MALLOC(state->total_data);
8773 if (state->data == NULL) {
8774 DEBUG(0,("reply_trans2: data malloc fail for %u "
8775 "bytes !\n", (unsigned int)state->total_data));
8776 TALLOC_FREE(state);
8777 reply_nterror(req, NT_STATUS_NO_MEMORY);
8778 END_PROFILE(SMBtrans2);
8779 return;
8782 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8785 if (state->total_param) {
8787 if (trans_oob(state->total_param, 0, pscnt)
8788 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8789 goto bad_param;
8792 /* Can't use talloc here, the core routines do realloc on the
8793 * params and data. */
8794 state->param = (char *)SMB_MALLOC(state->total_param);
8795 if (state->param == NULL) {
8796 DEBUG(0,("reply_trans: param malloc fail for %u "
8797 "bytes !\n", (unsigned int)state->total_param));
8798 SAFE_FREE(state->data);
8799 TALLOC_FREE(state);
8800 reply_nterror(req, NT_STATUS_NO_MEMORY);
8801 END_PROFILE(SMBtrans2);
8802 return;
8805 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8808 state->received_data = dscnt;
8809 state->received_param = pscnt;
8811 if ((state->received_param == state->total_param) &&
8812 (state->received_data == state->total_data)) {
8814 handle_trans2(conn, req, state);
8816 SAFE_FREE(state->data);
8817 SAFE_FREE(state->param);
8818 TALLOC_FREE(state);
8819 END_PROFILE(SMBtrans2);
8820 return;
8823 DLIST_ADD(conn->pending_trans, state);
8825 /* We need to send an interim response then receive the rest
8826 of the parameter/data bytes */
8827 reply_outbuf(req, 0, 0);
8828 show_msg((char *)req->outbuf);
8829 END_PROFILE(SMBtrans2);
8830 return;
8832 bad_param:
8834 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8835 SAFE_FREE(state->data);
8836 SAFE_FREE(state->param);
8837 TALLOC_FREE(state);
8838 END_PROFILE(SMBtrans2);
8839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8843 /****************************************************************************
8844 Reply to a SMBtranss2
8845 ****************************************************************************/
8847 void reply_transs2(struct smb_request *req)
8849 connection_struct *conn = req->conn;
8850 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8851 struct trans_state *state;
8853 START_PROFILE(SMBtranss2);
8855 show_msg((char *)req->inbuf);
8857 /* Windows clients expect all replies to
8858 a transact secondary (SMBtranss2 0x33)
8859 to have a command code of transact
8860 (SMBtrans2 0x32). See bug #8989
8861 and also [MS-CIFS] section 2.2.4.47.2
8862 for details.
8864 req->cmd = SMBtrans2;
8866 if (req->wct < 8) {
8867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8868 END_PROFILE(SMBtranss2);
8869 return;
8872 for (state = conn->pending_trans; state != NULL;
8873 state = state->next) {
8874 if (state->mid == req->mid) {
8875 break;
8879 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8881 END_PROFILE(SMBtranss2);
8882 return;
8885 /* Revise state->total_param and state->total_data in case they have
8886 changed downwards */
8888 if (SVAL(req->vwv+0, 0) < state->total_param)
8889 state->total_param = SVAL(req->vwv+0, 0);
8890 if (SVAL(req->vwv+1, 0) < state->total_data)
8891 state->total_data = SVAL(req->vwv+1, 0);
8893 pcnt = SVAL(req->vwv+2, 0);
8894 poff = SVAL(req->vwv+3, 0);
8895 pdisp = SVAL(req->vwv+4, 0);
8897 dcnt = SVAL(req->vwv+5, 0);
8898 doff = SVAL(req->vwv+6, 0);
8899 ddisp = SVAL(req->vwv+7, 0);
8901 state->received_param += pcnt;
8902 state->received_data += dcnt;
8904 if ((state->received_data > state->total_data) ||
8905 (state->received_param > state->total_param))
8906 goto bad_param;
8908 if (pcnt) {
8909 if (trans_oob(state->total_param, pdisp, pcnt)
8910 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8911 goto bad_param;
8913 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8916 if (dcnt) {
8917 if (trans_oob(state->total_data, ddisp, dcnt)
8918 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8919 goto bad_param;
8921 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8924 if ((state->received_param < state->total_param) ||
8925 (state->received_data < state->total_data)) {
8926 END_PROFILE(SMBtranss2);
8927 return;
8930 handle_trans2(conn, req, state);
8932 DLIST_REMOVE(conn->pending_trans, state);
8933 SAFE_FREE(state->data);
8934 SAFE_FREE(state->param);
8935 TALLOC_FREE(state);
8937 END_PROFILE(SMBtranss2);
8938 return;
8940 bad_param:
8942 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8943 DLIST_REMOVE(conn->pending_trans, state);
8944 SAFE_FREE(state->data);
8945 SAFE_FREE(state->param);
8946 TALLOC_FREE(state);
8947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8948 END_PROFILE(SMBtranss2);
8949 return;