s3-waf: Set HAVE_GSSAPI if gssapi libs were found
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob4032120007e8343fe66742fbb05e1f0c984ba144
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
58 return val;
61 /********************************************************************
62 Create a 64 bit FileIndex. If the file is on the same device as
63 the root of the share, just return the 64-bit inode. If it isn't,
64 mangle as we used to do.
65 ********************************************************************/
67 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
69 uint64_t file_index;
70 if (conn->base_share_dev == psbuf->st_ex_dev) {
71 return (uint64_t)psbuf->st_ex_ino;
73 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
74 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
75 return file_index;
78 /****************************************************************************
79 Utility functions for dealing with extended attributes.
80 ****************************************************************************/
82 /****************************************************************************
83 Refuse to allow clients to overwrite our private xattrs.
84 ****************************************************************************/
86 static bool samba_private_attr_name(const char *unix_ea_name)
88 static const char * const prohibited_ea_names[] = {
89 SAMBA_POSIX_INHERITANCE_EA_NAME,
90 SAMBA_XATTR_DOS_ATTRIB,
91 SAMBA_XATTR_MARKER,
92 XATTR_NTACL_NAME,
93 NULL
96 int i;
98 for (i = 0; prohibited_ea_names[i]; i++) {
99 if (strequal( prohibited_ea_names[i], unix_ea_name))
100 return true;
102 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
103 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
104 return true;
106 return false;
109 /****************************************************************************
110 Get one EA value. Fill in a struct ea_struct.
111 ****************************************************************************/
113 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
114 files_struct *fsp, const char *fname,
115 const char *ea_name, struct ea_struct *pea)
117 /* Get the value of this xattr. Max size is 64k. */
118 size_t attr_size = 256;
119 char *val = NULL;
120 ssize_t sizeret;
122 again:
124 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
125 if (!val) {
126 return NT_STATUS_NO_MEMORY;
129 if (fsp && fsp->fh->fd != -1) {
130 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
131 } else {
132 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
135 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
136 attr_size = 65536;
137 goto again;
140 if (sizeret == -1) {
141 return map_nt_error_from_unix(errno);
144 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
145 dump_data(10, (uint8 *)val, sizeret);
147 pea->flags = 0;
148 if (strnequal(ea_name, "user.", 5)) {
149 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
150 } else {
151 pea->name = talloc_strdup(mem_ctx, ea_name);
153 if (pea->name == NULL) {
154 TALLOC_FREE(val);
155 return NT_STATUS_NO_MEMORY;
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
159 return NT_STATUS_OK;
162 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
163 files_struct *fsp, const char *fname,
164 char ***pnames, size_t *pnum_names)
166 /* Get a list of all xattrs. Max namesize is 64k. */
167 size_t ea_namelist_size = 1024;
168 char *ea_namelist = NULL;
170 char *p;
171 char **names, **tmp;
172 size_t num_names;
173 ssize_t sizeret = -1;
175 if (!lp_ea_support(SNUM(conn))) {
176 if (pnames) {
177 *pnames = NULL;
179 *pnum_names = 0;
180 return NT_STATUS_OK;
184 * TALLOC the result early to get the talloc hierarchy right.
187 names = TALLOC_ARRAY(mem_ctx, char *, 1);
188 if (names == NULL) {
189 DEBUG(0, ("talloc failed\n"));
190 return NT_STATUS_NO_MEMORY;
193 while (ea_namelist_size <= 65536) {
195 ea_namelist = TALLOC_REALLOC_ARRAY(
196 names, ea_namelist, char, ea_namelist_size);
197 if (ea_namelist == NULL) {
198 DEBUG(0, ("talloc failed\n"));
199 TALLOC_FREE(names);
200 return NT_STATUS_NO_MEMORY;
203 if (fsp && fsp->fh->fd != -1) {
204 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
205 ea_namelist_size);
206 } else {
207 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
208 ea_namelist_size);
211 if ((sizeret == -1) && (errno == ERANGE)) {
212 ea_namelist_size *= 2;
214 else {
215 break;
219 if (sizeret == -1) {
220 TALLOC_FREE(names);
221 return map_nt_error_from_unix(errno);
224 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
225 (unsigned int)sizeret));
227 if (sizeret == 0) {
228 TALLOC_FREE(names);
229 if (pnames) {
230 *pnames = NULL;
232 *pnum_names = 0;
233 return NT_STATUS_OK;
237 * Ensure the result is 0-terminated
240 if (ea_namelist[sizeret-1] != '\0') {
241 TALLOC_FREE(names);
242 return NT_STATUS_INTERNAL_ERROR;
246 * count the names
248 num_names = 0;
250 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
251 num_names += 1;
254 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
255 if (tmp == NULL) {
256 DEBUG(0, ("talloc failed\n"));
257 TALLOC_FREE(names);
258 return NT_STATUS_NO_MEMORY;
261 names = tmp;
262 num_names = 0;
264 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
265 names[num_names++] = p;
268 if (pnames) {
269 *pnames = names;
270 } else {
271 TALLOC_FREE(names);
273 *pnum_names = num_names;
274 return NT_STATUS_OK;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
285 size_t i, num_names;
286 char **names;
287 struct ea_list *ea_list_head = NULL;
288 NTSTATUS status;
290 *pea_total_len = 0;
292 if (!lp_ea_support(SNUM(conn))) {
293 return NULL;
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
297 &names, &num_names);
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
300 return NULL;
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
305 fstring dos_ea_name;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
309 continue;
311 listp = TALLOC_P(mem_ctx, struct ea_list);
312 if (listp == NULL) {
313 return NULL;
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
317 fname, names[i],
318 &listp->ea))) {
319 return NULL;
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 *pea_total_len +=
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
337 *pea_total_len += 4;
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
343 return ea_list_head;
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 that was filled.
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
355 char *p = pdata;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
360 SIVAL(pdata,4,0);
361 return 4;
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
365 size_t dos_namelen;
366 fstring dos_ea_name;
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
370 break;
372 if (ea_list->ea.value.length > 65535) {
373 break;
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
376 break;
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
397 char *pdata,
398 unsigned int total_data_size,
399 unsigned int *ret_data_size,
400 connection_struct *conn,
401 struct ea_list *ea_list)
403 uint8_t *p = (uint8_t *)pdata;
404 uint8_t *last_start = NULL;
406 *ret_data_size = 0;
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_NO_EAS_ON_FILE;
412 for (; ea_list; ea_list = ea_list->next) {
413 size_t dos_namelen;
414 fstring dos_ea_name;
415 size_t this_size;
417 if (last_start) {
418 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
420 last_start = p;
422 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
423 dos_namelen = strlen(dos_ea_name);
424 if (dos_namelen > 255 || dos_namelen == 0) {
425 return NT_STATUS_INTERNAL_ERROR;
427 if (ea_list->ea.value.length > 65535) {
428 return NT_STATUS_INTERNAL_ERROR;
431 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
433 if (ea_list->next) {
434 size_t pad = 4 - (this_size % 4);
435 this_size += pad;
438 if (this_size > total_data_size) {
439 return NT_STATUS_INFO_LENGTH_MISMATCH;
442 /* We know we have room. */
443 SIVAL(p, 0x00, 0); /* next offset */
444 SCVAL(p, 0x04, ea_list->ea.flags);
445 SCVAL(p, 0x05, dos_namelen);
446 SSVAL(p, 0x06, ea_list->ea.value.length);
447 fstrcpy((char *)(p+0x08), dos_ea_name);
448 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
450 total_data_size -= this_size;
451 p += this_size;
454 *ret_data_size = PTR_DIFF(p, pdata);
455 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
456 return NT_STATUS_OK;
459 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
461 size_t total_ea_len = 0;
462 TALLOC_CTX *mem_ctx = NULL;
464 if (!lp_ea_support(SNUM(conn))) {
465 return 0;
467 mem_ctx = talloc_tos();
468 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
469 return total_ea_len;
472 /****************************************************************************
473 Ensure the EA name is case insensitive by matching any existing EA name.
474 ****************************************************************************/
476 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
478 size_t total_ea_len;
479 TALLOC_CTX *mem_ctx = talloc_tos();
480 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
482 for (; ea_list; ea_list = ea_list->next) {
483 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
484 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
485 &unix_ea_name[5], ea_list->ea.name));
486 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
487 break;
492 /****************************************************************************
493 Set or delete an extended attribute.
494 ****************************************************************************/
496 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
497 const struct smb_filename *smb_fname, struct ea_list *ea_list)
499 char *fname = NULL;
501 if (!lp_ea_support(SNUM(conn))) {
502 return NT_STATUS_EAS_NOT_SUPPORTED;
505 /* For now setting EAs on streams isn't supported. */
506 fname = smb_fname->base_name;
508 for (;ea_list; ea_list = ea_list->next) {
509 int ret;
510 fstring unix_ea_name;
512 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
513 fstrcat(unix_ea_name, ea_list->ea.name);
515 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
517 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
519 if (samba_private_attr_name(unix_ea_name)) {
520 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
521 return NT_STATUS_ACCESS_DENIED;
524 if (ea_list->ea.value.length == 0) {
525 /* Remove the attribute. */
526 if (fsp && (fsp->fh->fd != -1)) {
527 DEBUG(10,("set_ea: deleting ea name %s on "
528 "file %s by file descriptor.\n",
529 unix_ea_name, fsp_str_dbg(fsp)));
530 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
531 } else {
532 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
533 unix_ea_name, fname));
534 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
536 #ifdef ENOATTR
537 /* Removing a non existent attribute always succeeds. */
538 if (ret == -1 && errno == ENOATTR) {
539 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
540 unix_ea_name));
541 ret = 0;
543 #endif
544 } else {
545 if (fsp && (fsp->fh->fd != -1)) {
546 DEBUG(10,("set_ea: setting ea name %s on file "
547 "%s by file descriptor.\n",
548 unix_ea_name, fsp_str_dbg(fsp)));
549 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
550 ea_list->ea.value.data, ea_list->ea.value.length, 0);
551 } else {
552 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
553 unix_ea_name, fname));
554 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
555 ea_list->ea.value.data, ea_list->ea.value.length, 0);
559 if (ret == -1) {
560 #ifdef ENOTSUP
561 if (errno == ENOTSUP) {
562 return NT_STATUS_EAS_NOT_SUPPORTED;
564 #endif
565 return map_nt_error_from_unix(errno);
569 return NT_STATUS_OK;
571 /****************************************************************************
572 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
573 ****************************************************************************/
575 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
577 struct ea_list *ea_list_head = NULL;
578 size_t converted_size, offset = 0;
580 while (offset + 2 < data_size) {
581 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
582 unsigned int namelen = CVAL(pdata,offset);
584 offset++; /* Go past the namelen byte. */
586 /* integer wrap paranioa. */
587 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
588 (offset > data_size) || (namelen > data_size) ||
589 (offset + namelen >= data_size)) {
590 break;
592 /* Ensure the name is null terminated. */
593 if (pdata[offset + namelen] != '\0') {
594 return NULL;
596 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
597 &converted_size)) {
598 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
599 "failed: %s", strerror(errno)));
601 if (!eal->ea.name) {
602 return NULL;
605 offset += (namelen + 1); /* Go past the name + terminating zero. */
606 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
607 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
610 return ea_list_head;
613 /****************************************************************************
614 Read one EA list entry from the buffer.
615 ****************************************************************************/
617 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
619 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
620 uint16 val_len;
621 unsigned int namelen;
622 size_t converted_size;
624 if (!eal) {
625 return NULL;
628 if (data_size < 6) {
629 return NULL;
632 eal->ea.flags = CVAL(pdata,0);
633 namelen = CVAL(pdata,1);
634 val_len = SVAL(pdata,2);
636 if (4 + namelen + 1 + val_len > data_size) {
637 return NULL;
640 /* Ensure the name is null terminated. */
641 if (pdata[namelen + 4] != '\0') {
642 return NULL;
644 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
645 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
646 strerror(errno)));
648 if (!eal->ea.name) {
649 return NULL;
652 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
653 if (!eal->ea.value.data) {
654 return NULL;
657 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
659 /* Ensure we're null terminated just in case we print the value. */
660 eal->ea.value.data[val_len] = '\0';
661 /* But don't count the null. */
662 eal->ea.value.length--;
664 if (pbytes_used) {
665 *pbytes_used = 4 + namelen + 1 + val_len;
668 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
669 dump_data(10, eal->ea.value.data, eal->ea.value.length);
671 return eal;
674 /****************************************************************************
675 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
676 ****************************************************************************/
678 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
680 struct ea_list *ea_list_head = NULL;
681 size_t offset = 0;
682 size_t bytes_used = 0;
684 while (offset < data_size) {
685 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
687 if (!eal) {
688 return NULL;
691 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
692 offset += bytes_used;
695 return ea_list_head;
698 /****************************************************************************
699 Count the total EA size needed.
700 ****************************************************************************/
702 static size_t ea_list_size(struct ea_list *ealist)
704 fstring dos_ea_name;
705 struct ea_list *listp;
706 size_t ret = 0;
708 for (listp = ealist; listp; listp = listp->next) {
709 push_ascii_fstring(dos_ea_name, listp->ea.name);
710 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
712 /* Add on 4 for total length. */
713 if (ret) {
714 ret += 4;
717 return ret;
720 /****************************************************************************
721 Return a union of EA's from a file list and a list of names.
722 The TALLOC context for the two lists *MUST* be identical as we steal
723 memory from one list to add to another. JRA.
724 ****************************************************************************/
726 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
728 struct ea_list *nlistp, *flistp;
730 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
731 for (flistp = file_list; flistp; flistp = flistp->next) {
732 if (strequal(nlistp->ea.name, flistp->ea.name)) {
733 break;
737 if (flistp) {
738 /* Copy the data from this entry. */
739 nlistp->ea.flags = flistp->ea.flags;
740 nlistp->ea.value = flistp->ea.value;
741 } else {
742 /* Null entry. */
743 nlistp->ea.flags = 0;
744 ZERO_STRUCT(nlistp->ea.value);
748 *total_ea_len = ea_list_size(name_list);
749 return name_list;
752 /****************************************************************************
753 Send the required number of replies back.
754 We assume all fields other than the data fields are
755 set correctly for the type of call.
756 HACK ! Always assumes smb_setup field is zero.
757 ****************************************************************************/
759 void send_trans2_replies(connection_struct *conn,
760 struct smb_request *req,
761 const char *params,
762 int paramsize,
763 const char *pdata,
764 int datasize,
765 int max_data_bytes)
767 /* As we are using a protocol > LANMAN1 then the max_send
768 variable must have been set in the sessetupX call.
769 This takes precedence over the max_xmit field in the
770 global struct. These different max_xmit variables should
771 be merged as this is now too confusing */
773 int data_to_send = datasize;
774 int params_to_send = paramsize;
775 int useable_space;
776 const char *pp = params;
777 const char *pd = pdata;
778 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
779 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
780 int data_alignment_offset = 0;
781 bool overflow = False;
782 struct smbd_server_connection *sconn = smbd_server_conn;
783 int max_send = sconn->smb1.sessions.max_send;
785 /* Modify the data_to_send and datasize and set the error if
786 we're trying to send more than max_data_bytes. We still send
787 the part of the packet(s) that fit. Strange, but needed
788 for OS/2. */
790 if (max_data_bytes > 0 && datasize > max_data_bytes) {
791 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
792 max_data_bytes, datasize ));
793 datasize = data_to_send = max_data_bytes;
794 overflow = True;
797 /* If there genuinely are no parameters or data to send just send the empty packet */
799 if(params_to_send == 0 && data_to_send == 0) {
800 reply_outbuf(req, 10, 0);
801 show_msg((char *)req->outbuf);
802 if (!srv_send_smb(smbd_server_fd(),
803 (char *)req->outbuf,
804 true, req->seqnum+1,
805 IS_CONN_ENCRYPTED(conn),
806 &req->pcd)) {
807 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
809 TALLOC_FREE(req->outbuf);
810 return;
813 /* When sending params and data ensure that both are nicely aligned */
814 /* Only do this alignment when there is also data to send - else
815 can cause NT redirector problems. */
817 if (((params_to_send % 4) != 0) && (data_to_send != 0))
818 data_alignment_offset = 4 - (params_to_send % 4);
820 /* Space is bufsize minus Netbios over TCP header minus SMB header */
821 /* The alignment_offset is to align the param bytes on an even byte
822 boundary. NT 4.0 Beta needs this to work correctly. */
824 useable_space = max_send - (smb_size
825 + 2 * 10 /* wct */
826 + alignment_offset
827 + data_alignment_offset);
829 if (useable_space < 0) {
830 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
831 "= %d!!!", useable_space));
832 exit_server_cleanly("send_trans2_replies: Not enough space");
835 while (params_to_send || data_to_send) {
836 /* Calculate whether we will totally or partially fill this packet */
838 total_sent_thistime = params_to_send + data_to_send;
840 /* We can never send more than useable_space */
842 * Note that 'useable_space' does not include the alignment offsets,
843 * but we must include the alignment offsets in the calculation of
844 * the length of the data we send over the wire, as the alignment offsets
845 * are sent here. Fix from Marc_Jacobsen@hp.com.
848 total_sent_thistime = MIN(total_sent_thistime, useable_space);
850 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
851 + data_alignment_offset);
854 * We might have SMBtrans2s in req which was transferred to
855 * the outbuf, fix that.
857 SCVAL(req->outbuf, smb_com, SMBtrans2);
859 /* Set total params and data to be sent */
860 SSVAL(req->outbuf,smb_tprcnt,paramsize);
861 SSVAL(req->outbuf,smb_tdrcnt,datasize);
863 /* Calculate how many parameters and data we can fit into
864 * this packet. Parameters get precedence
867 params_sent_thistime = MIN(params_to_send,useable_space);
868 data_sent_thistime = useable_space - params_sent_thistime;
869 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
871 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
873 /* smb_proff is the offset from the start of the SMB header to the
874 parameter bytes, however the first 4 bytes of outbuf are
875 the Netbios over TCP header. Thus use smb_base() to subtract
876 them from the calculation */
878 SSVAL(req->outbuf,smb_proff,
879 ((smb_buf(req->outbuf)+alignment_offset)
880 - smb_base(req->outbuf)));
882 if(params_sent_thistime == 0)
883 SSVAL(req->outbuf,smb_prdisp,0);
884 else
885 /* Absolute displacement of param bytes sent in this packet */
886 SSVAL(req->outbuf,smb_prdisp,pp - params);
888 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
889 if(data_sent_thistime == 0) {
890 SSVAL(req->outbuf,smb_droff,0);
891 SSVAL(req->outbuf,smb_drdisp, 0);
892 } else {
893 /* The offset of the data bytes is the offset of the
894 parameter bytes plus the number of parameters being sent this time */
895 SSVAL(req->outbuf, smb_droff,
896 ((smb_buf(req->outbuf)+alignment_offset)
897 - smb_base(req->outbuf))
898 + params_sent_thistime + data_alignment_offset);
899 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
902 /* Initialize the padding for alignment */
904 if (alignment_offset != 0) {
905 memset(smb_buf(req->outbuf), 0, alignment_offset);
908 /* Copy the param bytes into the packet */
910 if(params_sent_thistime) {
911 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
912 params_sent_thistime);
915 /* Copy in the data bytes */
916 if(data_sent_thistime) {
917 if (data_alignment_offset != 0) {
918 memset((smb_buf(req->outbuf)+alignment_offset+
919 params_sent_thistime), 0,
920 data_alignment_offset);
922 memcpy(smb_buf(req->outbuf)+alignment_offset
923 +params_sent_thistime+data_alignment_offset,
924 pd,data_sent_thistime);
927 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
928 params_sent_thistime, data_sent_thistime, useable_space));
929 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
930 params_to_send, data_to_send, paramsize, datasize));
932 if (overflow) {
933 error_packet_set((char *)req->outbuf,
934 ERRDOS,ERRbufferoverflow,
935 STATUS_BUFFER_OVERFLOW,
936 __LINE__,__FILE__);
939 /* Send the packet */
940 show_msg((char *)req->outbuf);
941 if (!srv_send_smb(smbd_server_fd(),
942 (char *)req->outbuf,
943 true, req->seqnum+1,
944 IS_CONN_ENCRYPTED(conn),
945 &req->pcd))
946 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
948 TALLOC_FREE(req->outbuf);
950 pp += params_sent_thistime;
951 pd += data_sent_thistime;
953 params_to_send -= params_sent_thistime;
954 data_to_send -= data_sent_thistime;
956 /* Sanity check */
957 if(params_to_send < 0 || data_to_send < 0) {
958 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
959 params_to_send, data_to_send));
960 return;
964 return;
967 /****************************************************************************
968 Reply to a TRANSACT2_OPEN.
969 ****************************************************************************/
971 static void call_trans2open(connection_struct *conn,
972 struct smb_request *req,
973 char **pparams, int total_params,
974 char **ppdata, int total_data,
975 unsigned int max_data_bytes)
977 struct smb_filename *smb_fname = NULL;
978 char *params = *pparams;
979 char *pdata = *ppdata;
980 int deny_mode;
981 int32 open_attr;
982 bool oplock_request;
983 #if 0
984 bool return_additional_info;
985 int16 open_sattr;
986 time_t open_time;
987 #endif
988 int open_ofun;
989 uint32 open_size;
990 char *pname;
991 char *fname = NULL;
992 SMB_OFF_T size=0;
993 int fattr=0,mtime=0;
994 SMB_INO_T inode = 0;
995 int smb_action = 0;
996 files_struct *fsp;
997 struct ea_list *ea_list = NULL;
998 uint16 flags = 0;
999 NTSTATUS status;
1000 uint32 access_mask;
1001 uint32 share_mode;
1002 uint32 create_disposition;
1003 uint32 create_options = 0;
1004 uint32_t private_flags = 0;
1005 TALLOC_CTX *ctx = talloc_tos();
1008 * Ensure we have enough parameters to perform the operation.
1011 if (total_params < 29) {
1012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1013 goto out;
1016 flags = SVAL(params, 0);
1017 deny_mode = SVAL(params, 2);
1018 open_attr = SVAL(params,6);
1019 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1020 if (oplock_request) {
1021 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1024 #if 0
1025 return_additional_info = BITSETW(params,0);
1026 open_sattr = SVAL(params, 4);
1027 open_time = make_unix_date3(params+8);
1028 #endif
1029 open_ofun = SVAL(params,12);
1030 open_size = IVAL(params,14);
1031 pname = &params[28];
1033 if (IS_IPC(conn)) {
1034 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1035 goto out;
1038 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1039 total_params - 28, STR_TERMINATE,
1040 &status);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 reply_nterror(req, status);
1043 goto out;
1046 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1047 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1048 (unsigned int)open_ofun, open_size));
1050 status = filename_convert(ctx,
1051 conn,
1052 req->flags2 & FLAGS2_DFS_PATHNAMES,
1053 fname,
1055 NULL,
1056 &smb_fname);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1059 reply_botherror(req,
1060 NT_STATUS_PATH_NOT_COVERED,
1061 ERRSRV, ERRbadpath);
1062 goto out;
1064 reply_nterror(req, status);
1065 goto out;
1068 if (open_ofun == 0) {
1069 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1070 goto out;
1073 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1074 &access_mask, &share_mode,
1075 &create_disposition,
1076 &create_options,
1077 &private_flags)) {
1078 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1079 goto out;
1082 /* Any data in this call is an EA list. */
1083 if (total_data && (total_data != 4)) {
1084 if (total_data < 10) {
1085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1086 goto out;
1089 if (IVAL(pdata,0) > total_data) {
1090 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1091 IVAL(pdata,0), (unsigned int)total_data));
1092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1093 goto out;
1096 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1097 total_data - 4);
1098 if (!ea_list) {
1099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1100 goto out;
1103 if (!lp_ea_support(SNUM(conn))) {
1104 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1105 goto out;
1109 status = SMB_VFS_CREATE_FILE(
1110 conn, /* conn */
1111 req, /* req */
1112 0, /* root_dir_fid */
1113 smb_fname, /* fname */
1114 access_mask, /* access_mask */
1115 share_mode, /* share_access */
1116 create_disposition, /* create_disposition*/
1117 create_options, /* create_options */
1118 open_attr, /* file_attributes */
1119 oplock_request, /* oplock_request */
1120 open_size, /* allocation_size */
1121 private_flags,
1122 NULL, /* sd */
1123 ea_list, /* ea_list */
1124 &fsp, /* result */
1125 &smb_action); /* psbuf */
1127 if (!NT_STATUS_IS_OK(status)) {
1128 if (open_was_deferred(req->mid)) {
1129 /* We have re-scheduled this call. */
1130 goto out;
1132 reply_openerror(req, status);
1133 goto out;
1136 size = get_file_size_stat(&smb_fname->st);
1137 fattr = dos_mode(conn, smb_fname);
1138 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1139 inode = smb_fname->st.st_ex_ino;
1140 if (fattr & aDIR) {
1141 close_file(req, fsp, ERROR_CLOSE);
1142 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1143 goto out;
1146 /* Realloc the size of parameters and data we will return */
1147 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1148 if(*pparams == NULL ) {
1149 reply_nterror(req, NT_STATUS_NO_MEMORY);
1150 goto out;
1152 params = *pparams;
1154 SSVAL(params,0,fsp->fnum);
1155 SSVAL(params,2,fattr);
1156 srv_put_dos_date2(params,4, mtime);
1157 SIVAL(params,8, (uint32)size);
1158 SSVAL(params,12,deny_mode);
1159 SSVAL(params,14,0); /* open_type - file or directory. */
1160 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1162 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1163 smb_action |= EXTENDED_OPLOCK_GRANTED;
1166 SSVAL(params,18,smb_action);
1169 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1171 SIVAL(params,20,inode);
1172 SSVAL(params,24,0); /* Padding. */
1173 if (flags & 8) {
1174 uint32 ea_size = estimate_ea_size(conn, fsp,
1175 fsp->fsp_name->base_name);
1176 SIVAL(params, 26, ea_size);
1177 } else {
1178 SIVAL(params, 26, 0);
1181 /* Send the required number of replies */
1182 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1183 out:
1184 TALLOC_FREE(smb_fname);
1187 /*********************************************************
1188 Routine to check if a given string matches exactly.
1189 as a special case a mask of "." does NOT match. That
1190 is required for correct wildcard semantics
1191 Case can be significant or not.
1192 **********************************************************/
1194 static bool exact_match(bool has_wild,
1195 bool case_sensitive,
1196 const char *str,
1197 const char *mask)
1199 if (mask[0] == '.' && mask[1] == 0) {
1200 return false;
1203 if (has_wild) {
1204 return false;
1207 if (case_sensitive) {
1208 return strcmp(str,mask)==0;
1209 } else {
1210 return StrCaseCmp(str,mask) == 0;
1214 /****************************************************************************
1215 Return the filetype for UNIX extensions.
1216 ****************************************************************************/
1218 static uint32 unix_filetype(mode_t mode)
1220 if(S_ISREG(mode))
1221 return UNIX_TYPE_FILE;
1222 else if(S_ISDIR(mode))
1223 return UNIX_TYPE_DIR;
1224 #ifdef S_ISLNK
1225 else if(S_ISLNK(mode))
1226 return UNIX_TYPE_SYMLINK;
1227 #endif
1228 #ifdef S_ISCHR
1229 else if(S_ISCHR(mode))
1230 return UNIX_TYPE_CHARDEV;
1231 #endif
1232 #ifdef S_ISBLK
1233 else if(S_ISBLK(mode))
1234 return UNIX_TYPE_BLKDEV;
1235 #endif
1236 #ifdef S_ISFIFO
1237 else if(S_ISFIFO(mode))
1238 return UNIX_TYPE_FIFO;
1239 #endif
1240 #ifdef S_ISSOCK
1241 else if(S_ISSOCK(mode))
1242 return UNIX_TYPE_SOCKET;
1243 #endif
1245 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1246 return UNIX_TYPE_UNKNOWN;
1249 /****************************************************************************
1250 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1251 ****************************************************************************/
1253 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1255 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1256 const SMB_STRUCT_STAT *psbuf,
1257 uint32 perms,
1258 enum perm_type ptype,
1259 mode_t *ret_perms)
1261 mode_t ret = 0;
1263 if (perms == SMB_MODE_NO_CHANGE) {
1264 if (!VALID_STAT(*psbuf)) {
1265 return NT_STATUS_INVALID_PARAMETER;
1266 } else {
1267 *ret_perms = psbuf->st_ex_mode;
1268 return NT_STATUS_OK;
1272 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1273 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1274 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1275 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1276 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1277 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1278 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1279 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1280 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1281 #ifdef S_ISVTX
1282 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1283 #endif
1284 #ifdef S_ISGID
1285 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1286 #endif
1287 #ifdef S_ISUID
1288 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1289 #endif
1291 switch (ptype) {
1292 case PERM_NEW_FILE:
1293 /* Apply mode mask */
1294 ret &= lp_create_mask(SNUM(conn));
1295 /* Add in force bits */
1296 ret |= lp_force_create_mode(SNUM(conn));
1297 break;
1298 case PERM_NEW_DIR:
1299 ret &= lp_dir_mask(SNUM(conn));
1300 /* Add in force bits */
1301 ret |= lp_force_dir_mode(SNUM(conn));
1302 break;
1303 case PERM_EXISTING_FILE:
1304 /* Apply mode mask */
1305 ret &= lp_security_mask(SNUM(conn));
1306 /* Add in force bits */
1307 ret |= lp_force_security_mode(SNUM(conn));
1308 break;
1309 case PERM_EXISTING_DIR:
1310 /* Apply mode mask */
1311 ret &= lp_dir_security_mask(SNUM(conn));
1312 /* Add in force bits */
1313 ret |= lp_force_dir_security_mode(SNUM(conn));
1314 break;
1317 *ret_perms = ret;
1318 return NT_STATUS_OK;
1321 /****************************************************************************
1322 Needed to show the msdfs symlinks as directories. Modifies psbuf
1323 to be a directory if it's a msdfs link.
1324 ****************************************************************************/
1326 static bool check_msdfs_link(connection_struct *conn,
1327 const char *pathname,
1328 SMB_STRUCT_STAT *psbuf)
1330 int saved_errno = errno;
1331 if(lp_host_msdfs() &&
1332 lp_msdfs_root(SNUM(conn)) &&
1333 is_msdfs_link(conn, pathname, psbuf)) {
1335 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1336 "as a directory\n",
1337 pathname));
1338 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1339 errno = saved_errno;
1340 return true;
1342 errno = saved_errno;
1343 return false;
1347 /****************************************************************************
1348 Get a level dependent lanman2 dir entry.
1349 ****************************************************************************/
1351 struct smbd_dirptr_lanman2_state {
1352 connection_struct *conn;
1353 uint32_t info_level;
1354 bool check_mangled_names;
1355 bool has_wild;
1356 bool got_exact_match;
1359 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1360 void *private_data,
1361 const char *dname,
1362 const char *mask,
1363 char **_fname)
1365 struct smbd_dirptr_lanman2_state *state =
1366 (struct smbd_dirptr_lanman2_state *)private_data;
1367 bool ok;
1368 char mangled_name[13]; /* mangled 8.3 name. */
1369 bool got_match;
1370 const char *fname;
1372 /* Mangle fname if it's an illegal name. */
1373 if (mangle_must_mangle(dname, state->conn->params)) {
1374 ok = name_to_8_3(dname, mangled_name,
1375 true, state->conn->params);
1376 if (!ok) {
1377 return false;
1379 fname = mangled_name;
1380 } else {
1381 fname = dname;
1384 got_match = exact_match(state->has_wild,
1385 state->conn->case_sensitive,
1386 fname, mask);
1387 state->got_exact_match = got_match;
1388 if (!got_match) {
1389 got_match = mask_match(fname, mask,
1390 state->conn->case_sensitive);
1393 if(!got_match && state->check_mangled_names &&
1394 !mangle_is_8_3(fname, false, state->conn->params)) {
1396 * It turns out that NT matches wildcards against
1397 * both long *and* short names. This may explain some
1398 * of the wildcard wierdness from old DOS clients
1399 * that some people have been seeing.... JRA.
1401 /* Force the mangling into 8.3. */
1402 ok = name_to_8_3(fname, mangled_name,
1403 false, state->conn->params);
1404 if (!ok) {
1405 return false;
1408 got_match = exact_match(state->has_wild,
1409 state->conn->case_sensitive,
1410 mangled_name, mask);
1411 state->got_exact_match = got_match;
1412 if (!got_match) {
1413 got_match = mask_match(mangled_name, mask,
1414 state->conn->case_sensitive);
1418 if (!got_match) {
1419 return false;
1422 *_fname = talloc_strdup(ctx, fname);
1423 if (*_fname == NULL) {
1424 return false;
1427 return true;
1430 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1431 void *private_data,
1432 struct smb_filename *smb_fname,
1433 uint32_t *_mode)
1435 struct smbd_dirptr_lanman2_state *state =
1436 (struct smbd_dirptr_lanman2_state *)private_data;
1437 bool ms_dfs_link = false;
1438 uint32_t mode = 0;
1440 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1441 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1442 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1443 "Couldn't lstat [%s] (%s)\n",
1444 smb_fname_str_dbg(smb_fname),
1445 strerror(errno)));
1446 return false;
1448 } else if (!VALID_STAT(smb_fname->st) &&
1449 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1450 /* Needed to show the msdfs symlinks as
1451 * directories */
1453 ms_dfs_link = check_msdfs_link(state->conn,
1454 smb_fname->base_name,
1455 &smb_fname->st);
1456 if (!ms_dfs_link) {
1457 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1458 "Couldn't stat [%s] (%s)\n",
1459 smb_fname_str_dbg(smb_fname),
1460 strerror(errno)));
1461 return false;
1465 if (ms_dfs_link) {
1466 mode = dos_mode_msdfs(state->conn, smb_fname);
1467 } else {
1468 mode = dos_mode(state->conn, smb_fname);
1471 *_mode = mode;
1472 return true;
1475 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1476 connection_struct *conn,
1477 uint16_t flags2,
1478 uint32_t info_level,
1479 struct ea_list *name_list,
1480 bool check_mangled_names,
1481 bool requires_resume_key,
1482 uint32_t mode,
1483 const char *fname,
1484 const struct smb_filename *smb_fname,
1485 int space_remaining,
1486 uint8_t align,
1487 bool do_pad,
1488 char *base_data,
1489 char **ppdata,
1490 char *end_data,
1491 bool *out_of_space,
1492 uint64_t *last_entry_off)
1494 char *p, *q, *pdata = *ppdata;
1495 uint32_t reskey=0;
1496 uint64_t file_size = 0;
1497 uint64_t allocation_size = 0;
1498 uint64_t file_index = 0;
1499 uint32_t len;
1500 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1501 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1502 time_t c_date = (time_t)0;
1503 char *nameptr;
1504 char *last_entry_ptr;
1505 bool was_8_3;
1506 int off;
1507 int pad = 0;
1509 *out_of_space = false;
1511 ZERO_STRUCT(mdate_ts);
1512 ZERO_STRUCT(adate_ts);
1513 ZERO_STRUCT(create_date_ts);
1514 ZERO_STRUCT(cdate_ts);
1516 if (!(mode & aDIR)) {
1517 file_size = get_file_size_stat(&smb_fname->st);
1519 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1521 file_index = get_FileIndex(conn, &smb_fname->st);
1523 mdate_ts = smb_fname->st.st_ex_mtime;
1524 adate_ts = smb_fname->st.st_ex_atime;
1525 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1526 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1528 if (lp_dos_filetime_resolution(SNUM(conn))) {
1529 dos_filetime_timespec(&create_date_ts);
1530 dos_filetime_timespec(&mdate_ts);
1531 dos_filetime_timespec(&adate_ts);
1532 dos_filetime_timespec(&cdate_ts);
1535 create_date = convert_timespec_to_time_t(create_date_ts);
1536 mdate = convert_timespec_to_time_t(mdate_ts);
1537 adate = convert_timespec_to_time_t(adate_ts);
1538 c_date = convert_timespec_to_time_t(cdate_ts);
1540 /* align the record */
1541 SMB_ASSERT(align >= 1);
1543 off = (int)PTR_DIFF(pdata, base_data);
1544 pad = (off + (align-1)) & ~(align-1);
1545 pad -= off;
1547 if (pad && pad > space_remaining) {
1548 *out_of_space = true;
1549 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1550 "for padding (wanted %u, had %d)\n",
1551 (unsigned int)pad,
1552 space_remaining ));
1553 return false; /* Not finished - just out of space */
1556 off += pad;
1557 /* initialize padding to 0 */
1558 if (pad) {
1559 memset(pdata, 0, pad);
1561 space_remaining -= pad;
1563 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1564 space_remaining ));
1566 pdata += pad;
1567 p = pdata;
1568 last_entry_ptr = p;
1570 pad = 0;
1571 off = 0;
1573 switch (info_level) {
1574 case SMB_FIND_INFO_STANDARD:
1575 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1576 if(requires_resume_key) {
1577 SIVAL(p,0,reskey);
1578 p += 4;
1580 srv_put_dos_date2(p,0,create_date);
1581 srv_put_dos_date2(p,4,adate);
1582 srv_put_dos_date2(p,8,mdate);
1583 SIVAL(p,12,(uint32)file_size);
1584 SIVAL(p,16,(uint32)allocation_size);
1585 SSVAL(p,20,mode);
1586 p += 23;
1587 nameptr = p;
1588 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1589 p += ucs2_align(base_data, p, 0);
1591 len = srvstr_push(base_data, flags2, p,
1592 fname, PTR_DIFF(end_data, p),
1593 STR_TERMINATE);
1594 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1595 if (len > 2) {
1596 SCVAL(nameptr, -1, len - 2);
1597 } else {
1598 SCVAL(nameptr, -1, 0);
1600 } else {
1601 if (len > 1) {
1602 SCVAL(nameptr, -1, len - 1);
1603 } else {
1604 SCVAL(nameptr, -1, 0);
1607 p += len;
1608 break;
1610 case SMB_FIND_EA_SIZE:
1611 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1612 if (requires_resume_key) {
1613 SIVAL(p,0,reskey);
1614 p += 4;
1616 srv_put_dos_date2(p,0,create_date);
1617 srv_put_dos_date2(p,4,adate);
1618 srv_put_dos_date2(p,8,mdate);
1619 SIVAL(p,12,(uint32)file_size);
1620 SIVAL(p,16,(uint32)allocation_size);
1621 SSVAL(p,20,mode);
1623 unsigned int ea_size = estimate_ea_size(conn, NULL,
1624 smb_fname->base_name);
1625 SIVAL(p,22,ea_size); /* Extended attributes */
1627 p += 27;
1628 nameptr = p - 1;
1629 len = srvstr_push(base_data, flags2,
1630 p, fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE | STR_NOALIGN);
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1633 if (len > 2) {
1634 len -= 2;
1635 } else {
1636 len = 0;
1638 } else {
1639 if (len > 1) {
1640 len -= 1;
1641 } else {
1642 len = 0;
1645 SCVAL(nameptr,0,len);
1646 p += len;
1647 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1648 break;
1650 case SMB_FIND_EA_LIST:
1652 struct ea_list *file_list = NULL;
1653 size_t ea_len = 0;
1655 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1656 if (!name_list) {
1657 return false;
1659 if (requires_resume_key) {
1660 SIVAL(p,0,reskey);
1661 p += 4;
1663 srv_put_dos_date2(p,0,create_date);
1664 srv_put_dos_date2(p,4,adate);
1665 srv_put_dos_date2(p,8,mdate);
1666 SIVAL(p,12,(uint32)file_size);
1667 SIVAL(p,16,(uint32)allocation_size);
1668 SSVAL(p,20,mode);
1669 p += 22; /* p now points to the EA area. */
1671 file_list = get_ea_list_from_file(ctx, conn, NULL,
1672 smb_fname->base_name,
1673 &ea_len);
1674 name_list = ea_list_union(name_list, file_list, &ea_len);
1676 /* We need to determine if this entry will fit in the space available. */
1677 /* Max string size is 255 bytes. */
1678 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1679 *out_of_space = true;
1680 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1681 "(wanted %u, had %d)\n",
1682 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1683 space_remaining ));
1684 return False; /* Not finished - just out of space */
1687 /* Push the ea_data followed by the name. */
1688 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1689 nameptr = p;
1690 len = srvstr_push(base_data, flags2,
1691 p + 1, fname, PTR_DIFF(end_data, p+1),
1692 STR_TERMINATE | STR_NOALIGN);
1693 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1694 if (len > 2) {
1695 len -= 2;
1696 } else {
1697 len = 0;
1699 } else {
1700 if (len > 1) {
1701 len -= 1;
1702 } else {
1703 len = 0;
1706 SCVAL(nameptr,0,len);
1707 p += len + 1;
1708 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1709 break;
1712 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1713 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1714 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1715 p += 4;
1716 SIVAL(p,0,reskey); p += 4;
1717 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1718 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1719 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1720 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1721 SOFF_T(p,0,file_size); p += 8;
1722 SOFF_T(p,0,allocation_size); p += 8;
1723 SIVAL(p,0,mode); p += 4;
1724 q = p; p += 4; /* q is placeholder for name length. */
1726 unsigned int ea_size = estimate_ea_size(conn, NULL,
1727 smb_fname->base_name);
1728 SIVAL(p,0,ea_size); /* Extended attributes */
1729 p += 4;
1731 /* Clear the short name buffer. This is
1732 * IMPORTANT as not doing so will trigger
1733 * a Win2k client bug. JRA.
1735 if (!was_8_3 && check_mangled_names) {
1736 char mangled_name[13]; /* mangled 8.3 name. */
1737 if (!name_to_8_3(fname,mangled_name,True,
1738 conn->params)) {
1739 /* Error - mangle failed ! */
1740 memset(mangled_name,'\0',12);
1742 mangled_name[12] = 0;
1743 len = srvstr_push(base_data, flags2,
1744 p+2, mangled_name, 24,
1745 STR_UPPER|STR_UNICODE);
1746 if (len < 24) {
1747 memset(p + 2 + len,'\0',24 - len);
1749 SSVAL(p, 0, len);
1750 } else {
1751 memset(p,'\0',26);
1753 p += 2 + 24;
1754 len = srvstr_push(base_data, flags2, p,
1755 fname, PTR_DIFF(end_data, p),
1756 STR_TERMINATE_ASCII);
1757 SIVAL(q,0,len);
1758 p += len;
1760 len = PTR_DIFF(p, pdata);
1761 pad = (len + (align-1)) & ~(align-1);
1763 * offset to the next entry, the caller
1764 * will overwrite it for the last entry
1765 * that's why we always include the padding
1767 SIVAL(pdata,0,pad);
1769 * set padding to zero
1771 if (do_pad) {
1772 memset(p, 0, pad - len);
1773 p = pdata + pad;
1774 } else {
1775 p = pdata + len;
1777 break;
1779 case SMB_FIND_FILE_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1781 p += 4;
1782 SIVAL(p,0,reskey); p += 4;
1783 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1784 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1787 SOFF_T(p,0,file_size); p += 8;
1788 SOFF_T(p,0,allocation_size); p += 8;
1789 SIVAL(p,0,mode); p += 4;
1790 len = srvstr_push(base_data, flags2,
1791 p + 4, fname, PTR_DIFF(end_data, p+4),
1792 STR_TERMINATE_ASCII);
1793 SIVAL(p,0,len);
1794 p += 4 + len;
1796 len = PTR_DIFF(p, pdata);
1797 pad = (len + (align-1)) & ~(align-1);
1799 * offset to the next entry, the caller
1800 * will overwrite it for the last entry
1801 * that's why we always include the padding
1803 SIVAL(pdata,0,pad);
1805 * set padding to zero
1807 if (do_pad) {
1808 memset(p, 0, pad - len);
1809 p = pdata + pad;
1810 } else {
1811 p = pdata + len;
1813 break;
1815 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1816 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1817 p += 4;
1818 SIVAL(p,0,reskey); p += 4;
1819 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1820 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1821 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1823 SOFF_T(p,0,file_size); p += 8;
1824 SOFF_T(p,0,allocation_size); p += 8;
1825 SIVAL(p,0,mode); p += 4;
1826 q = p; p += 4; /* q is placeholder for name length. */
1828 unsigned int ea_size = estimate_ea_size(conn, NULL,
1829 smb_fname->base_name);
1830 SIVAL(p,0,ea_size); /* Extended attributes */
1831 p +=4;
1833 len = srvstr_push(base_data, flags2, p,
1834 fname, PTR_DIFF(end_data, p),
1835 STR_TERMINATE_ASCII);
1836 SIVAL(q, 0, len);
1837 p += len;
1839 len = PTR_DIFF(p, pdata);
1840 pad = (len + (align-1)) & ~(align-1);
1842 * offset to the next entry, the caller
1843 * will overwrite it for the last entry
1844 * that's why we always include the padding
1846 SIVAL(pdata,0,pad);
1848 * set padding to zero
1850 if (do_pad) {
1851 memset(p, 0, pad - len);
1852 p = pdata + pad;
1853 } else {
1854 p = pdata + len;
1856 break;
1858 case SMB_FIND_FILE_NAMES_INFO:
1859 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1860 p += 4;
1861 SIVAL(p,0,reskey); p += 4;
1862 p += 4;
1863 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1864 acl on a dir (tridge) */
1865 len = srvstr_push(base_data, flags2, p,
1866 fname, PTR_DIFF(end_data, p),
1867 STR_TERMINATE_ASCII);
1868 SIVAL(p, -4, len);
1869 p += len;
1871 len = PTR_DIFF(p, pdata);
1872 pad = (len + (align-1)) & ~(align-1);
1874 * offset to the next entry, the caller
1875 * will overwrite it for the last entry
1876 * that's why we always include the padding
1878 SIVAL(pdata,0,pad);
1880 * set padding to zero
1882 if (do_pad) {
1883 memset(p, 0, pad - len);
1884 p = pdata + pad;
1885 } else {
1886 p = pdata + len;
1888 break;
1890 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1891 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1892 p += 4;
1893 SIVAL(p,0,reskey); p += 4;
1894 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1895 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1896 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1898 SOFF_T(p,0,file_size); p += 8;
1899 SOFF_T(p,0,allocation_size); p += 8;
1900 SIVAL(p,0,mode); p += 4;
1901 q = p; p += 4; /* q is placeholder for name length. */
1903 unsigned int ea_size = estimate_ea_size(conn, NULL,
1904 smb_fname->base_name);
1905 SIVAL(p,0,ea_size); /* Extended attributes */
1906 p +=4;
1908 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1909 SBVAL(p,0,file_index); p += 8;
1910 len = srvstr_push(base_data, flags2, p,
1911 fname, PTR_DIFF(end_data, p),
1912 STR_TERMINATE_ASCII);
1913 SIVAL(q, 0, len);
1914 p += len;
1916 len = PTR_DIFF(p, pdata);
1917 pad = (len + (align-1)) & ~(align-1);
1919 * offset to the next entry, the caller
1920 * will overwrite it for the last entry
1921 * that's why we always include the padding
1923 SIVAL(pdata,0,pad);
1925 * set padding to zero
1927 if (do_pad) {
1928 memset(p, 0, pad - len);
1929 p = pdata + pad;
1930 } else {
1931 p = pdata + len;
1933 break;
1935 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1937 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1938 p += 4;
1939 SIVAL(p,0,reskey); p += 4;
1940 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1941 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1942 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1944 SOFF_T(p,0,file_size); p += 8;
1945 SOFF_T(p,0,allocation_size); p += 8;
1946 SIVAL(p,0,mode); p += 4;
1947 q = p; p += 4; /* q is placeholder for name length */
1949 unsigned int ea_size = estimate_ea_size(conn, NULL,
1950 smb_fname->base_name);
1951 SIVAL(p,0,ea_size); /* Extended attributes */
1952 p +=4;
1954 /* Clear the short name buffer. This is
1955 * IMPORTANT as not doing so will trigger
1956 * a Win2k client bug. JRA.
1958 if (!was_8_3 && check_mangled_names) {
1959 char mangled_name[13]; /* mangled 8.3 name. */
1960 if (!name_to_8_3(fname,mangled_name,True,
1961 conn->params)) {
1962 /* Error - mangle failed ! */
1963 memset(mangled_name,'\0',12);
1965 mangled_name[12] = 0;
1966 len = srvstr_push(base_data, flags2,
1967 p+2, mangled_name, 24,
1968 STR_UPPER|STR_UNICODE);
1969 SSVAL(p, 0, len);
1970 if (len < 24) {
1971 memset(p + 2 + len,'\0',24 - len);
1973 SSVAL(p, 0, len);
1974 } else {
1975 memset(p,'\0',26);
1977 p += 26;
1978 SSVAL(p,0,0); p += 2; /* Reserved ? */
1979 SBVAL(p,0,file_index); p += 8;
1980 len = srvstr_push(base_data, flags2, p,
1981 fname, PTR_DIFF(end_data, p),
1982 STR_TERMINATE_ASCII);
1983 SIVAL(q,0,len);
1984 p += len;
1986 len = PTR_DIFF(p, pdata);
1987 pad = (len + (align-1)) & ~(align-1);
1989 * offset to the next entry, the caller
1990 * will overwrite it for the last entry
1991 * that's why we always include the padding
1993 SIVAL(pdata,0,pad);
1995 * set padding to zero
1997 if (do_pad) {
1998 memset(p, 0, pad - len);
1999 p = pdata + pad;
2000 } else {
2001 p = pdata + len;
2003 break;
2005 /* CIFS UNIX Extension. */
2007 case SMB_FIND_FILE_UNIX:
2008 case SMB_FIND_FILE_UNIX_INFO2:
2009 p+= 4;
2010 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2012 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2014 if (info_level == SMB_FIND_FILE_UNIX) {
2015 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2016 p = store_file_unix_basic(conn, p,
2017 NULL, &smb_fname->st);
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE);
2021 } else {
2022 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2023 p = store_file_unix_basic_info2(conn, p,
2024 NULL, &smb_fname->st);
2025 nameptr = p;
2026 p += 4;
2027 len = srvstr_push(base_data, flags2, p, fname,
2028 PTR_DIFF(end_data, p), 0);
2029 SIVAL(nameptr, 0, len);
2032 p += len;
2034 len = PTR_DIFF(p, pdata);
2035 pad = (len + (align-1)) & ~(align-1);
2037 * offset to the next entry, the caller
2038 * will overwrite it for the last entry
2039 * that's why we always include the padding
2041 SIVAL(pdata,0,pad);
2043 * set padding to zero
2045 if (do_pad) {
2046 memset(p, 0, pad - len);
2047 p = pdata + pad;
2048 } else {
2049 p = pdata + len;
2051 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2053 break;
2055 default:
2056 return false;
2059 if (PTR_DIFF(p,pdata) > space_remaining) {
2060 *out_of_space = true;
2061 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2062 "(wanted %u, had %d)\n",
2063 (unsigned int)PTR_DIFF(p,pdata),
2064 space_remaining ));
2065 return false; /* Not finished - just out of space */
2068 /* Setup the last entry pointer, as an offset from base_data */
2069 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2070 /* Advance the data pointer to the next slot */
2071 *ppdata = p;
2073 return true;
2076 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2077 connection_struct *conn,
2078 struct dptr_struct *dirptr,
2079 uint16 flags2,
2080 const char *path_mask,
2081 uint32 dirtype,
2082 int info_level,
2083 int requires_resume_key,
2084 bool dont_descend,
2085 bool ask_sharemode,
2086 uint8_t align,
2087 bool do_pad,
2088 char **ppdata,
2089 char *base_data,
2090 char *end_data,
2091 int space_remaining,
2092 bool *out_of_space,
2093 bool *got_exact_match,
2094 int *_last_entry_off,
2095 struct ea_list *name_list)
2097 const char *p;
2098 const char *mask = NULL;
2099 long prev_dirpos = 0;
2100 uint32_t mode = 0;
2101 char *fname = NULL;
2102 struct smb_filename *smb_fname = NULL;
2103 struct smbd_dirptr_lanman2_state state;
2104 bool ok;
2105 uint64_t last_entry_off = 0;
2107 ZERO_STRUCT(state);
2108 state.conn = conn;
2109 state.info_level = info_level;
2110 state.check_mangled_names = lp_manglednames(conn->params);
2111 state.has_wild = dptr_has_wild(dirptr);
2112 state.got_exact_match = false;
2114 *out_of_space = false;
2115 *got_exact_match = false;
2117 p = strrchr_m(path_mask,'/');
2118 if(p != NULL) {
2119 if(p[1] == '\0') {
2120 mask = "*.*";
2121 } else {
2122 mask = p+1;
2124 } else {
2125 mask = path_mask;
2128 ok = smbd_dirptr_get_entry(ctx,
2129 dirptr,
2130 mask,
2131 dirtype,
2132 dont_descend,
2133 ask_sharemode,
2134 smbd_dirptr_lanman2_match_fn,
2135 smbd_dirptr_lanman2_mode_fn,
2136 &state,
2137 &fname,
2138 &smb_fname,
2139 &mode,
2140 &prev_dirpos);
2141 if (!ok) {
2142 return false;
2145 *got_exact_match = state.got_exact_match;
2147 ok = smbd_marshall_dir_entry(ctx,
2148 conn,
2149 flags2,
2150 info_level,
2151 name_list,
2152 state.check_mangled_names,
2153 requires_resume_key,
2154 mode,
2155 fname,
2156 smb_fname,
2157 space_remaining,
2158 align,
2159 do_pad,
2160 base_data,
2161 ppdata,
2162 end_data,
2163 out_of_space,
2164 &last_entry_off);
2165 TALLOC_FREE(fname);
2166 TALLOC_FREE(smb_fname);
2167 if (*out_of_space) {
2168 dptr_SeekDir(dirptr, prev_dirpos);
2169 return false;
2171 if (!ok) {
2172 return false;
2175 *_last_entry_off = last_entry_off;
2176 return true;
2179 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2180 connection_struct *conn,
2181 struct dptr_struct *dirptr,
2182 uint16 flags2,
2183 const char *path_mask,
2184 uint32 dirtype,
2185 int info_level,
2186 bool requires_resume_key,
2187 bool dont_descend,
2188 bool ask_sharemode,
2189 char **ppdata,
2190 char *base_data,
2191 char *end_data,
2192 int space_remaining,
2193 bool *out_of_space,
2194 bool *got_exact_match,
2195 int *last_entry_off,
2196 struct ea_list *name_list)
2198 uint8_t align = 4;
2199 const bool do_pad = true;
2201 if (info_level >= 1 && info_level <= 3) {
2202 /* No alignment on earlier info levels. */
2203 align = 1;
2206 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2207 path_mask, dirtype, info_level,
2208 requires_resume_key, dont_descend, ask_sharemode,
2209 align, do_pad,
2210 ppdata, base_data, end_data,
2211 space_remaining,
2212 out_of_space, got_exact_match,
2213 last_entry_off, name_list);
2216 /****************************************************************************
2217 Reply to a TRANS2_FINDFIRST.
2218 ****************************************************************************/
2220 static void call_trans2findfirst(connection_struct *conn,
2221 struct smb_request *req,
2222 char **pparams, int total_params,
2223 char **ppdata, int total_data,
2224 unsigned int max_data_bytes)
2226 /* We must be careful here that we don't return more than the
2227 allowed number of data bytes. If this means returning fewer than
2228 maxentries then so be it. We assume that the redirector has
2229 enough room for the fixed number of parameter bytes it has
2230 requested. */
2231 struct smb_filename *smb_dname = NULL;
2232 char *params = *pparams;
2233 char *pdata = *ppdata;
2234 char *data_end;
2235 uint32 dirtype;
2236 int maxentries;
2237 uint16 findfirst_flags;
2238 bool close_after_first;
2239 bool close_if_end;
2240 bool requires_resume_key;
2241 int info_level;
2242 char *directory = NULL;
2243 char *mask = NULL;
2244 char *p;
2245 int last_entry_off=0;
2246 int dptr_num = -1;
2247 int numentries = 0;
2248 int i;
2249 bool finished = False;
2250 bool dont_descend = False;
2251 bool out_of_space = False;
2252 int space_remaining;
2253 bool mask_contains_wcard = False;
2254 struct ea_list *ea_list = NULL;
2255 NTSTATUS ntstatus = NT_STATUS_OK;
2256 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2257 TALLOC_CTX *ctx = talloc_tos();
2258 struct dptr_struct *dirptr = NULL;
2259 struct smbd_server_connection *sconn = smbd_server_conn;
2261 if (total_params < 13) {
2262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2263 goto out;
2266 dirtype = SVAL(params,0);
2267 maxentries = SVAL(params,2);
2268 findfirst_flags = SVAL(params,4);
2269 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2270 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2271 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2272 info_level = SVAL(params,6);
2274 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2275 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2276 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2277 info_level, max_data_bytes));
2279 if (!maxentries) {
2280 /* W2K3 seems to treat zero as 1. */
2281 maxentries = 1;
2284 switch (info_level) {
2285 case SMB_FIND_INFO_STANDARD:
2286 case SMB_FIND_EA_SIZE:
2287 case SMB_FIND_EA_LIST:
2288 case SMB_FIND_FILE_DIRECTORY_INFO:
2289 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_NAMES_INFO:
2291 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2292 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2293 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2294 break;
2295 case SMB_FIND_FILE_UNIX:
2296 case SMB_FIND_FILE_UNIX_INFO2:
2297 /* Always use filesystem for UNIX mtime query. */
2298 ask_sharemode = false;
2299 if (!lp_unix_extensions()) {
2300 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2301 goto out;
2303 break;
2304 default:
2305 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2306 goto out;
2309 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2310 params+12, total_params - 12,
2311 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2312 if (!NT_STATUS_IS_OK(ntstatus)) {
2313 reply_nterror(req, ntstatus);
2314 goto out;
2317 ntstatus = filename_convert(ctx, conn,
2318 req->flags2 & FLAGS2_DFS_PATHNAMES,
2319 directory,
2320 (UCF_SAVE_LCOMP |
2321 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2322 &mask_contains_wcard,
2323 &smb_dname);
2324 if (!NT_STATUS_IS_OK(ntstatus)) {
2325 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2326 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2327 ERRSRV, ERRbadpath);
2328 goto out;
2330 reply_nterror(req, ntstatus);
2331 goto out;
2334 mask = smb_dname->original_lcomp;
2336 directory = smb_dname->base_name;
2338 p = strrchr_m(directory,'/');
2339 if(p == NULL) {
2340 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2341 if((directory[0] == '.') && (directory[1] == '\0')) {
2342 mask = talloc_strdup(ctx,"*");
2343 if (!mask) {
2344 reply_nterror(req, NT_STATUS_NO_MEMORY);
2345 goto out;
2347 mask_contains_wcard = True;
2349 directory = talloc_strdup(talloc_tos(), "./");
2350 if (!directory) {
2351 reply_nterror(req, NT_STATUS_NO_MEMORY);
2352 goto out;
2354 } else {
2355 *p = 0;
2358 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2360 if (info_level == SMB_FIND_EA_LIST) {
2361 uint32 ea_size;
2363 if (total_data < 4) {
2364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2365 goto out;
2368 ea_size = IVAL(pdata,0);
2369 if (ea_size != total_data) {
2370 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2371 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2373 goto out;
2376 if (!lp_ea_support(SNUM(conn))) {
2377 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2378 goto out;
2381 /* Pull out the list of names. */
2382 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2383 if (!ea_list) {
2384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2385 goto out;
2389 *ppdata = (char *)SMB_REALLOC(
2390 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2391 if(*ppdata == NULL ) {
2392 reply_nterror(req, NT_STATUS_NO_MEMORY);
2393 goto out;
2395 pdata = *ppdata;
2396 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2398 /* Realloc the params space */
2399 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2400 if (*pparams == NULL) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2402 goto out;
2404 params = *pparams;
2406 /* Save the wildcard match and attribs we are using on this directory -
2407 needed as lanman2 assumes these are being saved between calls */
2409 ntstatus = dptr_create(conn,
2410 directory,
2411 False,
2412 True,
2413 req->smbpid,
2414 mask,
2415 mask_contains_wcard,
2416 dirtype,
2417 &dirptr);
2419 if (!NT_STATUS_IS_OK(ntstatus)) {
2420 reply_nterror(req, ntstatus);
2421 goto out;
2424 dptr_num = dptr_dnum(dirptr);
2425 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2427 /* Initialize per TRANS2_FIND_FIRST operation data */
2428 dptr_init_search_op(dirptr);
2430 /* We don't need to check for VOL here as this is returned by
2431 a different TRANS2 call. */
2433 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2434 directory,lp_dontdescend(SNUM(conn))));
2435 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2436 dont_descend = True;
2438 p = pdata;
2439 space_remaining = max_data_bytes;
2440 out_of_space = False;
2442 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2443 bool got_exact_match = False;
2445 /* this is a heuristic to avoid seeking the dirptr except when
2446 absolutely necessary. It allows for a filename of about 40 chars */
2447 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2448 out_of_space = True;
2449 finished = False;
2450 } else {
2451 finished = !get_lanman2_dir_entry(ctx,
2452 conn,
2453 dirptr,
2454 req->flags2,
2455 mask,dirtype,info_level,
2456 requires_resume_key,dont_descend,
2457 ask_sharemode,
2458 &p,pdata,data_end,
2459 space_remaining, &out_of_space,
2460 &got_exact_match,
2461 &last_entry_off, ea_list);
2464 if (finished && out_of_space)
2465 finished = False;
2467 if (!finished && !out_of_space)
2468 numentries++;
2471 * As an optimisation if we know we aren't looking
2472 * for a wildcard name (ie. the name matches the wildcard exactly)
2473 * then we can finish on any (first) match.
2474 * This speeds up large directory searches. JRA.
2477 if(got_exact_match)
2478 finished = True;
2480 /* Ensure space_remaining never goes -ve. */
2481 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2482 space_remaining = 0;
2483 out_of_space = true;
2484 } else {
2485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2489 /* Check if we can close the dirptr */
2490 if(close_after_first || (finished && close_if_end)) {
2491 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2492 dptr_close(sconn, &dptr_num);
2496 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2497 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2498 * the protocol level is less than NT1. Tested with smbclient. JRA.
2499 * This should fix the OS/2 client bug #2335.
2502 if(numentries == 0) {
2503 dptr_close(sconn, &dptr_num);
2504 if (get_Protocol() < PROTOCOL_NT1) {
2505 reply_force_doserror(req, ERRDOS, ERRnofiles);
2506 goto out;
2507 } else {
2508 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2509 ERRDOS, ERRbadfile);
2510 goto out;
2514 /* At this point pdata points to numentries directory entries. */
2516 /* Set up the return parameter block */
2517 SSVAL(params,0,dptr_num);
2518 SSVAL(params,2,numentries);
2519 SSVAL(params,4,finished);
2520 SSVAL(params,6,0); /* Never an EA error */
2521 SSVAL(params,8,last_entry_off);
2523 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2524 max_data_bytes);
2526 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2527 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2528 if (!directory) {
2529 reply_nterror(req, NT_STATUS_NO_MEMORY);
2533 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2534 smb_fn_name(req->cmd),
2535 mask, directory, dirtype, numentries ) );
2538 * Force a name mangle here to ensure that the
2539 * mask as an 8.3 name is top of the mangled cache.
2540 * The reasons for this are subtle. Don't remove
2541 * this code unless you know what you are doing
2542 * (see PR#13758). JRA.
2545 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2546 char mangled_name[13];
2547 name_to_8_3(mask, mangled_name, True, conn->params);
2549 out:
2550 TALLOC_FREE(smb_dname);
2551 return;
2554 /****************************************************************************
2555 Reply to a TRANS2_FINDNEXT.
2556 ****************************************************************************/
2558 static void call_trans2findnext(connection_struct *conn,
2559 struct smb_request *req,
2560 char **pparams, int total_params,
2561 char **ppdata, int total_data,
2562 unsigned int max_data_bytes)
2564 /* We must be careful here that we don't return more than the
2565 allowed number of data bytes. If this means returning fewer than
2566 maxentries then so be it. We assume that the redirector has
2567 enough room for the fixed number of parameter bytes it has
2568 requested. */
2569 char *params = *pparams;
2570 char *pdata = *ppdata;
2571 char *data_end;
2572 int dptr_num;
2573 int maxentries;
2574 uint16 info_level;
2575 uint32 resume_key;
2576 uint16 findnext_flags;
2577 bool close_after_request;
2578 bool close_if_end;
2579 bool requires_resume_key;
2580 bool continue_bit;
2581 bool mask_contains_wcard = False;
2582 char *resume_name = NULL;
2583 const char *mask = NULL;
2584 const char *directory = NULL;
2585 char *p = NULL;
2586 uint16 dirtype;
2587 int numentries = 0;
2588 int i, last_entry_off=0;
2589 bool finished = False;
2590 bool dont_descend = False;
2591 bool out_of_space = False;
2592 int space_remaining;
2593 struct ea_list *ea_list = NULL;
2594 NTSTATUS ntstatus = NT_STATUS_OK;
2595 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2596 TALLOC_CTX *ctx = talloc_tos();
2597 struct dptr_struct *dirptr;
2598 struct smbd_server_connection *sconn = smbd_server_conn;
2600 if (total_params < 13) {
2601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2602 return;
2605 dptr_num = SVAL(params,0);
2606 maxentries = SVAL(params,2);
2607 info_level = SVAL(params,4);
2608 resume_key = IVAL(params,6);
2609 findnext_flags = SVAL(params,10);
2610 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2611 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2612 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2613 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2615 if (!continue_bit) {
2616 /* We only need resume_name if continue_bit is zero. */
2617 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2618 params+12,
2619 total_params - 12, STR_TERMINATE, &ntstatus,
2620 &mask_contains_wcard);
2621 if (!NT_STATUS_IS_OK(ntstatus)) {
2622 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2623 complain (it thinks we're asking for the directory above the shared
2624 path or an invalid name). Catch this as the resume name is only compared, never used in
2625 a file access. JRA. */
2626 srvstr_pull_talloc(ctx, params, req->flags2,
2627 &resume_name, params+12,
2628 total_params - 12,
2629 STR_TERMINATE);
2631 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2632 reply_nterror(req, ntstatus);
2633 return;
2638 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2639 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2640 resume_key = %d resume name = %s continue=%d level = %d\n",
2641 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2642 requires_resume_key, resume_key,
2643 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2645 if (!maxentries) {
2646 /* W2K3 seems to treat zero as 1. */
2647 maxentries = 1;
2650 switch (info_level) {
2651 case SMB_FIND_INFO_STANDARD:
2652 case SMB_FIND_EA_SIZE:
2653 case SMB_FIND_EA_LIST:
2654 case SMB_FIND_FILE_DIRECTORY_INFO:
2655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2656 case SMB_FIND_FILE_NAMES_INFO:
2657 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2658 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2659 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2660 break;
2661 case SMB_FIND_FILE_UNIX:
2662 case SMB_FIND_FILE_UNIX_INFO2:
2663 /* Always use filesystem for UNIX mtime query. */
2664 ask_sharemode = false;
2665 if (!lp_unix_extensions()) {
2666 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2667 return;
2669 break;
2670 default:
2671 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2672 return;
2675 if (info_level == SMB_FIND_EA_LIST) {
2676 uint32 ea_size;
2678 if (total_data < 4) {
2679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2680 return;
2683 ea_size = IVAL(pdata,0);
2684 if (ea_size != total_data) {
2685 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2686 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2688 return;
2691 if (!lp_ea_support(SNUM(conn))) {
2692 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2693 return;
2696 /* Pull out the list of names. */
2697 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2698 if (!ea_list) {
2699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2700 return;
2704 *ppdata = (char *)SMB_REALLOC(
2705 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2706 if(*ppdata == NULL) {
2707 reply_nterror(req, NT_STATUS_NO_MEMORY);
2708 return;
2711 pdata = *ppdata;
2712 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2714 /* Realloc the params space */
2715 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2716 if(*pparams == NULL ) {
2717 reply_nterror(req, NT_STATUS_NO_MEMORY);
2718 return;
2721 params = *pparams;
2723 /* Check that the dptr is valid */
2724 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2725 reply_nterror(req, STATUS_NO_MORE_FILES);
2726 return;
2729 directory = dptr_path(sconn, dptr_num);
2731 /* Get the wildcard mask from the dptr */
2732 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2733 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2734 reply_nterror(req, STATUS_NO_MORE_FILES);
2735 return;
2738 mask = p;
2740 /* Get the attr mask from the dptr */
2741 dirtype = dptr_attr(sconn, dptr_num);
2743 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2744 dptr_num, mask, dirtype,
2745 (long)dirptr,
2746 dptr_TellDir(dirptr)));
2748 /* Initialize per TRANS2_FIND_NEXT operation data */
2749 dptr_init_search_op(dirptr);
2751 /* We don't need to check for VOL here as this is returned by
2752 a different TRANS2 call. */
2754 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2755 directory,lp_dontdescend(SNUM(conn))));
2756 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2757 dont_descend = True;
2759 p = pdata;
2760 space_remaining = max_data_bytes;
2761 out_of_space = False;
2764 * Seek to the correct position. We no longer use the resume key but
2765 * depend on the last file name instead.
2768 if(!continue_bit && resume_name && *resume_name) {
2769 SMB_STRUCT_STAT st;
2771 long current_pos = 0;
2773 * Remember, name_to_8_3 is called by
2774 * get_lanman2_dir_entry(), so the resume name
2775 * could be mangled. Ensure we check the unmangled name.
2778 if (mangle_is_mangled(resume_name, conn->params)) {
2779 char *new_resume_name = NULL;
2780 mangle_lookup_name_from_8_3(ctx,
2781 resume_name,
2782 &new_resume_name,
2783 conn->params);
2784 if (new_resume_name) {
2785 resume_name = new_resume_name;
2790 * Fix for NT redirector problem triggered by resume key indexes
2791 * changing between directory scans. We now return a resume key of 0
2792 * and instead look for the filename to continue from (also given
2793 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2794 * findfirst/findnext (as is usual) then the directory pointer
2795 * should already be at the correct place.
2798 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2799 } /* end if resume_name && !continue_bit */
2801 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2802 bool got_exact_match = False;
2804 /* this is a heuristic to avoid seeking the dirptr except when
2805 absolutely necessary. It allows for a filename of about 40 chars */
2806 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2807 out_of_space = True;
2808 finished = False;
2809 } else {
2810 finished = !get_lanman2_dir_entry(ctx,
2811 conn,
2812 dirptr,
2813 req->flags2,
2814 mask,dirtype,info_level,
2815 requires_resume_key,dont_descend,
2816 ask_sharemode,
2817 &p,pdata,data_end,
2818 space_remaining, &out_of_space,
2819 &got_exact_match,
2820 &last_entry_off, ea_list);
2823 if (finished && out_of_space)
2824 finished = False;
2826 if (!finished && !out_of_space)
2827 numentries++;
2830 * As an optimisation if we know we aren't looking
2831 * for a wildcard name (ie. the name matches the wildcard exactly)
2832 * then we can finish on any (first) match.
2833 * This speeds up large directory searches. JRA.
2836 if(got_exact_match)
2837 finished = True;
2839 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2842 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2843 smb_fn_name(req->cmd),
2844 mask, directory, dirtype, numentries ) );
2846 /* Check if we can close the dirptr */
2847 if(close_after_request || (finished && close_if_end)) {
2848 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2849 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2852 /* Set up the return parameter block */
2853 SSVAL(params,0,numentries);
2854 SSVAL(params,2,finished);
2855 SSVAL(params,4,0); /* Never an EA error */
2856 SSVAL(params,6,last_entry_off);
2858 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2859 max_data_bytes);
2861 return;
2864 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2866 E_md4hash(lp_servicename(SNUM(conn)),objid);
2867 return objid;
2870 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2872 SMB_ASSERT(extended_info != NULL);
2874 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2875 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2876 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2877 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2878 #ifdef SAMBA_VERSION_REVISION
2879 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2880 #endif
2881 extended_info->samba_subversion = 0;
2882 #ifdef SAMBA_VERSION_RC_RELEASE
2883 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2884 #else
2885 #ifdef SAMBA_VERSION_PRE_RELEASE
2886 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2887 #endif
2888 #endif
2889 #ifdef SAMBA_VERSION_VENDOR_PATCH
2890 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2891 #endif
2892 extended_info->samba_gitcommitdate = 0;
2893 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2894 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2895 #endif
2897 memset(extended_info->samba_version_string, 0,
2898 sizeof(extended_info->samba_version_string));
2900 snprintf (extended_info->samba_version_string,
2901 sizeof(extended_info->samba_version_string),
2902 "%s", samba_version_string());
2905 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2906 TALLOC_CTX *mem_ctx,
2907 uint16_t info_level,
2908 uint16_t flags2,
2909 unsigned int max_data_bytes,
2910 char **ppdata,
2911 int *ret_data_len)
2913 char *pdata, *end_data;
2914 int data_len = 0, len;
2915 const char *vname = volume_label(SNUM(conn));
2916 int snum = SNUM(conn);
2917 char *fstype = lp_fstype(SNUM(conn));
2918 uint32 additional_flags = 0;
2919 struct smb_filename smb_fname_dot;
2920 SMB_STRUCT_STAT st;
2922 if (IS_IPC(conn)) {
2923 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2924 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2925 "info level (0x%x) on IPC$.\n",
2926 (unsigned int)info_level));
2927 return NT_STATUS_ACCESS_DENIED;
2931 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2933 ZERO_STRUCT(smb_fname_dot);
2934 smb_fname_dot.base_name = discard_const_p(char, ".");
2936 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2937 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2938 return map_nt_error_from_unix(errno);
2941 st = smb_fname_dot.st;
2943 *ppdata = (char *)SMB_REALLOC(
2944 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2945 if (*ppdata == NULL) {
2946 return NT_STATUS_NO_MEMORY;
2949 pdata = *ppdata;
2950 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2951 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2953 switch (info_level) {
2954 case SMB_INFO_ALLOCATION:
2956 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2957 data_len = 18;
2958 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2959 return map_nt_error_from_unix(errno);
2962 block_size = lp_block_size(snum);
2963 if (bsize < block_size) {
2964 uint64_t factor = block_size/bsize;
2965 bsize = block_size;
2966 dsize /= factor;
2967 dfree /= factor;
2969 if (bsize > block_size) {
2970 uint64_t factor = bsize/block_size;
2971 bsize = block_size;
2972 dsize *= factor;
2973 dfree *= factor;
2975 bytes_per_sector = 512;
2976 sectors_per_unit = bsize/bytes_per_sector;
2978 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2979 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2980 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2982 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2983 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2984 SIVAL(pdata,l1_cUnit,dsize);
2985 SIVAL(pdata,l1_cUnitAvail,dfree);
2986 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2987 break;
2990 case SMB_INFO_VOLUME:
2991 /* Return volume name */
2993 * Add volume serial number - hash of a combination of
2994 * the called hostname and the service name.
2996 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2998 * Win2k3 and previous mess this up by sending a name length
2999 * one byte short. I believe only older clients (OS/2 Win9x) use
3000 * this call so try fixing this by adding a terminating null to
3001 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3003 len = srvstr_push(
3004 pdata, flags2,
3005 pdata+l2_vol_szVolLabel, vname,
3006 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3007 STR_NOALIGN|STR_TERMINATE);
3008 SCVAL(pdata,l2_vol_cch,len);
3009 data_len = l2_vol_szVolLabel + len;
3010 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3011 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3012 len, vname));
3013 break;
3015 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3016 case SMB_FS_ATTRIBUTE_INFORMATION:
3018 additional_flags = 0;
3019 #if defined(HAVE_SYS_QUOTAS)
3020 additional_flags |= FILE_VOLUME_QUOTAS;
3021 #endif
3023 if(lp_nt_acl_support(SNUM(conn))) {
3024 additional_flags |= FILE_PERSISTENT_ACLS;
3027 /* Capabilities are filled in at connection time through STATVFS call */
3028 additional_flags |= conn->fs_capabilities;
3029 additional_flags |= lp_parm_int(conn->params->service,
3030 "share", "fake_fscaps",
3033 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3034 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3035 additional_flags); /* FS ATTRIBUTES */
3037 SIVAL(pdata,4,255); /* Max filename component length */
3038 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3039 and will think we can't do long filenames */
3040 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3041 PTR_DIFF(end_data, pdata+12),
3042 STR_UNICODE);
3043 SIVAL(pdata,8,len);
3044 data_len = 12 + len;
3045 break;
3047 case SMB_QUERY_FS_LABEL_INFO:
3048 case SMB_FS_LABEL_INFORMATION:
3049 len = srvstr_push(pdata, flags2, pdata+4, vname,
3050 PTR_DIFF(end_data, pdata+4), 0);
3051 data_len = 4 + len;
3052 SIVAL(pdata,0,len);
3053 break;
3055 case SMB_QUERY_FS_VOLUME_INFO:
3056 case SMB_FS_VOLUME_INFORMATION:
3059 * Add volume serial number - hash of a combination of
3060 * the called hostname and the service name.
3062 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3063 (str_checksum(get_local_machine_name())<<16));
3065 /* Max label len is 32 characters. */
3066 len = srvstr_push(pdata, flags2, pdata+18, vname,
3067 PTR_DIFF(end_data, pdata+18),
3068 STR_UNICODE);
3069 SIVAL(pdata,12,len);
3070 data_len = 18+len;
3072 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3073 (int)strlen(vname),vname, lp_servicename(snum)));
3074 break;
3076 case SMB_QUERY_FS_SIZE_INFO:
3077 case SMB_FS_SIZE_INFORMATION:
3079 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3080 data_len = 24;
3081 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3082 return map_nt_error_from_unix(errno);
3084 block_size = lp_block_size(snum);
3085 if (bsize < block_size) {
3086 uint64_t factor = block_size/bsize;
3087 bsize = block_size;
3088 dsize /= factor;
3089 dfree /= factor;
3091 if (bsize > block_size) {
3092 uint64_t factor = bsize/block_size;
3093 bsize = block_size;
3094 dsize *= factor;
3095 dfree *= factor;
3097 bytes_per_sector = 512;
3098 sectors_per_unit = bsize/bytes_per_sector;
3099 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3100 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3101 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3102 SBIG_UINT(pdata,0,dsize);
3103 SBIG_UINT(pdata,8,dfree);
3104 SIVAL(pdata,16,sectors_per_unit);
3105 SIVAL(pdata,20,bytes_per_sector);
3106 break;
3109 case SMB_FS_FULL_SIZE_INFORMATION:
3111 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3112 data_len = 32;
3113 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3114 return map_nt_error_from_unix(errno);
3116 block_size = lp_block_size(snum);
3117 if (bsize < block_size) {
3118 uint64_t factor = block_size/bsize;
3119 bsize = block_size;
3120 dsize /= factor;
3121 dfree /= factor;
3123 if (bsize > block_size) {
3124 uint64_t factor = bsize/block_size;
3125 bsize = block_size;
3126 dsize *= factor;
3127 dfree *= factor;
3129 bytes_per_sector = 512;
3130 sectors_per_unit = bsize/bytes_per_sector;
3131 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3132 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3133 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3134 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3135 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3136 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3137 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3138 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3139 break;
3142 case SMB_QUERY_FS_DEVICE_INFO:
3143 case SMB_FS_DEVICE_INFORMATION:
3145 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3147 if (!CAN_WRITE(conn)) {
3148 characteristics |= FILE_READ_ONLY_DEVICE;
3150 data_len = 8;
3151 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3152 SIVAL(pdata,4,characteristics);
3153 break;
3156 #ifdef HAVE_SYS_QUOTAS
3157 case SMB_FS_QUOTA_INFORMATION:
3159 * what we have to send --metze:
3161 * Unknown1: 24 NULL bytes
3162 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3163 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3164 * Quota Flags: 2 byte :
3165 * Unknown3: 6 NULL bytes
3167 * 48 bytes total
3169 * details for Quota Flags:
3171 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3172 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3173 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3174 * 0x0001 Enable Quotas: enable quota for this fs
3178 /* we need to fake up a fsp here,
3179 * because its not send in this call
3181 files_struct fsp;
3182 SMB_NTQUOTA_STRUCT quotas;
3184 ZERO_STRUCT(fsp);
3185 ZERO_STRUCT(quotas);
3187 fsp.conn = conn;
3188 fsp.fnum = -1;
3190 /* access check */
3191 if (conn->server_info->utok.uid != sec_initial_uid()) {
3192 DEBUG(0,("set_user_quota: access_denied "
3193 "service [%s] user [%s]\n",
3194 lp_servicename(SNUM(conn)),
3195 conn->server_info->unix_name));
3196 return NT_STATUS_ACCESS_DENIED;
3199 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3200 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3201 return map_nt_error_from_unix(errno);
3204 data_len = 48;
3206 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3207 lp_servicename(SNUM(conn))));
3209 /* Unknown1 24 NULL bytes*/
3210 SBIG_UINT(pdata,0,(uint64_t)0);
3211 SBIG_UINT(pdata,8,(uint64_t)0);
3212 SBIG_UINT(pdata,16,(uint64_t)0);
3214 /* Default Soft Quota 8 bytes */
3215 SBIG_UINT(pdata,24,quotas.softlim);
3217 /* Default Hard Quota 8 bytes */
3218 SBIG_UINT(pdata,32,quotas.hardlim);
3220 /* Quota flag 2 bytes */
3221 SSVAL(pdata,40,quotas.qflags);
3223 /* Unknown3 6 NULL bytes */
3224 SSVAL(pdata,42,0);
3225 SIVAL(pdata,44,0);
3227 break;
3229 #endif /* HAVE_SYS_QUOTAS */
3230 case SMB_FS_OBJECTID_INFORMATION:
3232 unsigned char objid[16];
3233 struct smb_extended_info extended_info;
3234 memcpy(pdata,create_volume_objectid(conn, objid),16);
3235 samba_extended_info_version (&extended_info);
3236 SIVAL(pdata,16,extended_info.samba_magic);
3237 SIVAL(pdata,20,extended_info.samba_version);
3238 SIVAL(pdata,24,extended_info.samba_subversion);
3239 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3240 memcpy(pdata+36,extended_info.samba_version_string,28);
3241 data_len = 64;
3242 break;
3246 * Query the version and capabilities of the CIFS UNIX extensions
3247 * in use.
3250 case SMB_QUERY_CIFS_UNIX_INFO:
3252 bool large_write = lp_min_receive_file_size() &&
3253 !srv_is_signing_active(smbd_server_conn);
3254 bool large_read = !srv_is_signing_active(smbd_server_conn);
3255 int encrypt_caps = 0;
3257 if (!lp_unix_extensions()) {
3258 return NT_STATUS_INVALID_LEVEL;
3261 switch (conn->encrypt_level) {
3262 case 0:
3263 encrypt_caps = 0;
3264 break;
3265 case 1:
3266 case Auto:
3267 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3268 break;
3269 case Required:
3270 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3271 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3272 large_write = false;
3273 large_read = false;
3274 break;
3277 data_len = 12;
3278 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3279 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3281 /* We have POSIX ACLs, pathname, encryption,
3282 * large read/write, and locking capability. */
3284 SBIG_UINT(pdata,4,((uint64_t)(
3285 CIFS_UNIX_POSIX_ACLS_CAP|
3286 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3287 CIFS_UNIX_FCNTL_LOCKS_CAP|
3288 CIFS_UNIX_EXTATTR_CAP|
3289 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3290 encrypt_caps|
3291 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3292 (large_write ?
3293 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3294 break;
3297 case SMB_QUERY_POSIX_FS_INFO:
3299 int rc;
3300 vfs_statvfs_struct svfs;
3302 if (!lp_unix_extensions()) {
3303 return NT_STATUS_INVALID_LEVEL;
3306 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3308 if (!rc) {
3309 data_len = 56;
3310 SIVAL(pdata,0,svfs.OptimalTransferSize);
3311 SIVAL(pdata,4,svfs.BlockSize);
3312 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3313 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3314 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3315 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3316 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3317 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3318 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3319 #ifdef EOPNOTSUPP
3320 } else if (rc == EOPNOTSUPP) {
3321 return NT_STATUS_INVALID_LEVEL;
3322 #endif /* EOPNOTSUPP */
3323 } else {
3324 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3325 return NT_STATUS_DOS(ERRSRV, ERRerror);
3327 break;
3330 case SMB_QUERY_POSIX_WHOAMI:
3332 uint32_t flags = 0;
3333 uint32_t sid_bytes;
3334 int i;
3336 if (!lp_unix_extensions()) {
3337 return NT_STATUS_INVALID_LEVEL;
3340 if (max_data_bytes < 40) {
3341 return NT_STATUS_BUFFER_TOO_SMALL;
3344 /* We ARE guest if global_sid_Builtin_Guests is
3345 * in our list of SIDs.
3347 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3348 conn->server_info->ptok)) {
3349 flags |= SMB_WHOAMI_GUEST;
3352 /* We are NOT guest if global_sid_Authenticated_Users
3353 * is in our list of SIDs.
3355 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3356 conn->server_info->ptok)) {
3357 flags &= ~SMB_WHOAMI_GUEST;
3360 /* NOTE: 8 bytes for UID/GID, irrespective of native
3361 * platform size. This matches
3362 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3364 data_len = 4 /* flags */
3365 + 4 /* flag mask */
3366 + 8 /* uid */
3367 + 8 /* gid */
3368 + 4 /* ngroups */
3369 + 4 /* num_sids */
3370 + 4 /* SID bytes */
3371 + 4 /* pad/reserved */
3372 + (conn->server_info->utok.ngroups * 8)
3373 /* groups list */
3374 + (conn->server_info->ptok->num_sids *
3375 SID_MAX_SIZE)
3376 /* SID list */;
3378 SIVAL(pdata, 0, flags);
3379 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3380 SBIG_UINT(pdata, 8,
3381 (uint64_t)conn->server_info->utok.uid);
3382 SBIG_UINT(pdata, 16,
3383 (uint64_t)conn->server_info->utok.gid);
3386 if (data_len >= max_data_bytes) {
3387 /* Potential overflow, skip the GIDs and SIDs. */
3389 SIVAL(pdata, 24, 0); /* num_groups */
3390 SIVAL(pdata, 28, 0); /* num_sids */
3391 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3392 SIVAL(pdata, 36, 0); /* reserved */
3394 data_len = 40;
3395 break;
3398 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3399 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3401 /* We walk the SID list twice, but this call is fairly
3402 * infrequent, and I don't expect that it's performance
3403 * sensitive -- jpeach
3405 for (i = 0, sid_bytes = 0;
3406 i < conn->server_info->ptok->num_sids; ++i) {
3407 sid_bytes += ndr_size_dom_sid(
3408 &conn->server_info->ptok->user_sids[i],
3412 /* SID list byte count */
3413 SIVAL(pdata, 32, sid_bytes);
3415 /* 4 bytes pad/reserved - must be zero */
3416 SIVAL(pdata, 36, 0);
3417 data_len = 40;
3419 /* GID list */
3420 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3421 SBIG_UINT(pdata, data_len,
3422 (uint64_t)conn->server_info->utok.groups[i]);
3423 data_len += 8;
3426 /* SID list */
3427 for (i = 0;
3428 i < conn->server_info->ptok->num_sids; ++i) {
3429 int sid_len = ndr_size_dom_sid(
3430 &conn->server_info->ptok->user_sids[i],
3433 sid_linearize(pdata + data_len, sid_len,
3434 &conn->server_info->ptok->user_sids[i]);
3435 data_len += sid_len;
3438 break;
3441 case SMB_MAC_QUERY_FS_INFO:
3443 * Thursby MAC extension... ONLY on NTFS filesystems
3444 * once we do streams then we don't need this
3446 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3447 data_len = 88;
3448 SIVAL(pdata,84,0x100); /* Don't support mac... */
3449 break;
3451 /* drop through */
3452 default:
3453 return NT_STATUS_INVALID_LEVEL;
3456 *ret_data_len = data_len;
3457 return NT_STATUS_OK;
3460 /****************************************************************************
3461 Reply to a TRANS2_QFSINFO (query filesystem info).
3462 ****************************************************************************/
3464 static void call_trans2qfsinfo(connection_struct *conn,
3465 struct smb_request *req,
3466 char **pparams, int total_params,
3467 char **ppdata, int total_data,
3468 unsigned int max_data_bytes)
3470 char *params = *pparams;
3471 uint16_t info_level;
3472 int data_len = 0;
3473 NTSTATUS status;
3475 if (total_params < 2) {
3476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3477 return;
3480 info_level = SVAL(params,0);
3482 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3483 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3484 DEBUG(0,("call_trans2qfsinfo: encryption required "
3485 "and info level 0x%x sent.\n",
3486 (unsigned int)info_level));
3487 exit_server_cleanly("encryption required "
3488 "on connection");
3489 return;
3493 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3495 status = smbd_do_qfsinfo(conn, req,
3496 info_level,
3497 req->flags2,
3498 max_data_bytes,
3499 ppdata, &data_len);
3500 if (!NT_STATUS_IS_OK(status)) {
3501 reply_nterror(req, status);
3502 return;
3505 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3506 max_data_bytes);
3508 DEBUG( 4, ( "%s info_level = %d\n",
3509 smb_fn_name(req->cmd), info_level) );
3511 return;
3514 /****************************************************************************
3515 Reply to a TRANS2_SETFSINFO (set filesystem info).
3516 ****************************************************************************/
3518 static void call_trans2setfsinfo(connection_struct *conn,
3519 struct smb_request *req,
3520 char **pparams, int total_params,
3521 char **ppdata, int total_data,
3522 unsigned int max_data_bytes)
3524 char *pdata = *ppdata;
3525 char *params = *pparams;
3526 uint16 info_level;
3528 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3530 /* */
3531 if (total_params < 4) {
3532 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3533 total_params));
3534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3535 return;
3538 info_level = SVAL(params,2);
3540 if (IS_IPC(conn)) {
3541 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3542 info_level != SMB_SET_CIFS_UNIX_INFO) {
3543 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3544 "info level (0x%x) on IPC$.\n",
3545 (unsigned int)info_level));
3546 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3547 return;
3551 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3552 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3553 DEBUG(0,("call_trans2setfsinfo: encryption required "
3554 "and info level 0x%x sent.\n",
3555 (unsigned int)info_level));
3556 exit_server_cleanly("encryption required "
3557 "on connection");
3558 return;
3562 switch(info_level) {
3563 case SMB_SET_CIFS_UNIX_INFO:
3565 uint16 client_unix_major;
3566 uint16 client_unix_minor;
3567 uint32 client_unix_cap_low;
3568 uint32 client_unix_cap_high;
3570 if (!lp_unix_extensions()) {
3571 reply_nterror(req,
3572 NT_STATUS_INVALID_LEVEL);
3573 return;
3576 /* There should be 12 bytes of capabilities set. */
3577 if (total_data < 8) {
3578 reply_nterror(
3579 req,
3580 NT_STATUS_INVALID_PARAMETER);
3581 return;
3583 client_unix_major = SVAL(pdata,0);
3584 client_unix_minor = SVAL(pdata,2);
3585 client_unix_cap_low = IVAL(pdata,4);
3586 client_unix_cap_high = IVAL(pdata,8);
3587 /* Just print these values for now. */
3588 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3589 cap_low = 0x%x, cap_high = 0x%x\n",
3590 (unsigned int)client_unix_major,
3591 (unsigned int)client_unix_minor,
3592 (unsigned int)client_unix_cap_low,
3593 (unsigned int)client_unix_cap_high ));
3595 /* Here is where we must switch to posix pathname processing... */
3596 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3597 lp_set_posix_pathnames();
3598 mangle_change_to_posix();
3601 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3602 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3603 /* Client that knows how to do posix locks,
3604 * but not posix open/mkdir operations. Set a
3605 * default type for read/write checks. */
3607 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3610 break;
3613 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3615 NTSTATUS status;
3616 size_t param_len = 0;
3617 size_t data_len = total_data;
3619 if (!lp_unix_extensions()) {
3620 reply_nterror(
3621 req,
3622 NT_STATUS_INVALID_LEVEL);
3623 return;
3626 if (lp_smb_encrypt(SNUM(conn)) == false) {
3627 reply_nterror(
3628 req,
3629 NT_STATUS_NOT_SUPPORTED);
3630 return;
3633 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3634 DEBUG( 2,("call_trans2setfsinfo: "
3635 "request transport encryption disabled"
3636 "with 'fork echo handler = yes'\n"));
3637 reply_nterror(
3638 req,
3639 NT_STATUS_NOT_SUPPORTED);
3640 return;
3643 DEBUG( 4,("call_trans2setfsinfo: "
3644 "request transport encryption.\n"));
3646 status = srv_request_encryption_setup(conn,
3647 (unsigned char **)ppdata,
3648 &data_len,
3649 (unsigned char **)pparams,
3650 &param_len);
3652 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3653 !NT_STATUS_IS_OK(status)) {
3654 reply_nterror(req, status);
3655 return;
3658 send_trans2_replies(conn, req,
3659 *pparams,
3660 param_len,
3661 *ppdata,
3662 data_len,
3663 max_data_bytes);
3665 if (NT_STATUS_IS_OK(status)) {
3666 /* Server-side transport
3667 * encryption is now *on*. */
3668 status = srv_encryption_start(conn);
3669 if (!NT_STATUS_IS_OK(status)) {
3670 exit_server_cleanly(
3671 "Failure in setting "
3672 "up encrypted transport");
3675 return;
3678 case SMB_FS_QUOTA_INFORMATION:
3680 files_struct *fsp = NULL;
3681 SMB_NTQUOTA_STRUCT quotas;
3683 ZERO_STRUCT(quotas);
3685 /* access check */
3686 if ((conn->server_info->utok.uid != sec_initial_uid())
3687 ||!CAN_WRITE(conn)) {
3688 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3689 lp_servicename(SNUM(conn)),
3690 conn->server_info->unix_name));
3691 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3692 return;
3695 /* note: normaly there're 48 bytes,
3696 * but we didn't use the last 6 bytes for now
3697 * --metze
3699 fsp = file_fsp(req, SVAL(params,0));
3701 if (!check_fsp_ntquota_handle(conn, req,
3702 fsp)) {
3703 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3704 reply_nterror(
3705 req, NT_STATUS_INVALID_HANDLE);
3706 return;
3709 if (total_data < 42) {
3710 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3711 total_data));
3712 reply_nterror(
3713 req,
3714 NT_STATUS_INVALID_PARAMETER);
3715 return;
3718 /* unknown_1 24 NULL bytes in pdata*/
3720 /* the soft quotas 8 bytes (uint64_t)*/
3721 quotas.softlim = (uint64_t)IVAL(pdata,24);
3722 #ifdef LARGE_SMB_OFF_T
3723 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3724 #else /* LARGE_SMB_OFF_T */
3725 if ((IVAL(pdata,28) != 0)&&
3726 ((quotas.softlim != 0xFFFFFFFF)||
3727 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3728 /* more than 32 bits? */
3729 reply_nterror(
3730 req,
3731 NT_STATUS_INVALID_PARAMETER);
3732 return;
3734 #endif /* LARGE_SMB_OFF_T */
3736 /* the hard quotas 8 bytes (uint64_t)*/
3737 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3738 #ifdef LARGE_SMB_OFF_T
3739 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3740 #else /* LARGE_SMB_OFF_T */
3741 if ((IVAL(pdata,36) != 0)&&
3742 ((quotas.hardlim != 0xFFFFFFFF)||
3743 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3744 /* more than 32 bits? */
3745 reply_nterror(
3746 req,
3747 NT_STATUS_INVALID_PARAMETER);
3748 return;
3750 #endif /* LARGE_SMB_OFF_T */
3752 /* quota_flags 2 bytes **/
3753 quotas.qflags = SVAL(pdata,40);
3755 /* unknown_2 6 NULL bytes follow*/
3757 /* now set the quotas */
3758 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3759 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3760 reply_nterror(req, map_nt_error_from_unix(errno));
3761 return;
3764 break;
3766 default:
3767 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3768 info_level));
3769 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3770 return;
3771 break;
3775 * sending this reply works fine,
3776 * but I'm not sure it's the same
3777 * like windows do...
3778 * --metze
3780 reply_outbuf(req, 10, 0);
3783 #if defined(HAVE_POSIX_ACLS)
3784 /****************************************************************************
3785 Utility function to count the number of entries in a POSIX acl.
3786 ****************************************************************************/
3788 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3790 unsigned int ace_count = 0;
3791 int entry_id = SMB_ACL_FIRST_ENTRY;
3792 SMB_ACL_ENTRY_T entry;
3794 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3795 /* get_next... */
3796 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3797 entry_id = SMB_ACL_NEXT_ENTRY;
3799 ace_count++;
3801 return ace_count;
3804 /****************************************************************************
3805 Utility function to marshall a POSIX acl into wire format.
3806 ****************************************************************************/
3808 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3810 int entry_id = SMB_ACL_FIRST_ENTRY;
3811 SMB_ACL_ENTRY_T entry;
3813 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3814 SMB_ACL_TAG_T tagtype;
3815 SMB_ACL_PERMSET_T permset;
3816 unsigned char perms = 0;
3817 unsigned int own_grp;
3819 /* get_next... */
3820 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3821 entry_id = SMB_ACL_NEXT_ENTRY;
3824 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3825 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3826 return False;
3829 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3830 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3831 return False;
3834 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3835 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3836 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3838 SCVAL(pdata,1,perms);
3840 switch (tagtype) {
3841 case SMB_ACL_USER_OBJ:
3842 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3843 own_grp = (unsigned int)pst->st_ex_uid;
3844 SIVAL(pdata,2,own_grp);
3845 SIVAL(pdata,6,0);
3846 break;
3847 case SMB_ACL_USER:
3849 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3850 if (!puid) {
3851 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3852 return False;
3854 own_grp = (unsigned int)*puid;
3855 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3856 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3857 SIVAL(pdata,2,own_grp);
3858 SIVAL(pdata,6,0);
3859 break;
3861 case SMB_ACL_GROUP_OBJ:
3862 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3863 own_grp = (unsigned int)pst->st_ex_gid;
3864 SIVAL(pdata,2,own_grp);
3865 SIVAL(pdata,6,0);
3866 break;
3867 case SMB_ACL_GROUP:
3869 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3870 if (!pgid) {
3871 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3872 return False;
3874 own_grp = (unsigned int)*pgid;
3875 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3876 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3877 SIVAL(pdata,2,own_grp);
3878 SIVAL(pdata,6,0);
3879 break;
3881 case SMB_ACL_MASK:
3882 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3883 SIVAL(pdata,2,0xFFFFFFFF);
3884 SIVAL(pdata,6,0xFFFFFFFF);
3885 break;
3886 case SMB_ACL_OTHER:
3887 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3888 SIVAL(pdata,2,0xFFFFFFFF);
3889 SIVAL(pdata,6,0xFFFFFFFF);
3890 break;
3891 default:
3892 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3893 return False;
3895 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3898 return True;
3900 #endif
3902 /****************************************************************************
3903 Store the FILE_UNIX_BASIC info.
3904 ****************************************************************************/
3906 static char *store_file_unix_basic(connection_struct *conn,
3907 char *pdata,
3908 files_struct *fsp,
3909 const SMB_STRUCT_STAT *psbuf)
3911 uint64_t file_index = get_FileIndex(conn, psbuf);
3913 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3914 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3916 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3917 pdata += 8;
3919 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3920 pdata += 8;
3922 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3923 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3925 pdata += 24;
3927 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3928 SIVAL(pdata,4,0);
3929 pdata += 8;
3931 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3932 SIVAL(pdata,4,0);
3933 pdata += 8;
3935 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3936 pdata += 4;
3938 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3939 SIVAL(pdata,4,0);
3940 pdata += 8;
3942 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3943 SIVAL(pdata,4,0);
3944 pdata += 8;
3946 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3947 pdata += 8;
3949 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3950 SIVAL(pdata,4,0);
3951 pdata += 8;
3953 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3954 SIVAL(pdata,4,0);
3955 pdata += 8;
3957 return pdata;
3960 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3961 * the chflags(2) (or equivalent) flags.
3963 * XXX: this really should be behind the VFS interface. To do this, we would
3964 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3965 * Each VFS module could then implement its own mapping as appropriate for the
3966 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3968 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3969 info2_flags_map[] =
3971 #ifdef UF_NODUMP
3972 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3973 #endif
3975 #ifdef UF_IMMUTABLE
3976 { UF_IMMUTABLE, EXT_IMMUTABLE },
3977 #endif
3979 #ifdef UF_APPEND
3980 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3981 #endif
3983 #ifdef UF_HIDDEN
3984 { UF_HIDDEN, EXT_HIDDEN },
3985 #endif
3987 /* Do not remove. We need to guarantee that this array has at least one
3988 * entry to build on HP-UX.
3990 { 0, 0 }
3994 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3995 uint32 *smb_fflags, uint32 *smb_fmask)
3997 int i;
3999 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4000 *smb_fmask |= info2_flags_map[i].smb_fflag;
4001 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4002 *smb_fflags |= info2_flags_map[i].smb_fflag;
4007 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4008 const uint32 smb_fflags,
4009 const uint32 smb_fmask,
4010 int *stat_fflags)
4012 uint32 max_fmask = 0;
4013 int i;
4015 *stat_fflags = psbuf->st_ex_flags;
4017 /* For each flags requested in smb_fmask, check the state of the
4018 * corresponding flag in smb_fflags and set or clear the matching
4019 * stat flag.
4022 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4023 max_fmask |= info2_flags_map[i].smb_fflag;
4024 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4025 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4026 *stat_fflags |= info2_flags_map[i].stat_fflag;
4027 } else {
4028 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4033 /* If smb_fmask is asking to set any bits that are not supported by
4034 * our flag mappings, we should fail.
4036 if ((smb_fmask & max_fmask) != smb_fmask) {
4037 return False;
4040 return True;
4044 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4045 * of file flags and birth (create) time.
4047 static char *store_file_unix_basic_info2(connection_struct *conn,
4048 char *pdata,
4049 files_struct *fsp,
4050 const SMB_STRUCT_STAT *psbuf)
4052 uint32 file_flags = 0;
4053 uint32 flags_mask = 0;
4055 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4057 /* Create (birth) time 64 bit */
4058 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4059 pdata += 8;
4061 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4062 SIVAL(pdata, 0, file_flags); /* flags */
4063 SIVAL(pdata, 4, flags_mask); /* mask */
4064 pdata += 8;
4066 return pdata;
4069 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4070 const struct stream_struct *streams,
4071 char *data,
4072 unsigned int max_data_bytes,
4073 unsigned int *data_size)
4075 unsigned int i;
4076 unsigned int ofs = 0;
4078 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4079 unsigned int next_offset;
4080 size_t namelen;
4081 smb_ucs2_t *namebuf;
4083 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4084 streams[i].name, &namelen) ||
4085 namelen <= 2)
4087 return NT_STATUS_INVALID_PARAMETER;
4091 * name_buf is now null-terminated, we need to marshall as not
4092 * terminated
4095 namelen -= 2;
4097 SIVAL(data, ofs+4, namelen);
4098 SOFF_T(data, ofs+8, streams[i].size);
4099 SOFF_T(data, ofs+16, streams[i].alloc_size);
4100 memcpy(data+ofs+24, namebuf, namelen);
4101 TALLOC_FREE(namebuf);
4103 next_offset = ofs + 24 + namelen;
4105 if (i == num_streams-1) {
4106 SIVAL(data, ofs, 0);
4108 else {
4109 unsigned int align = ndr_align_size(next_offset, 8);
4111 memset(data+next_offset, 0, align);
4112 next_offset += align;
4114 SIVAL(data, ofs, next_offset - ofs);
4115 ofs = next_offset;
4118 ofs = next_offset;
4121 *data_size = ofs;
4123 return NT_STATUS_OK;
4126 /****************************************************************************
4127 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4128 ****************************************************************************/
4130 static void call_trans2qpipeinfo(connection_struct *conn,
4131 struct smb_request *req,
4132 unsigned int tran_call,
4133 char **pparams, int total_params,
4134 char **ppdata, int total_data,
4135 unsigned int max_data_bytes)
4137 char *params = *pparams;
4138 char *pdata = *ppdata;
4139 unsigned int data_size = 0;
4140 unsigned int param_size = 2;
4141 uint16 info_level;
4142 files_struct *fsp;
4144 if (!params) {
4145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4146 return;
4149 if (total_params < 4) {
4150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4151 return;
4154 fsp = file_fsp(req, SVAL(params,0));
4155 if (!fsp_is_np(fsp)) {
4156 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4157 return;
4160 info_level = SVAL(params,2);
4162 *pparams = (char *)SMB_REALLOC(*pparams,2);
4163 if (*pparams == NULL) {
4164 reply_nterror(req, NT_STATUS_NO_MEMORY);
4165 return;
4167 params = *pparams;
4168 SSVAL(params,0,0);
4169 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4170 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4171 if (*ppdata == NULL ) {
4172 reply_nterror(req, NT_STATUS_NO_MEMORY);
4173 return;
4175 pdata = *ppdata;
4177 switch (info_level) {
4178 case SMB_FILE_STANDARD_INFORMATION:
4179 memset(pdata,0,24);
4180 SOFF_T(pdata,0,4096LL);
4181 SIVAL(pdata,16,1);
4182 SIVAL(pdata,20,1);
4183 data_size = 24;
4184 break;
4186 default:
4187 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4188 return;
4191 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4192 max_data_bytes);
4194 return;
4197 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4198 TALLOC_CTX *mem_ctx,
4199 uint16_t info_level,
4200 files_struct *fsp,
4201 struct smb_filename *smb_fname,
4202 bool delete_pending,
4203 struct timespec write_time_ts,
4204 struct ea_list *ea_list,
4205 int lock_data_count,
4206 char *lock_data,
4207 uint16_t flags2,
4208 unsigned int max_data_bytes,
4209 char **ppdata,
4210 unsigned int *pdata_size)
4212 char *pdata = *ppdata;
4213 char *dstart, *dend;
4214 unsigned int data_size;
4215 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4216 time_t create_time, mtime, atime, c_time;
4217 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4218 char *p;
4219 char *base_name;
4220 char *dos_fname;
4221 int mode;
4222 int nlink;
4223 NTSTATUS status;
4224 uint64_t file_size = 0;
4225 uint64_t pos = 0;
4226 uint64_t allocation_size = 0;
4227 uint64_t file_index = 0;
4228 uint32_t access_mask = 0;
4230 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4231 return NT_STATUS_INVALID_LEVEL;
4234 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4235 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4236 info_level, max_data_bytes));
4238 mode = dos_mode(conn, smb_fname);
4239 nlink = psbuf->st_ex_nlink;
4241 if (nlink && (mode&aDIR)) {
4242 nlink = 1;
4245 if ((nlink > 0) && delete_pending) {
4246 nlink -= 1;
4249 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4250 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4251 if (*ppdata == NULL) {
4252 return NT_STATUS_NO_MEMORY;
4254 pdata = *ppdata;
4255 dstart = pdata;
4256 dend = dstart + data_size - 1;
4258 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4259 update_stat_ex_mtime(psbuf, write_time_ts);
4262 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4263 mtime_ts = psbuf->st_ex_mtime;
4264 atime_ts = psbuf->st_ex_atime;
4265 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4267 if (lp_dos_filetime_resolution(SNUM(conn))) {
4268 dos_filetime_timespec(&create_time_ts);
4269 dos_filetime_timespec(&mtime_ts);
4270 dos_filetime_timespec(&atime_ts);
4271 dos_filetime_timespec(&ctime_ts);
4274 create_time = convert_timespec_to_time_t(create_time_ts);
4275 mtime = convert_timespec_to_time_t(mtime_ts);
4276 atime = convert_timespec_to_time_t(atime_ts);
4277 c_time = convert_timespec_to_time_t(ctime_ts);
4279 p = strrchr_m(smb_fname->base_name,'/');
4280 if (!p)
4281 base_name = smb_fname->base_name;
4282 else
4283 base_name = p+1;
4285 /* NT expects the name to be in an exact form of the *full*
4286 filename. See the trans2 torture test */
4287 if (ISDOT(base_name)) {
4288 dos_fname = talloc_strdup(mem_ctx, "\\");
4289 if (!dos_fname) {
4290 return NT_STATUS_NO_MEMORY;
4292 } else {
4293 dos_fname = talloc_asprintf(mem_ctx,
4294 "\\%s",
4295 smb_fname->base_name);
4296 if (!dos_fname) {
4297 return NT_STATUS_NO_MEMORY;
4299 if (is_ntfs_stream_smb_fname(smb_fname)) {
4300 dos_fname = talloc_asprintf(dos_fname, "%s",
4301 smb_fname->stream_name);
4302 if (!dos_fname) {
4303 return NT_STATUS_NO_MEMORY;
4307 string_replace(dos_fname, '/', '\\');
4310 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4312 if (!fsp) {
4313 /* Do we have this path open ? */
4314 files_struct *fsp1;
4315 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4316 fsp1 = file_find_di_first(fileid);
4317 if (fsp1 && fsp1->initial_allocation_size) {
4318 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4322 if (!(mode & aDIR)) {
4323 file_size = get_file_size_stat(psbuf);
4326 if (fsp) {
4327 pos = fsp->fh->position_information;
4330 if (fsp) {
4331 access_mask = fsp->access_mask;
4332 } else {
4333 /* GENERIC_EXECUTE mapping from Windows */
4334 access_mask = 0x12019F;
4337 /* This should be an index number - looks like
4338 dev/ino to me :-)
4340 I think this causes us to fail the IFSKIT
4341 BasicFileInformationTest. -tpot */
4342 file_index = get_FileIndex(conn, psbuf);
4344 switch (info_level) {
4345 case SMB_INFO_STANDARD:
4346 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4347 data_size = 22;
4348 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4349 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4350 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4351 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4352 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4353 SSVAL(pdata,l1_attrFile,mode);
4354 break;
4356 case SMB_INFO_QUERY_EA_SIZE:
4358 unsigned int ea_size =
4359 estimate_ea_size(conn, fsp,
4360 smb_fname->base_name);
4361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4362 data_size = 26;
4363 srv_put_dos_date2(pdata,0,create_time);
4364 srv_put_dos_date2(pdata,4,atime);
4365 srv_put_dos_date2(pdata,8,mtime); /* write time */
4366 SIVAL(pdata,12,(uint32)file_size);
4367 SIVAL(pdata,16,(uint32)allocation_size);
4368 SSVAL(pdata,20,mode);
4369 SIVAL(pdata,22,ea_size);
4370 break;
4373 case SMB_INFO_IS_NAME_VALID:
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4375 if (fsp) {
4376 /* os/2 needs this ? really ?*/
4377 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4379 /* This is only reached for qpathinfo */
4380 data_size = 0;
4381 break;
4383 case SMB_INFO_QUERY_EAS_FROM_LIST:
4385 size_t total_ea_len = 0;
4386 struct ea_list *ea_file_list = NULL;
4388 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4390 ea_file_list =
4391 get_ea_list_from_file(mem_ctx, conn, fsp,
4392 smb_fname->base_name,
4393 &total_ea_len);
4394 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4396 if (!ea_list || (total_ea_len > data_size)) {
4397 data_size = 4;
4398 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4399 break;
4402 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4403 break;
4406 case SMB_INFO_QUERY_ALL_EAS:
4408 /* We have data_size bytes to put EA's into. */
4409 size_t total_ea_len = 0;
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4413 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4414 smb_fname->base_name,
4415 &total_ea_len);
4416 if (!ea_list || (total_ea_len > data_size)) {
4417 data_size = 4;
4418 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4419 break;
4422 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4423 break;
4426 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4428 /* This is FileFullEaInformation - 0xF which maps to
4429 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4431 /* We have data_size bytes to put EA's into. */
4432 size_t total_ea_len = 0;
4433 struct ea_list *ea_file_list = NULL;
4435 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4437 /*TODO: add filtering and index handling */
4439 ea_file_list =
4440 get_ea_list_from_file(mem_ctx, conn, fsp,
4441 smb_fname->base_name,
4442 &total_ea_len);
4443 if (!ea_file_list) {
4444 return NT_STATUS_NO_EAS_ON_FILE;
4447 status = fill_ea_chained_buffer(mem_ctx,
4448 pdata,
4449 data_size,
4450 &data_size,
4451 conn, ea_file_list);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 return status;
4455 break;
4458 case SMB_FILE_BASIC_INFORMATION:
4459 case SMB_QUERY_FILE_BASIC_INFO:
4461 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4463 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4464 } else {
4465 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4466 data_size = 40;
4467 SIVAL(pdata,36,0);
4469 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4470 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4471 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4472 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4473 SIVAL(pdata,32,mode);
4475 DEBUG(5,("SMB_QFBI - "));
4476 DEBUG(5,("create: %s ", ctime(&create_time)));
4477 DEBUG(5,("access: %s ", ctime(&atime)));
4478 DEBUG(5,("write: %s ", ctime(&mtime)));
4479 DEBUG(5,("change: %s ", ctime(&c_time)));
4480 DEBUG(5,("mode: %x\n", mode));
4481 break;
4483 case SMB_FILE_STANDARD_INFORMATION:
4484 case SMB_QUERY_FILE_STANDARD_INFO:
4486 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4487 data_size = 24;
4488 SOFF_T(pdata,0,allocation_size);
4489 SOFF_T(pdata,8,file_size);
4490 SIVAL(pdata,16,nlink);
4491 SCVAL(pdata,20,delete_pending?1:0);
4492 SCVAL(pdata,21,(mode&aDIR)?1:0);
4493 SSVAL(pdata,22,0); /* Padding. */
4494 break;
4496 case SMB_FILE_EA_INFORMATION:
4497 case SMB_QUERY_FILE_EA_INFO:
4499 unsigned int ea_size =
4500 estimate_ea_size(conn, fsp, smb_fname->base_name);
4501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4502 data_size = 4;
4503 SIVAL(pdata,0,ea_size);
4504 break;
4507 /* Get the 8.3 name - used if NT SMB was negotiated. */
4508 case SMB_QUERY_FILE_ALT_NAME_INFO:
4509 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4511 int len;
4512 char mangled_name[13];
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4514 if (!name_to_8_3(base_name,mangled_name,
4515 True,conn->params)) {
4516 return NT_STATUS_NO_MEMORY;
4518 len = srvstr_push(dstart, flags2,
4519 pdata+4, mangled_name,
4520 PTR_DIFF(dend, pdata+4),
4521 STR_UNICODE);
4522 data_size = 4 + len;
4523 SIVAL(pdata,0,len);
4524 break;
4527 case SMB_QUERY_FILE_NAME_INFO:
4529 int len;
4531 this must be *exactly* right for ACLs on mapped drives to work
4533 len = srvstr_push(dstart, flags2,
4534 pdata+4, dos_fname,
4535 PTR_DIFF(dend, pdata+4),
4536 STR_UNICODE);
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4538 data_size = 4 + len;
4539 SIVAL(pdata,0,len);
4540 break;
4543 case SMB_FILE_ALLOCATION_INFORMATION:
4544 case SMB_QUERY_FILE_ALLOCATION_INFO:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4546 data_size = 8;
4547 SOFF_T(pdata,0,allocation_size);
4548 break;
4550 case SMB_FILE_END_OF_FILE_INFORMATION:
4551 case SMB_QUERY_FILE_END_OF_FILEINFO:
4552 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4553 data_size = 8;
4554 SOFF_T(pdata,0,file_size);
4555 break;
4557 case SMB_QUERY_FILE_ALL_INFO:
4558 case SMB_FILE_ALL_INFORMATION:
4560 int len;
4561 unsigned int ea_size =
4562 estimate_ea_size(conn, fsp, smb_fname->base_name);
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4564 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4565 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4566 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4567 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4568 SIVAL(pdata,32,mode);
4569 SIVAL(pdata,36,0); /* padding. */
4570 pdata += 40;
4571 SOFF_T(pdata,0,allocation_size);
4572 SOFF_T(pdata,8,file_size);
4573 SIVAL(pdata,16,nlink);
4574 SCVAL(pdata,20,delete_pending);
4575 SCVAL(pdata,21,(mode&aDIR)?1:0);
4576 SSVAL(pdata,22,0);
4577 pdata += 24;
4578 SIVAL(pdata,0,ea_size);
4579 pdata += 4; /* EA info */
4580 len = srvstr_push(dstart, flags2,
4581 pdata+4, dos_fname,
4582 PTR_DIFF(dend, pdata+4),
4583 STR_UNICODE);
4584 SIVAL(pdata,0,len);
4585 pdata += 4 + len;
4586 data_size = PTR_DIFF(pdata,(*ppdata));
4587 break;
4590 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4592 int len;
4593 unsigned int ea_size =
4594 estimate_ea_size(conn, fsp, smb_fname->base_name);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4596 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4597 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4598 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4599 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4600 SIVAL(pdata, 0x20, mode);
4601 SIVAL(pdata, 0x24, 0); /* padding. */
4602 SBVAL(pdata, 0x28, allocation_size);
4603 SBVAL(pdata, 0x30, file_size);
4604 SIVAL(pdata, 0x38, nlink);
4605 SCVAL(pdata, 0x3C, delete_pending);
4606 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4607 SSVAL(pdata, 0x3E, 0); /* padding */
4608 SBVAL(pdata, 0x40, file_index);
4609 SIVAL(pdata, 0x48, ea_size);
4610 SIVAL(pdata, 0x4C, access_mask);
4611 SBVAL(pdata, 0x50, pos);
4612 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4613 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4615 pdata += 0x60;
4617 len = srvstr_push(dstart, flags2,
4618 pdata+4, dos_fname,
4619 PTR_DIFF(dend, pdata+4),
4620 STR_UNICODE);
4621 SIVAL(pdata,0,len);
4622 pdata += 4 + len;
4623 data_size = PTR_DIFF(pdata,(*ppdata));
4624 break;
4626 case SMB_FILE_INTERNAL_INFORMATION:
4628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4629 SBVAL(pdata, 0, file_index);
4630 data_size = 8;
4631 break;
4633 case SMB_FILE_ACCESS_INFORMATION:
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4635 SIVAL(pdata, 0, access_mask);
4636 data_size = 4;
4637 break;
4639 case SMB_FILE_NAME_INFORMATION:
4640 /* Pathname with leading '\'. */
4642 size_t byte_len;
4643 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4645 SIVAL(pdata,0,byte_len);
4646 data_size = 4 + byte_len;
4647 break;
4650 case SMB_FILE_DISPOSITION_INFORMATION:
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4652 data_size = 1;
4653 SCVAL(pdata,0,delete_pending);
4654 break;
4656 case SMB_FILE_POSITION_INFORMATION:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4658 data_size = 8;
4659 SOFF_T(pdata,0,pos);
4660 break;
4662 case SMB_FILE_MODE_INFORMATION:
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4664 SIVAL(pdata,0,mode);
4665 data_size = 4;
4666 break;
4668 case SMB_FILE_ALIGNMENT_INFORMATION:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4670 SIVAL(pdata,0,0); /* No alignment needed. */
4671 data_size = 4;
4672 break;
4675 * NT4 server just returns "invalid query" to this - if we try
4676 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4677 * want this. JRA.
4679 /* The first statement above is false - verified using Thursby
4680 * client against NT4 -- gcolley.
4682 case SMB_QUERY_FILE_STREAM_INFO:
4683 case SMB_FILE_STREAM_INFORMATION: {
4684 unsigned int num_streams;
4685 struct stream_struct *streams;
4687 DEBUG(10,("smbd_do_qfilepathinfo: "
4688 "SMB_FILE_STREAM_INFORMATION\n"));
4690 if (is_ntfs_stream_smb_fname(smb_fname)) {
4691 return NT_STATUS_INVALID_PARAMETER;
4694 status = SMB_VFS_STREAMINFO(
4695 conn, fsp, smb_fname->base_name, talloc_tos(),
4696 &num_streams, &streams);
4698 if (!NT_STATUS_IS_OK(status)) {
4699 DEBUG(10, ("could not get stream info: %s\n",
4700 nt_errstr(status)));
4701 return status;
4704 status = marshall_stream_info(num_streams, streams,
4705 pdata, max_data_bytes,
4706 &data_size);
4708 if (!NT_STATUS_IS_OK(status)) {
4709 DEBUG(10, ("marshall_stream_info failed: %s\n",
4710 nt_errstr(status)));
4711 return status;
4714 TALLOC_FREE(streams);
4716 break;
4718 case SMB_QUERY_COMPRESSION_INFO:
4719 case SMB_FILE_COMPRESSION_INFORMATION:
4720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4721 SOFF_T(pdata,0,file_size);
4722 SIVAL(pdata,8,0); /* ??? */
4723 SIVAL(pdata,12,0); /* ??? */
4724 data_size = 16;
4725 break;
4727 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4728 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4729 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4730 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4731 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4732 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4733 SOFF_T(pdata,32,allocation_size);
4734 SOFF_T(pdata,40,file_size);
4735 SIVAL(pdata,48,mode);
4736 SIVAL(pdata,52,0); /* ??? */
4737 data_size = 56;
4738 break;
4740 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4742 SIVAL(pdata,0,mode);
4743 SIVAL(pdata,4,0);
4744 data_size = 8;
4745 break;
4748 * CIFS UNIX Extensions.
4751 case SMB_QUERY_FILE_UNIX_BASIC:
4753 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4754 data_size = PTR_DIFF(pdata,(*ppdata));
4757 int i;
4758 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4760 for (i=0; i<100; i++)
4761 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4762 DEBUG(4,("\n"));
4765 break;
4767 case SMB_QUERY_FILE_UNIX_INFO2:
4769 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4770 data_size = PTR_DIFF(pdata,(*ppdata));
4773 int i;
4774 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4776 for (i=0; i<100; i++)
4777 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4778 DEBUG(4,("\n"));
4781 break;
4783 case SMB_QUERY_FILE_UNIX_LINK:
4785 int len;
4786 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4788 if (!buffer) {
4789 return NT_STATUS_NO_MEMORY;
4792 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4793 #ifdef S_ISLNK
4794 if(!S_ISLNK(psbuf->st_ex_mode)) {
4795 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4797 #else
4798 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4799 #endif
4800 len = SMB_VFS_READLINK(conn,
4801 smb_fname->base_name,
4802 buffer, PATH_MAX);
4803 if (len == -1) {
4804 return map_nt_error_from_unix(errno);
4806 buffer[len] = 0;
4807 len = srvstr_push(dstart, flags2,
4808 pdata, buffer,
4809 PTR_DIFF(dend, pdata),
4810 STR_TERMINATE);
4811 pdata += len;
4812 data_size = PTR_DIFF(pdata,(*ppdata));
4814 break;
4817 #if defined(HAVE_POSIX_ACLS)
4818 case SMB_QUERY_POSIX_ACL:
4820 SMB_ACL_T file_acl = NULL;
4821 SMB_ACL_T def_acl = NULL;
4822 uint16 num_file_acls = 0;
4823 uint16 num_def_acls = 0;
4825 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4826 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4827 } else {
4828 file_acl =
4829 SMB_VFS_SYS_ACL_GET_FILE(conn,
4830 smb_fname->base_name,
4831 SMB_ACL_TYPE_ACCESS);
4834 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4835 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4836 "not implemented on "
4837 "filesystem containing %s\n",
4838 smb_fname->base_name));
4839 return NT_STATUS_NOT_IMPLEMENTED;
4842 if (S_ISDIR(psbuf->st_ex_mode)) {
4843 if (fsp && fsp->is_directory) {
4844 def_acl =
4845 SMB_VFS_SYS_ACL_GET_FILE(
4846 conn,
4847 fsp->fsp_name->base_name,
4848 SMB_ACL_TYPE_DEFAULT);
4849 } else {
4850 def_acl =
4851 SMB_VFS_SYS_ACL_GET_FILE(
4852 conn,
4853 smb_fname->base_name,
4854 SMB_ACL_TYPE_DEFAULT);
4856 def_acl = free_empty_sys_acl(conn, def_acl);
4859 num_file_acls = count_acl_entries(conn, file_acl);
4860 num_def_acls = count_acl_entries(conn, def_acl);
4862 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4863 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4864 data_size,
4865 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4866 SMB_POSIX_ACL_HEADER_SIZE) ));
4867 if (file_acl) {
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4870 if (def_acl) {
4871 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4873 return NT_STATUS_BUFFER_TOO_SMALL;
4876 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4877 SSVAL(pdata,2,num_file_acls);
4878 SSVAL(pdata,4,num_def_acls);
4879 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4880 if (file_acl) {
4881 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4883 if (def_acl) {
4884 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4886 return NT_STATUS_INTERNAL_ERROR;
4888 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4889 if (file_acl) {
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4892 if (def_acl) {
4893 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4895 return NT_STATUS_INTERNAL_ERROR;
4898 if (file_acl) {
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4901 if (def_acl) {
4902 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4904 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4905 break;
4907 #endif
4910 case SMB_QUERY_POSIX_LOCK:
4912 uint64_t count;
4913 uint64_t offset;
4914 uint64_t smblctx;
4915 enum brl_type lock_type;
4917 /* We need an open file with a real fd for this. */
4918 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4919 return NT_STATUS_INVALID_LEVEL;
4922 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4923 return NT_STATUS_INVALID_PARAMETER;
4926 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4927 case POSIX_LOCK_TYPE_READ:
4928 lock_type = READ_LOCK;
4929 break;
4930 case POSIX_LOCK_TYPE_WRITE:
4931 lock_type = WRITE_LOCK;
4932 break;
4933 case POSIX_LOCK_TYPE_UNLOCK:
4934 default:
4935 /* There's no point in asking for an unlock... */
4936 return NT_STATUS_INVALID_PARAMETER;
4939 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4940 #if defined(HAVE_LONGLONG)
4941 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4942 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4943 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4944 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4945 #else /* HAVE_LONGLONG */
4946 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4947 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4948 #endif /* HAVE_LONGLONG */
4950 status = query_lock(fsp,
4951 &smblctx,
4952 &count,
4953 &offset,
4954 &lock_type,
4955 POSIX_LOCK);
4957 if (ERROR_WAS_LOCK_DENIED(status)) {
4958 /* Here we need to report who has it locked... */
4959 data_size = POSIX_LOCK_DATA_SIZE;
4961 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4962 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4963 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4964 #if defined(HAVE_LONGLONG)
4965 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4966 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4967 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4968 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4969 #else /* HAVE_LONGLONG */
4970 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4971 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4972 #endif /* HAVE_LONGLONG */
4974 } else if (NT_STATUS_IS_OK(status)) {
4975 /* For success we just return a copy of what we sent
4976 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4977 data_size = POSIX_LOCK_DATA_SIZE;
4978 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4979 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4980 } else {
4981 return status;
4983 break;
4986 default:
4987 return NT_STATUS_INVALID_LEVEL;
4990 *pdata_size = data_size;
4991 return NT_STATUS_OK;
4994 /****************************************************************************
4995 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4996 file name or file id).
4997 ****************************************************************************/
4999 static void call_trans2qfilepathinfo(connection_struct *conn,
5000 struct smb_request *req,
5001 unsigned int tran_call,
5002 char **pparams, int total_params,
5003 char **ppdata, int total_data,
5004 unsigned int max_data_bytes)
5006 char *params = *pparams;
5007 char *pdata = *ppdata;
5008 uint16 info_level;
5009 unsigned int data_size = 0;
5010 unsigned int param_size = 2;
5011 struct smb_filename *smb_fname = NULL;
5012 bool delete_pending = False;
5013 struct timespec write_time_ts;
5014 files_struct *fsp = NULL;
5015 struct file_id fileid;
5016 struct ea_list *ea_list = NULL;
5017 int lock_data_count = 0;
5018 char *lock_data = NULL;
5019 NTSTATUS status = NT_STATUS_OK;
5021 if (!params) {
5022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5023 return;
5026 ZERO_STRUCT(write_time_ts);
5028 if (tran_call == TRANSACT2_QFILEINFO) {
5029 if (total_params < 4) {
5030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5031 return;
5034 if (IS_IPC(conn)) {
5035 call_trans2qpipeinfo(conn, req, tran_call,
5036 pparams, total_params,
5037 ppdata, total_data,
5038 max_data_bytes);
5039 return;
5042 fsp = file_fsp(req, SVAL(params,0));
5043 info_level = SVAL(params,2);
5045 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5047 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5049 return;
5052 /* Initial check for valid fsp ptr. */
5053 if (!check_fsp_open(conn, req, fsp)) {
5054 return;
5057 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5058 &smb_fname);
5059 if (!NT_STATUS_IS_OK(status)) {
5060 reply_nterror(req, status);
5061 return;
5064 if(fsp->fake_file_handle) {
5066 * This is actually for the QUOTA_FAKE_FILE --metze
5069 /* We know this name is ok, it's already passed the checks. */
5071 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5073 * This is actually a QFILEINFO on a directory
5074 * handle (returned from an NT SMB). NT5.0 seems
5075 * to do this call. JRA.
5078 if (INFO_LEVEL_IS_UNIX(info_level)) {
5079 /* Always do lstat for UNIX calls. */
5080 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5081 DEBUG(3,("call_trans2qfilepathinfo: "
5082 "SMB_VFS_LSTAT of %s failed "
5083 "(%s)\n",
5084 smb_fname_str_dbg(smb_fname),
5085 strerror(errno)));
5086 reply_nterror(req,
5087 map_nt_error_from_unix(errno));
5088 return;
5090 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5091 DEBUG(3,("call_trans2qfilepathinfo: "
5092 "SMB_VFS_STAT of %s failed (%s)\n",
5093 smb_fname_str_dbg(smb_fname),
5094 strerror(errno)));
5095 reply_nterror(req,
5096 map_nt_error_from_unix(errno));
5097 return;
5100 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5101 get_file_infos(fileid, &delete_pending, &write_time_ts);
5102 } else {
5104 * Original code - this is an open file.
5106 if (!check_fsp(conn, req, fsp)) {
5107 return;
5110 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5111 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5112 fsp->fnum, strerror(errno)));
5113 reply_nterror(req,
5114 map_nt_error_from_unix(errno));
5115 return;
5117 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5118 get_file_infos(fileid, &delete_pending, &write_time_ts);
5121 } else {
5122 char *fname = NULL;
5124 /* qpathinfo */
5125 if (total_params < 7) {
5126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5127 return;
5130 info_level = SVAL(params,0);
5132 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5134 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5135 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5136 return;
5139 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5140 total_params - 6,
5141 STR_TERMINATE, &status);
5142 if (!NT_STATUS_IS_OK(status)) {
5143 reply_nterror(req, status);
5144 return;
5147 status = filename_convert(req,
5148 conn,
5149 req->flags2 & FLAGS2_DFS_PATHNAMES,
5150 fname,
5152 NULL,
5153 &smb_fname);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5156 reply_botherror(req,
5157 NT_STATUS_PATH_NOT_COVERED,
5158 ERRSRV, ERRbadpath);
5159 return;
5161 reply_nterror(req, status);
5162 return;
5165 /* If this is a stream, check if there is a delete_pending. */
5166 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5167 && is_ntfs_stream_smb_fname(smb_fname)) {
5168 struct smb_filename *smb_fname_base = NULL;
5170 /* Create an smb_filename with stream_name == NULL. */
5171 status =
5172 create_synthetic_smb_fname(talloc_tos(),
5173 smb_fname->base_name,
5174 NULL, NULL,
5175 &smb_fname_base);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 reply_nterror(req, status);
5178 return;
5181 if (INFO_LEVEL_IS_UNIX(info_level)) {
5182 /* Always do lstat for UNIX calls. */
5183 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5184 DEBUG(3,("call_trans2qfilepathinfo: "
5185 "SMB_VFS_LSTAT of %s failed "
5186 "(%s)\n",
5187 smb_fname_str_dbg(smb_fname_base),
5188 strerror(errno)));
5189 TALLOC_FREE(smb_fname_base);
5190 reply_nterror(req,
5191 map_nt_error_from_unix(errno));
5192 return;
5194 } else {
5195 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5196 DEBUG(3,("call_trans2qfilepathinfo: "
5197 "fileinfo of %s failed "
5198 "(%s)\n",
5199 smb_fname_str_dbg(smb_fname_base),
5200 strerror(errno)));
5201 TALLOC_FREE(smb_fname_base);
5202 reply_nterror(req,
5203 map_nt_error_from_unix(errno));
5204 return;
5208 fileid = vfs_file_id_from_sbuf(conn,
5209 &smb_fname_base->st);
5210 TALLOC_FREE(smb_fname_base);
5211 get_file_infos(fileid, &delete_pending, NULL);
5212 if (delete_pending) {
5213 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5214 return;
5218 if (INFO_LEVEL_IS_UNIX(info_level)) {
5219 /* Always do lstat for UNIX calls. */
5220 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5221 DEBUG(3,("call_trans2qfilepathinfo: "
5222 "SMB_VFS_LSTAT of %s failed (%s)\n",
5223 smb_fname_str_dbg(smb_fname),
5224 strerror(errno)));
5225 reply_nterror(req,
5226 map_nt_error_from_unix(errno));
5227 return;
5230 } else {
5231 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5232 DEBUG(3,("call_trans2qfilepathinfo: "
5233 "SMB_VFS_STAT of %s failed (%s)\n",
5234 smb_fname_str_dbg(smb_fname),
5235 strerror(errno)));
5236 reply_nterror(req,
5237 map_nt_error_from_unix(errno));
5238 return;
5242 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5243 get_file_infos(fileid, &delete_pending, &write_time_ts);
5244 if (delete_pending) {
5245 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5246 return;
5250 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5251 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5252 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5254 /* Pull out any data sent here before we realloc. */
5255 switch (info_level) {
5256 case SMB_INFO_QUERY_EAS_FROM_LIST:
5258 /* Pull any EA list from the data portion. */
5259 uint32 ea_size;
5261 if (total_data < 4) {
5262 reply_nterror(
5263 req, NT_STATUS_INVALID_PARAMETER);
5264 return;
5266 ea_size = IVAL(pdata,0);
5268 if (total_data > 0 && ea_size != total_data) {
5269 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5270 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5271 reply_nterror(
5272 req, NT_STATUS_INVALID_PARAMETER);
5273 return;
5276 if (!lp_ea_support(SNUM(conn))) {
5277 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5278 return;
5281 /* Pull out the list of names. */
5282 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5283 if (!ea_list) {
5284 reply_nterror(
5285 req, NT_STATUS_INVALID_PARAMETER);
5286 return;
5288 break;
5291 case SMB_QUERY_POSIX_LOCK:
5293 if (fsp == NULL || fsp->fh->fd == -1) {
5294 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5295 return;
5298 if (total_data != POSIX_LOCK_DATA_SIZE) {
5299 reply_nterror(
5300 req, NT_STATUS_INVALID_PARAMETER);
5301 return;
5304 /* Copy the lock range data. */
5305 lock_data = (char *)TALLOC_MEMDUP(
5306 req, pdata, total_data);
5307 if (!lock_data) {
5308 reply_nterror(req, NT_STATUS_NO_MEMORY);
5309 return;
5311 lock_data_count = total_data;
5313 default:
5314 break;
5317 *pparams = (char *)SMB_REALLOC(*pparams,2);
5318 if (*pparams == NULL) {
5319 reply_nterror(req, NT_STATUS_NO_MEMORY);
5320 return;
5322 params = *pparams;
5323 SSVAL(params,0,0);
5326 * draft-leach-cifs-v1-spec-02.txt
5327 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5328 * says:
5330 * The requested information is placed in the Data portion of the
5331 * transaction response. For the information levels greater than 0x100,
5332 * the transaction response has 1 parameter word which should be
5333 * ignored by the client.
5335 * However Windows only follows this rule for the IS_NAME_VALID call.
5337 switch (info_level) {
5338 case SMB_INFO_IS_NAME_VALID:
5339 param_size = 0;
5340 break;
5343 if ((info_level & 0xFF00) == 0xFF00) {
5345 * We use levels that start with 0xFF00
5346 * internally to represent SMB2 specific levels
5348 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5349 return;
5352 status = smbd_do_qfilepathinfo(conn, req, info_level,
5353 fsp, smb_fname,
5354 delete_pending, write_time_ts,
5355 ea_list,
5356 lock_data_count, lock_data,
5357 req->flags2, max_data_bytes,
5358 ppdata, &data_size);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 reply_nterror(req, status);
5361 return;
5364 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5365 max_data_bytes);
5367 return;
5370 /****************************************************************************
5371 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5372 code.
5373 ****************************************************************************/
5375 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5376 connection_struct *conn,
5377 struct smb_request *req,
5378 bool overwrite_if_exists,
5379 const struct smb_filename *smb_fname_old,
5380 struct smb_filename *smb_fname_new)
5382 NTSTATUS status = NT_STATUS_OK;
5384 /* source must already exist. */
5385 if (!VALID_STAT(smb_fname_old->st)) {
5386 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5389 if (VALID_STAT(smb_fname_new->st)) {
5390 if (overwrite_if_exists) {
5391 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5392 return NT_STATUS_FILE_IS_A_DIRECTORY;
5394 status = unlink_internals(conn,
5395 req,
5396 FILE_ATTRIBUTE_NORMAL,
5397 smb_fname_new,
5398 false);
5399 if (!NT_STATUS_IS_OK(status)) {
5400 return status;
5402 } else {
5403 /* Disallow if newname already exists. */
5404 return NT_STATUS_OBJECT_NAME_COLLISION;
5408 /* No links from a directory. */
5409 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5410 return NT_STATUS_FILE_IS_A_DIRECTORY;
5413 /* Setting a hardlink to/from a stream isn't currently supported. */
5414 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5415 is_ntfs_stream_smb_fname(smb_fname_new)) {
5416 return NT_STATUS_INVALID_PARAMETER;
5419 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5420 smb_fname_old->base_name, smb_fname_new->base_name));
5422 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5423 smb_fname_new->base_name) != 0) {
5424 status = map_nt_error_from_unix(errno);
5425 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5426 nt_errstr(status), smb_fname_old->base_name,
5427 smb_fname_new->base_name));
5429 return status;
5432 /****************************************************************************
5433 Deal with setting the time from any of the setfilepathinfo functions.
5434 ****************************************************************************/
5436 NTSTATUS smb_set_file_time(connection_struct *conn,
5437 files_struct *fsp,
5438 const struct smb_filename *smb_fname,
5439 struct smb_file_time *ft,
5440 bool setting_write_time)
5442 struct smb_filename smb_fname_base;
5443 uint32 action =
5444 FILE_NOTIFY_CHANGE_LAST_ACCESS
5445 |FILE_NOTIFY_CHANGE_LAST_WRITE
5446 |FILE_NOTIFY_CHANGE_CREATION;
5448 if (!VALID_STAT(smb_fname->st)) {
5449 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5452 /* get some defaults (no modifications) if any info is zero or -1. */
5453 if (null_timespec(ft->create_time)) {
5454 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5457 if (null_timespec(ft->atime)) {
5458 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5461 if (null_timespec(ft->mtime)) {
5462 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5465 if (!setting_write_time) {
5466 /* ft->mtime comes from change time, not write time. */
5467 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5470 /* Ensure the resolution is the correct for
5471 * what we can store on this filesystem. */
5473 round_timespec(conn->ts_res, &ft->create_time);
5474 round_timespec(conn->ts_res, &ft->ctime);
5475 round_timespec(conn->ts_res, &ft->atime);
5476 round_timespec(conn->ts_res, &ft->mtime);
5478 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5479 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5480 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5482 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5484 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5487 if (setting_write_time) {
5489 * This was a Windows setfileinfo on an open file.
5490 * NT does this a lot. We also need to
5491 * set the time here, as it can be read by
5492 * FindFirst/FindNext and with the patch for bug #2045
5493 * in smbd/fileio.c it ensures that this timestamp is
5494 * kept sticky even after a write. We save the request
5495 * away and will set it on file close and after a write. JRA.
5498 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5499 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5501 if (fsp != NULL) {
5502 if (fsp->base_fsp) {
5503 set_sticky_write_time_fsp(fsp->base_fsp,
5504 ft->mtime);
5505 } else {
5506 set_sticky_write_time_fsp(fsp, ft->mtime);
5508 } else {
5509 set_sticky_write_time_path(
5510 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5511 ft->mtime);
5515 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5517 /* Always call ntimes on the base, even if a stream was passed in. */
5518 smb_fname_base = *smb_fname;
5519 smb_fname_base.stream_name = NULL;
5521 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5522 return map_nt_error_from_unix(errno);
5525 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5526 smb_fname->base_name);
5527 return NT_STATUS_OK;
5530 /****************************************************************************
5531 Deal with setting the dosmode from any of the setfilepathinfo functions.
5532 ****************************************************************************/
5534 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5535 const struct smb_filename *smb_fname,
5536 uint32 dosmode)
5538 struct smb_filename *smb_fname_base = NULL;
5539 NTSTATUS status;
5541 if (!VALID_STAT(smb_fname->st)) {
5542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5545 /* Always operate on the base_name, even if a stream was passed in. */
5546 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5547 NULL, &smb_fname->st,
5548 &smb_fname_base);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 return status;
5553 if (dosmode) {
5554 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5555 dosmode |= aDIR;
5556 } else {
5557 dosmode &= ~aDIR;
5561 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5563 /* check the mode isn't different, before changing it */
5564 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5565 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5566 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5567 (unsigned int)dosmode));
5569 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5570 false)) {
5571 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5572 "%s failed (%s)\n",
5573 smb_fname_str_dbg(smb_fname_base),
5574 strerror(errno)));
5575 status = map_nt_error_from_unix(errno);
5576 goto out;
5579 status = NT_STATUS_OK;
5580 out:
5581 TALLOC_FREE(smb_fname_base);
5582 return status;
5585 /****************************************************************************
5586 Deal with setting the size from any of the setfilepathinfo functions.
5587 ****************************************************************************/
5589 static NTSTATUS smb_set_file_size(connection_struct *conn,
5590 struct smb_request *req,
5591 files_struct *fsp,
5592 const struct smb_filename *smb_fname,
5593 const SMB_STRUCT_STAT *psbuf,
5594 SMB_OFF_T size,
5595 bool fail_after_createfile)
5597 NTSTATUS status = NT_STATUS_OK;
5598 struct smb_filename *smb_fname_tmp = NULL;
5599 files_struct *new_fsp = NULL;
5601 if (!VALID_STAT(*psbuf)) {
5602 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5605 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5607 if (size == get_file_size_stat(psbuf)) {
5608 return NT_STATUS_OK;
5611 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5612 smb_fname_str_dbg(smb_fname), (double)size));
5614 if (fsp && fsp->fh->fd != -1) {
5615 /* Handle based call. */
5616 if (vfs_set_filelen(fsp, size) == -1) {
5617 return map_nt_error_from_unix(errno);
5619 trigger_write_time_update_immediate(fsp);
5620 return NT_STATUS_OK;
5623 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5624 if (!NT_STATUS_IS_OK(status)) {
5625 return status;
5628 smb_fname_tmp->st = *psbuf;
5630 status = SMB_VFS_CREATE_FILE(
5631 conn, /* conn */
5632 req, /* req */
5633 0, /* root_dir_fid */
5634 smb_fname_tmp, /* fname */
5635 FILE_WRITE_DATA, /* access_mask */
5636 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5637 FILE_SHARE_DELETE),
5638 FILE_OPEN, /* create_disposition*/
5639 0, /* create_options */
5640 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5641 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5642 0, /* allocation_size */
5643 0, /* private_flags */
5644 NULL, /* sd */
5645 NULL, /* ea_list */
5646 &new_fsp, /* result */
5647 NULL); /* pinfo */
5649 TALLOC_FREE(smb_fname_tmp);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 /* NB. We check for open_was_deferred in the caller. */
5653 return status;
5656 /* See RAW-SFILEINFO-END-OF-FILE */
5657 if (fail_after_createfile) {
5658 close_file(req, new_fsp,NORMAL_CLOSE);
5659 return NT_STATUS_INVALID_LEVEL;
5662 if (vfs_set_filelen(new_fsp, size) == -1) {
5663 status = map_nt_error_from_unix(errno);
5664 close_file(req, new_fsp,NORMAL_CLOSE);
5665 return status;
5668 trigger_write_time_update_immediate(new_fsp);
5669 close_file(req, new_fsp,NORMAL_CLOSE);
5670 return NT_STATUS_OK;
5673 /****************************************************************************
5674 Deal with SMB_INFO_SET_EA.
5675 ****************************************************************************/
5677 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5678 const char *pdata,
5679 int total_data,
5680 files_struct *fsp,
5681 const struct smb_filename *smb_fname)
5683 struct ea_list *ea_list = NULL;
5684 TALLOC_CTX *ctx = NULL;
5685 NTSTATUS status = NT_STATUS_OK;
5687 if (total_data < 10) {
5689 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5690 length. They seem to have no effect. Bug #3212. JRA */
5692 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5693 /* We're done. We only get EA info in this call. */
5694 return NT_STATUS_OK;
5697 return NT_STATUS_INVALID_PARAMETER;
5700 if (IVAL(pdata,0) > total_data) {
5701 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5702 IVAL(pdata,0), (unsigned int)total_data));
5703 return NT_STATUS_INVALID_PARAMETER;
5706 ctx = talloc_tos();
5707 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5708 if (!ea_list) {
5709 return NT_STATUS_INVALID_PARAMETER;
5711 status = set_ea(conn, fsp, smb_fname, ea_list);
5713 return status;
5716 /****************************************************************************
5717 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5718 ****************************************************************************/
5720 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5721 const char *pdata,
5722 int total_data,
5723 files_struct *fsp)
5725 struct ea_list *ea_list = NULL;
5726 NTSTATUS status;
5728 if (!fsp) {
5729 return NT_STATUS_INVALID_HANDLE;
5732 if (!lp_ea_support(SNUM(conn))) {
5733 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5734 "EA's not supported.\n",
5735 (unsigned int)total_data));
5736 return NT_STATUS_EAS_NOT_SUPPORTED;
5739 if (total_data < 10) {
5740 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5741 "too small.\n",
5742 (unsigned int)total_data));
5743 return NT_STATUS_INVALID_PARAMETER;
5746 ea_list = read_nttrans_ea_list(talloc_tos(),
5747 pdata,
5748 total_data);
5750 if (!ea_list) {
5751 return NT_STATUS_INVALID_PARAMETER;
5753 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5755 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5756 smb_fname_str_dbg(fsp->fsp_name),
5757 nt_errstr(status) ));
5759 return status;
5763 /****************************************************************************
5764 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5765 ****************************************************************************/
5767 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5768 const char *pdata,
5769 int total_data,
5770 files_struct *fsp,
5771 struct smb_filename *smb_fname)
5773 NTSTATUS status = NT_STATUS_OK;
5774 bool delete_on_close;
5775 uint32 dosmode = 0;
5777 if (total_data < 1) {
5778 return NT_STATUS_INVALID_PARAMETER;
5781 if (fsp == NULL) {
5782 return NT_STATUS_INVALID_HANDLE;
5785 delete_on_close = (CVAL(pdata,0) ? True : False);
5786 dosmode = dos_mode(conn, smb_fname);
5788 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5789 "delete_on_close = %u\n",
5790 smb_fname_str_dbg(smb_fname),
5791 (unsigned int)dosmode,
5792 (unsigned int)delete_on_close ));
5794 if (delete_on_close) {
5795 status = can_set_delete_on_close(fsp, dosmode);
5796 if (!NT_STATUS_IS_OK(status)) {
5797 return status;
5801 /* The set is across all open files on this dev/inode pair. */
5802 if (!set_delete_on_close(fsp, delete_on_close,
5803 &conn->server_info->utok)) {
5804 return NT_STATUS_ACCESS_DENIED;
5806 return NT_STATUS_OK;
5809 /****************************************************************************
5810 Deal with SMB_FILE_POSITION_INFORMATION.
5811 ****************************************************************************/
5813 static NTSTATUS smb_file_position_information(connection_struct *conn,
5814 const char *pdata,
5815 int total_data,
5816 files_struct *fsp)
5818 uint64_t position_information;
5820 if (total_data < 8) {
5821 return NT_STATUS_INVALID_PARAMETER;
5824 if (fsp == NULL) {
5825 /* Ignore on pathname based set. */
5826 return NT_STATUS_OK;
5829 position_information = (uint64_t)IVAL(pdata,0);
5830 #ifdef LARGE_SMB_OFF_T
5831 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5832 #else /* LARGE_SMB_OFF_T */
5833 if (IVAL(pdata,4) != 0) {
5834 /* more than 32 bits? */
5835 return NT_STATUS_INVALID_PARAMETER;
5837 #endif /* LARGE_SMB_OFF_T */
5839 DEBUG(10,("smb_file_position_information: Set file position "
5840 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5841 (double)position_information));
5842 fsp->fh->position_information = position_information;
5843 return NT_STATUS_OK;
5846 /****************************************************************************
5847 Deal with SMB_FILE_MODE_INFORMATION.
5848 ****************************************************************************/
5850 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5851 const char *pdata,
5852 int total_data)
5854 uint32 mode;
5856 if (total_data < 4) {
5857 return NT_STATUS_INVALID_PARAMETER;
5859 mode = IVAL(pdata,0);
5860 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5861 return NT_STATUS_INVALID_PARAMETER;
5863 return NT_STATUS_OK;
5866 /****************************************************************************
5867 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5868 ****************************************************************************/
5870 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5871 struct smb_request *req,
5872 const char *pdata,
5873 int total_data,
5874 const struct smb_filename *smb_fname)
5876 char *link_target = NULL;
5877 const char *newname = smb_fname->base_name;
5878 TALLOC_CTX *ctx = talloc_tos();
5880 /* Set a symbolic link. */
5881 /* Don't allow this if follow links is false. */
5883 if (total_data == 0) {
5884 return NT_STATUS_INVALID_PARAMETER;
5887 if (!lp_symlinks(SNUM(conn))) {
5888 return NT_STATUS_ACCESS_DENIED;
5891 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5892 total_data, STR_TERMINATE);
5894 if (!link_target) {
5895 return NT_STATUS_INVALID_PARAMETER;
5898 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5899 newname, link_target ));
5901 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5902 return map_nt_error_from_unix(errno);
5905 return NT_STATUS_OK;
5908 /****************************************************************************
5909 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5910 ****************************************************************************/
5912 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5913 struct smb_request *req,
5914 const char *pdata, int total_data,
5915 struct smb_filename *smb_fname_new)
5917 char *oldname = NULL;
5918 struct smb_filename *smb_fname_old = NULL;
5919 TALLOC_CTX *ctx = talloc_tos();
5920 NTSTATUS status = NT_STATUS_OK;
5922 /* Set a hard link. */
5923 if (total_data == 0) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5928 total_data, STR_TERMINATE, &status);
5929 if (!NT_STATUS_IS_OK(status)) {
5930 return status;
5933 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5934 smb_fname_str_dbg(smb_fname_new), oldname));
5936 status = filename_convert(ctx,
5937 conn,
5938 req->flags2 & FLAGS2_DFS_PATHNAMES,
5939 oldname,
5941 NULL,
5942 &smb_fname_old);
5943 if (!NT_STATUS_IS_OK(status)) {
5944 return status;
5947 return hardlink_internals(ctx, conn, req, false,
5948 smb_fname_old, smb_fname_new);
5951 /****************************************************************************
5952 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5953 ****************************************************************************/
5955 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5956 struct smb_request *req,
5957 const char *pdata,
5958 int total_data,
5959 files_struct *fsp,
5960 struct smb_filename *smb_fname_src)
5962 bool overwrite;
5963 uint32_t len;
5964 char *newname = NULL;
5965 struct smb_filename *smb_fname_dst = NULL;
5966 NTSTATUS status = NT_STATUS_OK;
5967 TALLOC_CTX *ctx = talloc_tos();
5969 if (!fsp) {
5970 return NT_STATUS_INVALID_HANDLE;
5973 if (total_data < 20) {
5974 return NT_STATUS_INVALID_PARAMETER;
5977 overwrite = (CVAL(pdata,0) ? True : False);
5978 len = IVAL(pdata,16);
5980 if (len > (total_data - 20) || (len == 0)) {
5981 return NT_STATUS_INVALID_PARAMETER;
5984 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5985 &pdata[20], len, STR_TERMINATE,
5986 &status);
5987 if (!NT_STATUS_IS_OK(status)) {
5988 return status;
5991 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5992 newname));
5994 status = filename_convert(ctx,
5995 conn,
5996 req->flags2 & FLAGS2_DFS_PATHNAMES,
5997 newname,
5999 NULL,
6000 &smb_fname_dst);
6001 if (!NT_STATUS_IS_OK(status)) {
6002 return status;
6005 /* Ok, this looks wrong to me, but appears to
6006 * be how SMB2 renames work. CHECK WITH Microsoft !
6007 * jra.
6009 if (fsp->oplock_type != NO_OPLOCK) {
6010 return NT_STATUS_SHARING_VIOLATION;
6013 if (fsp->base_fsp) {
6014 /* newname must be a stream name. */
6015 if (newname[0] != ':') {
6016 return NT_STATUS_NOT_SUPPORTED;
6019 /* Create an smb_fname to call rename_internals_fsp() with. */
6020 status = create_synthetic_smb_fname(talloc_tos(),
6021 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6022 &smb_fname_dst);
6023 if (!NT_STATUS_IS_OK(status)) {
6024 goto out;
6028 * Set the original last component, since
6029 * rename_internals_fsp() requires it.
6031 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6032 newname);
6033 if (smb_fname_dst->original_lcomp == NULL) {
6034 status = NT_STATUS_NO_MEMORY;
6035 goto out;
6040 DEBUG(10,("smb2_file_rename_information: "
6041 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6042 fsp->fnum, fsp_str_dbg(fsp),
6043 smb_fname_str_dbg(smb_fname_dst)));
6044 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6045 overwrite);
6047 out:
6048 TALLOC_FREE(smb_fname_dst);
6049 return status;
6052 static NTSTATUS smb_file_link_information(connection_struct *conn,
6053 struct smb_request *req,
6054 const char *pdata,
6055 int total_data,
6056 files_struct *fsp,
6057 struct smb_filename *smb_fname_src)
6059 bool overwrite;
6060 uint32_t len;
6061 char *newname = NULL;
6062 struct smb_filename *smb_fname_dst = NULL;
6063 NTSTATUS status = NT_STATUS_OK;
6064 TALLOC_CTX *ctx = talloc_tos();
6066 if (!fsp) {
6067 return NT_STATUS_INVALID_HANDLE;
6070 if (total_data < 20) {
6071 return NT_STATUS_INVALID_PARAMETER;
6074 overwrite = (CVAL(pdata,0) ? true : false);
6075 len = IVAL(pdata,16);
6077 if (len > (total_data - 20) || (len == 0)) {
6078 return NT_STATUS_INVALID_PARAMETER;
6081 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6082 &pdata[20], len, STR_TERMINATE,
6083 &status);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 return status;
6088 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6089 newname));
6091 status = filename_convert(ctx,
6092 conn,
6093 req->flags2 & FLAGS2_DFS_PATHNAMES,
6094 newname,
6096 NULL,
6097 &smb_fname_dst);
6098 if (!NT_STATUS_IS_OK(status)) {
6099 return status;
6102 if (fsp->base_fsp) {
6103 /* No stream names. */
6104 return NT_STATUS_NOT_SUPPORTED;
6107 DEBUG(10,("smb_file_link_information: "
6108 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6109 fsp->fnum, fsp_str_dbg(fsp),
6110 smb_fname_str_dbg(smb_fname_dst)));
6111 status = hardlink_internals(ctx,
6112 conn,
6113 req,
6114 overwrite,
6115 fsp->fsp_name,
6116 smb_fname_dst);
6118 TALLOC_FREE(smb_fname_dst);
6119 return status;
6122 /****************************************************************************
6123 Deal with SMB_FILE_RENAME_INFORMATION.
6124 ****************************************************************************/
6126 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6127 struct smb_request *req,
6128 const char *pdata,
6129 int total_data,
6130 files_struct *fsp,
6131 struct smb_filename *smb_fname_src)
6133 bool overwrite;
6134 uint32 root_fid;
6135 uint32 len;
6136 char *newname = NULL;
6137 struct smb_filename *smb_fname_dst = NULL;
6138 bool dest_has_wcard = False;
6139 NTSTATUS status = NT_STATUS_OK;
6140 char *p;
6141 TALLOC_CTX *ctx = talloc_tos();
6143 if (total_data < 13) {
6144 return NT_STATUS_INVALID_PARAMETER;
6147 overwrite = (CVAL(pdata,0) ? True : False);
6148 root_fid = IVAL(pdata,4);
6149 len = IVAL(pdata,8);
6151 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6152 return NT_STATUS_INVALID_PARAMETER;
6155 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6156 len, 0, &status,
6157 &dest_has_wcard);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 return status;
6162 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6163 newname));
6165 status = resolve_dfspath_wcard(ctx, conn,
6166 req->flags2 & FLAGS2_DFS_PATHNAMES,
6167 newname,
6168 true,
6169 &newname,
6170 &dest_has_wcard);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 return status;
6175 /* Check the new name has no '/' characters. */
6176 if (strchr_m(newname, '/')) {
6177 return NT_STATUS_NOT_SUPPORTED;
6180 if (fsp && fsp->base_fsp) {
6181 /* newname must be a stream name. */
6182 if (newname[0] != ':') {
6183 return NT_STATUS_NOT_SUPPORTED;
6186 /* Create an smb_fname to call rename_internals_fsp() with. */
6187 status = create_synthetic_smb_fname(talloc_tos(),
6188 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6189 &smb_fname_dst);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 goto out;
6195 * Set the original last component, since
6196 * rename_internals_fsp() requires it.
6198 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6199 newname);
6200 if (smb_fname_dst->original_lcomp == NULL) {
6201 status = NT_STATUS_NO_MEMORY;
6202 goto out;
6205 } else {
6207 * Build up an smb_fname_dst based on the filename passed in.
6208 * We basically just strip off the last component, and put on
6209 * the newname instead.
6211 char *base_name = NULL;
6213 /* newname must *not* be a stream name. */
6214 if (newname[0] == ':') {
6215 return NT_STATUS_NOT_SUPPORTED;
6219 * Strip off the last component (filename) of the path passed
6220 * in.
6222 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6223 if (!base_name) {
6224 return NT_STATUS_NO_MEMORY;
6226 p = strrchr_m(base_name, '/');
6227 if (p) {
6228 p[1] = '\0';
6229 } else {
6230 base_name = talloc_strdup(ctx, "./");
6231 if (!base_name) {
6232 return NT_STATUS_NO_MEMORY;
6235 /* Append the new name. */
6236 base_name = talloc_asprintf_append(base_name,
6237 "%s",
6238 newname);
6239 if (!base_name) {
6240 return NT_STATUS_NO_MEMORY;
6243 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6244 (UCF_SAVE_LCOMP |
6245 (dest_has_wcard ?
6246 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6247 0)));
6249 /* If an error we expect this to be
6250 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6252 if (!NT_STATUS_IS_OK(status)) {
6253 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6254 status)) {
6255 goto out;
6257 /* Create an smb_fname to call rename_internals_fsp() */
6258 status = create_synthetic_smb_fname(ctx,
6259 base_name, NULL,
6260 NULL,
6261 &smb_fname_dst);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 goto out;
6268 if (fsp) {
6269 DEBUG(10,("smb_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6271 fsp->fnum, fsp_str_dbg(fsp),
6272 smb_fname_str_dbg(smb_fname_dst)));
6273 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6274 overwrite);
6275 } else {
6276 DEBUG(10,("smb_file_rename_information: "
6277 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6278 smb_fname_str_dbg(smb_fname_src),
6279 smb_fname_str_dbg(smb_fname_dst)));
6280 status = rename_internals(ctx, conn, req, smb_fname_src,
6281 smb_fname_dst, 0, overwrite, false,
6282 dest_has_wcard,
6283 FILE_WRITE_ATTRIBUTES);
6285 out:
6286 TALLOC_FREE(smb_fname_dst);
6287 return status;
6290 /****************************************************************************
6291 Deal with SMB_SET_POSIX_ACL.
6292 ****************************************************************************/
6294 #if defined(HAVE_POSIX_ACLS)
6295 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6296 const char *pdata,
6297 int total_data,
6298 files_struct *fsp,
6299 const struct smb_filename *smb_fname)
6301 uint16 posix_acl_version;
6302 uint16 num_file_acls;
6303 uint16 num_def_acls;
6304 bool valid_file_acls = True;
6305 bool valid_def_acls = True;
6307 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6308 return NT_STATUS_INVALID_PARAMETER;
6310 posix_acl_version = SVAL(pdata,0);
6311 num_file_acls = SVAL(pdata,2);
6312 num_def_acls = SVAL(pdata,4);
6314 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6315 valid_file_acls = False;
6316 num_file_acls = 0;
6319 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6320 valid_def_acls = False;
6321 num_def_acls = 0;
6324 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6325 return NT_STATUS_INVALID_PARAMETER;
6328 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6329 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6330 return NT_STATUS_INVALID_PARAMETER;
6333 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6334 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6335 (unsigned int)num_file_acls,
6336 (unsigned int)num_def_acls));
6338 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6339 smb_fname->base_name, num_file_acls,
6340 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6341 return map_nt_error_from_unix(errno);
6344 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6345 smb_fname->base_name, &smb_fname->st, num_def_acls,
6346 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6347 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6348 return map_nt_error_from_unix(errno);
6350 return NT_STATUS_OK;
6352 #endif
6354 /****************************************************************************
6355 Deal with SMB_SET_POSIX_LOCK.
6356 ****************************************************************************/
6358 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6359 struct smb_request *req,
6360 const char *pdata,
6361 int total_data,
6362 files_struct *fsp)
6364 uint64_t count;
6365 uint64_t offset;
6366 uint64_t smblctx;
6367 bool blocking_lock = False;
6368 enum brl_type lock_type;
6370 NTSTATUS status = NT_STATUS_OK;
6372 if (fsp == NULL || fsp->fh->fd == -1) {
6373 return NT_STATUS_INVALID_HANDLE;
6376 if (total_data != POSIX_LOCK_DATA_SIZE) {
6377 return NT_STATUS_INVALID_PARAMETER;
6380 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6381 case POSIX_LOCK_TYPE_READ:
6382 lock_type = READ_LOCK;
6383 break;
6384 case POSIX_LOCK_TYPE_WRITE:
6385 /* Return the right POSIX-mappable error code for files opened read-only. */
6386 if (!fsp->can_write) {
6387 return NT_STATUS_INVALID_HANDLE;
6389 lock_type = WRITE_LOCK;
6390 break;
6391 case POSIX_LOCK_TYPE_UNLOCK:
6392 lock_type = UNLOCK_LOCK;
6393 break;
6394 default:
6395 return NT_STATUS_INVALID_PARAMETER;
6398 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6399 blocking_lock = False;
6400 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6401 blocking_lock = True;
6402 } else {
6403 return NT_STATUS_INVALID_PARAMETER;
6406 if (!lp_blocking_locks(SNUM(conn))) {
6407 blocking_lock = False;
6410 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6411 #if defined(HAVE_LONGLONG)
6412 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6413 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6414 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6415 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6416 #else /* HAVE_LONGLONG */
6417 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6418 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6419 #endif /* HAVE_LONGLONG */
6421 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6422 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6423 fsp_str_dbg(fsp),
6424 (unsigned int)lock_type,
6425 (unsigned long long)smblctx,
6426 (double)count,
6427 (double)offset ));
6429 if (lock_type == UNLOCK_LOCK) {
6430 status = do_unlock(smbd_messaging_context(),
6431 fsp,
6432 smblctx,
6433 count,
6434 offset,
6435 POSIX_LOCK);
6436 } else {
6437 uint64_t block_smblctx;
6439 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6440 fsp,
6441 smblctx,
6442 count,
6443 offset,
6444 lock_type,
6445 POSIX_LOCK,
6446 blocking_lock,
6447 &status,
6448 &block_smblctx,
6449 NULL);
6451 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6453 * A blocking lock was requested. Package up
6454 * this smb into a queued request and push it
6455 * onto the blocking lock queue.
6457 if(push_blocking_lock_request(br_lck,
6458 req,
6459 fsp,
6460 -1, /* infinite timeout. */
6462 smblctx,
6463 lock_type,
6464 POSIX_LOCK,
6465 offset,
6466 count,
6467 block_smblctx)) {
6468 TALLOC_FREE(br_lck);
6469 return status;
6472 TALLOC_FREE(br_lck);
6475 return status;
6478 /****************************************************************************
6479 Deal with SMB_SET_FILE_BASIC_INFO.
6480 ****************************************************************************/
6482 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6483 const char *pdata,
6484 int total_data,
6485 files_struct *fsp,
6486 const struct smb_filename *smb_fname)
6488 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6489 struct smb_file_time ft;
6490 uint32 dosmode = 0;
6491 NTSTATUS status = NT_STATUS_OK;
6493 ZERO_STRUCT(ft);
6495 if (total_data < 36) {
6496 return NT_STATUS_INVALID_PARAMETER;
6499 /* Set the attributes */
6500 dosmode = IVAL(pdata,32);
6501 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6502 if (!NT_STATUS_IS_OK(status)) {
6503 return status;
6506 /* create time */
6507 ft.create_time = interpret_long_date(pdata);
6509 /* access time */
6510 ft.atime = interpret_long_date(pdata+8);
6512 /* write time. */
6513 ft.mtime = interpret_long_date(pdata+16);
6515 /* change time. */
6516 ft.ctime = interpret_long_date(pdata+24);
6518 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6519 smb_fname_str_dbg(smb_fname)));
6521 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6522 true);
6525 /****************************************************************************
6526 Deal with SMB_INFO_STANDARD.
6527 ****************************************************************************/
6529 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6530 const char *pdata,
6531 int total_data,
6532 files_struct *fsp,
6533 const struct smb_filename *smb_fname)
6535 struct smb_file_time ft;
6537 ZERO_STRUCT(ft);
6539 if (total_data < 12) {
6540 return NT_STATUS_INVALID_PARAMETER;
6543 /* create time */
6544 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6545 /* access time */
6546 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6547 /* write time */
6548 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6550 DEBUG(10,("smb_set_info_standard: file %s\n",
6551 smb_fname_str_dbg(smb_fname)));
6553 return smb_set_file_time(conn,
6554 fsp,
6555 smb_fname,
6556 &ft,
6557 true);
6560 /****************************************************************************
6561 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6562 ****************************************************************************/
6564 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6565 struct smb_request *req,
6566 const char *pdata,
6567 int total_data,
6568 files_struct *fsp,
6569 struct smb_filename *smb_fname)
6571 uint64_t allocation_size = 0;
6572 NTSTATUS status = NT_STATUS_OK;
6573 files_struct *new_fsp = NULL;
6575 if (!VALID_STAT(smb_fname->st)) {
6576 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6579 if (total_data < 8) {
6580 return NT_STATUS_INVALID_PARAMETER;
6583 allocation_size = (uint64_t)IVAL(pdata,0);
6584 #ifdef LARGE_SMB_OFF_T
6585 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6586 #else /* LARGE_SMB_OFF_T */
6587 if (IVAL(pdata,4) != 0) {
6588 /* more than 32 bits? */
6589 return NT_STATUS_INVALID_PARAMETER;
6591 #endif /* LARGE_SMB_OFF_T */
6593 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6594 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6595 (double)allocation_size));
6597 if (allocation_size) {
6598 allocation_size = smb_roundup(conn, allocation_size);
6601 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6602 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6603 (double)allocation_size));
6605 if (fsp && fsp->fh->fd != -1) {
6606 /* Open file handle. */
6607 /* Only change if needed. */
6608 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6609 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6610 return map_nt_error_from_unix(errno);
6613 /* But always update the time. */
6615 * This is equivalent to a write. Ensure it's seen immediately
6616 * if there are no pending writes.
6618 trigger_write_time_update_immediate(fsp);
6619 return NT_STATUS_OK;
6622 /* Pathname or stat or directory file. */
6623 status = SMB_VFS_CREATE_FILE(
6624 conn, /* conn */
6625 req, /* req */
6626 0, /* root_dir_fid */
6627 smb_fname, /* fname */
6628 FILE_WRITE_DATA, /* access_mask */
6629 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6630 FILE_SHARE_DELETE),
6631 FILE_OPEN, /* create_disposition*/
6632 0, /* create_options */
6633 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6634 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6635 0, /* allocation_size */
6636 0, /* private_flags */
6637 NULL, /* sd */
6638 NULL, /* ea_list */
6639 &new_fsp, /* result */
6640 NULL); /* pinfo */
6642 if (!NT_STATUS_IS_OK(status)) {
6643 /* NB. We check for open_was_deferred in the caller. */
6644 return status;
6647 /* Only change if needed. */
6648 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6649 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6650 status = map_nt_error_from_unix(errno);
6651 close_file(req, new_fsp, NORMAL_CLOSE);
6652 return status;
6656 /* Changing the allocation size should set the last mod time. */
6658 * This is equivalent to a write. Ensure it's seen immediately
6659 * if there are no pending writes.
6661 trigger_write_time_update_immediate(new_fsp);
6663 close_file(req, new_fsp, NORMAL_CLOSE);
6664 return NT_STATUS_OK;
6667 /****************************************************************************
6668 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6669 ****************************************************************************/
6671 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6672 struct smb_request *req,
6673 const char *pdata,
6674 int total_data,
6675 files_struct *fsp,
6676 const struct smb_filename *smb_fname,
6677 bool fail_after_createfile)
6679 SMB_OFF_T size;
6681 if (total_data < 8) {
6682 return NT_STATUS_INVALID_PARAMETER;
6685 size = IVAL(pdata,0);
6686 #ifdef LARGE_SMB_OFF_T
6687 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6688 #else /* LARGE_SMB_OFF_T */
6689 if (IVAL(pdata,4) != 0) {
6690 /* more than 32 bits? */
6691 return NT_STATUS_INVALID_PARAMETER;
6693 #endif /* LARGE_SMB_OFF_T */
6694 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6695 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6696 (double)size));
6698 return smb_set_file_size(conn, req,
6699 fsp,
6700 smb_fname,
6701 &smb_fname->st,
6702 size,
6703 fail_after_createfile);
6706 /****************************************************************************
6707 Allow a UNIX info mknod.
6708 ****************************************************************************/
6710 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6711 const char *pdata,
6712 int total_data,
6713 const struct smb_filename *smb_fname)
6715 uint32 file_type = IVAL(pdata,56);
6716 #if defined(HAVE_MAKEDEV)
6717 uint32 dev_major = IVAL(pdata,60);
6718 uint32 dev_minor = IVAL(pdata,68);
6719 #endif
6720 SMB_DEV_T dev = (SMB_DEV_T)0;
6721 uint32 raw_unixmode = IVAL(pdata,84);
6722 NTSTATUS status;
6723 mode_t unixmode;
6725 if (total_data < 100) {
6726 return NT_STATUS_INVALID_PARAMETER;
6729 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6730 PERM_NEW_FILE, &unixmode);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 return status;
6735 #if defined(HAVE_MAKEDEV)
6736 dev = makedev(dev_major, dev_minor);
6737 #endif
6739 switch (file_type) {
6740 #if defined(S_IFIFO)
6741 case UNIX_TYPE_FIFO:
6742 unixmode |= S_IFIFO;
6743 break;
6744 #endif
6745 #if defined(S_IFSOCK)
6746 case UNIX_TYPE_SOCKET:
6747 unixmode |= S_IFSOCK;
6748 break;
6749 #endif
6750 #if defined(S_IFCHR)
6751 case UNIX_TYPE_CHARDEV:
6752 unixmode |= S_IFCHR;
6753 break;
6754 #endif
6755 #if defined(S_IFBLK)
6756 case UNIX_TYPE_BLKDEV:
6757 unixmode |= S_IFBLK;
6758 break;
6759 #endif
6760 default:
6761 return NT_STATUS_INVALID_PARAMETER;
6764 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6765 "%.0f mode 0%o for file %s\n", (double)dev,
6766 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6768 /* Ok - do the mknod. */
6769 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6770 return map_nt_error_from_unix(errno);
6773 /* If any of the other "set" calls fail we
6774 * don't want to end up with a half-constructed mknod.
6777 if (lp_inherit_perms(SNUM(conn))) {
6778 char *parent;
6779 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6780 &parent, NULL)) {
6781 return NT_STATUS_NO_MEMORY;
6783 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6784 unixmode);
6785 TALLOC_FREE(parent);
6788 return NT_STATUS_OK;
6791 /****************************************************************************
6792 Deal with SMB_SET_FILE_UNIX_BASIC.
6793 ****************************************************************************/
6795 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6796 struct smb_request *req,
6797 const char *pdata,
6798 int total_data,
6799 files_struct *fsp,
6800 const struct smb_filename *smb_fname)
6802 struct smb_file_time ft;
6803 uint32 raw_unixmode;
6804 mode_t unixmode;
6805 SMB_OFF_T size = 0;
6806 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6807 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6808 NTSTATUS status = NT_STATUS_OK;
6809 bool delete_on_fail = False;
6810 enum perm_type ptype;
6811 files_struct *all_fsps = NULL;
6812 bool modify_mtime = true;
6813 struct file_id id;
6814 SMB_STRUCT_STAT sbuf;
6816 ZERO_STRUCT(ft);
6818 if (total_data < 100) {
6819 return NT_STATUS_INVALID_PARAMETER;
6822 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6823 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6824 size=IVAL(pdata,0); /* first 8 Bytes are size */
6825 #ifdef LARGE_SMB_OFF_T
6826 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6827 #else /* LARGE_SMB_OFF_T */
6828 if (IVAL(pdata,4) != 0) {
6829 /* more than 32 bits? */
6830 return NT_STATUS_INVALID_PARAMETER;
6832 #endif /* LARGE_SMB_OFF_T */
6835 ft.atime = interpret_long_date(pdata+24); /* access_time */
6836 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6837 set_owner = (uid_t)IVAL(pdata,40);
6838 set_grp = (gid_t)IVAL(pdata,48);
6839 raw_unixmode = IVAL(pdata,84);
6841 if (VALID_STAT(smb_fname->st)) {
6842 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6843 ptype = PERM_EXISTING_DIR;
6844 } else {
6845 ptype = PERM_EXISTING_FILE;
6847 } else {
6848 ptype = PERM_NEW_FILE;
6851 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6852 ptype, &unixmode);
6853 if (!NT_STATUS_IS_OK(status)) {
6854 return status;
6857 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6858 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6859 smb_fname_str_dbg(smb_fname), (double)size,
6860 (unsigned int)set_owner, (unsigned int)set_grp,
6861 (int)raw_unixmode));
6863 sbuf = smb_fname->st;
6865 if (!VALID_STAT(sbuf)) {
6866 struct smb_filename *smb_fname_tmp = NULL;
6868 * The only valid use of this is to create character and block
6869 * devices, and named pipes. This is deprecated (IMHO) and
6870 * a new info level should be used for mknod. JRA.
6873 status = smb_unix_mknod(conn,
6874 pdata,
6875 total_data,
6876 smb_fname);
6877 if (!NT_STATUS_IS_OK(status)) {
6878 return status;
6881 status = copy_smb_filename(talloc_tos(), smb_fname,
6882 &smb_fname_tmp);
6883 if (!NT_STATUS_IS_OK(status)) {
6884 return status;
6887 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6888 status = map_nt_error_from_unix(errno);
6889 TALLOC_FREE(smb_fname_tmp);
6890 SMB_VFS_UNLINK(conn, smb_fname);
6891 return status;
6894 sbuf = smb_fname_tmp->st;
6895 TALLOC_FREE(smb_fname_tmp);
6897 /* Ensure we don't try and change anything else. */
6898 raw_unixmode = SMB_MODE_NO_CHANGE;
6899 size = get_file_size_stat(&sbuf);
6900 ft.atime = sbuf.st_ex_atime;
6901 ft.mtime = sbuf.st_ex_mtime;
6903 * We continue here as we might want to change the
6904 * owner uid/gid.
6906 delete_on_fail = True;
6909 #if 1
6910 /* Horrible backwards compatibility hack as an old server bug
6911 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6912 * */
6914 if (!size) {
6915 size = get_file_size_stat(&sbuf);
6917 #endif
6920 * Deal with the UNIX specific mode set.
6923 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6924 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6925 "setting mode 0%o for file %s\n",
6926 (unsigned int)unixmode,
6927 smb_fname_str_dbg(smb_fname)));
6928 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6929 return map_nt_error_from_unix(errno);
6934 * Deal with the UNIX specific uid set.
6937 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6938 (sbuf.st_ex_uid != set_owner)) {
6939 int ret;
6941 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6942 "changing owner %u for path %s\n",
6943 (unsigned int)set_owner,
6944 smb_fname_str_dbg(smb_fname)));
6946 if (S_ISLNK(sbuf.st_ex_mode)) {
6947 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6948 set_owner, (gid_t)-1);
6949 } else {
6950 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6951 set_owner, (gid_t)-1);
6954 if (ret != 0) {
6955 status = map_nt_error_from_unix(errno);
6956 if (delete_on_fail) {
6957 SMB_VFS_UNLINK(conn, smb_fname);
6959 return status;
6964 * Deal with the UNIX specific gid set.
6967 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6968 (sbuf.st_ex_gid != set_grp)) {
6969 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6970 "changing group %u for file %s\n",
6971 (unsigned int)set_owner,
6972 smb_fname_str_dbg(smb_fname)));
6973 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6974 set_grp) != 0) {
6975 status = map_nt_error_from_unix(errno);
6976 if (delete_on_fail) {
6977 SMB_VFS_UNLINK(conn, smb_fname);
6979 return status;
6983 /* Deal with any size changes. */
6985 status = smb_set_file_size(conn, req,
6986 fsp,
6987 smb_fname,
6988 &sbuf,
6989 size,
6990 false);
6991 if (!NT_STATUS_IS_OK(status)) {
6992 return status;
6995 /* Deal with any time changes. */
6996 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6997 /* No change, don't cancel anything. */
6998 return status;
7001 id = vfs_file_id_from_sbuf(conn, &sbuf);
7002 for(all_fsps = file_find_di_first(id); all_fsps;
7003 all_fsps = file_find_di_next(all_fsps)) {
7005 * We're setting the time explicitly for UNIX.
7006 * Cancel any pending changes over all handles.
7008 all_fsps->update_write_time_on_close = false;
7009 TALLOC_FREE(all_fsps->update_write_time_event);
7013 * Override the "setting_write_time"
7014 * parameter here as it almost does what
7015 * we need. Just remember if we modified
7016 * mtime and send the notify ourselves.
7018 if (null_timespec(ft.mtime)) {
7019 modify_mtime = false;
7022 status = smb_set_file_time(conn,
7023 fsp,
7024 smb_fname,
7025 &ft,
7026 false);
7027 if (modify_mtime) {
7028 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7029 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7031 return status;
7034 /****************************************************************************
7035 Deal with SMB_SET_FILE_UNIX_INFO2.
7036 ****************************************************************************/
7038 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7039 struct smb_request *req,
7040 const char *pdata,
7041 int total_data,
7042 files_struct *fsp,
7043 const struct smb_filename *smb_fname)
7045 NTSTATUS status;
7046 uint32 smb_fflags;
7047 uint32 smb_fmask;
7049 if (total_data < 116) {
7050 return NT_STATUS_INVALID_PARAMETER;
7053 /* Start by setting all the fields that are common between UNIX_BASIC
7054 * and UNIX_INFO2.
7056 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7057 fsp, smb_fname);
7058 if (!NT_STATUS_IS_OK(status)) {
7059 return status;
7062 smb_fflags = IVAL(pdata, 108);
7063 smb_fmask = IVAL(pdata, 112);
7065 /* NB: We should only attempt to alter the file flags if the client
7066 * sends a non-zero mask.
7068 if (smb_fmask != 0) {
7069 int stat_fflags = 0;
7071 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7072 smb_fmask, &stat_fflags)) {
7073 /* Client asked to alter a flag we don't understand. */
7074 return NT_STATUS_INVALID_PARAMETER;
7077 if (fsp && fsp->fh->fd != -1) {
7078 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7079 return NT_STATUS_NOT_SUPPORTED;
7080 } else {
7081 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7082 stat_fflags) != 0) {
7083 return map_nt_error_from_unix(errno);
7088 /* XXX: need to add support for changing the create_time here. You
7089 * can do this for paths on Darwin with setattrlist(2). The right way
7090 * to hook this up is probably by extending the VFS utimes interface.
7093 return NT_STATUS_OK;
7096 /****************************************************************************
7097 Create a directory with POSIX semantics.
7098 ****************************************************************************/
7100 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7101 struct smb_request *req,
7102 char **ppdata,
7103 int total_data,
7104 struct smb_filename *smb_fname,
7105 int *pdata_return_size)
7107 NTSTATUS status = NT_STATUS_OK;
7108 uint32 raw_unixmode = 0;
7109 uint32 mod_unixmode = 0;
7110 mode_t unixmode = (mode_t)0;
7111 files_struct *fsp = NULL;
7112 uint16 info_level_return = 0;
7113 int info;
7114 char *pdata = *ppdata;
7116 if (total_data < 18) {
7117 return NT_STATUS_INVALID_PARAMETER;
7120 raw_unixmode = IVAL(pdata,8);
7121 /* Next 4 bytes are not yet defined. */
7123 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7124 PERM_NEW_DIR, &unixmode);
7125 if (!NT_STATUS_IS_OK(status)) {
7126 return status;
7129 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7131 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7132 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7134 status = SMB_VFS_CREATE_FILE(
7135 conn, /* conn */
7136 req, /* req */
7137 0, /* root_dir_fid */
7138 smb_fname, /* fname */
7139 FILE_READ_ATTRIBUTES, /* access_mask */
7140 FILE_SHARE_NONE, /* share_access */
7141 FILE_CREATE, /* create_disposition*/
7142 FILE_DIRECTORY_FILE, /* create_options */
7143 mod_unixmode, /* file_attributes */
7144 0, /* oplock_request */
7145 0, /* allocation_size */
7146 0, /* private_flags */
7147 NULL, /* sd */
7148 NULL, /* ea_list */
7149 &fsp, /* result */
7150 &info); /* pinfo */
7152 if (NT_STATUS_IS_OK(status)) {
7153 close_file(req, fsp, NORMAL_CLOSE);
7156 info_level_return = SVAL(pdata,16);
7158 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7159 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7160 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7161 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7162 } else {
7163 *pdata_return_size = 12;
7166 /* Realloc the data size */
7167 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7168 if (*ppdata == NULL) {
7169 *pdata_return_size = 0;
7170 return NT_STATUS_NO_MEMORY;
7172 pdata = *ppdata;
7174 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7175 SSVAL(pdata,2,0); /* No fnum. */
7176 SIVAL(pdata,4,info); /* Was directory created. */
7178 switch (info_level_return) {
7179 case SMB_QUERY_FILE_UNIX_BASIC:
7180 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7181 SSVAL(pdata,10,0); /* Padding. */
7182 store_file_unix_basic(conn, pdata + 12, fsp,
7183 &smb_fname->st);
7184 break;
7185 case SMB_QUERY_FILE_UNIX_INFO2:
7186 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7187 SSVAL(pdata,10,0); /* Padding. */
7188 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7189 &smb_fname->st);
7190 break;
7191 default:
7192 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7193 SSVAL(pdata,10,0); /* Padding. */
7194 break;
7197 return status;
7200 /****************************************************************************
7201 Open/Create a file with POSIX semantics.
7202 ****************************************************************************/
7204 static NTSTATUS smb_posix_open(connection_struct *conn,
7205 struct smb_request *req,
7206 char **ppdata,
7207 int total_data,
7208 struct smb_filename *smb_fname,
7209 int *pdata_return_size)
7211 bool extended_oplock_granted = False;
7212 char *pdata = *ppdata;
7213 uint32 flags = 0;
7214 uint32 wire_open_mode = 0;
7215 uint32 raw_unixmode = 0;
7216 uint32 mod_unixmode = 0;
7217 uint32 create_disp = 0;
7218 uint32 access_mask = 0;
7219 uint32 create_options = 0;
7220 NTSTATUS status = NT_STATUS_OK;
7221 mode_t unixmode = (mode_t)0;
7222 files_struct *fsp = NULL;
7223 int oplock_request = 0;
7224 int info = 0;
7225 uint16 info_level_return = 0;
7227 if (total_data < 18) {
7228 return NT_STATUS_INVALID_PARAMETER;
7231 flags = IVAL(pdata,0);
7232 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7233 if (oplock_request) {
7234 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7237 wire_open_mode = IVAL(pdata,4);
7239 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7240 return smb_posix_mkdir(conn, req,
7241 ppdata,
7242 total_data,
7243 smb_fname,
7244 pdata_return_size);
7247 switch (wire_open_mode & SMB_ACCMODE) {
7248 case SMB_O_RDONLY:
7249 access_mask = FILE_READ_DATA;
7250 break;
7251 case SMB_O_WRONLY:
7252 access_mask = FILE_WRITE_DATA;
7253 break;
7254 case SMB_O_RDWR:
7255 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7256 break;
7257 default:
7258 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7259 (unsigned int)wire_open_mode ));
7260 return NT_STATUS_INVALID_PARAMETER;
7263 wire_open_mode &= ~SMB_ACCMODE;
7265 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7266 create_disp = FILE_CREATE;
7267 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7268 create_disp = FILE_OVERWRITE_IF;
7269 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7270 create_disp = FILE_OPEN_IF;
7271 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7272 create_disp = FILE_OPEN;
7273 } else {
7274 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7275 (unsigned int)wire_open_mode ));
7276 return NT_STATUS_INVALID_PARAMETER;
7279 raw_unixmode = IVAL(pdata,8);
7280 /* Next 4 bytes are not yet defined. */
7282 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7283 (VALID_STAT(smb_fname->st) ?
7284 PERM_EXISTING_FILE : PERM_NEW_FILE),
7285 &unixmode);
7287 if (!NT_STATUS_IS_OK(status)) {
7288 return status;
7291 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7293 if (wire_open_mode & SMB_O_SYNC) {
7294 create_options |= FILE_WRITE_THROUGH;
7296 if (wire_open_mode & SMB_O_APPEND) {
7297 access_mask |= FILE_APPEND_DATA;
7299 if (wire_open_mode & SMB_O_DIRECT) {
7300 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7303 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7304 smb_fname_str_dbg(smb_fname),
7305 (unsigned int)wire_open_mode,
7306 (unsigned int)unixmode ));
7308 status = SMB_VFS_CREATE_FILE(
7309 conn, /* conn */
7310 req, /* req */
7311 0, /* root_dir_fid */
7312 smb_fname, /* fname */
7313 access_mask, /* access_mask */
7314 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7315 FILE_SHARE_DELETE),
7316 create_disp, /* create_disposition*/
7317 FILE_NON_DIRECTORY_FILE, /* create_options */
7318 mod_unixmode, /* file_attributes */
7319 oplock_request, /* oplock_request */
7320 0, /* allocation_size */
7321 0, /* private_flags */
7322 NULL, /* sd */
7323 NULL, /* ea_list */
7324 &fsp, /* result */
7325 &info); /* pinfo */
7327 if (!NT_STATUS_IS_OK(status)) {
7328 return status;
7331 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7332 extended_oplock_granted = True;
7335 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7336 extended_oplock_granted = True;
7339 info_level_return = SVAL(pdata,16);
7341 /* Allocate the correct return size. */
7343 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7344 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7345 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7346 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7347 } else {
7348 *pdata_return_size = 12;
7351 /* Realloc the data size */
7352 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7353 if (*ppdata == NULL) {
7354 close_file(req, fsp, ERROR_CLOSE);
7355 *pdata_return_size = 0;
7356 return NT_STATUS_NO_MEMORY;
7358 pdata = *ppdata;
7360 if (extended_oplock_granted) {
7361 if (flags & REQUEST_BATCH_OPLOCK) {
7362 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7363 } else {
7364 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7366 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7367 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7368 } else {
7369 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7372 SSVAL(pdata,2,fsp->fnum);
7373 SIVAL(pdata,4,info); /* Was file created etc. */
7375 switch (info_level_return) {
7376 case SMB_QUERY_FILE_UNIX_BASIC:
7377 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7378 SSVAL(pdata,10,0); /* padding. */
7379 store_file_unix_basic(conn, pdata + 12, fsp,
7380 &smb_fname->st);
7381 break;
7382 case SMB_QUERY_FILE_UNIX_INFO2:
7383 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7384 SSVAL(pdata,10,0); /* padding. */
7385 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7386 &smb_fname->st);
7387 break;
7388 default:
7389 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7390 SSVAL(pdata,10,0); /* padding. */
7391 break;
7393 return NT_STATUS_OK;
7396 /****************************************************************************
7397 Delete a file with POSIX semantics.
7398 ****************************************************************************/
7400 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7401 struct smb_request *req,
7402 const char *pdata,
7403 int total_data,
7404 struct smb_filename *smb_fname)
7406 NTSTATUS status = NT_STATUS_OK;
7407 files_struct *fsp = NULL;
7408 uint16 flags = 0;
7409 char del = 1;
7410 int info = 0;
7411 int create_options = 0;
7412 int i;
7413 struct share_mode_lock *lck = NULL;
7415 if (total_data < 2) {
7416 return NT_STATUS_INVALID_PARAMETER;
7419 flags = SVAL(pdata,0);
7421 if (!VALID_STAT(smb_fname->st)) {
7422 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7425 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7426 !VALID_STAT_OF_DIR(smb_fname->st)) {
7427 return NT_STATUS_NOT_A_DIRECTORY;
7430 DEBUG(10,("smb_posix_unlink: %s %s\n",
7431 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7432 smb_fname_str_dbg(smb_fname)));
7434 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7435 create_options |= FILE_DIRECTORY_FILE;
7438 status = SMB_VFS_CREATE_FILE(
7439 conn, /* conn */
7440 req, /* req */
7441 0, /* root_dir_fid */
7442 smb_fname, /* fname */
7443 DELETE_ACCESS, /* access_mask */
7444 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7445 FILE_SHARE_DELETE),
7446 FILE_OPEN, /* create_disposition*/
7447 create_options, /* create_options */
7448 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7449 0, /* oplock_request */
7450 0, /* allocation_size */
7451 0, /* private_flags */
7452 NULL, /* sd */
7453 NULL, /* ea_list */
7454 &fsp, /* result */
7455 &info); /* pinfo */
7457 if (!NT_STATUS_IS_OK(status)) {
7458 return status;
7462 * Don't lie to client. If we can't really delete due to
7463 * non-POSIX opens return SHARING_VIOLATION.
7466 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7467 NULL);
7468 if (lck == NULL) {
7469 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7470 "lock for file %s\n", fsp_str_dbg(fsp)));
7471 close_file(req, fsp, NORMAL_CLOSE);
7472 return NT_STATUS_INVALID_PARAMETER;
7476 * See if others still have the file open. If this is the case, then
7477 * don't delete. If all opens are POSIX delete we can set the delete
7478 * on close disposition.
7480 for (i=0; i<lck->num_share_modes; i++) {
7481 struct share_mode_entry *e = &lck->share_modes[i];
7482 if (is_valid_share_mode_entry(e)) {
7483 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7484 continue;
7486 /* Fail with sharing violation. */
7487 close_file(req, fsp, NORMAL_CLOSE);
7488 TALLOC_FREE(lck);
7489 return NT_STATUS_SHARING_VIOLATION;
7494 * Set the delete on close.
7496 status = smb_set_file_disposition_info(conn,
7497 &del,
7499 fsp,
7500 smb_fname);
7502 if (!NT_STATUS_IS_OK(status)) {
7503 close_file(req, fsp, NORMAL_CLOSE);
7504 TALLOC_FREE(lck);
7505 return status;
7507 TALLOC_FREE(lck);
7508 return close_file(req, fsp, NORMAL_CLOSE);
7511 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7512 struct smb_request *req,
7513 TALLOC_CTX *mem_ctx,
7514 uint16_t info_level,
7515 files_struct *fsp,
7516 struct smb_filename *smb_fname,
7517 char **ppdata, int total_data,
7518 int *ret_data_size)
7520 char *pdata = *ppdata;
7521 NTSTATUS status = NT_STATUS_OK;
7522 int data_return_size = 0;
7524 *ret_data_size = 0;
7526 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7527 return NT_STATUS_INVALID_LEVEL;
7530 if (!CAN_WRITE(conn)) {
7531 /* Allow POSIX opens. The open path will deny
7532 * any non-readonly opens. */
7533 if (info_level != SMB_POSIX_PATH_OPEN) {
7534 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7538 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7539 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7540 fsp ? fsp->fnum : -1, info_level, total_data));
7542 switch (info_level) {
7544 case SMB_INFO_STANDARD:
7546 status = smb_set_info_standard(conn,
7547 pdata,
7548 total_data,
7549 fsp,
7550 smb_fname);
7551 break;
7554 case SMB_INFO_SET_EA:
7556 status = smb_info_set_ea(conn,
7557 pdata,
7558 total_data,
7559 fsp,
7560 smb_fname);
7561 break;
7564 case SMB_SET_FILE_BASIC_INFO:
7565 case SMB_FILE_BASIC_INFORMATION:
7567 status = smb_set_file_basic_info(conn,
7568 pdata,
7569 total_data,
7570 fsp,
7571 smb_fname);
7572 break;
7575 case SMB_FILE_ALLOCATION_INFORMATION:
7576 case SMB_SET_FILE_ALLOCATION_INFO:
7578 status = smb_set_file_allocation_info(conn, req,
7579 pdata,
7580 total_data,
7581 fsp,
7582 smb_fname);
7583 break;
7586 case SMB_FILE_END_OF_FILE_INFORMATION:
7587 case SMB_SET_FILE_END_OF_FILE_INFO:
7590 * XP/Win7 both fail after the createfile with
7591 * SMB_SET_FILE_END_OF_FILE_INFO but not
7592 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7593 * The level is known here, so pass it down
7594 * appropriately.
7596 bool should_fail =
7597 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7599 status = smb_set_file_end_of_file_info(conn, req,
7600 pdata,
7601 total_data,
7602 fsp,
7603 smb_fname,
7604 should_fail);
7605 break;
7608 case SMB_FILE_DISPOSITION_INFORMATION:
7609 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7611 #if 0
7612 /* JRA - We used to just ignore this on a path ?
7613 * Shouldn't this be invalid level on a pathname
7614 * based call ?
7616 if (tran_call != TRANSACT2_SETFILEINFO) {
7617 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7619 #endif
7620 status = smb_set_file_disposition_info(conn,
7621 pdata,
7622 total_data,
7623 fsp,
7624 smb_fname);
7625 break;
7628 case SMB_FILE_POSITION_INFORMATION:
7630 status = smb_file_position_information(conn,
7631 pdata,
7632 total_data,
7633 fsp);
7634 break;
7637 case SMB_FILE_FULL_EA_INFORMATION:
7639 status = smb_set_file_full_ea_info(conn,
7640 pdata,
7641 total_data,
7642 fsp);
7643 break;
7646 /* From tridge Samba4 :
7647 * MODE_INFORMATION in setfileinfo (I have no
7648 * idea what "mode information" on a file is - it takes a value of 0,
7649 * 2, 4 or 6. What could it be?).
7652 case SMB_FILE_MODE_INFORMATION:
7654 status = smb_file_mode_information(conn,
7655 pdata,
7656 total_data);
7657 break;
7661 * CIFS UNIX extensions.
7664 case SMB_SET_FILE_UNIX_BASIC:
7666 status = smb_set_file_unix_basic(conn, req,
7667 pdata,
7668 total_data,
7669 fsp,
7670 smb_fname);
7671 break;
7674 case SMB_SET_FILE_UNIX_INFO2:
7676 status = smb_set_file_unix_info2(conn, req,
7677 pdata,
7678 total_data,
7679 fsp,
7680 smb_fname);
7681 break;
7684 case SMB_SET_FILE_UNIX_LINK:
7686 if (fsp) {
7687 /* We must have a pathname for this. */
7688 return NT_STATUS_INVALID_LEVEL;
7690 status = smb_set_file_unix_link(conn, req, pdata,
7691 total_data, smb_fname);
7692 break;
7695 case SMB_SET_FILE_UNIX_HLINK:
7697 if (fsp) {
7698 /* We must have a pathname for this. */
7699 return NT_STATUS_INVALID_LEVEL;
7701 status = smb_set_file_unix_hlink(conn, req,
7702 pdata, total_data,
7703 smb_fname);
7704 break;
7707 case SMB_FILE_RENAME_INFORMATION:
7709 status = smb_file_rename_information(conn, req,
7710 pdata, total_data,
7711 fsp, smb_fname);
7712 break;
7715 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7717 /* SMB2 rename information. */
7718 status = smb2_file_rename_information(conn, req,
7719 pdata, total_data,
7720 fsp, smb_fname);
7721 break;
7724 case SMB_FILE_LINK_INFORMATION:
7726 status = smb_file_link_information(conn, req,
7727 pdata, total_data,
7728 fsp, smb_fname);
7729 break;
7732 #if defined(HAVE_POSIX_ACLS)
7733 case SMB_SET_POSIX_ACL:
7735 status = smb_set_posix_acl(conn,
7736 pdata,
7737 total_data,
7738 fsp,
7739 smb_fname);
7740 break;
7742 #endif
7744 case SMB_SET_POSIX_LOCK:
7746 if (!fsp) {
7747 return NT_STATUS_INVALID_LEVEL;
7749 status = smb_set_posix_lock(conn, req,
7750 pdata, total_data, fsp);
7751 break;
7754 case SMB_POSIX_PATH_OPEN:
7756 if (fsp) {
7757 /* We must have a pathname for this. */
7758 return NT_STATUS_INVALID_LEVEL;
7761 status = smb_posix_open(conn, req,
7762 ppdata,
7763 total_data,
7764 smb_fname,
7765 &data_return_size);
7766 break;
7769 case SMB_POSIX_PATH_UNLINK:
7771 if (fsp) {
7772 /* We must have a pathname for this. */
7773 return NT_STATUS_INVALID_LEVEL;
7776 status = smb_posix_unlink(conn, req,
7777 pdata,
7778 total_data,
7779 smb_fname);
7780 break;
7783 default:
7784 return NT_STATUS_INVALID_LEVEL;
7787 if (!NT_STATUS_IS_OK(status)) {
7788 return status;
7791 *ret_data_size = data_return_size;
7792 return NT_STATUS_OK;
7795 /****************************************************************************
7796 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7797 ****************************************************************************/
7799 static void call_trans2setfilepathinfo(connection_struct *conn,
7800 struct smb_request *req,
7801 unsigned int tran_call,
7802 char **pparams, int total_params,
7803 char **ppdata, int total_data,
7804 unsigned int max_data_bytes)
7806 char *params = *pparams;
7807 char *pdata = *ppdata;
7808 uint16 info_level;
7809 struct smb_filename *smb_fname = NULL;
7810 files_struct *fsp = NULL;
7811 NTSTATUS status = NT_STATUS_OK;
7812 int data_return_size = 0;
7814 if (!params) {
7815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7816 return;
7819 if (tran_call == TRANSACT2_SETFILEINFO) {
7820 if (total_params < 4) {
7821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7822 return;
7825 fsp = file_fsp(req, SVAL(params,0));
7826 /* Basic check for non-null fsp. */
7827 if (!check_fsp_open(conn, req, fsp)) {
7828 return;
7830 info_level = SVAL(params,2);
7832 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7833 &smb_fname);
7834 if (!NT_STATUS_IS_OK(status)) {
7835 reply_nterror(req, status);
7836 return;
7839 if(fsp->is_directory || fsp->fh->fd == -1) {
7841 * This is actually a SETFILEINFO on a directory
7842 * handle (returned from an NT SMB). NT5.0 seems
7843 * to do this call. JRA.
7845 if (INFO_LEVEL_IS_UNIX(info_level)) {
7846 /* Always do lstat for UNIX calls. */
7847 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7848 DEBUG(3,("call_trans2setfilepathinfo: "
7849 "SMB_VFS_LSTAT of %s failed "
7850 "(%s)\n",
7851 smb_fname_str_dbg(smb_fname),
7852 strerror(errno)));
7853 reply_nterror(req, map_nt_error_from_unix(errno));
7854 return;
7856 } else {
7857 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7858 DEBUG(3,("call_trans2setfilepathinfo: "
7859 "fileinfo of %s failed (%s)\n",
7860 smb_fname_str_dbg(smb_fname),
7861 strerror(errno)));
7862 reply_nterror(req, map_nt_error_from_unix(errno));
7863 return;
7866 } else if (fsp->print_file) {
7868 * Doing a DELETE_ON_CLOSE should cancel a print job.
7870 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7871 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7873 DEBUG(3,("call_trans2setfilepathinfo: "
7874 "Cancelling print job (%s)\n",
7875 fsp_str_dbg(fsp)));
7877 SSVAL(params,0,0);
7878 send_trans2_replies(conn, req, params, 2,
7879 *ppdata, 0,
7880 max_data_bytes);
7881 return;
7882 } else {
7883 reply_nterror(req,
7884 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7885 return;
7887 } else {
7889 * Original code - this is an open file.
7891 if (!check_fsp(conn, req, fsp)) {
7892 return;
7895 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7896 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7897 "of fnum %d failed (%s)\n", fsp->fnum,
7898 strerror(errno)));
7899 reply_nterror(req, map_nt_error_from_unix(errno));
7900 return;
7903 } else {
7904 char *fname = NULL;
7906 /* set path info */
7907 if (total_params < 7) {
7908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7909 return;
7912 info_level = SVAL(params,0);
7913 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7914 total_params - 6, STR_TERMINATE,
7915 &status);
7916 if (!NT_STATUS_IS_OK(status)) {
7917 reply_nterror(req, status);
7918 return;
7921 status = filename_convert(req, conn,
7922 req->flags2 & FLAGS2_DFS_PATHNAMES,
7923 fname,
7925 NULL,
7926 &smb_fname);
7927 if (!NT_STATUS_IS_OK(status)) {
7928 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7929 reply_botherror(req,
7930 NT_STATUS_PATH_NOT_COVERED,
7931 ERRSRV, ERRbadpath);
7932 return;
7934 reply_nterror(req, status);
7935 return;
7938 if (INFO_LEVEL_IS_UNIX(info_level)) {
7940 * For CIFS UNIX extensions the target name may not exist.
7943 /* Always do lstat for UNIX calls. */
7944 SMB_VFS_LSTAT(conn, smb_fname);
7946 } else if (!VALID_STAT(smb_fname->st) &&
7947 SMB_VFS_STAT(conn, smb_fname)) {
7948 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7949 "%s failed (%s)\n",
7950 smb_fname_str_dbg(smb_fname),
7951 strerror(errno)));
7952 reply_nterror(req, map_nt_error_from_unix(errno));
7953 return;
7957 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7958 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7959 fsp ? fsp->fnum : -1, info_level,total_data));
7961 /* Realloc the parameter size */
7962 *pparams = (char *)SMB_REALLOC(*pparams,2);
7963 if (*pparams == NULL) {
7964 reply_nterror(req, NT_STATUS_NO_MEMORY);
7965 return;
7967 params = *pparams;
7969 SSVAL(params,0,0);
7971 status = smbd_do_setfilepathinfo(conn, req, req,
7972 info_level,
7973 fsp,
7974 smb_fname,
7975 ppdata, total_data,
7976 &data_return_size);
7977 if (!NT_STATUS_IS_OK(status)) {
7978 if (open_was_deferred(req->mid)) {
7979 /* We have re-scheduled this call. */
7980 return;
7982 if (blocking_lock_was_deferred_smb1(req->mid)) {
7983 /* We have re-scheduled this call. */
7984 return;
7986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7987 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7988 ERRSRV, ERRbadpath);
7989 return;
7991 if (info_level == SMB_POSIX_PATH_OPEN) {
7992 reply_openerror(req, status);
7993 return;
7996 reply_nterror(req, status);
7997 return;
8000 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8001 max_data_bytes);
8003 return;
8006 /****************************************************************************
8007 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8008 ****************************************************************************/
8010 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8011 char **pparams, int total_params,
8012 char **ppdata, int total_data,
8013 unsigned int max_data_bytes)
8015 struct smb_filename *smb_dname = NULL;
8016 char *params = *pparams;
8017 char *pdata = *ppdata;
8018 char *directory = NULL;
8019 NTSTATUS status = NT_STATUS_OK;
8020 struct ea_list *ea_list = NULL;
8021 TALLOC_CTX *ctx = talloc_tos();
8023 if (!CAN_WRITE(conn)) {
8024 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8025 return;
8028 if (total_params < 5) {
8029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8030 return;
8033 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8034 total_params - 4, STR_TERMINATE,
8035 &status);
8036 if (!NT_STATUS_IS_OK(status)) {
8037 reply_nterror(req, status);
8038 return;
8041 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8043 status = filename_convert(ctx,
8044 conn,
8045 req->flags2 & FLAGS2_DFS_PATHNAMES,
8046 directory,
8048 NULL,
8049 &smb_dname);
8051 if (!NT_STATUS_IS_OK(status)) {
8052 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8053 reply_botherror(req,
8054 NT_STATUS_PATH_NOT_COVERED,
8055 ERRSRV, ERRbadpath);
8056 return;
8058 reply_nterror(req, status);
8059 return;
8063 * OS/2 workplace shell seems to send SET_EA requests of "null"
8064 * length (4 bytes containing IVAL 4).
8065 * They seem to have no effect. Bug #3212. JRA.
8068 if (total_data && (total_data != 4)) {
8069 /* Any data in this call is an EA list. */
8070 if (total_data < 10) {
8071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8072 goto out;
8075 if (IVAL(pdata,0) > total_data) {
8076 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8077 IVAL(pdata,0), (unsigned int)total_data));
8078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8079 goto out;
8082 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8083 total_data - 4);
8084 if (!ea_list) {
8085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8086 goto out;
8089 if (!lp_ea_support(SNUM(conn))) {
8090 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8091 goto out;
8094 /* If total_data == 4 Windows doesn't care what values
8095 * are placed in that field, it just ignores them.
8096 * The System i QNTC IBM SMB client puts bad values here,
8097 * so ignore them. */
8099 status = create_directory(conn, req, smb_dname);
8101 if (!NT_STATUS_IS_OK(status)) {
8102 reply_nterror(req, status);
8103 goto out;
8106 /* Try and set any given EA. */
8107 if (ea_list) {
8108 status = set_ea(conn, NULL, smb_dname, ea_list);
8109 if (!NT_STATUS_IS_OK(status)) {
8110 reply_nterror(req, status);
8111 goto out;
8115 /* Realloc the parameter and data sizes */
8116 *pparams = (char *)SMB_REALLOC(*pparams,2);
8117 if(*pparams == NULL) {
8118 reply_nterror(req, NT_STATUS_NO_MEMORY);
8119 goto out;
8121 params = *pparams;
8123 SSVAL(params,0,0);
8125 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8127 out:
8128 TALLOC_FREE(smb_dname);
8129 return;
8132 /****************************************************************************
8133 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8134 We don't actually do this - we just send a null response.
8135 ****************************************************************************/
8137 static void call_trans2findnotifyfirst(connection_struct *conn,
8138 struct smb_request *req,
8139 char **pparams, int total_params,
8140 char **ppdata, int total_data,
8141 unsigned int max_data_bytes)
8143 char *params = *pparams;
8144 uint16 info_level;
8146 if (total_params < 6) {
8147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8148 return;
8151 info_level = SVAL(params,4);
8152 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8154 switch (info_level) {
8155 case 1:
8156 case 2:
8157 break;
8158 default:
8159 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8160 return;
8163 /* Realloc the parameter and data sizes */
8164 *pparams = (char *)SMB_REALLOC(*pparams,6);
8165 if (*pparams == NULL) {
8166 reply_nterror(req, NT_STATUS_NO_MEMORY);
8167 return;
8169 params = *pparams;
8171 SSVAL(params,0,fnf_handle);
8172 SSVAL(params,2,0); /* No changes */
8173 SSVAL(params,4,0); /* No EA errors */
8175 fnf_handle++;
8177 if(fnf_handle == 0)
8178 fnf_handle = 257;
8180 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8182 return;
8185 /****************************************************************************
8186 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8187 changes). Currently this does nothing.
8188 ****************************************************************************/
8190 static void call_trans2findnotifynext(connection_struct *conn,
8191 struct smb_request *req,
8192 char **pparams, int total_params,
8193 char **ppdata, int total_data,
8194 unsigned int max_data_bytes)
8196 char *params = *pparams;
8198 DEBUG(3,("call_trans2findnotifynext\n"));
8200 /* Realloc the parameter and data sizes */
8201 *pparams = (char *)SMB_REALLOC(*pparams,4);
8202 if (*pparams == NULL) {
8203 reply_nterror(req, NT_STATUS_NO_MEMORY);
8204 return;
8206 params = *pparams;
8208 SSVAL(params,0,0); /* No changes */
8209 SSVAL(params,2,0); /* No EA errors */
8211 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8213 return;
8216 /****************************************************************************
8217 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8218 ****************************************************************************/
8220 static void call_trans2getdfsreferral(connection_struct *conn,
8221 struct smb_request *req,
8222 char **pparams, int total_params,
8223 char **ppdata, int total_data,
8224 unsigned int max_data_bytes)
8226 char *params = *pparams;
8227 char *pathname = NULL;
8228 int reply_size = 0;
8229 int max_referral_level;
8230 NTSTATUS status = NT_STATUS_OK;
8231 TALLOC_CTX *ctx = talloc_tos();
8233 DEBUG(10,("call_trans2getdfsreferral\n"));
8235 if (total_params < 3) {
8236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8237 return;
8240 max_referral_level = SVAL(params,0);
8242 if(!lp_host_msdfs()) {
8243 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8244 return;
8247 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8248 total_params - 2, STR_TERMINATE);
8249 if (!pathname) {
8250 reply_nterror(req, NT_STATUS_NOT_FOUND);
8251 return;
8253 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8254 ppdata,&status)) < 0) {
8255 reply_nterror(req, status);
8256 return;
8259 SSVAL(req->inbuf, smb_flg2,
8260 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8261 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8263 return;
8266 #define LMCAT_SPL 0x53
8267 #define LMFUNC_GETJOBID 0x60
8269 /****************************************************************************
8270 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8271 ****************************************************************************/
8273 static void call_trans2ioctl(connection_struct *conn,
8274 struct smb_request *req,
8275 char **pparams, int total_params,
8276 char **ppdata, int total_data,
8277 unsigned int max_data_bytes)
8279 char *pdata = *ppdata;
8280 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8282 /* check for an invalid fid before proceeding */
8284 if (!fsp) {
8285 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8286 return;
8289 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8290 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8291 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8292 if (*ppdata == NULL) {
8293 reply_nterror(req, NT_STATUS_NO_MEMORY);
8294 return;
8296 pdata = *ppdata;
8298 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8299 CAN ACCEPT THIS IN UNICODE. JRA. */
8301 /* Job number */
8302 if (fsp->print_file) {
8303 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8304 } else {
8305 SSVAL(pdata, 0, 0);
8307 srvstr_push(pdata, req->flags2, pdata + 2,
8308 global_myname(), 15,
8309 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8310 srvstr_push(pdata, req->flags2, pdata+18,
8311 lp_servicename(SNUM(conn)), 13,
8312 STR_ASCII|STR_TERMINATE); /* Service name */
8313 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8314 max_data_bytes);
8315 return;
8318 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8319 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8322 /****************************************************************************
8323 Reply to a SMBfindclose (stop trans2 directory search).
8324 ****************************************************************************/
8326 void reply_findclose(struct smb_request *req)
8328 int dptr_num;
8329 struct smbd_server_connection *sconn = smbd_server_conn;
8331 START_PROFILE(SMBfindclose);
8333 if (req->wct < 1) {
8334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8335 END_PROFILE(SMBfindclose);
8336 return;
8339 dptr_num = SVALS(req->vwv+0, 0);
8341 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8343 dptr_close(sconn, &dptr_num);
8345 reply_outbuf(req, 0, 0);
8347 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8349 END_PROFILE(SMBfindclose);
8350 return;
8353 /****************************************************************************
8354 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8355 ****************************************************************************/
8357 void reply_findnclose(struct smb_request *req)
8359 int dptr_num;
8361 START_PROFILE(SMBfindnclose);
8363 if (req->wct < 1) {
8364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8365 END_PROFILE(SMBfindnclose);
8366 return;
8369 dptr_num = SVAL(req->vwv+0, 0);
8371 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8373 /* We never give out valid handles for a
8374 findnotifyfirst - so any dptr_num is ok here.
8375 Just ignore it. */
8377 reply_outbuf(req, 0, 0);
8379 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8381 END_PROFILE(SMBfindnclose);
8382 return;
8385 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8386 struct trans_state *state)
8388 if (get_Protocol() >= PROTOCOL_NT1) {
8389 req->flags2 |= 0x40; /* IS_LONG_NAME */
8390 SSVAL(req->inbuf,smb_flg2,req->flags2);
8393 if (conn->encrypt_level == Required && !req->encrypted) {
8394 if (state->call != TRANSACT2_QFSINFO &&
8395 state->call != TRANSACT2_SETFSINFO) {
8396 DEBUG(0,("handle_trans2: encryption required "
8397 "with call 0x%x\n",
8398 (unsigned int)state->call));
8399 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8400 return;
8404 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8406 /* Now we must call the relevant TRANS2 function */
8407 switch(state->call) {
8408 case TRANSACT2_OPEN:
8410 START_PROFILE(Trans2_open);
8411 call_trans2open(conn, req,
8412 &state->param, state->total_param,
8413 &state->data, state->total_data,
8414 state->max_data_return);
8415 END_PROFILE(Trans2_open);
8416 break;
8419 case TRANSACT2_FINDFIRST:
8421 START_PROFILE(Trans2_findfirst);
8422 call_trans2findfirst(conn, req,
8423 &state->param, state->total_param,
8424 &state->data, state->total_data,
8425 state->max_data_return);
8426 END_PROFILE(Trans2_findfirst);
8427 break;
8430 case TRANSACT2_FINDNEXT:
8432 START_PROFILE(Trans2_findnext);
8433 call_trans2findnext(conn, req,
8434 &state->param, state->total_param,
8435 &state->data, state->total_data,
8436 state->max_data_return);
8437 END_PROFILE(Trans2_findnext);
8438 break;
8441 case TRANSACT2_QFSINFO:
8443 START_PROFILE(Trans2_qfsinfo);
8444 call_trans2qfsinfo(conn, req,
8445 &state->param, state->total_param,
8446 &state->data, state->total_data,
8447 state->max_data_return);
8448 END_PROFILE(Trans2_qfsinfo);
8449 break;
8452 case TRANSACT2_SETFSINFO:
8454 START_PROFILE(Trans2_setfsinfo);
8455 call_trans2setfsinfo(conn, req,
8456 &state->param, state->total_param,
8457 &state->data, state->total_data,
8458 state->max_data_return);
8459 END_PROFILE(Trans2_setfsinfo);
8460 break;
8463 case TRANSACT2_QPATHINFO:
8464 case TRANSACT2_QFILEINFO:
8466 START_PROFILE(Trans2_qpathinfo);
8467 call_trans2qfilepathinfo(conn, req, state->call,
8468 &state->param, state->total_param,
8469 &state->data, state->total_data,
8470 state->max_data_return);
8471 END_PROFILE(Trans2_qpathinfo);
8472 break;
8475 case TRANSACT2_SETPATHINFO:
8476 case TRANSACT2_SETFILEINFO:
8478 START_PROFILE(Trans2_setpathinfo);
8479 call_trans2setfilepathinfo(conn, req, state->call,
8480 &state->param, state->total_param,
8481 &state->data, state->total_data,
8482 state->max_data_return);
8483 END_PROFILE(Trans2_setpathinfo);
8484 break;
8487 case TRANSACT2_FINDNOTIFYFIRST:
8489 START_PROFILE(Trans2_findnotifyfirst);
8490 call_trans2findnotifyfirst(conn, req,
8491 &state->param, state->total_param,
8492 &state->data, state->total_data,
8493 state->max_data_return);
8494 END_PROFILE(Trans2_findnotifyfirst);
8495 break;
8498 case TRANSACT2_FINDNOTIFYNEXT:
8500 START_PROFILE(Trans2_findnotifynext);
8501 call_trans2findnotifynext(conn, req,
8502 &state->param, state->total_param,
8503 &state->data, state->total_data,
8504 state->max_data_return);
8505 END_PROFILE(Trans2_findnotifynext);
8506 break;
8509 case TRANSACT2_MKDIR:
8511 START_PROFILE(Trans2_mkdir);
8512 call_trans2mkdir(conn, req,
8513 &state->param, state->total_param,
8514 &state->data, state->total_data,
8515 state->max_data_return);
8516 END_PROFILE(Trans2_mkdir);
8517 break;
8520 case TRANSACT2_GET_DFS_REFERRAL:
8522 START_PROFILE(Trans2_get_dfs_referral);
8523 call_trans2getdfsreferral(conn, req,
8524 &state->param, state->total_param,
8525 &state->data, state->total_data,
8526 state->max_data_return);
8527 END_PROFILE(Trans2_get_dfs_referral);
8528 break;
8531 case TRANSACT2_IOCTL:
8533 START_PROFILE(Trans2_ioctl);
8534 call_trans2ioctl(conn, req,
8535 &state->param, state->total_param,
8536 &state->data, state->total_data,
8537 state->max_data_return);
8538 END_PROFILE(Trans2_ioctl);
8539 break;
8542 default:
8543 /* Error in request */
8544 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8545 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8549 /****************************************************************************
8550 Reply to a SMBtrans2.
8551 ****************************************************************************/
8553 void reply_trans2(struct smb_request *req)
8555 connection_struct *conn = req->conn;
8556 unsigned int dsoff;
8557 unsigned int dscnt;
8558 unsigned int psoff;
8559 unsigned int pscnt;
8560 unsigned int tran_call;
8561 struct trans_state *state;
8562 NTSTATUS result;
8564 START_PROFILE(SMBtrans2);
8566 if (req->wct < 14) {
8567 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8568 END_PROFILE(SMBtrans2);
8569 return;
8572 dsoff = SVAL(req->vwv+12, 0);
8573 dscnt = SVAL(req->vwv+11, 0);
8574 psoff = SVAL(req->vwv+10, 0);
8575 pscnt = SVAL(req->vwv+9, 0);
8576 tran_call = SVAL(req->vwv+14, 0);
8578 result = allow_new_trans(conn->pending_trans, req->mid);
8579 if (!NT_STATUS_IS_OK(result)) {
8580 DEBUG(2, ("Got invalid trans2 request: %s\n",
8581 nt_errstr(result)));
8582 reply_nterror(req, result);
8583 END_PROFILE(SMBtrans2);
8584 return;
8587 if (IS_IPC(conn)) {
8588 switch (tran_call) {
8589 /* List the allowed trans2 calls on IPC$ */
8590 case TRANSACT2_OPEN:
8591 case TRANSACT2_GET_DFS_REFERRAL:
8592 case TRANSACT2_QFILEINFO:
8593 case TRANSACT2_QFSINFO:
8594 case TRANSACT2_SETFSINFO:
8595 break;
8596 default:
8597 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8598 END_PROFILE(SMBtrans2);
8599 return;
8603 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8604 DEBUG(0, ("talloc failed\n"));
8605 reply_nterror(req, NT_STATUS_NO_MEMORY);
8606 END_PROFILE(SMBtrans2);
8607 return;
8610 state->cmd = SMBtrans2;
8612 state->mid = req->mid;
8613 state->vuid = req->vuid;
8614 state->setup_count = SVAL(req->vwv+13, 0);
8615 state->setup = NULL;
8616 state->total_param = SVAL(req->vwv+0, 0);
8617 state->param = NULL;
8618 state->total_data = SVAL(req->vwv+1, 0);
8619 state->data = NULL;
8620 state->max_param_return = SVAL(req->vwv+2, 0);
8621 state->max_data_return = SVAL(req->vwv+3, 0);
8622 state->max_setup_return = SVAL(req->vwv+4, 0);
8623 state->close_on_completion = BITSETW(req->vwv+5, 0);
8624 state->one_way = BITSETW(req->vwv+5, 1);
8626 state->call = tran_call;
8628 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8629 is so as a sanity check */
8630 if (state->setup_count != 1) {
8632 * Need to have rc=0 for ioctl to get job id for OS/2.
8633 * Network printing will fail if function is not successful.
8634 * Similar function in reply.c will be used if protocol
8635 * is LANMAN1.0 instead of LM1.2X002.
8636 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8637 * outbuf doesn't have to be set(only job id is used).
8639 if ( (state->setup_count == 4)
8640 && (tran_call == TRANSACT2_IOCTL)
8641 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8642 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8643 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8644 } else {
8645 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8646 DEBUG(2,("Transaction is %d\n",tran_call));
8647 TALLOC_FREE(state);
8648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8649 END_PROFILE(SMBtrans2);
8650 return;
8654 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8655 goto bad_param;
8657 if (state->total_data) {
8659 if (trans_oob(state->total_data, 0, dscnt)
8660 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8661 goto bad_param;
8664 /* Can't use talloc here, the core routines do realloc on the
8665 * params and data. */
8666 state->data = (char *)SMB_MALLOC(state->total_data);
8667 if (state->data == NULL) {
8668 DEBUG(0,("reply_trans2: data malloc fail for %u "
8669 "bytes !\n", (unsigned int)state->total_data));
8670 TALLOC_FREE(state);
8671 reply_nterror(req, NT_STATUS_NO_MEMORY);
8672 END_PROFILE(SMBtrans2);
8673 return;
8676 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8679 if (state->total_param) {
8681 if (trans_oob(state->total_param, 0, pscnt)
8682 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8683 goto bad_param;
8686 /* Can't use talloc here, the core routines do realloc on the
8687 * params and data. */
8688 state->param = (char *)SMB_MALLOC(state->total_param);
8689 if (state->param == NULL) {
8690 DEBUG(0,("reply_trans: param malloc fail for %u "
8691 "bytes !\n", (unsigned int)state->total_param));
8692 SAFE_FREE(state->data);
8693 TALLOC_FREE(state);
8694 reply_nterror(req, NT_STATUS_NO_MEMORY);
8695 END_PROFILE(SMBtrans2);
8696 return;
8699 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8702 state->received_data = dscnt;
8703 state->received_param = pscnt;
8705 if ((state->received_param == state->total_param) &&
8706 (state->received_data == state->total_data)) {
8708 handle_trans2(conn, req, state);
8710 SAFE_FREE(state->data);
8711 SAFE_FREE(state->param);
8712 TALLOC_FREE(state);
8713 END_PROFILE(SMBtrans2);
8714 return;
8717 DLIST_ADD(conn->pending_trans, state);
8719 /* We need to send an interim response then receive the rest
8720 of the parameter/data bytes */
8721 reply_outbuf(req, 0, 0);
8722 show_msg((char *)req->outbuf);
8723 END_PROFILE(SMBtrans2);
8724 return;
8726 bad_param:
8728 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8729 SAFE_FREE(state->data);
8730 SAFE_FREE(state->param);
8731 TALLOC_FREE(state);
8732 END_PROFILE(SMBtrans2);
8733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8737 /****************************************************************************
8738 Reply to a SMBtranss2
8739 ****************************************************************************/
8741 void reply_transs2(struct smb_request *req)
8743 connection_struct *conn = req->conn;
8744 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8745 struct trans_state *state;
8747 START_PROFILE(SMBtranss2);
8749 show_msg((char *)req->inbuf);
8751 if (req->wct < 8) {
8752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8753 END_PROFILE(SMBtranss2);
8754 return;
8757 for (state = conn->pending_trans; state != NULL;
8758 state = state->next) {
8759 if (state->mid == req->mid) {
8760 break;
8764 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8766 END_PROFILE(SMBtranss2);
8767 return;
8770 /* Revise state->total_param and state->total_data in case they have
8771 changed downwards */
8773 if (SVAL(req->vwv+0, 0) < state->total_param)
8774 state->total_param = SVAL(req->vwv+0, 0);
8775 if (SVAL(req->vwv+1, 0) < state->total_data)
8776 state->total_data = SVAL(req->vwv+1, 0);
8778 pcnt = SVAL(req->vwv+2, 0);
8779 poff = SVAL(req->vwv+3, 0);
8780 pdisp = SVAL(req->vwv+4, 0);
8782 dcnt = SVAL(req->vwv+5, 0);
8783 doff = SVAL(req->vwv+6, 0);
8784 ddisp = SVAL(req->vwv+7, 0);
8786 state->received_param += pcnt;
8787 state->received_data += dcnt;
8789 if ((state->received_data > state->total_data) ||
8790 (state->received_param > state->total_param))
8791 goto bad_param;
8793 if (pcnt) {
8794 if (trans_oob(state->total_param, pdisp, pcnt)
8795 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8796 goto bad_param;
8798 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8801 if (dcnt) {
8802 if (trans_oob(state->total_data, ddisp, dcnt)
8803 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8804 goto bad_param;
8806 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8809 if ((state->received_param < state->total_param) ||
8810 (state->received_data < state->total_data)) {
8811 END_PROFILE(SMBtranss2);
8812 return;
8815 handle_trans2(conn, req, state);
8817 DLIST_REMOVE(conn->pending_trans, state);
8818 SAFE_FREE(state->data);
8819 SAFE_FREE(state->param);
8820 TALLOC_FREE(state);
8822 END_PROFILE(SMBtranss2);
8823 return;
8825 bad_param:
8827 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8828 DLIST_REMOVE(conn->pending_trans, state);
8829 SAFE_FREE(state->data);
8830 SAFE_FREE(state->param);
8831 TALLOC_FREE(state);
8832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8833 END_PROFILE(SMBtranss2);
8834 return;