torture: Add ntprinting latin1 test.
[Samba.git] / source3 / smbd / trans2.c
blobdf4fa64929e434abb2727c13e48758fd06f4ae59
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 struct smb_filename *fname,
2925 char **ppdata,
2926 int *ret_data_len)
2928 char *pdata, *end_data;
2929 int data_len = 0, len;
2930 const char *vname = volume_label(SNUM(conn));
2931 int snum = SNUM(conn);
2932 char *fstype = lp_fstype(SNUM(conn));
2933 const char *filename = NULL;
2934 uint32 additional_flags = 0;
2935 struct smb_filename smb_fname;
2936 SMB_STRUCT_STAT st;
2938 if (fname == NULL || fname->base_name == NULL) {
2939 filename = ".";
2940 } else {
2941 filename = fname->base_name;
2944 if (IS_IPC(conn)) {
2945 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2946 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2947 "info level (0x%x) on IPC$.\n",
2948 (unsigned int)info_level));
2949 return NT_STATUS_ACCESS_DENIED;
2953 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2955 ZERO_STRUCT(smb_fname);
2956 smb_fname.base_name = discard_const_p(char, filename);
2958 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
2959 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2960 return map_nt_error_from_unix(errno);
2963 st = smb_fname.st;
2965 *ppdata = (char *)SMB_REALLOC(
2966 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2967 if (*ppdata == NULL) {
2968 return NT_STATUS_NO_MEMORY;
2971 pdata = *ppdata;
2972 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2973 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2975 switch (info_level) {
2976 case SMB_INFO_ALLOCATION:
2978 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2979 data_len = 18;
2980 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2981 return map_nt_error_from_unix(errno);
2984 block_size = lp_block_size(snum);
2985 if (bsize < block_size) {
2986 uint64_t factor = block_size/bsize;
2987 bsize = block_size;
2988 dsize /= factor;
2989 dfree /= factor;
2991 if (bsize > block_size) {
2992 uint64_t factor = bsize/block_size;
2993 bsize = block_size;
2994 dsize *= factor;
2995 dfree *= factor;
2997 bytes_per_sector = 512;
2998 sectors_per_unit = bsize/bytes_per_sector;
3000 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3001 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3002 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3004 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3005 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3006 SIVAL(pdata,l1_cUnit,dsize);
3007 SIVAL(pdata,l1_cUnitAvail,dfree);
3008 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3009 break;
3012 case SMB_INFO_VOLUME:
3013 /* Return volume name */
3015 * Add volume serial number - hash of a combination of
3016 * the called hostname and the service name.
3018 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3020 * Win2k3 and previous mess this up by sending a name length
3021 * one byte short. I believe only older clients (OS/2 Win9x) use
3022 * this call so try fixing this by adding a terminating null to
3023 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3025 len = srvstr_push(
3026 pdata, flags2,
3027 pdata+l2_vol_szVolLabel, vname,
3028 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3029 STR_NOALIGN|STR_TERMINATE);
3030 SCVAL(pdata,l2_vol_cch,len);
3031 data_len = l2_vol_szVolLabel + len;
3032 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3033 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3034 len, vname));
3035 break;
3037 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3038 case SMB_FS_ATTRIBUTE_INFORMATION:
3040 additional_flags = 0;
3041 #if defined(HAVE_SYS_QUOTAS)
3042 additional_flags |= FILE_VOLUME_QUOTAS;
3043 #endif
3045 if(lp_nt_acl_support(SNUM(conn))) {
3046 additional_flags |= FILE_PERSISTENT_ACLS;
3049 /* Capabilities are filled in at connection time through STATVFS call */
3050 additional_flags |= conn->fs_capabilities;
3051 additional_flags |= lp_parm_int(conn->params->service,
3052 "share", "fake_fscaps",
3055 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3056 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3057 additional_flags); /* FS ATTRIBUTES */
3059 SIVAL(pdata,4,255); /* Max filename component length */
3060 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3061 and will think we can't do long filenames */
3062 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3063 PTR_DIFF(end_data, pdata+12),
3064 STR_UNICODE);
3065 SIVAL(pdata,8,len);
3066 data_len = 12 + len;
3067 break;
3069 case SMB_QUERY_FS_LABEL_INFO:
3070 case SMB_FS_LABEL_INFORMATION:
3071 len = srvstr_push(pdata, flags2, pdata+4, vname,
3072 PTR_DIFF(end_data, pdata+4), 0);
3073 data_len = 4 + len;
3074 SIVAL(pdata,0,len);
3075 break;
3077 case SMB_QUERY_FS_VOLUME_INFO:
3078 case SMB_FS_VOLUME_INFORMATION:
3081 * Add volume serial number - hash of a combination of
3082 * the called hostname and the service name.
3084 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3085 (str_checksum(get_local_machine_name())<<16));
3087 /* Max label len is 32 characters. */
3088 len = srvstr_push(pdata, flags2, pdata+18, vname,
3089 PTR_DIFF(end_data, pdata+18),
3090 STR_UNICODE);
3091 SIVAL(pdata,12,len);
3092 data_len = 18+len;
3094 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3095 (int)strlen(vname),vname, lp_servicename(snum)));
3096 break;
3098 case SMB_QUERY_FS_SIZE_INFO:
3099 case SMB_FS_SIZE_INFORMATION:
3101 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3102 data_len = 24;
3103 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3104 return map_nt_error_from_unix(errno);
3106 block_size = lp_block_size(snum);
3107 if (bsize < block_size) {
3108 uint64_t factor = block_size/bsize;
3109 bsize = block_size;
3110 dsize /= factor;
3111 dfree /= factor;
3113 if (bsize > block_size) {
3114 uint64_t factor = bsize/block_size;
3115 bsize = block_size;
3116 dsize *= factor;
3117 dfree *= factor;
3119 bytes_per_sector = 512;
3120 sectors_per_unit = bsize/bytes_per_sector;
3121 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3122 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3123 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3124 SBIG_UINT(pdata,0,dsize);
3125 SBIG_UINT(pdata,8,dfree);
3126 SIVAL(pdata,16,sectors_per_unit);
3127 SIVAL(pdata,20,bytes_per_sector);
3128 break;
3131 case SMB_FS_FULL_SIZE_INFORMATION:
3133 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3134 data_len = 32;
3135 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3136 return map_nt_error_from_unix(errno);
3138 block_size = lp_block_size(snum);
3139 if (bsize < block_size) {
3140 uint64_t factor = block_size/bsize;
3141 bsize = block_size;
3142 dsize /= factor;
3143 dfree /= factor;
3145 if (bsize > block_size) {
3146 uint64_t factor = bsize/block_size;
3147 bsize = block_size;
3148 dsize *= factor;
3149 dfree *= factor;
3151 bytes_per_sector = 512;
3152 sectors_per_unit = bsize/bytes_per_sector;
3153 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3154 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3155 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3156 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3157 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3158 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3159 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3160 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3161 break;
3164 case SMB_QUERY_FS_DEVICE_INFO:
3165 case SMB_FS_DEVICE_INFORMATION:
3167 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3169 if (!CAN_WRITE(conn)) {
3170 characteristics |= FILE_READ_ONLY_DEVICE;
3172 data_len = 8;
3173 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3174 SIVAL(pdata,4,characteristics);
3175 break;
3178 #ifdef HAVE_SYS_QUOTAS
3179 case SMB_FS_QUOTA_INFORMATION:
3181 * what we have to send --metze:
3183 * Unknown1: 24 NULL bytes
3184 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3185 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3186 * Quota Flags: 2 byte :
3187 * Unknown3: 6 NULL bytes
3189 * 48 bytes total
3191 * details for Quota Flags:
3193 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3194 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3195 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3196 * 0x0001 Enable Quotas: enable quota for this fs
3200 /* we need to fake up a fsp here,
3201 * because its not send in this call
3203 files_struct fsp;
3204 SMB_NTQUOTA_STRUCT quotas;
3206 ZERO_STRUCT(fsp);
3207 ZERO_STRUCT(quotas);
3209 fsp.conn = conn;
3210 fsp.fnum = -1;
3212 /* access check */
3213 if (get_current_uid(conn) != 0) {
3214 DEBUG(0,("set_user_quota: access_denied "
3215 "service [%s] user [%s]\n",
3216 lp_servicename(SNUM(conn)),
3217 conn->session_info->unix_name));
3218 return NT_STATUS_ACCESS_DENIED;
3221 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3222 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3223 return map_nt_error_from_unix(errno);
3226 data_len = 48;
3228 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3229 lp_servicename(SNUM(conn))));
3231 /* Unknown1 24 NULL bytes*/
3232 SBIG_UINT(pdata,0,(uint64_t)0);
3233 SBIG_UINT(pdata,8,(uint64_t)0);
3234 SBIG_UINT(pdata,16,(uint64_t)0);
3236 /* Default Soft Quota 8 bytes */
3237 SBIG_UINT(pdata,24,quotas.softlim);
3239 /* Default Hard Quota 8 bytes */
3240 SBIG_UINT(pdata,32,quotas.hardlim);
3242 /* Quota flag 2 bytes */
3243 SSVAL(pdata,40,quotas.qflags);
3245 /* Unknown3 6 NULL bytes */
3246 SSVAL(pdata,42,0);
3247 SIVAL(pdata,44,0);
3249 break;
3251 #endif /* HAVE_SYS_QUOTAS */
3252 case SMB_FS_OBJECTID_INFORMATION:
3254 unsigned char objid[16];
3255 struct smb_extended_info extended_info;
3256 memcpy(pdata,create_volume_objectid(conn, objid),16);
3257 samba_extended_info_version (&extended_info);
3258 SIVAL(pdata,16,extended_info.samba_magic);
3259 SIVAL(pdata,20,extended_info.samba_version);
3260 SIVAL(pdata,24,extended_info.samba_subversion);
3261 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3262 memcpy(pdata+36,extended_info.samba_version_string,28);
3263 data_len = 64;
3264 break;
3268 * Query the version and capabilities of the CIFS UNIX extensions
3269 * in use.
3272 case SMB_QUERY_CIFS_UNIX_INFO:
3274 bool large_write = lp_min_receive_file_size() &&
3275 !srv_is_signing_active(conn->sconn);
3276 bool large_read = !srv_is_signing_active(conn->sconn);
3277 int encrypt_caps = 0;
3279 if (!lp_unix_extensions()) {
3280 return NT_STATUS_INVALID_LEVEL;
3283 switch (conn->encrypt_level) {
3284 case 0:
3285 encrypt_caps = 0;
3286 break;
3287 case 1:
3288 case Auto:
3289 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3290 break;
3291 case Required:
3292 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3293 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3294 large_write = false;
3295 large_read = false;
3296 break;
3299 data_len = 12;
3300 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3301 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3303 /* We have POSIX ACLs, pathname, encryption,
3304 * large read/write, and locking capability. */
3306 SBIG_UINT(pdata,4,((uint64_t)(
3307 CIFS_UNIX_POSIX_ACLS_CAP|
3308 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3309 CIFS_UNIX_FCNTL_LOCKS_CAP|
3310 CIFS_UNIX_EXTATTR_CAP|
3311 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3312 encrypt_caps|
3313 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3314 (large_write ?
3315 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3316 break;
3319 case SMB_QUERY_POSIX_FS_INFO:
3321 int rc;
3322 vfs_statvfs_struct svfs;
3324 if (!lp_unix_extensions()) {
3325 return NT_STATUS_INVALID_LEVEL;
3328 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3330 if (!rc) {
3331 data_len = 56;
3332 SIVAL(pdata,0,svfs.OptimalTransferSize);
3333 SIVAL(pdata,4,svfs.BlockSize);
3334 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3335 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3336 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3337 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3338 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3339 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3340 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3341 #ifdef EOPNOTSUPP
3342 } else if (rc == EOPNOTSUPP) {
3343 return NT_STATUS_INVALID_LEVEL;
3344 #endif /* EOPNOTSUPP */
3345 } else {
3346 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3347 return NT_STATUS_DOS(ERRSRV, ERRerror);
3349 break;
3352 case SMB_QUERY_POSIX_WHOAMI:
3354 uint32_t flags = 0;
3355 uint32_t sid_bytes;
3356 int i;
3358 if (!lp_unix_extensions()) {
3359 return NT_STATUS_INVALID_LEVEL;
3362 if (max_data_bytes < 40) {
3363 return NT_STATUS_BUFFER_TOO_SMALL;
3366 /* We ARE guest if global_sid_Builtin_Guests is
3367 * in our list of SIDs.
3369 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3370 conn->session_info->security_token)) {
3371 flags |= SMB_WHOAMI_GUEST;
3374 /* We are NOT guest if global_sid_Authenticated_Users
3375 * is in our list of SIDs.
3377 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3378 conn->session_info->security_token)) {
3379 flags &= ~SMB_WHOAMI_GUEST;
3382 /* NOTE: 8 bytes for UID/GID, irrespective of native
3383 * platform size. This matches
3384 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3386 data_len = 4 /* flags */
3387 + 4 /* flag mask */
3388 + 8 /* uid */
3389 + 8 /* gid */
3390 + 4 /* ngroups */
3391 + 4 /* num_sids */
3392 + 4 /* SID bytes */
3393 + 4 /* pad/reserved */
3394 + (conn->session_info->utok.ngroups * 8)
3395 /* groups list */
3396 + (conn->session_info->security_token->num_sids *
3397 SID_MAX_SIZE)
3398 /* SID list */;
3400 SIVAL(pdata, 0, flags);
3401 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3402 SBIG_UINT(pdata, 8,
3403 (uint64_t)conn->session_info->utok.uid);
3404 SBIG_UINT(pdata, 16,
3405 (uint64_t)conn->session_info->utok.gid);
3408 if (data_len >= max_data_bytes) {
3409 /* Potential overflow, skip the GIDs and SIDs. */
3411 SIVAL(pdata, 24, 0); /* num_groups */
3412 SIVAL(pdata, 28, 0); /* num_sids */
3413 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3414 SIVAL(pdata, 36, 0); /* reserved */
3416 data_len = 40;
3417 break;
3420 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3421 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3423 /* We walk the SID list twice, but this call is fairly
3424 * infrequent, and I don't expect that it's performance
3425 * sensitive -- jpeach
3427 for (i = 0, sid_bytes = 0;
3428 i < conn->session_info->security_token->num_sids; ++i) {
3429 sid_bytes += ndr_size_dom_sid(
3430 &conn->session_info->security_token->sids[i],
3434 /* SID list byte count */
3435 SIVAL(pdata, 32, sid_bytes);
3437 /* 4 bytes pad/reserved - must be zero */
3438 SIVAL(pdata, 36, 0);
3439 data_len = 40;
3441 /* GID list */
3442 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3443 SBIG_UINT(pdata, data_len,
3444 (uint64_t)conn->session_info->utok.groups[i]);
3445 data_len += 8;
3448 /* SID list */
3449 for (i = 0;
3450 i < conn->session_info->security_token->num_sids; ++i) {
3451 int sid_len = ndr_size_dom_sid(
3452 &conn->session_info->security_token->sids[i],
3455 sid_linearize(pdata + data_len, sid_len,
3456 &conn->session_info->security_token->sids[i]);
3457 data_len += sid_len;
3460 break;
3463 case SMB_MAC_QUERY_FS_INFO:
3465 * Thursby MAC extension... ONLY on NTFS filesystems
3466 * once we do streams then we don't need this
3468 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3469 data_len = 88;
3470 SIVAL(pdata,84,0x100); /* Don't support mac... */
3471 break;
3473 /* drop through */
3474 default:
3475 return NT_STATUS_INVALID_LEVEL;
3478 *ret_data_len = data_len;
3479 return NT_STATUS_OK;
3482 /****************************************************************************
3483 Reply to a TRANS2_QFSINFO (query filesystem info).
3484 ****************************************************************************/
3486 static void call_trans2qfsinfo(connection_struct *conn,
3487 struct smb_request *req,
3488 char **pparams, int total_params,
3489 char **ppdata, int total_data,
3490 unsigned int max_data_bytes)
3492 char *params = *pparams;
3493 uint16_t info_level;
3494 int data_len = 0;
3495 NTSTATUS status;
3497 if (total_params < 2) {
3498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3499 return;
3502 info_level = SVAL(params,0);
3504 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3505 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3506 DEBUG(0,("call_trans2qfsinfo: encryption required "
3507 "and info level 0x%x sent.\n",
3508 (unsigned int)info_level));
3509 exit_server_cleanly("encryption required "
3510 "on connection");
3511 return;
3515 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3517 status = smbd_do_qfsinfo(conn, req,
3518 info_level,
3519 req->flags2,
3520 max_data_bytes,
3521 NULL,
3522 ppdata, &data_len);
3523 if (!NT_STATUS_IS_OK(status)) {
3524 reply_nterror(req, status);
3525 return;
3528 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3529 max_data_bytes);
3531 DEBUG( 4, ( "%s info_level = %d\n",
3532 smb_fn_name(req->cmd), info_level) );
3534 return;
3537 /****************************************************************************
3538 Reply to a TRANS2_SETFSINFO (set filesystem info).
3539 ****************************************************************************/
3541 static void call_trans2setfsinfo(connection_struct *conn,
3542 struct smb_request *req,
3543 char **pparams, int total_params,
3544 char **ppdata, int total_data,
3545 unsigned int max_data_bytes)
3547 char *pdata = *ppdata;
3548 char *params = *pparams;
3549 uint16 info_level;
3551 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3553 /* */
3554 if (total_params < 4) {
3555 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3556 total_params));
3557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3558 return;
3561 info_level = SVAL(params,2);
3563 if (IS_IPC(conn)) {
3564 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3565 info_level != SMB_SET_CIFS_UNIX_INFO) {
3566 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3567 "info level (0x%x) on IPC$.\n",
3568 (unsigned int)info_level));
3569 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3570 return;
3574 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3575 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3576 DEBUG(0,("call_trans2setfsinfo: encryption required "
3577 "and info level 0x%x sent.\n",
3578 (unsigned int)info_level));
3579 exit_server_cleanly("encryption required "
3580 "on connection");
3581 return;
3585 switch(info_level) {
3586 case SMB_SET_CIFS_UNIX_INFO:
3588 uint16 client_unix_major;
3589 uint16 client_unix_minor;
3590 uint32 client_unix_cap_low;
3591 uint32 client_unix_cap_high;
3593 if (!lp_unix_extensions()) {
3594 reply_nterror(req,
3595 NT_STATUS_INVALID_LEVEL);
3596 return;
3599 /* There should be 12 bytes of capabilities set. */
3600 if (total_data < 8) {
3601 reply_nterror(
3602 req,
3603 NT_STATUS_INVALID_PARAMETER);
3604 return;
3606 client_unix_major = SVAL(pdata,0);
3607 client_unix_minor = SVAL(pdata,2);
3608 client_unix_cap_low = IVAL(pdata,4);
3609 client_unix_cap_high = IVAL(pdata,8);
3610 /* Just print these values for now. */
3611 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3612 cap_low = 0x%x, cap_high = 0x%x\n",
3613 (unsigned int)client_unix_major,
3614 (unsigned int)client_unix_minor,
3615 (unsigned int)client_unix_cap_low,
3616 (unsigned int)client_unix_cap_high ));
3618 /* Here is where we must switch to posix pathname processing... */
3619 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3620 lp_set_posix_pathnames();
3621 mangle_change_to_posix();
3624 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3625 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3626 /* Client that knows how to do posix locks,
3627 * but not posix open/mkdir operations. Set a
3628 * default type for read/write checks. */
3630 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3633 break;
3636 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3638 NTSTATUS status;
3639 size_t param_len = 0;
3640 size_t data_len = total_data;
3642 if (!lp_unix_extensions()) {
3643 reply_nterror(
3644 req,
3645 NT_STATUS_INVALID_LEVEL);
3646 return;
3649 if (lp_smb_encrypt(SNUM(conn)) == false) {
3650 reply_nterror(
3651 req,
3652 NT_STATUS_NOT_SUPPORTED);
3653 return;
3656 if (req->sconn->smb1.echo_handler.trusted_fde) {
3657 DEBUG( 2,("call_trans2setfsinfo: "
3658 "request transport encryption disabled"
3659 "with 'fork echo handler = yes'\n"));
3660 reply_nterror(
3661 req,
3662 NT_STATUS_NOT_SUPPORTED);
3663 return;
3666 DEBUG( 4,("call_trans2setfsinfo: "
3667 "request transport encryption.\n"));
3669 status = srv_request_encryption_setup(conn,
3670 (unsigned char **)ppdata,
3671 &data_len,
3672 (unsigned char **)pparams,
3673 &param_len);
3675 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3676 !NT_STATUS_IS_OK(status)) {
3677 reply_nterror(req, status);
3678 return;
3681 send_trans2_replies(conn, req,
3682 *pparams,
3683 param_len,
3684 *ppdata,
3685 data_len,
3686 max_data_bytes);
3688 if (NT_STATUS_IS_OK(status)) {
3689 /* Server-side transport
3690 * encryption is now *on*. */
3691 status = srv_encryption_start(conn);
3692 if (!NT_STATUS_IS_OK(status)) {
3693 exit_server_cleanly(
3694 "Failure in setting "
3695 "up encrypted transport");
3698 return;
3701 case SMB_FS_QUOTA_INFORMATION:
3703 files_struct *fsp = NULL;
3704 SMB_NTQUOTA_STRUCT quotas;
3706 ZERO_STRUCT(quotas);
3708 /* access check */
3709 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3710 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3711 lp_servicename(SNUM(conn)),
3712 conn->session_info->unix_name));
3713 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3714 return;
3717 /* note: normaly there're 48 bytes,
3718 * but we didn't use the last 6 bytes for now
3719 * --metze
3721 fsp = file_fsp(req, SVAL(params,0));
3723 if (!check_fsp_ntquota_handle(conn, req,
3724 fsp)) {
3725 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3726 reply_nterror(
3727 req, NT_STATUS_INVALID_HANDLE);
3728 return;
3731 if (total_data < 42) {
3732 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3733 total_data));
3734 reply_nterror(
3735 req,
3736 NT_STATUS_INVALID_PARAMETER);
3737 return;
3740 /* unknown_1 24 NULL bytes in pdata*/
3742 /* the soft quotas 8 bytes (uint64_t)*/
3743 quotas.softlim = BVAL(pdata,24);
3745 /* the hard quotas 8 bytes (uint64_t)*/
3746 quotas.hardlim = BVAL(pdata,32);
3748 /* quota_flags 2 bytes **/
3749 quotas.qflags = SVAL(pdata,40);
3751 /* unknown_2 6 NULL bytes follow*/
3753 /* now set the quotas */
3754 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3755 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3756 reply_nterror(req, map_nt_error_from_unix(errno));
3757 return;
3760 break;
3762 default:
3763 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3764 info_level));
3765 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3766 return;
3767 break;
3771 * sending this reply works fine,
3772 * but I'm not sure it's the same
3773 * like windows do...
3774 * --metze
3776 reply_outbuf(req, 10, 0);
3779 #if defined(HAVE_POSIX_ACLS)
3780 /****************************************************************************
3781 Utility function to count the number of entries in a POSIX acl.
3782 ****************************************************************************/
3784 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3786 unsigned int ace_count = 0;
3787 int entry_id = SMB_ACL_FIRST_ENTRY;
3788 SMB_ACL_ENTRY_T entry;
3790 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3791 /* get_next... */
3792 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3793 entry_id = SMB_ACL_NEXT_ENTRY;
3795 ace_count++;
3797 return ace_count;
3800 /****************************************************************************
3801 Utility function to marshall a POSIX acl into wire format.
3802 ****************************************************************************/
3804 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3806 int entry_id = SMB_ACL_FIRST_ENTRY;
3807 SMB_ACL_ENTRY_T entry;
3809 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3810 SMB_ACL_TAG_T tagtype;
3811 SMB_ACL_PERMSET_T permset;
3812 unsigned char perms = 0;
3813 unsigned int own_grp;
3815 /* get_next... */
3816 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3817 entry_id = SMB_ACL_NEXT_ENTRY;
3820 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3821 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3822 return False;
3825 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3827 return False;
3830 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3831 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3832 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3834 SCVAL(pdata,1,perms);
3836 switch (tagtype) {
3837 case SMB_ACL_USER_OBJ:
3838 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3839 own_grp = (unsigned int)pst->st_ex_uid;
3840 SIVAL(pdata,2,own_grp);
3841 SIVAL(pdata,6,0);
3842 break;
3843 case SMB_ACL_USER:
3845 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3846 if (!puid) {
3847 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3848 return False;
3850 own_grp = (unsigned int)*puid;
3851 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3852 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3853 SIVAL(pdata,2,own_grp);
3854 SIVAL(pdata,6,0);
3855 break;
3857 case SMB_ACL_GROUP_OBJ:
3858 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3859 own_grp = (unsigned int)pst->st_ex_gid;
3860 SIVAL(pdata,2,own_grp);
3861 SIVAL(pdata,6,0);
3862 break;
3863 case SMB_ACL_GROUP:
3865 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3866 if (!pgid) {
3867 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3868 return False;
3870 own_grp = (unsigned int)*pgid;
3871 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3872 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3873 SIVAL(pdata,2,own_grp);
3874 SIVAL(pdata,6,0);
3875 break;
3877 case SMB_ACL_MASK:
3878 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3879 SIVAL(pdata,2,0xFFFFFFFF);
3880 SIVAL(pdata,6,0xFFFFFFFF);
3881 break;
3882 case SMB_ACL_OTHER:
3883 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3884 SIVAL(pdata,2,0xFFFFFFFF);
3885 SIVAL(pdata,6,0xFFFFFFFF);
3886 break;
3887 default:
3888 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3889 return False;
3891 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3894 return True;
3896 #endif
3898 /****************************************************************************
3899 Store the FILE_UNIX_BASIC info.
3900 ****************************************************************************/
3902 static char *store_file_unix_basic(connection_struct *conn,
3903 char *pdata,
3904 files_struct *fsp,
3905 const SMB_STRUCT_STAT *psbuf)
3907 uint64_t file_index = get_FileIndex(conn, psbuf);
3909 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3910 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3912 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3913 pdata += 8;
3915 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3916 pdata += 8;
3918 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3919 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3920 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3921 pdata += 24;
3923 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3924 SIVAL(pdata,4,0);
3925 pdata += 8;
3927 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3928 SIVAL(pdata,4,0);
3929 pdata += 8;
3931 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3932 pdata += 4;
3934 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3935 SIVAL(pdata,4,0);
3936 pdata += 8;
3938 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3939 SIVAL(pdata,4,0);
3940 pdata += 8;
3942 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3943 pdata += 8;
3945 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3946 SIVAL(pdata,4,0);
3947 pdata += 8;
3949 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3950 SIVAL(pdata,4,0);
3951 pdata += 8;
3953 return pdata;
3956 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3957 * the chflags(2) (or equivalent) flags.
3959 * XXX: this really should be behind the VFS interface. To do this, we would
3960 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3961 * Each VFS module could then implement its own mapping as appropriate for the
3962 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3964 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3965 info2_flags_map[] =
3967 #ifdef UF_NODUMP
3968 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3969 #endif
3971 #ifdef UF_IMMUTABLE
3972 { UF_IMMUTABLE, EXT_IMMUTABLE },
3973 #endif
3975 #ifdef UF_APPEND
3976 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3977 #endif
3979 #ifdef UF_HIDDEN
3980 { UF_HIDDEN, EXT_HIDDEN },
3981 #endif
3983 /* Do not remove. We need to guarantee that this array has at least one
3984 * entry to build on HP-UX.
3986 { 0, 0 }
3990 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3991 uint32 *smb_fflags, uint32 *smb_fmask)
3993 int i;
3995 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3996 *smb_fmask |= info2_flags_map[i].smb_fflag;
3997 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3998 *smb_fflags |= info2_flags_map[i].smb_fflag;
4003 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4004 const uint32 smb_fflags,
4005 const uint32 smb_fmask,
4006 int *stat_fflags)
4008 uint32 max_fmask = 0;
4009 int i;
4011 *stat_fflags = psbuf->st_ex_flags;
4013 /* For each flags requested in smb_fmask, check the state of the
4014 * corresponding flag in smb_fflags and set or clear the matching
4015 * stat flag.
4018 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4019 max_fmask |= info2_flags_map[i].smb_fflag;
4020 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4021 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4022 *stat_fflags |= info2_flags_map[i].stat_fflag;
4023 } else {
4024 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4029 /* If smb_fmask is asking to set any bits that are not supported by
4030 * our flag mappings, we should fail.
4032 if ((smb_fmask & max_fmask) != smb_fmask) {
4033 return False;
4036 return True;
4040 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4041 * of file flags and birth (create) time.
4043 static char *store_file_unix_basic_info2(connection_struct *conn,
4044 char *pdata,
4045 files_struct *fsp,
4046 const SMB_STRUCT_STAT *psbuf)
4048 uint32 file_flags = 0;
4049 uint32 flags_mask = 0;
4051 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4053 /* Create (birth) time 64 bit */
4054 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4055 pdata += 8;
4057 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4058 SIVAL(pdata, 0, file_flags); /* flags */
4059 SIVAL(pdata, 4, flags_mask); /* mask */
4060 pdata += 8;
4062 return pdata;
4065 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4066 const struct stream_struct *streams,
4067 char *data,
4068 unsigned int max_data_bytes,
4069 unsigned int *data_size)
4071 unsigned int i;
4072 unsigned int ofs = 0;
4074 for (i = 0; i < num_streams; i++) {
4075 unsigned int next_offset;
4076 size_t namelen;
4077 smb_ucs2_t *namebuf;
4079 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4080 streams[i].name, &namelen) ||
4081 namelen <= 2)
4083 return NT_STATUS_INVALID_PARAMETER;
4087 * name_buf is now null-terminated, we need to marshall as not
4088 * terminated
4091 namelen -= 2;
4094 * We cannot overflow ...
4096 if ((ofs + 24 + namelen) > max_data_bytes) {
4097 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4098 i));
4099 TALLOC_FREE(namebuf);
4100 return STATUS_BUFFER_OVERFLOW;
4103 SIVAL(data, ofs+4, namelen);
4104 SOFF_T(data, ofs+8, streams[i].size);
4105 SOFF_T(data, ofs+16, streams[i].alloc_size);
4106 memcpy(data+ofs+24, namebuf, namelen);
4107 TALLOC_FREE(namebuf);
4109 next_offset = ofs + 24 + namelen;
4111 if (i == num_streams-1) {
4112 SIVAL(data, ofs, 0);
4114 else {
4115 unsigned int align = ndr_align_size(next_offset, 8);
4117 if ((next_offset + align) > max_data_bytes) {
4118 DEBUG(10, ("refusing to overflow align "
4119 "reply at stream %u\n",
4120 i));
4121 TALLOC_FREE(namebuf);
4122 return STATUS_BUFFER_OVERFLOW;
4125 memset(data+next_offset, 0, align);
4126 next_offset += align;
4128 SIVAL(data, ofs, next_offset - ofs);
4129 ofs = next_offset;
4132 ofs = next_offset;
4135 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4137 *data_size = ofs;
4139 return NT_STATUS_OK;
4142 /****************************************************************************
4143 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4144 ****************************************************************************/
4146 static void call_trans2qpipeinfo(connection_struct *conn,
4147 struct smb_request *req,
4148 unsigned int tran_call,
4149 char **pparams, int total_params,
4150 char **ppdata, int total_data,
4151 unsigned int max_data_bytes)
4153 char *params = *pparams;
4154 char *pdata = *ppdata;
4155 unsigned int data_size = 0;
4156 unsigned int param_size = 2;
4157 uint16 info_level;
4158 files_struct *fsp;
4160 if (!params) {
4161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4162 return;
4165 if (total_params < 4) {
4166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4167 return;
4170 fsp = file_fsp(req, SVAL(params,0));
4171 if (!fsp_is_np(fsp)) {
4172 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4173 return;
4176 info_level = SVAL(params,2);
4178 *pparams = (char *)SMB_REALLOC(*pparams,2);
4179 if (*pparams == NULL) {
4180 reply_nterror(req, NT_STATUS_NO_MEMORY);
4181 return;
4183 params = *pparams;
4184 SSVAL(params,0,0);
4185 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4186 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4187 if (*ppdata == NULL ) {
4188 reply_nterror(req, NT_STATUS_NO_MEMORY);
4189 return;
4191 pdata = *ppdata;
4193 switch (info_level) {
4194 case SMB_FILE_STANDARD_INFORMATION:
4195 memset(pdata,0,24);
4196 SOFF_T(pdata,0,4096LL);
4197 SIVAL(pdata,16,1);
4198 SIVAL(pdata,20,1);
4199 data_size = 24;
4200 break;
4202 default:
4203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4204 return;
4207 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4208 max_data_bytes);
4210 return;
4213 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4214 TALLOC_CTX *mem_ctx,
4215 uint16_t info_level,
4216 files_struct *fsp,
4217 struct smb_filename *smb_fname,
4218 bool delete_pending,
4219 struct timespec write_time_ts,
4220 struct ea_list *ea_list,
4221 int lock_data_count,
4222 char *lock_data,
4223 uint16_t flags2,
4224 unsigned int max_data_bytes,
4225 char **ppdata,
4226 unsigned int *pdata_size)
4228 char *pdata = *ppdata;
4229 char *dstart, *dend;
4230 unsigned int data_size;
4231 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4232 time_t create_time, mtime, atime, c_time;
4233 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4234 char *p;
4235 char *base_name;
4236 char *dos_fname;
4237 int mode;
4238 int nlink;
4239 NTSTATUS status;
4240 uint64_t file_size = 0;
4241 uint64_t pos = 0;
4242 uint64_t allocation_size = 0;
4243 uint64_t file_index = 0;
4244 uint32_t access_mask = 0;
4246 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4247 return NT_STATUS_INVALID_LEVEL;
4250 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4251 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4252 info_level, max_data_bytes));
4254 mode = dos_mode(conn, smb_fname);
4255 nlink = psbuf->st_ex_nlink;
4257 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4258 nlink = 1;
4261 if ((nlink > 0) && delete_pending) {
4262 nlink -= 1;
4265 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4266 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4267 if (*ppdata == NULL) {
4268 return NT_STATUS_NO_MEMORY;
4270 pdata = *ppdata;
4271 dstart = pdata;
4272 dend = dstart + data_size - 1;
4274 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4275 update_stat_ex_mtime(psbuf, write_time_ts);
4278 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4279 mtime_ts = psbuf->st_ex_mtime;
4280 atime_ts = psbuf->st_ex_atime;
4281 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4283 if (lp_dos_filetime_resolution(SNUM(conn))) {
4284 dos_filetime_timespec(&create_time_ts);
4285 dos_filetime_timespec(&mtime_ts);
4286 dos_filetime_timespec(&atime_ts);
4287 dos_filetime_timespec(&ctime_ts);
4290 create_time = convert_timespec_to_time_t(create_time_ts);
4291 mtime = convert_timespec_to_time_t(mtime_ts);
4292 atime = convert_timespec_to_time_t(atime_ts);
4293 c_time = convert_timespec_to_time_t(ctime_ts);
4295 p = strrchr_m(smb_fname->base_name,'/');
4296 if (!p)
4297 base_name = smb_fname->base_name;
4298 else
4299 base_name = p+1;
4301 /* NT expects the name to be in an exact form of the *full*
4302 filename. See the trans2 torture test */
4303 if (ISDOT(base_name)) {
4304 dos_fname = talloc_strdup(mem_ctx, "\\");
4305 if (!dos_fname) {
4306 return NT_STATUS_NO_MEMORY;
4308 } else {
4309 dos_fname = talloc_asprintf(mem_ctx,
4310 "\\%s",
4311 smb_fname->base_name);
4312 if (!dos_fname) {
4313 return NT_STATUS_NO_MEMORY;
4315 if (is_ntfs_stream_smb_fname(smb_fname)) {
4316 dos_fname = talloc_asprintf(dos_fname, "%s",
4317 smb_fname->stream_name);
4318 if (!dos_fname) {
4319 return NT_STATUS_NO_MEMORY;
4323 string_replace(dos_fname, '/', '\\');
4326 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4328 if (!fsp) {
4329 /* Do we have this path open ? */
4330 files_struct *fsp1;
4331 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4332 fsp1 = file_find_di_first(conn->sconn, fileid);
4333 if (fsp1 && fsp1->initial_allocation_size) {
4334 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4338 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4339 file_size = get_file_size_stat(psbuf);
4342 if (fsp) {
4343 pos = fsp->fh->position_information;
4346 if (fsp) {
4347 access_mask = fsp->access_mask;
4348 } else {
4349 /* GENERIC_EXECUTE mapping from Windows */
4350 access_mask = 0x12019F;
4353 /* This should be an index number - looks like
4354 dev/ino to me :-)
4356 I think this causes us to fail the IFSKIT
4357 BasicFileInformationTest. -tpot */
4358 file_index = get_FileIndex(conn, psbuf);
4360 switch (info_level) {
4361 case SMB_INFO_STANDARD:
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4363 data_size = 22;
4364 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4365 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4366 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4367 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4368 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4369 SSVAL(pdata,l1_attrFile,mode);
4370 break;
4372 case SMB_INFO_QUERY_EA_SIZE:
4374 unsigned int ea_size =
4375 estimate_ea_size(conn, fsp,
4376 smb_fname->base_name);
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4378 data_size = 26;
4379 srv_put_dos_date2(pdata,0,create_time);
4380 srv_put_dos_date2(pdata,4,atime);
4381 srv_put_dos_date2(pdata,8,mtime); /* write time */
4382 SIVAL(pdata,12,(uint32)file_size);
4383 SIVAL(pdata,16,(uint32)allocation_size);
4384 SSVAL(pdata,20,mode);
4385 SIVAL(pdata,22,ea_size);
4386 break;
4389 case SMB_INFO_IS_NAME_VALID:
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4391 if (fsp) {
4392 /* os/2 needs this ? really ?*/
4393 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4395 /* This is only reached for qpathinfo */
4396 data_size = 0;
4397 break;
4399 case SMB_INFO_QUERY_EAS_FROM_LIST:
4401 size_t total_ea_len = 0;
4402 struct ea_list *ea_file_list = NULL;
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4406 ea_file_list =
4407 get_ea_list_from_file(mem_ctx, conn, fsp,
4408 smb_fname->base_name,
4409 &total_ea_len);
4410 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4412 if (!ea_list || (total_ea_len > data_size)) {
4413 data_size = 4;
4414 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4415 break;
4418 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4419 break;
4422 case SMB_INFO_QUERY_ALL_EAS:
4424 /* We have data_size bytes to put EA's into. */
4425 size_t total_ea_len = 0;
4427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4429 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4430 smb_fname->base_name,
4431 &total_ea_len);
4432 if (!ea_list || (total_ea_len > data_size)) {
4433 data_size = 4;
4434 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4435 break;
4438 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4439 break;
4442 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4444 /* This is FileFullEaInformation - 0xF which maps to
4445 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4447 /* We have data_size bytes to put EA's into. */
4448 size_t total_ea_len = 0;
4449 struct ea_list *ea_file_list = NULL;
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4453 /*TODO: add filtering and index handling */
4455 ea_file_list =
4456 get_ea_list_from_file(mem_ctx, conn, fsp,
4457 smb_fname->base_name,
4458 &total_ea_len);
4459 if (!ea_file_list) {
4460 return NT_STATUS_NO_EAS_ON_FILE;
4463 status = fill_ea_chained_buffer(mem_ctx,
4464 pdata,
4465 data_size,
4466 &data_size,
4467 conn, ea_file_list);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 return status;
4471 break;
4474 case SMB_FILE_BASIC_INFORMATION:
4475 case SMB_QUERY_FILE_BASIC_INFO:
4477 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4479 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4480 } else {
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4482 data_size = 40;
4483 SIVAL(pdata,36,0);
4485 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4486 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4487 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4488 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4489 SIVAL(pdata,32,mode);
4491 DEBUG(5,("SMB_QFBI - "));
4492 DEBUG(5,("create: %s ", ctime(&create_time)));
4493 DEBUG(5,("access: %s ", ctime(&atime)));
4494 DEBUG(5,("write: %s ", ctime(&mtime)));
4495 DEBUG(5,("change: %s ", ctime(&c_time)));
4496 DEBUG(5,("mode: %x\n", mode));
4497 break;
4499 case SMB_FILE_STANDARD_INFORMATION:
4500 case SMB_QUERY_FILE_STANDARD_INFO:
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4503 data_size = 24;
4504 SOFF_T(pdata,0,allocation_size);
4505 SOFF_T(pdata,8,file_size);
4506 SIVAL(pdata,16,nlink);
4507 SCVAL(pdata,20,delete_pending?1:0);
4508 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4509 SSVAL(pdata,22,0); /* Padding. */
4510 break;
4512 case SMB_FILE_EA_INFORMATION:
4513 case SMB_QUERY_FILE_EA_INFO:
4515 unsigned int ea_size =
4516 estimate_ea_size(conn, fsp, smb_fname->base_name);
4517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4518 data_size = 4;
4519 SIVAL(pdata,0,ea_size);
4520 break;
4523 /* Get the 8.3 name - used if NT SMB was negotiated. */
4524 case SMB_QUERY_FILE_ALT_NAME_INFO:
4525 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4527 int len;
4528 char mangled_name[13];
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4530 if (!name_to_8_3(base_name,mangled_name,
4531 True,conn->params)) {
4532 return NT_STATUS_NO_MEMORY;
4534 len = srvstr_push(dstart, flags2,
4535 pdata+4, mangled_name,
4536 PTR_DIFF(dend, pdata+4),
4537 STR_UNICODE);
4538 data_size = 4 + len;
4539 SIVAL(pdata,0,len);
4540 break;
4543 case SMB_QUERY_FILE_NAME_INFO:
4545 int len;
4547 this must be *exactly* right for ACLs on mapped drives to work
4549 len = srvstr_push(dstart, flags2,
4550 pdata+4, dos_fname,
4551 PTR_DIFF(dend, pdata+4),
4552 STR_UNICODE);
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4554 data_size = 4 + len;
4555 SIVAL(pdata,0,len);
4556 break;
4559 case SMB_FILE_ALLOCATION_INFORMATION:
4560 case SMB_QUERY_FILE_ALLOCATION_INFO:
4561 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4562 data_size = 8;
4563 SOFF_T(pdata,0,allocation_size);
4564 break;
4566 case SMB_FILE_END_OF_FILE_INFORMATION:
4567 case SMB_QUERY_FILE_END_OF_FILEINFO:
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4569 data_size = 8;
4570 SOFF_T(pdata,0,file_size);
4571 break;
4573 case SMB_QUERY_FILE_ALL_INFO:
4574 case SMB_FILE_ALL_INFORMATION:
4576 int len;
4577 unsigned int ea_size =
4578 estimate_ea_size(conn, fsp, smb_fname->base_name);
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4580 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4581 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4582 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4583 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4584 SIVAL(pdata,32,mode);
4585 SIVAL(pdata,36,0); /* padding. */
4586 pdata += 40;
4587 SOFF_T(pdata,0,allocation_size);
4588 SOFF_T(pdata,8,file_size);
4589 SIVAL(pdata,16,nlink);
4590 SCVAL(pdata,20,delete_pending);
4591 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4592 SSVAL(pdata,22,0);
4593 pdata += 24;
4594 SIVAL(pdata,0,ea_size);
4595 pdata += 4; /* EA info */
4596 len = srvstr_push(dstart, flags2,
4597 pdata+4, dos_fname,
4598 PTR_DIFF(dend, pdata+4),
4599 STR_UNICODE);
4600 SIVAL(pdata,0,len);
4601 pdata += 4 + len;
4602 data_size = PTR_DIFF(pdata,(*ppdata));
4603 break;
4606 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4608 int len;
4609 unsigned int ea_size =
4610 estimate_ea_size(conn, fsp, smb_fname->base_name);
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4612 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4613 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4614 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4615 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4616 SIVAL(pdata, 0x20, mode);
4617 SIVAL(pdata, 0x24, 0); /* padding. */
4618 SBVAL(pdata, 0x28, allocation_size);
4619 SBVAL(pdata, 0x30, file_size);
4620 SIVAL(pdata, 0x38, nlink);
4621 SCVAL(pdata, 0x3C, delete_pending);
4622 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4623 SSVAL(pdata, 0x3E, 0); /* padding */
4624 SBVAL(pdata, 0x40, file_index);
4625 SIVAL(pdata, 0x48, ea_size);
4626 SIVAL(pdata, 0x4C, access_mask);
4627 SBVAL(pdata, 0x50, pos);
4628 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4629 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4631 pdata += 0x60;
4633 len = srvstr_push(dstart, flags2,
4634 pdata+4, dos_fname,
4635 PTR_DIFF(dend, pdata+4),
4636 STR_UNICODE);
4637 SIVAL(pdata,0,len);
4638 pdata += 4 + len;
4639 data_size = PTR_DIFF(pdata,(*ppdata));
4640 break;
4642 case SMB_FILE_INTERNAL_INFORMATION:
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4645 SBVAL(pdata, 0, file_index);
4646 data_size = 8;
4647 break;
4649 case SMB_FILE_ACCESS_INFORMATION:
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4651 SIVAL(pdata, 0, access_mask);
4652 data_size = 4;
4653 break;
4655 case SMB_FILE_NAME_INFORMATION:
4656 /* Pathname with leading '\'. */
4658 size_t byte_len;
4659 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4661 SIVAL(pdata,0,byte_len);
4662 data_size = 4 + byte_len;
4663 break;
4666 case SMB_FILE_DISPOSITION_INFORMATION:
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4668 data_size = 1;
4669 SCVAL(pdata,0,delete_pending);
4670 break;
4672 case SMB_FILE_POSITION_INFORMATION:
4673 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4674 data_size = 8;
4675 SOFF_T(pdata,0,pos);
4676 break;
4678 case SMB_FILE_MODE_INFORMATION:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4680 SIVAL(pdata,0,mode);
4681 data_size = 4;
4682 break;
4684 case SMB_FILE_ALIGNMENT_INFORMATION:
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4686 SIVAL(pdata,0,0); /* No alignment needed. */
4687 data_size = 4;
4688 break;
4691 * NT4 server just returns "invalid query" to this - if we try
4692 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4693 * want this. JRA.
4695 /* The first statement above is false - verified using Thursby
4696 * client against NT4 -- gcolley.
4698 case SMB_QUERY_FILE_STREAM_INFO:
4699 case SMB_FILE_STREAM_INFORMATION: {
4700 unsigned int num_streams = 0;
4701 struct stream_struct *streams = NULL;
4703 DEBUG(10,("smbd_do_qfilepathinfo: "
4704 "SMB_FILE_STREAM_INFORMATION\n"));
4706 if (is_ntfs_stream_smb_fname(smb_fname)) {
4707 return NT_STATUS_INVALID_PARAMETER;
4710 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4711 talloc_tos(), &num_streams, &streams);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 DEBUG(10, ("could not get stream info: %s\n",
4715 nt_errstr(status)));
4716 return status;
4719 status = marshall_stream_info(num_streams, streams,
4720 pdata, max_data_bytes,
4721 &data_size);
4723 if (!NT_STATUS_IS_OK(status)) {
4724 DEBUG(10, ("marshall_stream_info failed: %s\n",
4725 nt_errstr(status)));
4726 TALLOC_FREE(streams);
4727 return status;
4730 TALLOC_FREE(streams);
4732 break;
4734 case SMB_QUERY_COMPRESSION_INFO:
4735 case SMB_FILE_COMPRESSION_INFORMATION:
4736 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4737 SOFF_T(pdata,0,file_size);
4738 SIVAL(pdata,8,0); /* ??? */
4739 SIVAL(pdata,12,0); /* ??? */
4740 data_size = 16;
4741 break;
4743 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4745 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4746 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4747 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4748 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4749 SOFF_T(pdata,32,allocation_size);
4750 SOFF_T(pdata,40,file_size);
4751 SIVAL(pdata,48,mode);
4752 SIVAL(pdata,52,0); /* ??? */
4753 data_size = 56;
4754 break;
4756 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4758 SIVAL(pdata,0,mode);
4759 SIVAL(pdata,4,0);
4760 data_size = 8;
4761 break;
4764 * CIFS UNIX Extensions.
4767 case SMB_QUERY_FILE_UNIX_BASIC:
4769 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4770 data_size = PTR_DIFF(pdata,(*ppdata));
4772 DEBUG(4,("smbd_do_qfilepathinfo: "
4773 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4774 dump_data(4, (uint8_t *)(*ppdata), data_size);
4776 break;
4778 case SMB_QUERY_FILE_UNIX_INFO2:
4780 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4781 data_size = PTR_DIFF(pdata,(*ppdata));
4784 int i;
4785 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4787 for (i=0; i<100; i++)
4788 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4789 DEBUG(4,("\n"));
4792 break;
4794 case SMB_QUERY_FILE_UNIX_LINK:
4796 int len;
4797 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4799 if (!buffer) {
4800 return NT_STATUS_NO_MEMORY;
4803 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4804 #ifdef S_ISLNK
4805 if(!S_ISLNK(psbuf->st_ex_mode)) {
4806 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4808 #else
4809 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4810 #endif
4811 len = SMB_VFS_READLINK(conn,
4812 smb_fname->base_name,
4813 buffer, PATH_MAX);
4814 if (len == -1) {
4815 return map_nt_error_from_unix(errno);
4817 buffer[len] = 0;
4818 len = srvstr_push(dstart, flags2,
4819 pdata, buffer,
4820 PTR_DIFF(dend, pdata),
4821 STR_TERMINATE);
4822 pdata += len;
4823 data_size = PTR_DIFF(pdata,(*ppdata));
4825 break;
4828 #if defined(HAVE_POSIX_ACLS)
4829 case SMB_QUERY_POSIX_ACL:
4831 SMB_ACL_T file_acl = NULL;
4832 SMB_ACL_T def_acl = NULL;
4833 uint16 num_file_acls = 0;
4834 uint16 num_def_acls = 0;
4836 if (fsp && fsp->fh->fd != -1) {
4837 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4838 } else {
4839 file_acl =
4840 SMB_VFS_SYS_ACL_GET_FILE(conn,
4841 smb_fname->base_name,
4842 SMB_ACL_TYPE_ACCESS);
4845 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4846 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4847 "not implemented on "
4848 "filesystem containing %s\n",
4849 smb_fname->base_name));
4850 return NT_STATUS_NOT_IMPLEMENTED;
4853 if (S_ISDIR(psbuf->st_ex_mode)) {
4854 if (fsp && fsp->is_directory) {
4855 def_acl =
4856 SMB_VFS_SYS_ACL_GET_FILE(
4857 conn,
4858 fsp->fsp_name->base_name,
4859 SMB_ACL_TYPE_DEFAULT);
4860 } else {
4861 def_acl =
4862 SMB_VFS_SYS_ACL_GET_FILE(
4863 conn,
4864 smb_fname->base_name,
4865 SMB_ACL_TYPE_DEFAULT);
4867 def_acl = free_empty_sys_acl(conn, def_acl);
4870 num_file_acls = count_acl_entries(conn, file_acl);
4871 num_def_acls = count_acl_entries(conn, def_acl);
4873 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4874 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4875 data_size,
4876 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4877 SMB_POSIX_ACL_HEADER_SIZE) ));
4878 if (file_acl) {
4879 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4881 if (def_acl) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4884 return NT_STATUS_BUFFER_TOO_SMALL;
4887 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4888 SSVAL(pdata,2,num_file_acls);
4889 SSVAL(pdata,4,num_def_acls);
4890 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_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;
4899 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
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 return NT_STATUS_INTERNAL_ERROR;
4909 if (file_acl) {
4910 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4912 if (def_acl) {
4913 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4915 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4916 break;
4918 #endif
4921 case SMB_QUERY_POSIX_LOCK:
4923 uint64_t count;
4924 uint64_t offset;
4925 uint64_t smblctx;
4926 enum brl_type lock_type;
4928 /* We need an open file with a real fd for this. */
4929 if (!fsp || fsp->fh->fd == -1) {
4930 return NT_STATUS_INVALID_LEVEL;
4933 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4934 return NT_STATUS_INVALID_PARAMETER;
4937 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4938 case POSIX_LOCK_TYPE_READ:
4939 lock_type = READ_LOCK;
4940 break;
4941 case POSIX_LOCK_TYPE_WRITE:
4942 lock_type = WRITE_LOCK;
4943 break;
4944 case POSIX_LOCK_TYPE_UNLOCK:
4945 default:
4946 /* There's no point in asking for an unlock... */
4947 return NT_STATUS_INVALID_PARAMETER;
4950 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4951 #if defined(HAVE_LONGLONG)
4952 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4953 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4954 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4955 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4956 #else /* HAVE_LONGLONG */
4957 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4958 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4959 #endif /* HAVE_LONGLONG */
4961 status = query_lock(fsp,
4962 &smblctx,
4963 &count,
4964 &offset,
4965 &lock_type,
4966 POSIX_LOCK);
4968 if (ERROR_WAS_LOCK_DENIED(status)) {
4969 /* Here we need to report who has it locked... */
4970 data_size = POSIX_LOCK_DATA_SIZE;
4972 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4973 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4974 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4975 #if defined(HAVE_LONGLONG)
4976 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4977 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4978 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4979 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4980 #else /* HAVE_LONGLONG */
4981 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4982 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4983 #endif /* HAVE_LONGLONG */
4985 } else if (NT_STATUS_IS_OK(status)) {
4986 /* For success we just return a copy of what we sent
4987 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4988 data_size = POSIX_LOCK_DATA_SIZE;
4989 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4990 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4991 } else {
4992 return status;
4994 break;
4997 default:
4998 return NT_STATUS_INVALID_LEVEL;
5001 *pdata_size = data_size;
5002 return NT_STATUS_OK;
5005 /****************************************************************************
5006 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5007 file name or file id).
5008 ****************************************************************************/
5010 static void call_trans2qfilepathinfo(connection_struct *conn,
5011 struct smb_request *req,
5012 unsigned int tran_call,
5013 char **pparams, int total_params,
5014 char **ppdata, int total_data,
5015 unsigned int max_data_bytes)
5017 char *params = *pparams;
5018 char *pdata = *ppdata;
5019 uint16 info_level;
5020 unsigned int data_size = 0;
5021 unsigned int param_size = 2;
5022 struct smb_filename *smb_fname = NULL;
5023 bool delete_pending = False;
5024 struct timespec write_time_ts;
5025 files_struct *fsp = NULL;
5026 struct file_id fileid;
5027 struct ea_list *ea_list = NULL;
5028 int lock_data_count = 0;
5029 char *lock_data = NULL;
5030 NTSTATUS status = NT_STATUS_OK;
5032 if (!params) {
5033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5034 return;
5037 ZERO_STRUCT(write_time_ts);
5039 if (tran_call == TRANSACT2_QFILEINFO) {
5040 if (total_params < 4) {
5041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5042 return;
5045 if (IS_IPC(conn)) {
5046 call_trans2qpipeinfo(conn, req, tran_call,
5047 pparams, total_params,
5048 ppdata, total_data,
5049 max_data_bytes);
5050 return;
5053 fsp = file_fsp(req, SVAL(params,0));
5054 info_level = SVAL(params,2);
5056 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5058 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5059 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5060 return;
5063 /* Initial check for valid fsp ptr. */
5064 if (!check_fsp_open(conn, req, fsp)) {
5065 return;
5068 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5069 &smb_fname);
5070 if (!NT_STATUS_IS_OK(status)) {
5071 reply_nterror(req, status);
5072 return;
5075 if(fsp->fake_file_handle) {
5077 * This is actually for the QUOTA_FAKE_FILE --metze
5080 /* We know this name is ok, it's already passed the checks. */
5082 } else if(fsp->fh->fd == -1) {
5084 * This is actually a QFILEINFO on a directory
5085 * handle (returned from an NT SMB). NT5.0 seems
5086 * to do this call. JRA.
5089 if (INFO_LEVEL_IS_UNIX(info_level)) {
5090 /* Always do lstat for UNIX calls. */
5091 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5092 DEBUG(3,("call_trans2qfilepathinfo: "
5093 "SMB_VFS_LSTAT of %s failed "
5094 "(%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;
5101 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5102 DEBUG(3,("call_trans2qfilepathinfo: "
5103 "SMB_VFS_STAT of %s failed (%s)\n",
5104 smb_fname_str_dbg(smb_fname),
5105 strerror(errno)));
5106 reply_nterror(req,
5107 map_nt_error_from_unix(errno));
5108 return;
5111 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5112 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5113 } else {
5115 * Original code - this is an open file.
5117 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5118 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5119 fsp->fnum, strerror(errno)));
5120 reply_nterror(req,
5121 map_nt_error_from_unix(errno));
5122 return;
5124 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5125 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5128 } else {
5129 uint32_t name_hash;
5130 char *fname = NULL;
5131 uint32_t ucf_flags = 0;
5133 /* qpathinfo */
5134 if (total_params < 7) {
5135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5136 return;
5139 info_level = SVAL(params,0);
5141 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5143 if (INFO_LEVEL_IS_UNIX(info_level)) {
5144 if (!lp_unix_extensions()) {
5145 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5146 return;
5148 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5149 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5150 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5151 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5155 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5156 total_params - 6,
5157 STR_TERMINATE, &status);
5158 if (!NT_STATUS_IS_OK(status)) {
5159 reply_nterror(req, status);
5160 return;
5163 status = filename_convert(req,
5164 conn,
5165 req->flags2 & FLAGS2_DFS_PATHNAMES,
5166 fname,
5167 ucf_flags,
5168 NULL,
5169 &smb_fname);
5170 if (!NT_STATUS_IS_OK(status)) {
5171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5172 reply_botherror(req,
5173 NT_STATUS_PATH_NOT_COVERED,
5174 ERRSRV, ERRbadpath);
5175 return;
5177 reply_nterror(req, status);
5178 return;
5181 /* If this is a stream, check if there is a delete_pending. */
5182 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5183 && is_ntfs_stream_smb_fname(smb_fname)) {
5184 struct smb_filename *smb_fname_base = NULL;
5186 /* Create an smb_filename with stream_name == NULL. */
5187 status =
5188 create_synthetic_smb_fname(talloc_tos(),
5189 smb_fname->base_name,
5190 NULL, NULL,
5191 &smb_fname_base);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 reply_nterror(req, status);
5194 return;
5197 if (INFO_LEVEL_IS_UNIX(info_level)) {
5198 /* Always do lstat for UNIX calls. */
5199 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5200 DEBUG(3,("call_trans2qfilepathinfo: "
5201 "SMB_VFS_LSTAT of %s failed "
5202 "(%s)\n",
5203 smb_fname_str_dbg(smb_fname_base),
5204 strerror(errno)));
5205 TALLOC_FREE(smb_fname_base);
5206 reply_nterror(req,
5207 map_nt_error_from_unix(errno));
5208 return;
5210 } else {
5211 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5212 DEBUG(3,("call_trans2qfilepathinfo: "
5213 "fileinfo of %s failed "
5214 "(%s)\n",
5215 smb_fname_str_dbg(smb_fname_base),
5216 strerror(errno)));
5217 TALLOC_FREE(smb_fname_base);
5218 reply_nterror(req,
5219 map_nt_error_from_unix(errno));
5220 return;
5224 status = file_name_hash(conn,
5225 smb_fname_str_dbg(smb_fname_base),
5226 &name_hash);
5227 if (!NT_STATUS_IS_OK(status)) {
5228 TALLOC_FREE(smb_fname_base);
5229 reply_nterror(req, status);
5230 return;
5233 fileid = vfs_file_id_from_sbuf(conn,
5234 &smb_fname_base->st);
5235 TALLOC_FREE(smb_fname_base);
5236 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5237 if (delete_pending) {
5238 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5239 return;
5243 if (INFO_LEVEL_IS_UNIX(info_level)) {
5244 /* Always do lstat for UNIX calls. */
5245 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5246 DEBUG(3,("call_trans2qfilepathinfo: "
5247 "SMB_VFS_LSTAT of %s failed (%s)\n",
5248 smb_fname_str_dbg(smb_fname),
5249 strerror(errno)));
5250 reply_nterror(req,
5251 map_nt_error_from_unix(errno));
5252 return;
5255 } else {
5256 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5257 DEBUG(3,("call_trans2qfilepathinfo: "
5258 "SMB_VFS_STAT of %s failed (%s)\n",
5259 smb_fname_str_dbg(smb_fname),
5260 strerror(errno)));
5261 reply_nterror(req,
5262 map_nt_error_from_unix(errno));
5263 return;
5267 status = file_name_hash(conn,
5268 smb_fname_str_dbg(smb_fname),
5269 &name_hash);
5270 if (!NT_STATUS_IS_OK(status)) {
5271 reply_nterror(req, status);
5272 return;
5275 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5276 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5277 if (delete_pending) {
5278 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5279 return;
5283 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5284 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5285 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5287 /* Pull out any data sent here before we realloc. */
5288 switch (info_level) {
5289 case SMB_INFO_QUERY_EAS_FROM_LIST:
5291 /* Pull any EA list from the data portion. */
5292 uint32 ea_size;
5294 if (total_data < 4) {
5295 reply_nterror(
5296 req, NT_STATUS_INVALID_PARAMETER);
5297 return;
5299 ea_size = IVAL(pdata,0);
5301 if (total_data > 0 && ea_size != total_data) {
5302 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5303 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5304 reply_nterror(
5305 req, NT_STATUS_INVALID_PARAMETER);
5306 return;
5309 if (!lp_ea_support(SNUM(conn))) {
5310 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5311 return;
5314 /* Pull out the list of names. */
5315 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5316 if (!ea_list) {
5317 reply_nterror(
5318 req, NT_STATUS_INVALID_PARAMETER);
5319 return;
5321 break;
5324 case SMB_QUERY_POSIX_LOCK:
5326 if (fsp == NULL || fsp->fh->fd == -1) {
5327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5328 return;
5331 if (total_data != POSIX_LOCK_DATA_SIZE) {
5332 reply_nterror(
5333 req, NT_STATUS_INVALID_PARAMETER);
5334 return;
5337 /* Copy the lock range data. */
5338 lock_data = (char *)TALLOC_MEMDUP(
5339 req, pdata, total_data);
5340 if (!lock_data) {
5341 reply_nterror(req, NT_STATUS_NO_MEMORY);
5342 return;
5344 lock_data_count = total_data;
5346 default:
5347 break;
5350 *pparams = (char *)SMB_REALLOC(*pparams,2);
5351 if (*pparams == NULL) {
5352 reply_nterror(req, NT_STATUS_NO_MEMORY);
5353 return;
5355 params = *pparams;
5356 SSVAL(params,0,0);
5359 * draft-leach-cifs-v1-spec-02.txt
5360 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5361 * says:
5363 * The requested information is placed in the Data portion of the
5364 * transaction response. For the information levels greater than 0x100,
5365 * the transaction response has 1 parameter word which should be
5366 * ignored by the client.
5368 * However Windows only follows this rule for the IS_NAME_VALID call.
5370 switch (info_level) {
5371 case SMB_INFO_IS_NAME_VALID:
5372 param_size = 0;
5373 break;
5376 if ((info_level & 0xFF00) == 0xFF00) {
5378 * We use levels that start with 0xFF00
5379 * internally to represent SMB2 specific levels
5381 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5382 return;
5385 status = smbd_do_qfilepathinfo(conn, req, info_level,
5386 fsp, smb_fname,
5387 delete_pending, write_time_ts,
5388 ea_list,
5389 lock_data_count, lock_data,
5390 req->flags2, max_data_bytes,
5391 ppdata, &data_size);
5392 if (!NT_STATUS_IS_OK(status)) {
5393 reply_nterror(req, status);
5394 return;
5397 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5398 max_data_bytes);
5400 return;
5403 /****************************************************************************
5404 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5405 code.
5406 ****************************************************************************/
5408 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5409 connection_struct *conn,
5410 struct smb_request *req,
5411 bool overwrite_if_exists,
5412 const struct smb_filename *smb_fname_old,
5413 struct smb_filename *smb_fname_new)
5415 NTSTATUS status = NT_STATUS_OK;
5417 /* source must already exist. */
5418 if (!VALID_STAT(smb_fname_old->st)) {
5419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5422 if (VALID_STAT(smb_fname_new->st)) {
5423 if (overwrite_if_exists) {
5424 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5425 return NT_STATUS_FILE_IS_A_DIRECTORY;
5427 status = unlink_internals(conn,
5428 req,
5429 FILE_ATTRIBUTE_NORMAL,
5430 smb_fname_new,
5431 false);
5432 if (!NT_STATUS_IS_OK(status)) {
5433 return status;
5435 } else {
5436 /* Disallow if newname already exists. */
5437 return NT_STATUS_OBJECT_NAME_COLLISION;
5441 /* No links from a directory. */
5442 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5443 return NT_STATUS_FILE_IS_A_DIRECTORY;
5446 /* Setting a hardlink to/from a stream isn't currently supported. */
5447 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5448 is_ntfs_stream_smb_fname(smb_fname_new)) {
5449 return NT_STATUS_INVALID_PARAMETER;
5452 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5453 smb_fname_old->base_name, smb_fname_new->base_name));
5455 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5456 smb_fname_new->base_name) != 0) {
5457 status = map_nt_error_from_unix(errno);
5458 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5459 nt_errstr(status), smb_fname_old->base_name,
5460 smb_fname_new->base_name));
5462 return status;
5465 /****************************************************************************
5466 Deal with setting the time from any of the setfilepathinfo functions.
5467 ****************************************************************************/
5469 NTSTATUS smb_set_file_time(connection_struct *conn,
5470 files_struct *fsp,
5471 const struct smb_filename *smb_fname,
5472 struct smb_file_time *ft,
5473 bool setting_write_time)
5475 struct smb_filename smb_fname_base;
5476 uint32 action =
5477 FILE_NOTIFY_CHANGE_LAST_ACCESS
5478 |FILE_NOTIFY_CHANGE_LAST_WRITE
5479 |FILE_NOTIFY_CHANGE_CREATION;
5481 if (!VALID_STAT(smb_fname->st)) {
5482 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5485 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5486 return NT_STATUS_ACCESS_DENIED;
5489 /* get some defaults (no modifications) if any info is zero or -1. */
5490 if (null_timespec(ft->create_time)) {
5491 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5494 if (null_timespec(ft->atime)) {
5495 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5498 if (null_timespec(ft->mtime)) {
5499 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5502 if (!setting_write_time) {
5503 /* ft->mtime comes from change time, not write time. */
5504 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5507 /* Ensure the resolution is the correct for
5508 * what we can store on this filesystem. */
5510 round_timespec(conn->ts_res, &ft->create_time);
5511 round_timespec(conn->ts_res, &ft->ctime);
5512 round_timespec(conn->ts_res, &ft->atime);
5513 round_timespec(conn->ts_res, &ft->mtime);
5515 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5516 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5517 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5518 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5519 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5520 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5521 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5522 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5524 if (setting_write_time) {
5526 * This was a Windows setfileinfo on an open file.
5527 * NT does this a lot. We also need to
5528 * set the time here, as it can be read by
5529 * FindFirst/FindNext and with the patch for bug #2045
5530 * in smbd/fileio.c it ensures that this timestamp is
5531 * kept sticky even after a write. We save the request
5532 * away and will set it on file close and after a write. JRA.
5535 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5536 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5538 if (fsp != NULL) {
5539 if (fsp->base_fsp) {
5540 set_sticky_write_time_fsp(fsp->base_fsp,
5541 ft->mtime);
5542 } else {
5543 set_sticky_write_time_fsp(fsp, ft->mtime);
5545 } else {
5546 set_sticky_write_time_path(
5547 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5548 ft->mtime);
5552 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5554 /* Always call ntimes on the base, even if a stream was passed in. */
5555 smb_fname_base = *smb_fname;
5556 smb_fname_base.stream_name = NULL;
5558 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5559 return map_nt_error_from_unix(errno);
5562 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5563 smb_fname->base_name);
5564 return NT_STATUS_OK;
5567 /****************************************************************************
5568 Deal with setting the dosmode from any of the setfilepathinfo functions.
5569 ****************************************************************************/
5571 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5572 const struct smb_filename *smb_fname,
5573 uint32 dosmode)
5575 struct smb_filename *smb_fname_base = NULL;
5576 NTSTATUS status;
5578 if (!VALID_STAT(smb_fname->st)) {
5579 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5582 /* Always operate on the base_name, even if a stream was passed in. */
5583 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5584 NULL, &smb_fname->st,
5585 &smb_fname_base);
5586 if (!NT_STATUS_IS_OK(status)) {
5587 return status;
5590 if (dosmode) {
5591 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5592 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5593 } else {
5594 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5598 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5600 /* check the mode isn't different, before changing it */
5601 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5602 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5603 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5604 (unsigned int)dosmode));
5606 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5607 false)) {
5608 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5609 "%s failed (%s)\n",
5610 smb_fname_str_dbg(smb_fname_base),
5611 strerror(errno)));
5612 status = map_nt_error_from_unix(errno);
5613 goto out;
5616 status = NT_STATUS_OK;
5617 out:
5618 TALLOC_FREE(smb_fname_base);
5619 return status;
5622 /****************************************************************************
5623 Deal with setting the size from any of the setfilepathinfo functions.
5624 ****************************************************************************/
5626 static NTSTATUS smb_set_file_size(connection_struct *conn,
5627 struct smb_request *req,
5628 files_struct *fsp,
5629 const struct smb_filename *smb_fname,
5630 const SMB_STRUCT_STAT *psbuf,
5631 SMB_OFF_T size,
5632 bool fail_after_createfile)
5634 NTSTATUS status = NT_STATUS_OK;
5635 struct smb_filename *smb_fname_tmp = NULL;
5636 files_struct *new_fsp = NULL;
5638 if (!VALID_STAT(*psbuf)) {
5639 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5642 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5643 return NT_STATUS_ACCESS_DENIED;
5646 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5648 if (size == get_file_size_stat(psbuf)) {
5649 return NT_STATUS_OK;
5652 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5653 smb_fname_str_dbg(smb_fname), (double)size));
5655 if (fsp && fsp->fh->fd != -1) {
5656 /* Handle based call. */
5657 if (vfs_set_filelen(fsp, size) == -1) {
5658 return map_nt_error_from_unix(errno);
5660 trigger_write_time_update_immediate(fsp);
5661 return NT_STATUS_OK;
5664 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5665 if (!NT_STATUS_IS_OK(status)) {
5666 return status;
5669 smb_fname_tmp->st = *psbuf;
5671 status = SMB_VFS_CREATE_FILE(
5672 conn, /* conn */
5673 req, /* req */
5674 0, /* root_dir_fid */
5675 smb_fname_tmp, /* fname */
5676 FILE_WRITE_DATA, /* access_mask */
5677 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5678 FILE_SHARE_DELETE),
5679 FILE_OPEN, /* create_disposition*/
5680 0, /* create_options */
5681 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5682 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5683 0, /* allocation_size */
5684 0, /* private_flags */
5685 NULL, /* sd */
5686 NULL, /* ea_list */
5687 &new_fsp, /* result */
5688 NULL); /* pinfo */
5690 TALLOC_FREE(smb_fname_tmp);
5692 if (!NT_STATUS_IS_OK(status)) {
5693 /* NB. We check for open_was_deferred in the caller. */
5694 return status;
5697 /* See RAW-SFILEINFO-END-OF-FILE */
5698 if (fail_after_createfile) {
5699 close_file(req, new_fsp,NORMAL_CLOSE);
5700 return NT_STATUS_INVALID_LEVEL;
5703 if (vfs_set_filelen(new_fsp, size) == -1) {
5704 status = map_nt_error_from_unix(errno);
5705 close_file(req, new_fsp,NORMAL_CLOSE);
5706 return status;
5709 trigger_write_time_update_immediate(new_fsp);
5710 close_file(req, new_fsp,NORMAL_CLOSE);
5711 return NT_STATUS_OK;
5714 /****************************************************************************
5715 Deal with SMB_INFO_SET_EA.
5716 ****************************************************************************/
5718 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5719 const char *pdata,
5720 int total_data,
5721 files_struct *fsp,
5722 const struct smb_filename *smb_fname)
5724 struct ea_list *ea_list = NULL;
5725 TALLOC_CTX *ctx = NULL;
5726 NTSTATUS status = NT_STATUS_OK;
5728 if (total_data < 10) {
5730 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5731 length. They seem to have no effect. Bug #3212. JRA */
5733 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5734 /* We're done. We only get EA info in this call. */
5735 return NT_STATUS_OK;
5738 return NT_STATUS_INVALID_PARAMETER;
5741 if (IVAL(pdata,0) > total_data) {
5742 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5743 IVAL(pdata,0), (unsigned int)total_data));
5744 return NT_STATUS_INVALID_PARAMETER;
5747 ctx = talloc_tos();
5748 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5749 if (!ea_list) {
5750 return NT_STATUS_INVALID_PARAMETER;
5753 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5754 return NT_STATUS_ACCESS_DENIED;
5757 status = set_ea(conn, fsp, smb_fname, ea_list);
5759 return status;
5762 /****************************************************************************
5763 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5764 ****************************************************************************/
5766 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5767 const char *pdata,
5768 int total_data,
5769 files_struct *fsp)
5771 struct ea_list *ea_list = NULL;
5772 NTSTATUS status;
5774 if (!fsp) {
5775 return NT_STATUS_INVALID_HANDLE;
5778 if (!lp_ea_support(SNUM(conn))) {
5779 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5780 "EA's not supported.\n",
5781 (unsigned int)total_data));
5782 return NT_STATUS_EAS_NOT_SUPPORTED;
5785 if (total_data < 10) {
5786 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5787 "too small.\n",
5788 (unsigned int)total_data));
5789 return NT_STATUS_INVALID_PARAMETER;
5792 ea_list = read_nttrans_ea_list(talloc_tos(),
5793 pdata,
5794 total_data);
5796 if (!ea_list) {
5797 return NT_STATUS_INVALID_PARAMETER;
5800 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5801 return NT_STATUS_ACCESS_DENIED;
5804 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5806 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5807 smb_fname_str_dbg(fsp->fsp_name),
5808 nt_errstr(status) ));
5810 return status;
5814 /****************************************************************************
5815 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5816 ****************************************************************************/
5818 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5819 const char *pdata,
5820 int total_data,
5821 files_struct *fsp,
5822 struct smb_filename *smb_fname)
5824 NTSTATUS status = NT_STATUS_OK;
5825 bool delete_on_close;
5826 uint32 dosmode = 0;
5828 if (total_data < 1) {
5829 return NT_STATUS_INVALID_PARAMETER;
5832 if (fsp == NULL) {
5833 return NT_STATUS_INVALID_HANDLE;
5836 delete_on_close = (CVAL(pdata,0) ? True : False);
5837 dosmode = dos_mode(conn, smb_fname);
5839 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5840 "delete_on_close = %u\n",
5841 smb_fname_str_dbg(smb_fname),
5842 (unsigned int)dosmode,
5843 (unsigned int)delete_on_close ));
5845 if (delete_on_close) {
5846 status = can_set_delete_on_close(fsp, dosmode);
5847 if (!NT_STATUS_IS_OK(status)) {
5848 return status;
5852 /* The set is across all open files on this dev/inode pair. */
5853 if (!set_delete_on_close(fsp, delete_on_close,
5854 conn->session_info->security_token,
5855 &conn->session_info->utok)) {
5856 return NT_STATUS_ACCESS_DENIED;
5858 return NT_STATUS_OK;
5861 /****************************************************************************
5862 Deal with SMB_FILE_POSITION_INFORMATION.
5863 ****************************************************************************/
5865 static NTSTATUS smb_file_position_information(connection_struct *conn,
5866 const char *pdata,
5867 int total_data,
5868 files_struct *fsp)
5870 uint64_t position_information;
5872 if (total_data < 8) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 if (fsp == NULL) {
5877 /* Ignore on pathname based set. */
5878 return NT_STATUS_OK;
5881 position_information = (uint64_t)IVAL(pdata,0);
5882 #ifdef LARGE_SMB_OFF_T
5883 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5884 #else /* LARGE_SMB_OFF_T */
5885 if (IVAL(pdata,4) != 0) {
5886 /* more than 32 bits? */
5887 return NT_STATUS_INVALID_PARAMETER;
5889 #endif /* LARGE_SMB_OFF_T */
5891 DEBUG(10,("smb_file_position_information: Set file position "
5892 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5893 (double)position_information));
5894 fsp->fh->position_information = position_information;
5895 return NT_STATUS_OK;
5898 /****************************************************************************
5899 Deal with SMB_FILE_MODE_INFORMATION.
5900 ****************************************************************************/
5902 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5903 const char *pdata,
5904 int total_data)
5906 uint32 mode;
5908 if (total_data < 4) {
5909 return NT_STATUS_INVALID_PARAMETER;
5911 mode = IVAL(pdata,0);
5912 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5913 return NT_STATUS_INVALID_PARAMETER;
5915 return NT_STATUS_OK;
5918 /****************************************************************************
5919 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5920 ****************************************************************************/
5922 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5923 struct smb_request *req,
5924 const char *pdata,
5925 int total_data,
5926 const struct smb_filename *smb_fname)
5928 char *link_target = NULL;
5929 const char *newname = smb_fname->base_name;
5930 TALLOC_CTX *ctx = talloc_tos();
5932 /* Set a symbolic link. */
5933 /* Don't allow this if follow links is false. */
5935 if (total_data == 0) {
5936 return NT_STATUS_INVALID_PARAMETER;
5939 if (!lp_symlinks(SNUM(conn))) {
5940 return NT_STATUS_ACCESS_DENIED;
5943 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5944 total_data, STR_TERMINATE);
5946 if (!link_target) {
5947 return NT_STATUS_INVALID_PARAMETER;
5950 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5951 newname, link_target ));
5953 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5954 return map_nt_error_from_unix(errno);
5957 return NT_STATUS_OK;
5960 /****************************************************************************
5961 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5962 ****************************************************************************/
5964 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5965 struct smb_request *req,
5966 const char *pdata, int total_data,
5967 struct smb_filename *smb_fname_new)
5969 char *oldname = NULL;
5970 struct smb_filename *smb_fname_old = NULL;
5971 TALLOC_CTX *ctx = talloc_tos();
5972 NTSTATUS status = NT_STATUS_OK;
5974 /* Set a hard link. */
5975 if (total_data == 0) {
5976 return NT_STATUS_INVALID_PARAMETER;
5979 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5980 total_data, STR_TERMINATE, &status);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 return status;
5985 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5986 smb_fname_str_dbg(smb_fname_new), oldname));
5988 status = filename_convert(ctx,
5989 conn,
5990 req->flags2 & FLAGS2_DFS_PATHNAMES,
5991 oldname,
5993 NULL,
5994 &smb_fname_old);
5995 if (!NT_STATUS_IS_OK(status)) {
5996 return status;
5999 return hardlink_internals(ctx, conn, req, false,
6000 smb_fname_old, smb_fname_new);
6003 /****************************************************************************
6004 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6005 ****************************************************************************/
6007 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6008 struct smb_request *req,
6009 const char *pdata,
6010 int total_data,
6011 files_struct *fsp,
6012 struct smb_filename *smb_fname_src)
6014 bool overwrite;
6015 uint32_t len;
6016 char *newname = NULL;
6017 struct smb_filename *smb_fname_dst = NULL;
6018 NTSTATUS status = NT_STATUS_OK;
6019 TALLOC_CTX *ctx = talloc_tos();
6021 if (!fsp) {
6022 return NT_STATUS_INVALID_HANDLE;
6025 if (total_data < 20) {
6026 return NT_STATUS_INVALID_PARAMETER;
6029 overwrite = (CVAL(pdata,0) ? True : False);
6030 len = IVAL(pdata,16);
6032 if (len > (total_data - 20) || (len == 0)) {
6033 return NT_STATUS_INVALID_PARAMETER;
6036 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6037 &pdata[20], len, STR_TERMINATE,
6038 &status);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 return status;
6043 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6044 newname));
6046 status = filename_convert(ctx,
6047 conn,
6048 req->flags2 & FLAGS2_DFS_PATHNAMES,
6049 newname,
6050 UCF_SAVE_LCOMP,
6051 NULL,
6052 &smb_fname_dst);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 return status;
6057 if (fsp->base_fsp) {
6058 /* newname must be a stream name. */
6059 if (newname[0] != ':') {
6060 return NT_STATUS_NOT_SUPPORTED;
6063 /* Create an smb_fname to call rename_internals_fsp() with. */
6064 status = create_synthetic_smb_fname(talloc_tos(),
6065 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6066 &smb_fname_dst);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 goto out;
6072 * Set the original last component, since
6073 * rename_internals_fsp() requires it.
6075 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6076 newname);
6077 if (smb_fname_dst->original_lcomp == NULL) {
6078 status = NT_STATUS_NO_MEMORY;
6079 goto out;
6084 DEBUG(10,("smb2_file_rename_information: "
6085 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6086 fsp->fnum, fsp_str_dbg(fsp),
6087 smb_fname_str_dbg(smb_fname_dst)));
6088 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6089 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6090 overwrite);
6092 out:
6093 TALLOC_FREE(smb_fname_dst);
6094 return status;
6097 static NTSTATUS smb_file_link_information(connection_struct *conn,
6098 struct smb_request *req,
6099 const char *pdata,
6100 int total_data,
6101 files_struct *fsp,
6102 struct smb_filename *smb_fname_src)
6104 bool overwrite;
6105 uint32_t len;
6106 char *newname = NULL;
6107 struct smb_filename *smb_fname_dst = NULL;
6108 NTSTATUS status = NT_STATUS_OK;
6109 TALLOC_CTX *ctx = talloc_tos();
6111 if (!fsp) {
6112 return NT_STATUS_INVALID_HANDLE;
6115 if (total_data < 20) {
6116 return NT_STATUS_INVALID_PARAMETER;
6119 overwrite = (CVAL(pdata,0) ? true : false);
6120 len = IVAL(pdata,16);
6122 if (len > (total_data - 20) || (len == 0)) {
6123 return NT_STATUS_INVALID_PARAMETER;
6126 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6127 &pdata[20], len, STR_TERMINATE,
6128 &status);
6129 if (!NT_STATUS_IS_OK(status)) {
6130 return status;
6133 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6134 newname));
6136 status = filename_convert(ctx,
6137 conn,
6138 req->flags2 & FLAGS2_DFS_PATHNAMES,
6139 newname,
6140 UCF_SAVE_LCOMP,
6141 NULL,
6142 &smb_fname_dst);
6143 if (!NT_STATUS_IS_OK(status)) {
6144 return status;
6147 if (fsp->base_fsp) {
6148 /* No stream names. */
6149 return NT_STATUS_NOT_SUPPORTED;
6152 DEBUG(10,("smb_file_link_information: "
6153 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6154 fsp->fnum, fsp_str_dbg(fsp),
6155 smb_fname_str_dbg(smb_fname_dst)));
6156 status = hardlink_internals(ctx,
6157 conn,
6158 req,
6159 overwrite,
6160 fsp->fsp_name,
6161 smb_fname_dst);
6163 TALLOC_FREE(smb_fname_dst);
6164 return status;
6167 /****************************************************************************
6168 Deal with SMB_FILE_RENAME_INFORMATION.
6169 ****************************************************************************/
6171 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6172 struct smb_request *req,
6173 const char *pdata,
6174 int total_data,
6175 files_struct *fsp,
6176 struct smb_filename *smb_fname_src)
6178 bool overwrite;
6179 uint32 root_fid;
6180 uint32 len;
6181 char *newname = NULL;
6182 struct smb_filename *smb_fname_dst = NULL;
6183 bool dest_has_wcard = False;
6184 NTSTATUS status = NT_STATUS_OK;
6185 char *p;
6186 TALLOC_CTX *ctx = talloc_tos();
6188 if (total_data < 13) {
6189 return NT_STATUS_INVALID_PARAMETER;
6192 overwrite = (CVAL(pdata,0) ? True : False);
6193 root_fid = IVAL(pdata,4);
6194 len = IVAL(pdata,8);
6196 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6197 return NT_STATUS_INVALID_PARAMETER;
6200 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6201 len, 0, &status,
6202 &dest_has_wcard);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 return status;
6207 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6208 newname));
6210 status = resolve_dfspath_wcard(ctx, conn,
6211 req->flags2 & FLAGS2_DFS_PATHNAMES,
6212 newname,
6213 true,
6214 &newname,
6215 &dest_has_wcard);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 return status;
6220 /* Check the new name has no '/' characters. */
6221 if (strchr_m(newname, '/')) {
6222 return NT_STATUS_NOT_SUPPORTED;
6225 if (fsp && fsp->base_fsp) {
6226 /* newname must be a stream name. */
6227 if (newname[0] != ':') {
6228 return NT_STATUS_NOT_SUPPORTED;
6231 /* Create an smb_fname to call rename_internals_fsp() with. */
6232 status = create_synthetic_smb_fname(talloc_tos(),
6233 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6234 &smb_fname_dst);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 goto out;
6240 * Set the original last component, since
6241 * rename_internals_fsp() requires it.
6243 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6244 newname);
6245 if (smb_fname_dst->original_lcomp == NULL) {
6246 status = NT_STATUS_NO_MEMORY;
6247 goto out;
6250 } else {
6252 * Build up an smb_fname_dst based on the filename passed in.
6253 * We basically just strip off the last component, and put on
6254 * the newname instead.
6256 char *base_name = NULL;
6258 /* newname must *not* be a stream name. */
6259 if (newname[0] == ':') {
6260 return NT_STATUS_NOT_SUPPORTED;
6264 * Strip off the last component (filename) of the path passed
6265 * in.
6267 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6268 if (!base_name) {
6269 return NT_STATUS_NO_MEMORY;
6271 p = strrchr_m(base_name, '/');
6272 if (p) {
6273 p[1] = '\0';
6274 } else {
6275 base_name = talloc_strdup(ctx, "");
6276 if (!base_name) {
6277 return NT_STATUS_NO_MEMORY;
6280 /* Append the new name. */
6281 base_name = talloc_asprintf_append(base_name,
6282 "%s",
6283 newname);
6284 if (!base_name) {
6285 return NT_STATUS_NO_MEMORY;
6288 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6289 (UCF_SAVE_LCOMP |
6290 (dest_has_wcard ?
6291 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6292 0)));
6294 /* If an error we expect this to be
6295 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6297 if (!NT_STATUS_IS_OK(status)) {
6298 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6299 status)) {
6300 goto out;
6302 /* Create an smb_fname to call rename_internals_fsp() */
6303 status = create_synthetic_smb_fname(ctx,
6304 base_name, NULL,
6305 NULL,
6306 &smb_fname_dst);
6307 if (!NT_STATUS_IS_OK(status)) {
6308 goto out;
6313 if (fsp) {
6314 DEBUG(10,("smb_file_rename_information: "
6315 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6316 fsp->fnum, fsp_str_dbg(fsp),
6317 smb_fname_str_dbg(smb_fname_dst)));
6318 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6319 overwrite);
6320 } else {
6321 DEBUG(10,("smb_file_rename_information: "
6322 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6323 smb_fname_str_dbg(smb_fname_src),
6324 smb_fname_str_dbg(smb_fname_dst)));
6325 status = rename_internals(ctx, conn, req, smb_fname_src,
6326 smb_fname_dst, 0, overwrite, false,
6327 dest_has_wcard,
6328 FILE_WRITE_ATTRIBUTES);
6330 out:
6331 TALLOC_FREE(smb_fname_dst);
6332 return status;
6335 /****************************************************************************
6336 Deal with SMB_SET_POSIX_ACL.
6337 ****************************************************************************/
6339 #if defined(HAVE_POSIX_ACLS)
6340 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6341 const char *pdata,
6342 int total_data,
6343 files_struct *fsp,
6344 const struct smb_filename *smb_fname)
6346 uint16 posix_acl_version;
6347 uint16 num_file_acls;
6348 uint16 num_def_acls;
6349 bool valid_file_acls = True;
6350 bool valid_def_acls = True;
6352 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6353 return NT_STATUS_INVALID_PARAMETER;
6355 posix_acl_version = SVAL(pdata,0);
6356 num_file_acls = SVAL(pdata,2);
6357 num_def_acls = SVAL(pdata,4);
6359 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6360 valid_file_acls = False;
6361 num_file_acls = 0;
6364 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6365 valid_def_acls = False;
6366 num_def_acls = 0;
6369 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6370 return NT_STATUS_INVALID_PARAMETER;
6373 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6374 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6375 return NT_STATUS_INVALID_PARAMETER;
6378 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6379 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6380 (unsigned int)num_file_acls,
6381 (unsigned int)num_def_acls));
6383 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6384 smb_fname->base_name, num_file_acls,
6385 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6386 return map_nt_error_from_unix(errno);
6389 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6390 smb_fname->base_name, &smb_fname->st, num_def_acls,
6391 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6392 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6393 return map_nt_error_from_unix(errno);
6395 return NT_STATUS_OK;
6397 #endif
6399 /****************************************************************************
6400 Deal with SMB_SET_POSIX_LOCK.
6401 ****************************************************************************/
6403 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6404 struct smb_request *req,
6405 const char *pdata,
6406 int total_data,
6407 files_struct *fsp)
6409 uint64_t count;
6410 uint64_t offset;
6411 uint64_t smblctx;
6412 bool blocking_lock = False;
6413 enum brl_type lock_type;
6415 NTSTATUS status = NT_STATUS_OK;
6417 if (fsp == NULL || fsp->fh->fd == -1) {
6418 return NT_STATUS_INVALID_HANDLE;
6421 if (total_data != POSIX_LOCK_DATA_SIZE) {
6422 return NT_STATUS_INVALID_PARAMETER;
6425 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6426 case POSIX_LOCK_TYPE_READ:
6427 lock_type = READ_LOCK;
6428 break;
6429 case POSIX_LOCK_TYPE_WRITE:
6430 /* Return the right POSIX-mappable error code for files opened read-only. */
6431 if (!fsp->can_write) {
6432 return NT_STATUS_INVALID_HANDLE;
6434 lock_type = WRITE_LOCK;
6435 break;
6436 case POSIX_LOCK_TYPE_UNLOCK:
6437 lock_type = UNLOCK_LOCK;
6438 break;
6439 default:
6440 return NT_STATUS_INVALID_PARAMETER;
6443 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6444 blocking_lock = False;
6445 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6446 blocking_lock = True;
6447 } else {
6448 return NT_STATUS_INVALID_PARAMETER;
6451 if (!lp_blocking_locks(SNUM(conn))) {
6452 blocking_lock = False;
6455 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6456 #if defined(HAVE_LONGLONG)
6457 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6458 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6459 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6460 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6461 #else /* HAVE_LONGLONG */
6462 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6463 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6464 #endif /* HAVE_LONGLONG */
6466 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6467 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6468 fsp_str_dbg(fsp),
6469 (unsigned int)lock_type,
6470 (unsigned long long)smblctx,
6471 (double)count,
6472 (double)offset ));
6474 if (lock_type == UNLOCK_LOCK) {
6475 status = do_unlock(req->sconn->msg_ctx,
6476 fsp,
6477 smblctx,
6478 count,
6479 offset,
6480 POSIX_LOCK);
6481 } else {
6482 uint64_t block_smblctx;
6484 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6485 fsp,
6486 smblctx,
6487 count,
6488 offset,
6489 lock_type,
6490 POSIX_LOCK,
6491 blocking_lock,
6492 &status,
6493 &block_smblctx,
6494 NULL);
6496 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6498 * A blocking lock was requested. Package up
6499 * this smb into a queued request and push it
6500 * onto the blocking lock queue.
6502 if(push_blocking_lock_request(br_lck,
6503 req,
6504 fsp,
6505 -1, /* infinite timeout. */
6507 smblctx,
6508 lock_type,
6509 POSIX_LOCK,
6510 offset,
6511 count,
6512 block_smblctx)) {
6513 TALLOC_FREE(br_lck);
6514 return status;
6517 TALLOC_FREE(br_lck);
6520 return status;
6523 /****************************************************************************
6524 Deal with SMB_SET_FILE_BASIC_INFO.
6525 ****************************************************************************/
6527 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6528 const char *pdata,
6529 int total_data,
6530 files_struct *fsp,
6531 const struct smb_filename *smb_fname)
6533 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6534 struct smb_file_time ft;
6535 uint32 dosmode = 0;
6536 NTSTATUS status = NT_STATUS_OK;
6538 ZERO_STRUCT(ft);
6540 if (total_data < 36) {
6541 return NT_STATUS_INVALID_PARAMETER;
6544 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6545 return NT_STATUS_ACCESS_DENIED;
6548 /* Set the attributes */
6549 dosmode = IVAL(pdata,32);
6550 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6551 if (!NT_STATUS_IS_OK(status)) {
6552 return status;
6555 /* create time */
6556 ft.create_time = interpret_long_date(pdata);
6558 /* access time */
6559 ft.atime = interpret_long_date(pdata+8);
6561 /* write time. */
6562 ft.mtime = interpret_long_date(pdata+16);
6564 /* change time. */
6565 ft.ctime = interpret_long_date(pdata+24);
6567 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6568 smb_fname_str_dbg(smb_fname)));
6570 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6571 true);
6574 /****************************************************************************
6575 Deal with SMB_INFO_STANDARD.
6576 ****************************************************************************/
6578 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6579 const char *pdata,
6580 int total_data,
6581 files_struct *fsp,
6582 const struct smb_filename *smb_fname)
6584 struct smb_file_time ft;
6586 ZERO_STRUCT(ft);
6588 if (total_data < 12) {
6589 return NT_STATUS_INVALID_PARAMETER;
6592 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6593 return NT_STATUS_ACCESS_DENIED;
6596 /* create time */
6597 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6598 /* access time */
6599 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6600 /* write time */
6601 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6603 DEBUG(10,("smb_set_info_standard: file %s\n",
6604 smb_fname_str_dbg(smb_fname)));
6606 return smb_set_file_time(conn,
6607 fsp,
6608 smb_fname,
6609 &ft,
6610 true);
6613 /****************************************************************************
6614 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6615 ****************************************************************************/
6617 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6618 struct smb_request *req,
6619 const char *pdata,
6620 int total_data,
6621 files_struct *fsp,
6622 struct smb_filename *smb_fname)
6624 uint64_t allocation_size = 0;
6625 NTSTATUS status = NT_STATUS_OK;
6626 files_struct *new_fsp = NULL;
6628 if (!VALID_STAT(smb_fname->st)) {
6629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6632 if (total_data < 8) {
6633 return NT_STATUS_INVALID_PARAMETER;
6636 allocation_size = (uint64_t)IVAL(pdata,0);
6637 #ifdef LARGE_SMB_OFF_T
6638 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6639 #else /* LARGE_SMB_OFF_T */
6640 if (IVAL(pdata,4) != 0) {
6641 /* more than 32 bits? */
6642 return NT_STATUS_INVALID_PARAMETER;
6644 #endif /* LARGE_SMB_OFF_T */
6646 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6647 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6648 (double)allocation_size));
6650 if (allocation_size) {
6651 allocation_size = smb_roundup(conn, allocation_size);
6654 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6655 return NT_STATUS_ACCESS_DENIED;
6658 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6659 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6660 (double)allocation_size));
6662 if (fsp && fsp->fh->fd != -1) {
6663 /* Open file handle. */
6664 /* Only change if needed. */
6665 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6666 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6667 return map_nt_error_from_unix(errno);
6670 /* But always update the time. */
6672 * This is equivalent to a write. Ensure it's seen immediately
6673 * if there are no pending writes.
6675 trigger_write_time_update_immediate(fsp);
6676 return NT_STATUS_OK;
6679 /* Pathname or stat or directory file. */
6680 status = SMB_VFS_CREATE_FILE(
6681 conn, /* conn */
6682 req, /* req */
6683 0, /* root_dir_fid */
6684 smb_fname, /* fname */
6685 FILE_WRITE_DATA, /* access_mask */
6686 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6687 FILE_SHARE_DELETE),
6688 FILE_OPEN, /* create_disposition*/
6689 0, /* create_options */
6690 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6691 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6692 0, /* allocation_size */
6693 0, /* private_flags */
6694 NULL, /* sd */
6695 NULL, /* ea_list */
6696 &new_fsp, /* result */
6697 NULL); /* pinfo */
6699 if (!NT_STATUS_IS_OK(status)) {
6700 /* NB. We check for open_was_deferred in the caller. */
6701 return status;
6704 /* Only change if needed. */
6705 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6706 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6707 status = map_nt_error_from_unix(errno);
6708 close_file(req, new_fsp, NORMAL_CLOSE);
6709 return status;
6713 /* Changing the allocation size should set the last mod time. */
6715 * This is equivalent to a write. Ensure it's seen immediately
6716 * if there are no pending writes.
6718 trigger_write_time_update_immediate(new_fsp);
6720 close_file(req, new_fsp, NORMAL_CLOSE);
6721 return NT_STATUS_OK;
6724 /****************************************************************************
6725 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6726 ****************************************************************************/
6728 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6729 struct smb_request *req,
6730 const char *pdata,
6731 int total_data,
6732 files_struct *fsp,
6733 const struct smb_filename *smb_fname,
6734 bool fail_after_createfile)
6736 SMB_OFF_T size;
6738 if (total_data < 8) {
6739 return NT_STATUS_INVALID_PARAMETER;
6742 size = IVAL(pdata,0);
6743 #ifdef LARGE_SMB_OFF_T
6744 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6745 #else /* LARGE_SMB_OFF_T */
6746 if (IVAL(pdata,4) != 0) {
6747 /* more than 32 bits? */
6748 return NT_STATUS_INVALID_PARAMETER;
6750 #endif /* LARGE_SMB_OFF_T */
6751 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6752 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6753 (double)size));
6755 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6756 return NT_STATUS_ACCESS_DENIED;
6759 return smb_set_file_size(conn, req,
6760 fsp,
6761 smb_fname,
6762 &smb_fname->st,
6763 size,
6764 fail_after_createfile);
6767 /****************************************************************************
6768 Allow a UNIX info mknod.
6769 ****************************************************************************/
6771 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6772 const char *pdata,
6773 int total_data,
6774 const struct smb_filename *smb_fname)
6776 uint32 file_type = IVAL(pdata,56);
6777 #if defined(HAVE_MAKEDEV)
6778 uint32 dev_major = IVAL(pdata,60);
6779 uint32 dev_minor = IVAL(pdata,68);
6780 #endif
6781 SMB_DEV_T dev = (SMB_DEV_T)0;
6782 uint32 raw_unixmode = IVAL(pdata,84);
6783 NTSTATUS status;
6784 mode_t unixmode;
6786 if (total_data < 100) {
6787 return NT_STATUS_INVALID_PARAMETER;
6790 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6791 PERM_NEW_FILE, &unixmode);
6792 if (!NT_STATUS_IS_OK(status)) {
6793 return status;
6796 #if defined(HAVE_MAKEDEV)
6797 dev = makedev(dev_major, dev_minor);
6798 #endif
6800 switch (file_type) {
6801 #if defined(S_IFIFO)
6802 case UNIX_TYPE_FIFO:
6803 unixmode |= S_IFIFO;
6804 break;
6805 #endif
6806 #if defined(S_IFSOCK)
6807 case UNIX_TYPE_SOCKET:
6808 unixmode |= S_IFSOCK;
6809 break;
6810 #endif
6811 #if defined(S_IFCHR)
6812 case UNIX_TYPE_CHARDEV:
6813 unixmode |= S_IFCHR;
6814 break;
6815 #endif
6816 #if defined(S_IFBLK)
6817 case UNIX_TYPE_BLKDEV:
6818 unixmode |= S_IFBLK;
6819 break;
6820 #endif
6821 default:
6822 return NT_STATUS_INVALID_PARAMETER;
6825 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6826 "%.0f mode 0%o for file %s\n", (double)dev,
6827 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6829 /* Ok - do the mknod. */
6830 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6831 return map_nt_error_from_unix(errno);
6834 /* If any of the other "set" calls fail we
6835 * don't want to end up with a half-constructed mknod.
6838 if (lp_inherit_perms(SNUM(conn))) {
6839 char *parent;
6840 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6841 &parent, NULL)) {
6842 return NT_STATUS_NO_MEMORY;
6844 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6845 unixmode);
6846 TALLOC_FREE(parent);
6849 return NT_STATUS_OK;
6852 /****************************************************************************
6853 Deal with SMB_SET_FILE_UNIX_BASIC.
6854 ****************************************************************************/
6856 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6857 struct smb_request *req,
6858 const char *pdata,
6859 int total_data,
6860 files_struct *fsp,
6861 const struct smb_filename *smb_fname)
6863 struct smb_file_time ft;
6864 uint32 raw_unixmode;
6865 mode_t unixmode;
6866 SMB_OFF_T size = 0;
6867 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6868 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6869 NTSTATUS status = NT_STATUS_OK;
6870 bool delete_on_fail = False;
6871 enum perm_type ptype;
6872 files_struct *all_fsps = NULL;
6873 bool modify_mtime = true;
6874 struct file_id id;
6875 struct smb_filename *smb_fname_tmp = NULL;
6876 SMB_STRUCT_STAT sbuf;
6878 ZERO_STRUCT(ft);
6880 if (total_data < 100) {
6881 return NT_STATUS_INVALID_PARAMETER;
6884 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6885 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6886 size=IVAL(pdata,0); /* first 8 Bytes are size */
6887 #ifdef LARGE_SMB_OFF_T
6888 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6889 #else /* LARGE_SMB_OFF_T */
6890 if (IVAL(pdata,4) != 0) {
6891 /* more than 32 bits? */
6892 return NT_STATUS_INVALID_PARAMETER;
6894 #endif /* LARGE_SMB_OFF_T */
6897 ft.atime = interpret_long_date(pdata+24); /* access_time */
6898 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6899 set_owner = (uid_t)IVAL(pdata,40);
6900 set_grp = (gid_t)IVAL(pdata,48);
6901 raw_unixmode = IVAL(pdata,84);
6903 if (VALID_STAT(smb_fname->st)) {
6904 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6905 ptype = PERM_EXISTING_DIR;
6906 } else {
6907 ptype = PERM_EXISTING_FILE;
6909 } else {
6910 ptype = PERM_NEW_FILE;
6913 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6914 ptype, &unixmode);
6915 if (!NT_STATUS_IS_OK(status)) {
6916 return status;
6919 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6920 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6921 smb_fname_str_dbg(smb_fname), (double)size,
6922 (unsigned int)set_owner, (unsigned int)set_grp,
6923 (int)raw_unixmode));
6925 sbuf = smb_fname->st;
6927 if (!VALID_STAT(sbuf)) {
6929 * The only valid use of this is to create character and block
6930 * devices, and named pipes. This is deprecated (IMHO) and
6931 * a new info level should be used for mknod. JRA.
6934 status = smb_unix_mknod(conn,
6935 pdata,
6936 total_data,
6937 smb_fname);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 return status;
6942 status = copy_smb_filename(talloc_tos(), smb_fname,
6943 &smb_fname_tmp);
6944 if (!NT_STATUS_IS_OK(status)) {
6945 return status;
6948 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6949 status = map_nt_error_from_unix(errno);
6950 TALLOC_FREE(smb_fname_tmp);
6951 SMB_VFS_UNLINK(conn, smb_fname);
6952 return status;
6955 sbuf = smb_fname_tmp->st;
6956 smb_fname = smb_fname_tmp;
6958 /* Ensure we don't try and change anything else. */
6959 raw_unixmode = SMB_MODE_NO_CHANGE;
6960 size = get_file_size_stat(&sbuf);
6961 ft.atime = sbuf.st_ex_atime;
6962 ft.mtime = sbuf.st_ex_mtime;
6964 * We continue here as we might want to change the
6965 * owner uid/gid.
6967 delete_on_fail = True;
6970 #if 1
6971 /* Horrible backwards compatibility hack as an old server bug
6972 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6973 * */
6975 if (!size) {
6976 size = get_file_size_stat(&sbuf);
6978 #endif
6981 * Deal with the UNIX specific mode set.
6984 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6985 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6986 "setting mode 0%o for file %s\n",
6987 (unsigned int)unixmode,
6988 smb_fname_str_dbg(smb_fname)));
6989 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6990 return map_nt_error_from_unix(errno);
6995 * Deal with the UNIX specific uid set.
6998 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6999 (sbuf.st_ex_uid != set_owner)) {
7000 int ret;
7002 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7003 "changing owner %u for path %s\n",
7004 (unsigned int)set_owner,
7005 smb_fname_str_dbg(smb_fname)));
7007 if (S_ISLNK(sbuf.st_ex_mode)) {
7008 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7009 set_owner, (gid_t)-1);
7010 } else {
7011 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7012 set_owner, (gid_t)-1);
7015 if (ret != 0) {
7016 status = map_nt_error_from_unix(errno);
7017 if (delete_on_fail) {
7018 SMB_VFS_UNLINK(conn, smb_fname);
7020 return status;
7025 * Deal with the UNIX specific gid set.
7028 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7029 (sbuf.st_ex_gid != set_grp)) {
7030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7031 "changing group %u for file %s\n",
7032 (unsigned int)set_owner,
7033 smb_fname_str_dbg(smb_fname)));
7034 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7035 set_grp) != 0) {
7036 status = map_nt_error_from_unix(errno);
7037 if (delete_on_fail) {
7038 SMB_VFS_UNLINK(conn, smb_fname);
7040 return status;
7044 /* Deal with any size changes. */
7046 status = smb_set_file_size(conn, req,
7047 fsp,
7048 smb_fname,
7049 &sbuf,
7050 size,
7051 false);
7052 if (!NT_STATUS_IS_OK(status)) {
7053 return status;
7056 /* Deal with any time changes. */
7057 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7058 /* No change, don't cancel anything. */
7059 return status;
7062 id = vfs_file_id_from_sbuf(conn, &sbuf);
7063 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7064 all_fsps = file_find_di_next(all_fsps)) {
7066 * We're setting the time explicitly for UNIX.
7067 * Cancel any pending changes over all handles.
7069 all_fsps->update_write_time_on_close = false;
7070 TALLOC_FREE(all_fsps->update_write_time_event);
7074 * Override the "setting_write_time"
7075 * parameter here as it almost does what
7076 * we need. Just remember if we modified
7077 * mtime and send the notify ourselves.
7079 if (null_timespec(ft.mtime)) {
7080 modify_mtime = false;
7083 status = smb_set_file_time(conn,
7084 fsp,
7085 smb_fname,
7086 &ft,
7087 false);
7088 if (modify_mtime) {
7089 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7090 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7092 return status;
7095 /****************************************************************************
7096 Deal with SMB_SET_FILE_UNIX_INFO2.
7097 ****************************************************************************/
7099 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7100 struct smb_request *req,
7101 const char *pdata,
7102 int total_data,
7103 files_struct *fsp,
7104 const struct smb_filename *smb_fname)
7106 NTSTATUS status;
7107 uint32 smb_fflags;
7108 uint32 smb_fmask;
7110 if (total_data < 116) {
7111 return NT_STATUS_INVALID_PARAMETER;
7114 /* Start by setting all the fields that are common between UNIX_BASIC
7115 * and UNIX_INFO2.
7117 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7118 fsp, smb_fname);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 return status;
7123 smb_fflags = IVAL(pdata, 108);
7124 smb_fmask = IVAL(pdata, 112);
7126 /* NB: We should only attempt to alter the file flags if the client
7127 * sends a non-zero mask.
7129 if (smb_fmask != 0) {
7130 int stat_fflags = 0;
7132 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7133 smb_fmask, &stat_fflags)) {
7134 /* Client asked to alter a flag we don't understand. */
7135 return NT_STATUS_INVALID_PARAMETER;
7138 if (fsp && fsp->fh->fd != -1) {
7139 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7140 return NT_STATUS_NOT_SUPPORTED;
7141 } else {
7142 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7143 stat_fflags) != 0) {
7144 return map_nt_error_from_unix(errno);
7149 /* XXX: need to add support for changing the create_time here. You
7150 * can do this for paths on Darwin with setattrlist(2). The right way
7151 * to hook this up is probably by extending the VFS utimes interface.
7154 return NT_STATUS_OK;
7157 /****************************************************************************
7158 Create a directory with POSIX semantics.
7159 ****************************************************************************/
7161 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7162 struct smb_request *req,
7163 char **ppdata,
7164 int total_data,
7165 struct smb_filename *smb_fname,
7166 int *pdata_return_size)
7168 NTSTATUS status = NT_STATUS_OK;
7169 uint32 raw_unixmode = 0;
7170 uint32 mod_unixmode = 0;
7171 mode_t unixmode = (mode_t)0;
7172 files_struct *fsp = NULL;
7173 uint16 info_level_return = 0;
7174 int info;
7175 char *pdata = *ppdata;
7177 if (total_data < 18) {
7178 return NT_STATUS_INVALID_PARAMETER;
7181 raw_unixmode = IVAL(pdata,8);
7182 /* Next 4 bytes are not yet defined. */
7184 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7185 PERM_NEW_DIR, &unixmode);
7186 if (!NT_STATUS_IS_OK(status)) {
7187 return status;
7190 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7192 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7193 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7195 status = SMB_VFS_CREATE_FILE(
7196 conn, /* conn */
7197 req, /* req */
7198 0, /* root_dir_fid */
7199 smb_fname, /* fname */
7200 FILE_READ_ATTRIBUTES, /* access_mask */
7201 FILE_SHARE_NONE, /* share_access */
7202 FILE_CREATE, /* create_disposition*/
7203 FILE_DIRECTORY_FILE, /* create_options */
7204 mod_unixmode, /* file_attributes */
7205 0, /* oplock_request */
7206 0, /* allocation_size */
7207 0, /* private_flags */
7208 NULL, /* sd */
7209 NULL, /* ea_list */
7210 &fsp, /* result */
7211 &info); /* pinfo */
7213 if (NT_STATUS_IS_OK(status)) {
7214 close_file(req, fsp, NORMAL_CLOSE);
7217 info_level_return = SVAL(pdata,16);
7219 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7220 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7221 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7222 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7223 } else {
7224 *pdata_return_size = 12;
7227 /* Realloc the data size */
7228 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7229 if (*ppdata == NULL) {
7230 *pdata_return_size = 0;
7231 return NT_STATUS_NO_MEMORY;
7233 pdata = *ppdata;
7235 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7236 SSVAL(pdata,2,0); /* No fnum. */
7237 SIVAL(pdata,4,info); /* Was directory created. */
7239 switch (info_level_return) {
7240 case SMB_QUERY_FILE_UNIX_BASIC:
7241 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7242 SSVAL(pdata,10,0); /* Padding. */
7243 store_file_unix_basic(conn, pdata + 12, fsp,
7244 &smb_fname->st);
7245 break;
7246 case SMB_QUERY_FILE_UNIX_INFO2:
7247 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7248 SSVAL(pdata,10,0); /* Padding. */
7249 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7250 &smb_fname->st);
7251 break;
7252 default:
7253 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7254 SSVAL(pdata,10,0); /* Padding. */
7255 break;
7258 return status;
7261 /****************************************************************************
7262 Open/Create a file with POSIX semantics.
7263 ****************************************************************************/
7265 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7266 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7268 static NTSTATUS smb_posix_open(connection_struct *conn,
7269 struct smb_request *req,
7270 char **ppdata,
7271 int total_data,
7272 struct smb_filename *smb_fname,
7273 int *pdata_return_size)
7275 bool extended_oplock_granted = False;
7276 char *pdata = *ppdata;
7277 uint32 flags = 0;
7278 uint32 wire_open_mode = 0;
7279 uint32 raw_unixmode = 0;
7280 uint32 mod_unixmode = 0;
7281 uint32 create_disp = 0;
7282 uint32 access_mask = 0;
7283 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7284 NTSTATUS status = NT_STATUS_OK;
7285 mode_t unixmode = (mode_t)0;
7286 files_struct *fsp = NULL;
7287 int oplock_request = 0;
7288 int info = 0;
7289 uint16 info_level_return = 0;
7291 if (total_data < 18) {
7292 return NT_STATUS_INVALID_PARAMETER;
7295 flags = IVAL(pdata,0);
7296 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7297 if (oplock_request) {
7298 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7301 wire_open_mode = IVAL(pdata,4);
7303 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7304 return smb_posix_mkdir(conn, req,
7305 ppdata,
7306 total_data,
7307 smb_fname,
7308 pdata_return_size);
7311 switch (wire_open_mode & SMB_ACCMODE) {
7312 case SMB_O_RDONLY:
7313 access_mask = SMB_O_RDONLY_MAPPING;
7314 break;
7315 case SMB_O_WRONLY:
7316 access_mask = SMB_O_WRONLY_MAPPING;
7317 break;
7318 case SMB_O_RDWR:
7319 access_mask = (SMB_O_RDONLY_MAPPING|
7320 SMB_O_WRONLY_MAPPING);
7321 break;
7322 default:
7323 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7324 (unsigned int)wire_open_mode ));
7325 return NT_STATUS_INVALID_PARAMETER;
7328 wire_open_mode &= ~SMB_ACCMODE;
7330 /* First take care of O_CREAT|O_EXCL interactions. */
7331 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7332 case (SMB_O_CREAT | SMB_O_EXCL):
7333 /* File exists fail. File not exist create. */
7334 create_disp = FILE_CREATE;
7335 break;
7336 case SMB_O_CREAT:
7337 /* File exists open. File not exist create. */
7338 create_disp = FILE_OPEN_IF;
7339 break;
7340 case SMB_O_EXCL:
7341 /* O_EXCL on its own without O_CREAT is undefined.
7342 We deliberately ignore it as some versions of
7343 Linux CIFSFS can send a bare O_EXCL on the
7344 wire which other filesystems in the kernel
7345 ignore. See bug 9519 for details. */
7347 /* Fallthrough. */
7349 case 0:
7350 /* File exists open. File not exist fail. */
7351 create_disp = FILE_OPEN;
7352 break;
7353 default:
7354 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7355 (unsigned int)wire_open_mode ));
7356 return NT_STATUS_INVALID_PARAMETER;
7359 /* Next factor in the effects of O_TRUNC. */
7360 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7362 if (wire_open_mode & SMB_O_TRUNC) {
7363 switch (create_disp) {
7364 case FILE_CREATE:
7365 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7366 /* Leave create_disp alone as
7367 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7369 /* File exists fail. File not exist create. */
7370 break;
7371 case FILE_OPEN_IF:
7372 /* SMB_O_CREAT | SMB_O_TRUNC */
7373 /* File exists overwrite. File not exist create. */
7374 create_disp = FILE_OVERWRITE_IF;
7375 break;
7376 case FILE_OPEN:
7377 /* SMB_O_TRUNC */
7378 /* File exists overwrite. File not exist fail. */
7379 create_disp = FILE_OVERWRITE;
7380 break;
7381 default:
7382 /* Cannot get here. */
7383 smb_panic("smb_posix_open: logic error");
7384 return NT_STATUS_INVALID_PARAMETER;
7388 raw_unixmode = IVAL(pdata,8);
7389 /* Next 4 bytes are not yet defined. */
7391 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7392 (VALID_STAT(smb_fname->st) ?
7393 PERM_EXISTING_FILE : PERM_NEW_FILE),
7394 &unixmode);
7396 if (!NT_STATUS_IS_OK(status)) {
7397 return status;
7400 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7402 if (wire_open_mode & SMB_O_SYNC) {
7403 create_options |= FILE_WRITE_THROUGH;
7405 if (wire_open_mode & SMB_O_APPEND) {
7406 access_mask |= FILE_APPEND_DATA;
7408 if (wire_open_mode & SMB_O_DIRECT) {
7409 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7412 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7413 VALID_STAT_OF_DIR(smb_fname->st)) {
7414 if (access_mask != SMB_O_RDONLY_MAPPING) {
7415 return NT_STATUS_FILE_IS_A_DIRECTORY;
7417 create_options &= ~FILE_NON_DIRECTORY_FILE;
7418 create_options |= FILE_DIRECTORY_FILE;
7421 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7422 smb_fname_str_dbg(smb_fname),
7423 (unsigned int)wire_open_mode,
7424 (unsigned int)unixmode ));
7426 status = SMB_VFS_CREATE_FILE(
7427 conn, /* conn */
7428 req, /* req */
7429 0, /* root_dir_fid */
7430 smb_fname, /* fname */
7431 access_mask, /* access_mask */
7432 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7433 FILE_SHARE_DELETE),
7434 create_disp, /* create_disposition*/
7435 create_options, /* create_options */
7436 mod_unixmode, /* file_attributes */
7437 oplock_request, /* oplock_request */
7438 0, /* allocation_size */
7439 0, /* private_flags */
7440 NULL, /* sd */
7441 NULL, /* ea_list */
7442 &fsp, /* result */
7443 &info); /* pinfo */
7445 if (!NT_STATUS_IS_OK(status)) {
7446 return status;
7449 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7450 extended_oplock_granted = True;
7453 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7454 extended_oplock_granted = True;
7457 info_level_return = SVAL(pdata,16);
7459 /* Allocate the correct return size. */
7461 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7462 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7463 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7464 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7465 } else {
7466 *pdata_return_size = 12;
7469 /* Realloc the data size */
7470 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7471 if (*ppdata == NULL) {
7472 close_file(req, fsp, ERROR_CLOSE);
7473 *pdata_return_size = 0;
7474 return NT_STATUS_NO_MEMORY;
7476 pdata = *ppdata;
7478 if (extended_oplock_granted) {
7479 if (flags & REQUEST_BATCH_OPLOCK) {
7480 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7481 } else {
7482 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7484 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7485 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7486 } else {
7487 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7490 SSVAL(pdata,2,fsp->fnum);
7491 SIVAL(pdata,4,info); /* Was file created etc. */
7493 switch (info_level_return) {
7494 case SMB_QUERY_FILE_UNIX_BASIC:
7495 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7496 SSVAL(pdata,10,0); /* padding. */
7497 store_file_unix_basic(conn, pdata + 12, fsp,
7498 &smb_fname->st);
7499 break;
7500 case SMB_QUERY_FILE_UNIX_INFO2:
7501 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7502 SSVAL(pdata,10,0); /* padding. */
7503 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7504 &smb_fname->st);
7505 break;
7506 default:
7507 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7508 SSVAL(pdata,10,0); /* padding. */
7509 break;
7511 return NT_STATUS_OK;
7514 /****************************************************************************
7515 Delete a file with POSIX semantics.
7516 ****************************************************************************/
7518 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7519 struct smb_request *req,
7520 const char *pdata,
7521 int total_data,
7522 struct smb_filename *smb_fname)
7524 NTSTATUS status = NT_STATUS_OK;
7525 files_struct *fsp = NULL;
7526 uint16 flags = 0;
7527 char del = 1;
7528 int info = 0;
7529 int create_options = 0;
7530 int i;
7531 struct share_mode_lock *lck = NULL;
7533 if (total_data < 2) {
7534 return NT_STATUS_INVALID_PARAMETER;
7537 flags = SVAL(pdata,0);
7539 if (!VALID_STAT(smb_fname->st)) {
7540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7543 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7544 !VALID_STAT_OF_DIR(smb_fname->st)) {
7545 return NT_STATUS_NOT_A_DIRECTORY;
7548 DEBUG(10,("smb_posix_unlink: %s %s\n",
7549 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7550 smb_fname_str_dbg(smb_fname)));
7552 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7553 create_options |= FILE_DIRECTORY_FILE;
7556 status = SMB_VFS_CREATE_FILE(
7557 conn, /* conn */
7558 req, /* req */
7559 0, /* root_dir_fid */
7560 smb_fname, /* fname */
7561 DELETE_ACCESS, /* access_mask */
7562 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7563 FILE_SHARE_DELETE),
7564 FILE_OPEN, /* create_disposition*/
7565 create_options, /* create_options */
7566 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7567 0, /* oplock_request */
7568 0, /* allocation_size */
7569 0, /* private_flags */
7570 NULL, /* sd */
7571 NULL, /* ea_list */
7572 &fsp, /* result */
7573 &info); /* pinfo */
7575 if (!NT_STATUS_IS_OK(status)) {
7576 return status;
7580 * Don't lie to client. If we can't really delete due to
7581 * non-POSIX opens return SHARING_VIOLATION.
7584 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7585 NULL);
7586 if (lck == NULL) {
7587 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7588 "lock for file %s\n", fsp_str_dbg(fsp)));
7589 close_file(req, fsp, NORMAL_CLOSE);
7590 return NT_STATUS_INVALID_PARAMETER;
7594 * See if others still have the file open. If this is the case, then
7595 * don't delete. If all opens are POSIX delete we can set the delete
7596 * on close disposition.
7598 for (i=0; i<lck->num_share_modes; i++) {
7599 struct share_mode_entry *e = &lck->share_modes[i];
7600 if (is_valid_share_mode_entry(e)) {
7601 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7602 continue;
7604 /* Fail with sharing violation. */
7605 TALLOC_FREE(lck);
7606 close_file(req, fsp, NORMAL_CLOSE);
7607 return NT_STATUS_SHARING_VIOLATION;
7612 * Set the delete on close.
7614 status = smb_set_file_disposition_info(conn,
7615 &del,
7617 fsp,
7618 smb_fname);
7620 TALLOC_FREE(lck);
7622 if (!NT_STATUS_IS_OK(status)) {
7623 close_file(req, fsp, NORMAL_CLOSE);
7624 return status;
7626 return close_file(req, fsp, NORMAL_CLOSE);
7629 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7630 struct smb_request *req,
7631 TALLOC_CTX *mem_ctx,
7632 uint16_t info_level,
7633 files_struct *fsp,
7634 struct smb_filename *smb_fname,
7635 char **ppdata, int total_data,
7636 int *ret_data_size)
7638 char *pdata = *ppdata;
7639 NTSTATUS status = NT_STATUS_OK;
7640 int data_return_size = 0;
7642 *ret_data_size = 0;
7644 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7645 return NT_STATUS_INVALID_LEVEL;
7648 if (!CAN_WRITE(conn)) {
7649 /* Allow POSIX opens. The open path will deny
7650 * any non-readonly opens. */
7651 if (info_level != SMB_POSIX_PATH_OPEN) {
7652 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7656 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7657 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7658 fsp ? fsp->fnum : -1, info_level, total_data));
7660 switch (info_level) {
7662 case SMB_INFO_STANDARD:
7664 status = smb_set_info_standard(conn,
7665 pdata,
7666 total_data,
7667 fsp,
7668 smb_fname);
7669 break;
7672 case SMB_INFO_SET_EA:
7674 status = smb_info_set_ea(conn,
7675 pdata,
7676 total_data,
7677 fsp,
7678 smb_fname);
7679 break;
7682 case SMB_SET_FILE_BASIC_INFO:
7683 case SMB_FILE_BASIC_INFORMATION:
7685 status = smb_set_file_basic_info(conn,
7686 pdata,
7687 total_data,
7688 fsp,
7689 smb_fname);
7690 break;
7693 case SMB_FILE_ALLOCATION_INFORMATION:
7694 case SMB_SET_FILE_ALLOCATION_INFO:
7696 status = smb_set_file_allocation_info(conn, req,
7697 pdata,
7698 total_data,
7699 fsp,
7700 smb_fname);
7701 break;
7704 case SMB_FILE_END_OF_FILE_INFORMATION:
7705 case SMB_SET_FILE_END_OF_FILE_INFO:
7708 * XP/Win7 both fail after the createfile with
7709 * SMB_SET_FILE_END_OF_FILE_INFO but not
7710 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7711 * The level is known here, so pass it down
7712 * appropriately.
7714 bool should_fail =
7715 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7717 status = smb_set_file_end_of_file_info(conn, req,
7718 pdata,
7719 total_data,
7720 fsp,
7721 smb_fname,
7722 should_fail);
7723 break;
7726 case SMB_FILE_DISPOSITION_INFORMATION:
7727 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7729 #if 0
7730 /* JRA - We used to just ignore this on a path ?
7731 * Shouldn't this be invalid level on a pathname
7732 * based call ?
7734 if (tran_call != TRANSACT2_SETFILEINFO) {
7735 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7737 #endif
7738 status = smb_set_file_disposition_info(conn,
7739 pdata,
7740 total_data,
7741 fsp,
7742 smb_fname);
7743 break;
7746 case SMB_FILE_POSITION_INFORMATION:
7748 status = smb_file_position_information(conn,
7749 pdata,
7750 total_data,
7751 fsp);
7752 break;
7755 case SMB_FILE_FULL_EA_INFORMATION:
7757 status = smb_set_file_full_ea_info(conn,
7758 pdata,
7759 total_data,
7760 fsp);
7761 break;
7764 /* From tridge Samba4 :
7765 * MODE_INFORMATION in setfileinfo (I have no
7766 * idea what "mode information" on a file is - it takes a value of 0,
7767 * 2, 4 or 6. What could it be?).
7770 case SMB_FILE_MODE_INFORMATION:
7772 status = smb_file_mode_information(conn,
7773 pdata,
7774 total_data);
7775 break;
7779 * CIFS UNIX extensions.
7782 case SMB_SET_FILE_UNIX_BASIC:
7784 status = smb_set_file_unix_basic(conn, req,
7785 pdata,
7786 total_data,
7787 fsp,
7788 smb_fname);
7789 break;
7792 case SMB_SET_FILE_UNIX_INFO2:
7794 status = smb_set_file_unix_info2(conn, req,
7795 pdata,
7796 total_data,
7797 fsp,
7798 smb_fname);
7799 break;
7802 case SMB_SET_FILE_UNIX_LINK:
7804 if (fsp) {
7805 /* We must have a pathname for this. */
7806 return NT_STATUS_INVALID_LEVEL;
7808 status = smb_set_file_unix_link(conn, req, pdata,
7809 total_data, smb_fname);
7810 break;
7813 case SMB_SET_FILE_UNIX_HLINK:
7815 if (fsp) {
7816 /* We must have a pathname for this. */
7817 return NT_STATUS_INVALID_LEVEL;
7819 status = smb_set_file_unix_hlink(conn, req,
7820 pdata, total_data,
7821 smb_fname);
7822 break;
7825 case SMB_FILE_RENAME_INFORMATION:
7827 status = smb_file_rename_information(conn, req,
7828 pdata, total_data,
7829 fsp, smb_fname);
7830 break;
7833 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7835 /* SMB2 rename information. */
7836 status = smb2_file_rename_information(conn, req,
7837 pdata, total_data,
7838 fsp, smb_fname);
7839 break;
7842 case SMB_FILE_LINK_INFORMATION:
7844 status = smb_file_link_information(conn, req,
7845 pdata, total_data,
7846 fsp, smb_fname);
7847 break;
7850 #if defined(HAVE_POSIX_ACLS)
7851 case SMB_SET_POSIX_ACL:
7853 status = smb_set_posix_acl(conn,
7854 pdata,
7855 total_data,
7856 fsp,
7857 smb_fname);
7858 break;
7860 #endif
7862 case SMB_SET_POSIX_LOCK:
7864 if (!fsp) {
7865 return NT_STATUS_INVALID_LEVEL;
7867 status = smb_set_posix_lock(conn, req,
7868 pdata, total_data, fsp);
7869 break;
7872 case SMB_POSIX_PATH_OPEN:
7874 if (fsp) {
7875 /* We must have a pathname for this. */
7876 return NT_STATUS_INVALID_LEVEL;
7879 status = smb_posix_open(conn, req,
7880 ppdata,
7881 total_data,
7882 smb_fname,
7883 &data_return_size);
7884 break;
7887 case SMB_POSIX_PATH_UNLINK:
7889 if (fsp) {
7890 /* We must have a pathname for this. */
7891 return NT_STATUS_INVALID_LEVEL;
7894 status = smb_posix_unlink(conn, req,
7895 pdata,
7896 total_data,
7897 smb_fname);
7898 break;
7901 default:
7902 return NT_STATUS_INVALID_LEVEL;
7905 if (!NT_STATUS_IS_OK(status)) {
7906 return status;
7909 *ret_data_size = data_return_size;
7910 return NT_STATUS_OK;
7913 /****************************************************************************
7914 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7915 ****************************************************************************/
7917 static void call_trans2setfilepathinfo(connection_struct *conn,
7918 struct smb_request *req,
7919 unsigned int tran_call,
7920 char **pparams, int total_params,
7921 char **ppdata, int total_data,
7922 unsigned int max_data_bytes)
7924 char *params = *pparams;
7925 char *pdata = *ppdata;
7926 uint16 info_level;
7927 struct smb_filename *smb_fname = NULL;
7928 files_struct *fsp = NULL;
7929 NTSTATUS status = NT_STATUS_OK;
7930 int data_return_size = 0;
7932 if (!params) {
7933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7934 return;
7937 if (tran_call == TRANSACT2_SETFILEINFO) {
7938 if (total_params < 4) {
7939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7940 return;
7943 fsp = file_fsp(req, SVAL(params,0));
7944 /* Basic check for non-null fsp. */
7945 if (!check_fsp_open(conn, req, fsp)) {
7946 return;
7948 info_level = SVAL(params,2);
7950 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7951 &smb_fname);
7952 if (!NT_STATUS_IS_OK(status)) {
7953 reply_nterror(req, status);
7954 return;
7957 if(fsp->fh->fd == -1) {
7959 * This is actually a SETFILEINFO on a directory
7960 * handle (returned from an NT SMB). NT5.0 seems
7961 * to do this call. JRA.
7963 if (INFO_LEVEL_IS_UNIX(info_level)) {
7964 /* Always do lstat for UNIX calls. */
7965 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7966 DEBUG(3,("call_trans2setfilepathinfo: "
7967 "SMB_VFS_LSTAT of %s failed "
7968 "(%s)\n",
7969 smb_fname_str_dbg(smb_fname),
7970 strerror(errno)));
7971 reply_nterror(req, map_nt_error_from_unix(errno));
7972 return;
7974 } else {
7975 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7976 DEBUG(3,("call_trans2setfilepathinfo: "
7977 "fileinfo of %s failed (%s)\n",
7978 smb_fname_str_dbg(smb_fname),
7979 strerror(errno)));
7980 reply_nterror(req, map_nt_error_from_unix(errno));
7981 return;
7984 } else if (fsp->print_file) {
7986 * Doing a DELETE_ON_CLOSE should cancel a print job.
7988 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7989 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7991 DEBUG(3,("call_trans2setfilepathinfo: "
7992 "Cancelling print job (%s)\n",
7993 fsp_str_dbg(fsp)));
7995 SSVAL(params,0,0);
7996 send_trans2_replies(conn, req, params, 2,
7997 *ppdata, 0,
7998 max_data_bytes);
7999 return;
8000 } else {
8001 reply_nterror(req,
8002 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8003 return;
8005 } else {
8007 * Original code - this is an open file.
8009 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8010 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8011 "of fnum %d failed (%s)\n", fsp->fnum,
8012 strerror(errno)));
8013 reply_nterror(req, map_nt_error_from_unix(errno));
8014 return;
8017 } else {
8018 char *fname = NULL;
8019 uint32_t ucf_flags = 0;
8021 /* set path info */
8022 if (total_params < 7) {
8023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8024 return;
8027 info_level = SVAL(params,0);
8028 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8029 total_params - 6, STR_TERMINATE,
8030 &status);
8031 if (!NT_STATUS_IS_OK(status)) {
8032 reply_nterror(req, status);
8033 return;
8036 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8037 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8038 info_level == SMB_FILE_RENAME_INFORMATION ||
8039 info_level == SMB_POSIX_PATH_UNLINK) {
8040 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8043 status = filename_convert(req, conn,
8044 req->flags2 & FLAGS2_DFS_PATHNAMES,
8045 fname,
8046 ucf_flags,
8047 NULL,
8048 &smb_fname);
8049 if (!NT_STATUS_IS_OK(status)) {
8050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8051 reply_botherror(req,
8052 NT_STATUS_PATH_NOT_COVERED,
8053 ERRSRV, ERRbadpath);
8054 return;
8056 reply_nterror(req, status);
8057 return;
8060 if (INFO_LEVEL_IS_UNIX(info_level)) {
8062 * For CIFS UNIX extensions the target name may not exist.
8065 /* Always do lstat for UNIX calls. */
8066 SMB_VFS_LSTAT(conn, smb_fname);
8068 } else if (!VALID_STAT(smb_fname->st) &&
8069 SMB_VFS_STAT(conn, smb_fname)) {
8070 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8071 "%s failed (%s)\n",
8072 smb_fname_str_dbg(smb_fname),
8073 strerror(errno)));
8074 reply_nterror(req, map_nt_error_from_unix(errno));
8075 return;
8079 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8080 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8081 fsp ? fsp->fnum : -1, info_level,total_data));
8083 /* Realloc the parameter size */
8084 *pparams = (char *)SMB_REALLOC(*pparams,2);
8085 if (*pparams == NULL) {
8086 reply_nterror(req, NT_STATUS_NO_MEMORY);
8087 return;
8089 params = *pparams;
8091 SSVAL(params,0,0);
8093 status = smbd_do_setfilepathinfo(conn, req, req,
8094 info_level,
8095 fsp,
8096 smb_fname,
8097 ppdata, total_data,
8098 &data_return_size);
8099 if (!NT_STATUS_IS_OK(status)) {
8100 if (open_was_deferred(req->mid)) {
8101 /* We have re-scheduled this call. */
8102 return;
8104 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8105 /* We have re-scheduled this call. */
8106 return;
8108 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8109 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8110 ERRSRV, ERRbadpath);
8111 return;
8113 if (info_level == SMB_POSIX_PATH_OPEN) {
8114 reply_openerror(req, status);
8115 return;
8118 reply_nterror(req, status);
8119 return;
8122 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8123 max_data_bytes);
8125 return;
8128 /****************************************************************************
8129 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8130 ****************************************************************************/
8132 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8133 char **pparams, int total_params,
8134 char **ppdata, int total_data,
8135 unsigned int max_data_bytes)
8137 struct smb_filename *smb_dname = NULL;
8138 char *params = *pparams;
8139 char *pdata = *ppdata;
8140 char *directory = NULL;
8141 NTSTATUS status = NT_STATUS_OK;
8142 struct ea_list *ea_list = NULL;
8143 TALLOC_CTX *ctx = talloc_tos();
8145 if (!CAN_WRITE(conn)) {
8146 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8147 return;
8150 if (total_params < 5) {
8151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8152 return;
8155 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8156 total_params - 4, STR_TERMINATE,
8157 &status);
8158 if (!NT_STATUS_IS_OK(status)) {
8159 reply_nterror(req, status);
8160 return;
8163 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8165 status = filename_convert(ctx,
8166 conn,
8167 req->flags2 & FLAGS2_DFS_PATHNAMES,
8168 directory,
8170 NULL,
8171 &smb_dname);
8173 if (!NT_STATUS_IS_OK(status)) {
8174 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8175 reply_botherror(req,
8176 NT_STATUS_PATH_NOT_COVERED,
8177 ERRSRV, ERRbadpath);
8178 return;
8180 reply_nterror(req, status);
8181 return;
8185 * OS/2 workplace shell seems to send SET_EA requests of "null"
8186 * length (4 bytes containing IVAL 4).
8187 * They seem to have no effect. Bug #3212. JRA.
8190 if (total_data && (total_data != 4)) {
8191 /* Any data in this call is an EA list. */
8192 if (total_data < 10) {
8193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8194 goto out;
8197 if (IVAL(pdata,0) > total_data) {
8198 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8199 IVAL(pdata,0), (unsigned int)total_data));
8200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8201 goto out;
8204 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8205 total_data - 4);
8206 if (!ea_list) {
8207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8208 goto out;
8211 if (!lp_ea_support(SNUM(conn))) {
8212 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8213 goto out;
8216 /* If total_data == 4 Windows doesn't care what values
8217 * are placed in that field, it just ignores them.
8218 * The System i QNTC IBM SMB client puts bad values here,
8219 * so ignore them. */
8221 status = create_directory(conn, req, smb_dname);
8223 if (!NT_STATUS_IS_OK(status)) {
8224 reply_nterror(req, status);
8225 goto out;
8228 /* Try and set any given EA. */
8229 if (ea_list) {
8230 status = set_ea(conn, NULL, smb_dname, ea_list);
8231 if (!NT_STATUS_IS_OK(status)) {
8232 reply_nterror(req, status);
8233 goto out;
8237 /* Realloc the parameter and data sizes */
8238 *pparams = (char *)SMB_REALLOC(*pparams,2);
8239 if(*pparams == NULL) {
8240 reply_nterror(req, NT_STATUS_NO_MEMORY);
8241 goto out;
8243 params = *pparams;
8245 SSVAL(params,0,0);
8247 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8249 out:
8250 TALLOC_FREE(smb_dname);
8251 return;
8254 /****************************************************************************
8255 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8256 We don't actually do this - we just send a null response.
8257 ****************************************************************************/
8259 static void call_trans2findnotifyfirst(connection_struct *conn,
8260 struct smb_request *req,
8261 char **pparams, int total_params,
8262 char **ppdata, int total_data,
8263 unsigned int max_data_bytes)
8265 char *params = *pparams;
8266 uint16 info_level;
8268 if (total_params < 6) {
8269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8270 return;
8273 info_level = SVAL(params,4);
8274 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8276 switch (info_level) {
8277 case 1:
8278 case 2:
8279 break;
8280 default:
8281 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8282 return;
8285 /* Realloc the parameter and data sizes */
8286 *pparams = (char *)SMB_REALLOC(*pparams,6);
8287 if (*pparams == NULL) {
8288 reply_nterror(req, NT_STATUS_NO_MEMORY);
8289 return;
8291 params = *pparams;
8293 SSVAL(params,0,fnf_handle);
8294 SSVAL(params,2,0); /* No changes */
8295 SSVAL(params,4,0); /* No EA errors */
8297 fnf_handle++;
8299 if(fnf_handle == 0)
8300 fnf_handle = 257;
8302 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8304 return;
8307 /****************************************************************************
8308 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8309 changes). Currently this does nothing.
8310 ****************************************************************************/
8312 static void call_trans2findnotifynext(connection_struct *conn,
8313 struct smb_request *req,
8314 char **pparams, int total_params,
8315 char **ppdata, int total_data,
8316 unsigned int max_data_bytes)
8318 char *params = *pparams;
8320 DEBUG(3,("call_trans2findnotifynext\n"));
8322 /* Realloc the parameter and data sizes */
8323 *pparams = (char *)SMB_REALLOC(*pparams,4);
8324 if (*pparams == NULL) {
8325 reply_nterror(req, NT_STATUS_NO_MEMORY);
8326 return;
8328 params = *pparams;
8330 SSVAL(params,0,0); /* No changes */
8331 SSVAL(params,2,0); /* No EA errors */
8333 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8335 return;
8338 /****************************************************************************
8339 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8340 ****************************************************************************/
8342 static void call_trans2getdfsreferral(connection_struct *conn,
8343 struct smb_request *req,
8344 char **pparams, int total_params,
8345 char **ppdata, int total_data,
8346 unsigned int max_data_bytes)
8348 char *params = *pparams;
8349 char *pathname = NULL;
8350 int reply_size = 0;
8351 int max_referral_level;
8352 NTSTATUS status = NT_STATUS_OK;
8353 TALLOC_CTX *ctx = talloc_tos();
8355 DEBUG(10,("call_trans2getdfsreferral\n"));
8357 if (total_params < 3) {
8358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8359 return;
8362 max_referral_level = SVAL(params,0);
8364 if(!lp_host_msdfs()) {
8365 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8366 return;
8369 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8370 total_params - 2, STR_TERMINATE);
8371 if (!pathname) {
8372 reply_nterror(req, NT_STATUS_NOT_FOUND);
8373 return;
8375 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8376 ppdata,&status)) < 0) {
8377 reply_nterror(req, status);
8378 return;
8381 SSVAL(req->inbuf, smb_flg2,
8382 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8383 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8385 return;
8388 #define LMCAT_SPL 0x53
8389 #define LMFUNC_GETJOBID 0x60
8391 /****************************************************************************
8392 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8393 ****************************************************************************/
8395 static void call_trans2ioctl(connection_struct *conn,
8396 struct smb_request *req,
8397 char **pparams, int total_params,
8398 char **ppdata, int total_data,
8399 unsigned int max_data_bytes)
8401 char *pdata = *ppdata;
8402 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8404 /* check for an invalid fid before proceeding */
8406 if (!fsp) {
8407 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8408 return;
8411 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8412 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8413 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8414 if (*ppdata == NULL) {
8415 reply_nterror(req, NT_STATUS_NO_MEMORY);
8416 return;
8418 pdata = *ppdata;
8420 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8421 CAN ACCEPT THIS IN UNICODE. JRA. */
8423 /* Job number */
8424 if (fsp->print_file) {
8425 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8426 } else {
8427 SSVAL(pdata, 0, 0);
8429 srvstr_push(pdata, req->flags2, pdata + 2,
8430 global_myname(), 15,
8431 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8432 srvstr_push(pdata, req->flags2, pdata+18,
8433 lp_servicename(SNUM(conn)), 13,
8434 STR_ASCII|STR_TERMINATE); /* Service name */
8435 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8436 max_data_bytes);
8437 return;
8440 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8441 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8444 /****************************************************************************
8445 Reply to a SMBfindclose (stop trans2 directory search).
8446 ****************************************************************************/
8448 void reply_findclose(struct smb_request *req)
8450 int dptr_num;
8451 struct smbd_server_connection *sconn = req->sconn;
8453 START_PROFILE(SMBfindclose);
8455 if (req->wct < 1) {
8456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8457 END_PROFILE(SMBfindclose);
8458 return;
8461 dptr_num = SVALS(req->vwv+0, 0);
8463 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8465 dptr_close(sconn, &dptr_num);
8467 reply_outbuf(req, 0, 0);
8469 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8471 END_PROFILE(SMBfindclose);
8472 return;
8475 /****************************************************************************
8476 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8477 ****************************************************************************/
8479 void reply_findnclose(struct smb_request *req)
8481 int dptr_num;
8483 START_PROFILE(SMBfindnclose);
8485 if (req->wct < 1) {
8486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8487 END_PROFILE(SMBfindnclose);
8488 return;
8491 dptr_num = SVAL(req->vwv+0, 0);
8493 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8495 /* We never give out valid handles for a
8496 findnotifyfirst - so any dptr_num is ok here.
8497 Just ignore it. */
8499 reply_outbuf(req, 0, 0);
8501 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8503 END_PROFILE(SMBfindnclose);
8504 return;
8507 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8508 struct trans_state *state)
8510 if (get_Protocol() >= PROTOCOL_NT1) {
8511 req->flags2 |= 0x40; /* IS_LONG_NAME */
8512 SSVAL(req->inbuf,smb_flg2,req->flags2);
8515 if (conn->encrypt_level == Required && !req->encrypted) {
8516 if (state->call != TRANSACT2_QFSINFO &&
8517 state->call != TRANSACT2_SETFSINFO) {
8518 DEBUG(0,("handle_trans2: encryption required "
8519 "with call 0x%x\n",
8520 (unsigned int)state->call));
8521 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8522 return;
8526 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8528 /* Now we must call the relevant TRANS2 function */
8529 switch(state->call) {
8530 case TRANSACT2_OPEN:
8532 START_PROFILE(Trans2_open);
8533 call_trans2open(conn, req,
8534 &state->param, state->total_param,
8535 &state->data, state->total_data,
8536 state->max_data_return);
8537 END_PROFILE(Trans2_open);
8538 break;
8541 case TRANSACT2_FINDFIRST:
8543 START_PROFILE(Trans2_findfirst);
8544 call_trans2findfirst(conn, req,
8545 &state->param, state->total_param,
8546 &state->data, state->total_data,
8547 state->max_data_return);
8548 END_PROFILE(Trans2_findfirst);
8549 break;
8552 case TRANSACT2_FINDNEXT:
8554 START_PROFILE(Trans2_findnext);
8555 call_trans2findnext(conn, req,
8556 &state->param, state->total_param,
8557 &state->data, state->total_data,
8558 state->max_data_return);
8559 END_PROFILE(Trans2_findnext);
8560 break;
8563 case TRANSACT2_QFSINFO:
8565 START_PROFILE(Trans2_qfsinfo);
8566 call_trans2qfsinfo(conn, req,
8567 &state->param, state->total_param,
8568 &state->data, state->total_data,
8569 state->max_data_return);
8570 END_PROFILE(Trans2_qfsinfo);
8571 break;
8574 case TRANSACT2_SETFSINFO:
8576 START_PROFILE(Trans2_setfsinfo);
8577 call_trans2setfsinfo(conn, req,
8578 &state->param, state->total_param,
8579 &state->data, state->total_data,
8580 state->max_data_return);
8581 END_PROFILE(Trans2_setfsinfo);
8582 break;
8585 case TRANSACT2_QPATHINFO:
8586 case TRANSACT2_QFILEINFO:
8588 START_PROFILE(Trans2_qpathinfo);
8589 call_trans2qfilepathinfo(conn, req, state->call,
8590 &state->param, state->total_param,
8591 &state->data, state->total_data,
8592 state->max_data_return);
8593 END_PROFILE(Trans2_qpathinfo);
8594 break;
8597 case TRANSACT2_SETPATHINFO:
8598 case TRANSACT2_SETFILEINFO:
8600 START_PROFILE(Trans2_setpathinfo);
8601 call_trans2setfilepathinfo(conn, req, state->call,
8602 &state->param, state->total_param,
8603 &state->data, state->total_data,
8604 state->max_data_return);
8605 END_PROFILE(Trans2_setpathinfo);
8606 break;
8609 case TRANSACT2_FINDNOTIFYFIRST:
8611 START_PROFILE(Trans2_findnotifyfirst);
8612 call_trans2findnotifyfirst(conn, req,
8613 &state->param, state->total_param,
8614 &state->data, state->total_data,
8615 state->max_data_return);
8616 END_PROFILE(Trans2_findnotifyfirst);
8617 break;
8620 case TRANSACT2_FINDNOTIFYNEXT:
8622 START_PROFILE(Trans2_findnotifynext);
8623 call_trans2findnotifynext(conn, req,
8624 &state->param, state->total_param,
8625 &state->data, state->total_data,
8626 state->max_data_return);
8627 END_PROFILE(Trans2_findnotifynext);
8628 break;
8631 case TRANSACT2_MKDIR:
8633 START_PROFILE(Trans2_mkdir);
8634 call_trans2mkdir(conn, req,
8635 &state->param, state->total_param,
8636 &state->data, state->total_data,
8637 state->max_data_return);
8638 END_PROFILE(Trans2_mkdir);
8639 break;
8642 case TRANSACT2_GET_DFS_REFERRAL:
8644 START_PROFILE(Trans2_get_dfs_referral);
8645 call_trans2getdfsreferral(conn, req,
8646 &state->param, state->total_param,
8647 &state->data, state->total_data,
8648 state->max_data_return);
8649 END_PROFILE(Trans2_get_dfs_referral);
8650 break;
8653 case TRANSACT2_IOCTL:
8655 START_PROFILE(Trans2_ioctl);
8656 call_trans2ioctl(conn, req,
8657 &state->param, state->total_param,
8658 &state->data, state->total_data,
8659 state->max_data_return);
8660 END_PROFILE(Trans2_ioctl);
8661 break;
8664 default:
8665 /* Error in request */
8666 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8667 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8671 /****************************************************************************
8672 Reply to a SMBtrans2.
8673 ****************************************************************************/
8675 void reply_trans2(struct smb_request *req)
8677 connection_struct *conn = req->conn;
8678 unsigned int dsoff;
8679 unsigned int dscnt;
8680 unsigned int psoff;
8681 unsigned int pscnt;
8682 unsigned int tran_call;
8683 struct trans_state *state;
8684 NTSTATUS result;
8686 START_PROFILE(SMBtrans2);
8688 if (req->wct < 14) {
8689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8690 END_PROFILE(SMBtrans2);
8691 return;
8694 dsoff = SVAL(req->vwv+12, 0);
8695 dscnt = SVAL(req->vwv+11, 0);
8696 psoff = SVAL(req->vwv+10, 0);
8697 pscnt = SVAL(req->vwv+9, 0);
8698 tran_call = SVAL(req->vwv+14, 0);
8700 result = allow_new_trans(conn->pending_trans, req->mid);
8701 if (!NT_STATUS_IS_OK(result)) {
8702 DEBUG(2, ("Got invalid trans2 request: %s\n",
8703 nt_errstr(result)));
8704 reply_nterror(req, result);
8705 END_PROFILE(SMBtrans2);
8706 return;
8709 if (IS_IPC(conn)) {
8710 switch (tran_call) {
8711 /* List the allowed trans2 calls on IPC$ */
8712 case TRANSACT2_OPEN:
8713 case TRANSACT2_GET_DFS_REFERRAL:
8714 case TRANSACT2_QFILEINFO:
8715 case TRANSACT2_QFSINFO:
8716 case TRANSACT2_SETFSINFO:
8717 break;
8718 default:
8719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8720 END_PROFILE(SMBtrans2);
8721 return;
8725 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8726 DEBUG(0, ("talloc failed\n"));
8727 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 END_PROFILE(SMBtrans2);
8729 return;
8732 state->cmd = SMBtrans2;
8734 state->mid = req->mid;
8735 state->vuid = req->vuid;
8736 state->setup_count = SVAL(req->vwv+13, 0);
8737 state->setup = NULL;
8738 state->total_param = SVAL(req->vwv+0, 0);
8739 state->param = NULL;
8740 state->total_data = SVAL(req->vwv+1, 0);
8741 state->data = NULL;
8742 state->max_param_return = SVAL(req->vwv+2, 0);
8743 state->max_data_return = SVAL(req->vwv+3, 0);
8744 state->max_setup_return = SVAL(req->vwv+4, 0);
8745 state->close_on_completion = BITSETW(req->vwv+5, 0);
8746 state->one_way = BITSETW(req->vwv+5, 1);
8748 state->call = tran_call;
8750 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8751 is so as a sanity check */
8752 if (state->setup_count != 1) {
8754 * Need to have rc=0 for ioctl to get job id for OS/2.
8755 * Network printing will fail if function is not successful.
8756 * Similar function in reply.c will be used if protocol
8757 * is LANMAN1.0 instead of LM1.2X002.
8758 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8759 * outbuf doesn't have to be set(only job id is used).
8761 if ( (state->setup_count == 4)
8762 && (tran_call == TRANSACT2_IOCTL)
8763 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8764 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8765 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8766 } else {
8767 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8768 DEBUG(2,("Transaction is %d\n",tran_call));
8769 TALLOC_FREE(state);
8770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8771 END_PROFILE(SMBtrans2);
8772 return;
8776 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8777 goto bad_param;
8779 if (state->total_data) {
8781 if (trans_oob(state->total_data, 0, dscnt)
8782 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8783 goto bad_param;
8786 /* Can't use talloc here, the core routines do realloc on the
8787 * params and data. */
8788 state->data = (char *)SMB_MALLOC(state->total_data);
8789 if (state->data == NULL) {
8790 DEBUG(0,("reply_trans2: data malloc fail for %u "
8791 "bytes !\n", (unsigned int)state->total_data));
8792 TALLOC_FREE(state);
8793 reply_nterror(req, NT_STATUS_NO_MEMORY);
8794 END_PROFILE(SMBtrans2);
8795 return;
8798 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8801 if (state->total_param) {
8803 if (trans_oob(state->total_param, 0, pscnt)
8804 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8805 goto bad_param;
8808 /* Can't use talloc here, the core routines do realloc on the
8809 * params and data. */
8810 state->param = (char *)SMB_MALLOC(state->total_param);
8811 if (state->param == NULL) {
8812 DEBUG(0,("reply_trans: param malloc fail for %u "
8813 "bytes !\n", (unsigned int)state->total_param));
8814 SAFE_FREE(state->data);
8815 TALLOC_FREE(state);
8816 reply_nterror(req, NT_STATUS_NO_MEMORY);
8817 END_PROFILE(SMBtrans2);
8818 return;
8821 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8824 state->received_data = dscnt;
8825 state->received_param = pscnt;
8827 if ((state->received_param == state->total_param) &&
8828 (state->received_data == state->total_data)) {
8830 handle_trans2(conn, req, state);
8832 SAFE_FREE(state->data);
8833 SAFE_FREE(state->param);
8834 TALLOC_FREE(state);
8835 END_PROFILE(SMBtrans2);
8836 return;
8839 DLIST_ADD(conn->pending_trans, state);
8841 /* We need to send an interim response then receive the rest
8842 of the parameter/data bytes */
8843 reply_outbuf(req, 0, 0);
8844 show_msg((char *)req->outbuf);
8845 END_PROFILE(SMBtrans2);
8846 return;
8848 bad_param:
8850 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8851 SAFE_FREE(state->data);
8852 SAFE_FREE(state->param);
8853 TALLOC_FREE(state);
8854 END_PROFILE(SMBtrans2);
8855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8859 /****************************************************************************
8860 Reply to a SMBtranss2
8861 ****************************************************************************/
8863 void reply_transs2(struct smb_request *req)
8865 connection_struct *conn = req->conn;
8866 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8867 struct trans_state *state;
8869 START_PROFILE(SMBtranss2);
8871 show_msg((char *)req->inbuf);
8873 /* Windows clients expect all replies to
8874 a transact secondary (SMBtranss2 0x33)
8875 to have a command code of transact
8876 (SMBtrans2 0x32). See bug #8989
8877 and also [MS-CIFS] section 2.2.4.47.2
8878 for details.
8880 req->cmd = SMBtrans2;
8882 if (req->wct < 8) {
8883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8884 END_PROFILE(SMBtranss2);
8885 return;
8888 for (state = conn->pending_trans; state != NULL;
8889 state = state->next) {
8890 if (state->mid == req->mid) {
8891 break;
8895 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8897 END_PROFILE(SMBtranss2);
8898 return;
8901 /* Revise state->total_param and state->total_data in case they have
8902 changed downwards */
8904 if (SVAL(req->vwv+0, 0) < state->total_param)
8905 state->total_param = SVAL(req->vwv+0, 0);
8906 if (SVAL(req->vwv+1, 0) < state->total_data)
8907 state->total_data = SVAL(req->vwv+1, 0);
8909 pcnt = SVAL(req->vwv+2, 0);
8910 poff = SVAL(req->vwv+3, 0);
8911 pdisp = SVAL(req->vwv+4, 0);
8913 dcnt = SVAL(req->vwv+5, 0);
8914 doff = SVAL(req->vwv+6, 0);
8915 ddisp = SVAL(req->vwv+7, 0);
8917 state->received_param += pcnt;
8918 state->received_data += dcnt;
8920 if ((state->received_data > state->total_data) ||
8921 (state->received_param > state->total_param))
8922 goto bad_param;
8924 if (pcnt) {
8925 if (trans_oob(state->total_param, pdisp, pcnt)
8926 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8927 goto bad_param;
8929 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8932 if (dcnt) {
8933 if (trans_oob(state->total_data, ddisp, dcnt)
8934 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8935 goto bad_param;
8937 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8940 if ((state->received_param < state->total_param) ||
8941 (state->received_data < state->total_data)) {
8942 END_PROFILE(SMBtranss2);
8943 return;
8946 handle_trans2(conn, req, state);
8948 DLIST_REMOVE(conn->pending_trans, state);
8949 SAFE_FREE(state->data);
8950 SAFE_FREE(state->param);
8951 TALLOC_FREE(state);
8953 END_PROFILE(SMBtranss2);
8954 return;
8956 bad_param:
8958 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8959 DLIST_REMOVE(conn->pending_trans, state);
8960 SAFE_FREE(state->data);
8961 SAFE_FREE(state->param);
8962 TALLOC_FREE(state);
8963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8964 END_PROFILE(SMBtranss2);
8965 return;