WHATSNEW: Update changes.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob12a27b174b2dd3d6f685be24447f7b4085276f27
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"
31 #include "../librpc/gen_ndr/ndr_security.h"
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Create a 64 bit FileIndex. If the file is on the same device as
64 the root of the share, just return the 64-bit inode. If it isn't,
65 mangle as we used to do.
66 ********************************************************************/
68 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
70 uint64_t file_index;
71 if (conn->base_share_dev == psbuf->st_ex_dev) {
72 return (uint64_t)psbuf->st_ex_ino;
74 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
75 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
76 return file_index;
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static bool samba_private_attr_name(const char *unix_ea_name)
89 static const char * const prohibited_ea_names[] = {
90 SAMBA_POSIX_INHERITANCE_EA_NAME,
91 SAMBA_XATTR_DOS_ATTRIB,
92 SAMBA_XATTR_MARKER,
93 XATTR_NTACL_NAME,
94 NULL
97 int i;
99 for (i = 0; prohibited_ea_names[i]; i++) {
100 if (strequal( prohibited_ea_names[i], unix_ea_name))
101 return true;
103 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
104 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
105 return true;
107 return false;
110 /****************************************************************************
111 Get one EA value. Fill in a struct ea_struct.
112 ****************************************************************************/
114 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
115 files_struct *fsp, const char *fname,
116 const char *ea_name, struct ea_struct *pea)
118 /* Get the value of this xattr. Max size is 64k. */
119 size_t attr_size = 256;
120 char *val = NULL;
121 ssize_t sizeret;
123 again:
125 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
126 if (!val) {
127 return NT_STATUS_NO_MEMORY;
130 if (fsp && fsp->fh->fd != -1) {
131 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
132 } else {
133 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
136 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 attr_size = 65536;
138 goto again;
141 if (sizeret == -1) {
142 return map_nt_error_from_unix(errno);
145 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
146 dump_data(10, (uint8 *)val, sizeret);
148 pea->flags = 0;
149 if (strnequal(ea_name, "user.", 5)) {
150 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
151 } else {
152 pea->name = talloc_strdup(mem_ctx, ea_name);
154 if (pea->name == NULL) {
155 TALLOC_FREE(val);
156 return NT_STATUS_NO_MEMORY;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return NT_STATUS_OK;
163 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
164 files_struct *fsp, const char *fname,
165 char ***pnames, size_t *pnum_names)
167 /* Get a list of all xattrs. Max namesize is 64k. */
168 size_t ea_namelist_size = 1024;
169 char *ea_namelist = NULL;
171 char *p;
172 char **names, **tmp;
173 size_t num_names;
174 ssize_t sizeret = -1;
176 if (!lp_ea_support(SNUM(conn))) {
177 if (pnames) {
178 *pnames = NULL;
180 *pnum_names = 0;
181 return NT_STATUS_OK;
185 * TALLOC the result early to get the talloc hierarchy right.
188 names = TALLOC_ARRAY(mem_ctx, char *, 1);
189 if (names == NULL) {
190 DEBUG(0, ("talloc failed\n"));
191 return NT_STATUS_NO_MEMORY;
194 while (ea_namelist_size <= 65536) {
196 ea_namelist = TALLOC_REALLOC_ARRAY(
197 names, ea_namelist, char, ea_namelist_size);
198 if (ea_namelist == NULL) {
199 DEBUG(0, ("talloc failed\n"));
200 TALLOC_FREE(names);
201 return NT_STATUS_NO_MEMORY;
204 if (fsp && fsp->fh->fd != -1) {
205 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
206 ea_namelist_size);
207 } else {
208 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
209 ea_namelist_size);
212 if ((sizeret == -1) && (errno == ERANGE)) {
213 ea_namelist_size *= 2;
215 else {
216 break;
220 if (sizeret == -1) {
221 TALLOC_FREE(names);
222 return map_nt_error_from_unix(errno);
225 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
226 (unsigned int)sizeret));
228 if (sizeret == 0) {
229 TALLOC_FREE(names);
230 if (pnames) {
231 *pnames = NULL;
233 *pnum_names = 0;
234 return NT_STATUS_OK;
238 * Ensure the result is 0-terminated
241 if (ea_namelist[sizeret-1] != '\0') {
242 TALLOC_FREE(names);
243 return NT_STATUS_INTERNAL_ERROR;
247 * count the names
249 num_names = 0;
251 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
252 num_names += 1;
255 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
256 if (tmp == NULL) {
257 DEBUG(0, ("talloc failed\n"));
258 TALLOC_FREE(names);
259 return NT_STATUS_NO_MEMORY;
262 names = tmp;
263 num_names = 0;
265 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
266 names[num_names++] = p;
269 if (pnames) {
270 *pnames = names;
271 } else {
272 TALLOC_FREE(names);
274 *pnum_names = num_names;
275 return NT_STATUS_OK;
278 /****************************************************************************
279 Return a linked list of the total EA's. Plus the total size
280 ****************************************************************************/
282 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
283 const char *fname, size_t *pea_total_len)
285 /* Get a list of all xattrs. Max namesize is 64k. */
286 size_t i, num_names;
287 char **names;
288 struct ea_list *ea_list_head = NULL;
289 NTSTATUS status;
291 *pea_total_len = 0;
293 if (!lp_ea_support(SNUM(conn))) {
294 return NULL;
297 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 &names, &num_names);
300 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
301 return NULL;
304 for (i=0; i<num_names; i++) {
305 struct ea_list *listp;
306 fstring dos_ea_name;
308 if (strnequal(names[i], "system.", 7)
309 || samba_private_attr_name(names[i]))
310 continue;
312 listp = TALLOC_P(mem_ctx, struct ea_list);
313 if (listp == NULL) {
314 return NULL;
317 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
318 fname, names[i],
319 &listp->ea))) {
320 return NULL;
323 push_ascii_fstring(dos_ea_name, listp->ea.name);
325 *pea_total_len +=
326 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
328 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
329 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
330 (unsigned int)listp->ea.value.length));
332 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
336 /* Add on 4 for total length. */
337 if (*pea_total_len) {
338 *pea_total_len += 4;
341 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
342 (unsigned int)*pea_total_len));
344 return ea_list_head;
347 /****************************************************************************
348 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 that was filled.
350 ****************************************************************************/
352 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
353 connection_struct *conn, struct ea_list *ea_list)
355 unsigned int ret_data_size = 4;
356 char *p = pdata;
358 SMB_ASSERT(total_data_size >= 4);
360 if (!lp_ea_support(SNUM(conn))) {
361 SIVAL(pdata,4,0);
362 return 4;
365 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 size_t dos_namelen;
367 fstring dos_ea_name;
368 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
369 dos_namelen = strlen(dos_ea_name);
370 if (dos_namelen > 255 || dos_namelen == 0) {
371 break;
373 if (ea_list->ea.value.length > 65535) {
374 break;
376 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
377 break;
380 /* We know we have room. */
381 SCVAL(p,0,ea_list->ea.flags);
382 SCVAL(p,1,dos_namelen);
383 SSVAL(p,2,ea_list->ea.value.length);
384 fstrcpy(p+4, dos_ea_name);
385 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
387 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
388 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
391 ret_data_size = PTR_DIFF(p, pdata);
392 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
393 SIVAL(pdata,0,ret_data_size);
394 return ret_data_size;
397 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
398 char *pdata,
399 unsigned int total_data_size,
400 unsigned int *ret_data_size,
401 connection_struct *conn,
402 struct ea_list *ea_list)
404 uint8_t *p = (uint8_t *)pdata;
405 uint8_t *last_start = NULL;
407 *ret_data_size = 0;
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_NO_EAS_ON_FILE;
413 for (; ea_list; ea_list = ea_list->next) {
414 size_t dos_namelen;
415 fstring dos_ea_name;
416 size_t this_size;
418 if (last_start) {
419 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
421 last_start = p;
423 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
424 dos_namelen = strlen(dos_ea_name);
425 if (dos_namelen > 255 || dos_namelen == 0) {
426 return NT_STATUS_INTERNAL_ERROR;
428 if (ea_list->ea.value.length > 65535) {
429 return NT_STATUS_INTERNAL_ERROR;
432 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
434 if (ea_list->next) {
435 size_t pad = 4 - (this_size % 4);
436 this_size += pad;
439 if (this_size > total_data_size) {
440 return NT_STATUS_INFO_LENGTH_MISMATCH;
443 /* We know we have room. */
444 SIVAL(p, 0x00, 0); /* next offset */
445 SCVAL(p, 0x04, ea_list->ea.flags);
446 SCVAL(p, 0x05, dos_namelen);
447 SSVAL(p, 0x06, ea_list->ea.value.length);
448 fstrcpy((char *)(p+0x08), dos_ea_name);
449 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
451 total_data_size -= this_size;
452 p += this_size;
455 *ret_data_size = PTR_DIFF(p, pdata);
456 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
457 return NT_STATUS_OK;
460 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
462 size_t total_ea_len = 0;
463 TALLOC_CTX *mem_ctx = NULL;
465 if (!lp_ea_support(SNUM(conn))) {
466 return 0;
468 mem_ctx = talloc_tos();
469 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
470 return total_ea_len;
473 /****************************************************************************
474 Ensure the EA name is case insensitive by matching any existing EA name.
475 ****************************************************************************/
477 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
479 size_t total_ea_len;
480 TALLOC_CTX *mem_ctx = talloc_tos();
481 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
483 for (; ea_list; ea_list = ea_list->next) {
484 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
485 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
486 &unix_ea_name[5], ea_list->ea.name));
487 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
488 break;
493 /****************************************************************************
494 Set or delete an extended attribute.
495 ****************************************************************************/
497 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
498 const struct smb_filename *smb_fname, struct ea_list *ea_list)
500 char *fname = NULL;
502 if (!lp_ea_support(SNUM(conn))) {
503 return NT_STATUS_EAS_NOT_SUPPORTED;
506 /* For now setting EAs on streams isn't supported. */
507 fname = smb_fname->base_name;
509 for (;ea_list; ea_list = ea_list->next) {
510 int ret;
511 fstring unix_ea_name;
513 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
514 fstrcat(unix_ea_name, ea_list->ea.name);
516 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
518 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
520 if (samba_private_attr_name(unix_ea_name)) {
521 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
522 return NT_STATUS_ACCESS_DENIED;
525 if (ea_list->ea.value.length == 0) {
526 /* Remove the attribute. */
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: deleting ea name %s on "
529 "file %s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
532 } else {
533 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
534 unix_ea_name, fname));
535 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
537 #ifdef ENOATTR
538 /* Removing a non existent attribute always succeeds. */
539 if (ret == -1 && errno == ENOATTR) {
540 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
541 unix_ea_name));
542 ret = 0;
544 #endif
545 } else {
546 if (fsp && (fsp->fh->fd != -1)) {
547 DEBUG(10,("set_ea: setting ea name %s on file "
548 "%s by file descriptor.\n",
549 unix_ea_name, fsp_str_dbg(fsp)));
550 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
551 ea_list->ea.value.data, ea_list->ea.value.length, 0);
552 } else {
553 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
554 unix_ea_name, fname));
555 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
556 ea_list->ea.value.data, ea_list->ea.value.length, 0);
560 if (ret == -1) {
561 #ifdef ENOTSUP
562 if (errno == ENOTSUP) {
563 return NT_STATUS_EAS_NOT_SUPPORTED;
565 #endif
566 return map_nt_error_from_unix(errno);
570 return NT_STATUS_OK;
572 /****************************************************************************
573 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
574 ****************************************************************************/
576 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
578 struct ea_list *ea_list_head = NULL;
579 size_t converted_size, offset = 0;
581 while (offset + 2 < data_size) {
582 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
583 unsigned int namelen = CVAL(pdata,offset);
585 offset++; /* Go past the namelen byte. */
587 /* integer wrap paranioa. */
588 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
589 (offset > data_size) || (namelen > data_size) ||
590 (offset + namelen >= data_size)) {
591 break;
593 /* Ensure the name is null terminated. */
594 if (pdata[offset + namelen] != '\0') {
595 return NULL;
597 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
598 &converted_size)) {
599 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
600 "failed: %s", strerror(errno)));
602 if (!eal->ea.name) {
603 return NULL;
606 offset += (namelen + 1); /* Go past the name + terminating zero. */
607 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
608 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
611 return ea_list_head;
614 /****************************************************************************
615 Read one EA list entry from the buffer.
616 ****************************************************************************/
618 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
620 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
621 uint16 val_len;
622 unsigned int namelen;
623 size_t converted_size;
625 if (!eal) {
626 return NULL;
629 if (data_size < 6) {
630 return NULL;
633 eal->ea.flags = CVAL(pdata,0);
634 namelen = CVAL(pdata,1);
635 val_len = SVAL(pdata,2);
637 if (4 + namelen + 1 + val_len > data_size) {
638 return NULL;
641 /* Ensure the name is null terminated. */
642 if (pdata[namelen + 4] != '\0') {
643 return NULL;
645 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
646 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
647 strerror(errno)));
649 if (!eal->ea.name) {
650 return NULL;
653 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
654 if (!eal->ea.value.data) {
655 return NULL;
658 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
660 /* Ensure we're null terminated just in case we print the value. */
661 eal->ea.value.data[val_len] = '\0';
662 /* But don't count the null. */
663 eal->ea.value.length--;
665 if (pbytes_used) {
666 *pbytes_used = 4 + namelen + 1 + val_len;
669 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
670 dump_data(10, eal->ea.value.data, eal->ea.value.length);
672 return eal;
675 /****************************************************************************
676 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
677 ****************************************************************************/
679 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
681 struct ea_list *ea_list_head = NULL;
682 size_t offset = 0;
683 size_t bytes_used = 0;
685 while (offset < data_size) {
686 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
688 if (!eal) {
689 return NULL;
692 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
693 offset += bytes_used;
696 return ea_list_head;
699 /****************************************************************************
700 Count the total EA size needed.
701 ****************************************************************************/
703 static size_t ea_list_size(struct ea_list *ealist)
705 fstring dos_ea_name;
706 struct ea_list *listp;
707 size_t ret = 0;
709 for (listp = ealist; listp; listp = listp->next) {
710 push_ascii_fstring(dos_ea_name, listp->ea.name);
711 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
713 /* Add on 4 for total length. */
714 if (ret) {
715 ret += 4;
718 return ret;
721 /****************************************************************************
722 Return a union of EA's from a file list and a list of names.
723 The TALLOC context for the two lists *MUST* be identical as we steal
724 memory from one list to add to another. JRA.
725 ****************************************************************************/
727 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
729 struct ea_list *nlistp, *flistp;
731 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
732 for (flistp = file_list; flistp; flistp = flistp->next) {
733 if (strequal(nlistp->ea.name, flistp->ea.name)) {
734 break;
738 if (flistp) {
739 /* Copy the data from this entry. */
740 nlistp->ea.flags = flistp->ea.flags;
741 nlistp->ea.value = flistp->ea.value;
742 } else {
743 /* Null entry. */
744 nlistp->ea.flags = 0;
745 ZERO_STRUCT(nlistp->ea.value);
749 *total_ea_len = ea_list_size(name_list);
750 return name_list;
753 /****************************************************************************
754 Send the required number of replies back.
755 We assume all fields other than the data fields are
756 set correctly for the type of call.
757 HACK ! Always assumes smb_setup field is zero.
758 ****************************************************************************/
760 void send_trans2_replies(connection_struct *conn,
761 struct smb_request *req,
762 const char *params,
763 int paramsize,
764 const char *pdata,
765 int datasize,
766 int max_data_bytes)
768 /* As we are using a protocol > LANMAN1 then the max_send
769 variable must have been set in the sessetupX call.
770 This takes precedence over the max_xmit field in the
771 global struct. These different max_xmit variables should
772 be merged as this is now too confusing */
774 int data_to_send = datasize;
775 int params_to_send = paramsize;
776 int useable_space;
777 const char *pp = params;
778 const char *pd = pdata;
779 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
780 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
781 int data_alignment_offset = 0;
782 bool overflow = False;
783 struct smbd_server_connection *sconn = req->sconn;
784 int max_send = sconn->smb1.sessions.max_send;
786 /* Modify the data_to_send and datasize and set the error if
787 we're trying to send more than max_data_bytes. We still send
788 the part of the packet(s) that fit. Strange, but needed
789 for OS/2. */
791 if (max_data_bytes > 0 && datasize > max_data_bytes) {
792 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
793 max_data_bytes, datasize ));
794 datasize = data_to_send = max_data_bytes;
795 overflow = True;
798 /* If there genuinely are no parameters or data to send just send the empty packet */
800 if(params_to_send == 0 && data_to_send == 0) {
801 reply_outbuf(req, 10, 0);
802 show_msg((char *)req->outbuf);
803 if (!srv_send_smb(smbd_server_fd(),
804 (char *)req->outbuf,
805 true, req->seqnum+1,
806 IS_CONN_ENCRYPTED(conn),
807 &req->pcd)) {
808 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
810 TALLOC_FREE(req->outbuf);
811 return;
814 /* When sending params and data ensure that both are nicely aligned */
815 /* Only do this alignment when there is also data to send - else
816 can cause NT redirector problems. */
818 if (((params_to_send % 4) != 0) && (data_to_send != 0))
819 data_alignment_offset = 4 - (params_to_send % 4);
821 /* Space is bufsize minus Netbios over TCP header minus SMB header */
822 /* The alignment_offset is to align the param bytes on an even byte
823 boundary. NT 4.0 Beta needs this to work correctly. */
825 useable_space = max_send - (smb_size
826 + 2 * 10 /* wct */
827 + alignment_offset
828 + data_alignment_offset);
830 if (useable_space < 0) {
831 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
832 "= %d!!!", useable_space));
833 exit_server_cleanly("send_trans2_replies: Not enough space");
836 while (params_to_send || data_to_send) {
837 /* Calculate whether we will totally or partially fill this packet */
839 total_sent_thistime = params_to_send + data_to_send;
841 /* We can never send more than useable_space */
843 * Note that 'useable_space' does not include the alignment offsets,
844 * but we must include the alignment offsets in the calculation of
845 * the length of the data we send over the wire, as the alignment offsets
846 * are sent here. Fix from Marc_Jacobsen@hp.com.
849 total_sent_thistime = MIN(total_sent_thistime, useable_space);
851 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
852 + data_alignment_offset);
855 * We might have SMBtrans2s in req which was transferred to
856 * the outbuf, fix that.
858 SCVAL(req->outbuf, smb_com, SMBtrans2);
860 /* Set total params and data to be sent */
861 SSVAL(req->outbuf,smb_tprcnt,paramsize);
862 SSVAL(req->outbuf,smb_tdrcnt,datasize);
864 /* Calculate how many parameters and data we can fit into
865 * this packet. Parameters get precedence
868 params_sent_thistime = MIN(params_to_send,useable_space);
869 data_sent_thistime = useable_space - params_sent_thistime;
870 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
872 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
874 /* smb_proff is the offset from the start of the SMB header to the
875 parameter bytes, however the first 4 bytes of outbuf are
876 the Netbios over TCP header. Thus use smb_base() to subtract
877 them from the calculation */
879 SSVAL(req->outbuf,smb_proff,
880 ((smb_buf(req->outbuf)+alignment_offset)
881 - smb_base(req->outbuf)));
883 if(params_sent_thistime == 0)
884 SSVAL(req->outbuf,smb_prdisp,0);
885 else
886 /* Absolute displacement of param bytes sent in this packet */
887 SSVAL(req->outbuf,smb_prdisp,pp - params);
889 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
890 if(data_sent_thistime == 0) {
891 SSVAL(req->outbuf,smb_droff,0);
892 SSVAL(req->outbuf,smb_drdisp, 0);
893 } else {
894 /* The offset of the data bytes is the offset of the
895 parameter bytes plus the number of parameters being sent this time */
896 SSVAL(req->outbuf, smb_droff,
897 ((smb_buf(req->outbuf)+alignment_offset)
898 - smb_base(req->outbuf))
899 + params_sent_thistime + data_alignment_offset);
900 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
903 /* Initialize the padding for alignment */
905 if (alignment_offset != 0) {
906 memset(smb_buf(req->outbuf), 0, alignment_offset);
909 /* Copy the param bytes into the packet */
911 if(params_sent_thistime) {
912 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
913 params_sent_thistime);
916 /* Copy in the data bytes */
917 if(data_sent_thistime) {
918 if (data_alignment_offset != 0) {
919 memset((smb_buf(req->outbuf)+alignment_offset+
920 params_sent_thistime), 0,
921 data_alignment_offset);
923 memcpy(smb_buf(req->outbuf)+alignment_offset
924 +params_sent_thistime+data_alignment_offset,
925 pd,data_sent_thistime);
928 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
929 params_sent_thistime, data_sent_thistime, useable_space));
930 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
931 params_to_send, data_to_send, paramsize, datasize));
933 if (overflow) {
934 error_packet_set((char *)req->outbuf,
935 ERRDOS,ERRbufferoverflow,
936 STATUS_BUFFER_OVERFLOW,
937 __LINE__,__FILE__);
940 /* Send the packet */
941 show_msg((char *)req->outbuf);
942 if (!srv_send_smb(smbd_server_fd(),
943 (char *)req->outbuf,
944 true, req->seqnum+1,
945 IS_CONN_ENCRYPTED(conn),
946 &req->pcd))
947 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
949 TALLOC_FREE(req->outbuf);
951 pp += params_sent_thistime;
952 pd += data_sent_thistime;
954 params_to_send -= params_sent_thistime;
955 data_to_send -= data_sent_thistime;
957 /* Sanity check */
958 if(params_to_send < 0 || data_to_send < 0) {
959 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
960 params_to_send, data_to_send));
961 return;
965 return;
968 /****************************************************************************
969 Reply to a TRANSACT2_OPEN.
970 ****************************************************************************/
972 static void call_trans2open(connection_struct *conn,
973 struct smb_request *req,
974 char **pparams, int total_params,
975 char **ppdata, int total_data,
976 unsigned int max_data_bytes)
978 struct smb_filename *smb_fname = NULL;
979 char *params = *pparams;
980 char *pdata = *ppdata;
981 int deny_mode;
982 int32 open_attr;
983 bool oplock_request;
984 #if 0
985 bool return_additional_info;
986 int16 open_sattr;
987 time_t open_time;
988 #endif
989 int open_ofun;
990 uint32 open_size;
991 char *pname;
992 char *fname = NULL;
993 SMB_OFF_T size=0;
994 int fattr=0,mtime=0;
995 SMB_INO_T inode = 0;
996 int smb_action = 0;
997 files_struct *fsp;
998 struct ea_list *ea_list = NULL;
999 uint16 flags = 0;
1000 NTSTATUS status;
1001 uint32 access_mask;
1002 uint32 share_mode;
1003 uint32 create_disposition;
1004 uint32 create_options = 0;
1005 uint32_t private_flags = 0;
1006 TALLOC_CTX *ctx = talloc_tos();
1009 * Ensure we have enough parameters to perform the operation.
1012 if (total_params < 29) {
1013 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1014 goto out;
1017 flags = SVAL(params, 0);
1018 deny_mode = SVAL(params, 2);
1019 open_attr = SVAL(params,6);
1020 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1021 if (oplock_request) {
1022 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1025 #if 0
1026 return_additional_info = BITSETW(params,0);
1027 open_sattr = SVAL(params, 4);
1028 open_time = make_unix_date3(params+8);
1029 #endif
1030 open_ofun = SVAL(params,12);
1031 open_size = IVAL(params,14);
1032 pname = &params[28];
1034 if (IS_IPC(conn)) {
1035 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1036 goto out;
1039 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1040 total_params - 28, STR_TERMINATE,
1041 &status);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 reply_nterror(req, status);
1044 goto out;
1047 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1048 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1049 (unsigned int)open_ofun, open_size));
1051 status = filename_convert(ctx,
1052 conn,
1053 req->flags2 & FLAGS2_DFS_PATHNAMES,
1054 fname,
1056 NULL,
1057 &smb_fname);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1060 reply_botherror(req,
1061 NT_STATUS_PATH_NOT_COVERED,
1062 ERRSRV, ERRbadpath);
1063 goto out;
1065 reply_nterror(req, status);
1066 goto out;
1069 if (open_ofun == 0) {
1070 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1071 goto out;
1074 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1075 &access_mask, &share_mode,
1076 &create_disposition,
1077 &create_options,
1078 &private_flags)) {
1079 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1080 goto out;
1083 /* Any data in this call is an EA list. */
1084 if (total_data && (total_data != 4)) {
1085 if (total_data < 10) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1090 if (IVAL(pdata,0) > total_data) {
1091 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1092 IVAL(pdata,0), (unsigned int)total_data));
1093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 goto out;
1097 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1098 total_data - 4);
1099 if (!ea_list) {
1100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1101 goto out;
1104 if (!lp_ea_support(SNUM(conn))) {
1105 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1106 goto out;
1110 status = SMB_VFS_CREATE_FILE(
1111 conn, /* conn */
1112 req, /* req */
1113 0, /* root_dir_fid */
1114 smb_fname, /* fname */
1115 access_mask, /* access_mask */
1116 share_mode, /* share_access */
1117 create_disposition, /* create_disposition*/
1118 create_options, /* create_options */
1119 open_attr, /* file_attributes */
1120 oplock_request, /* oplock_request */
1121 open_size, /* allocation_size */
1122 private_flags,
1123 NULL, /* sd */
1124 ea_list, /* ea_list */
1125 &fsp, /* result */
1126 &smb_action); /* psbuf */
1128 if (!NT_STATUS_IS_OK(status)) {
1129 if (open_was_deferred(req->mid)) {
1130 /* We have re-scheduled this call. */
1131 goto out;
1133 reply_openerror(req, status);
1134 goto out;
1137 size = get_file_size_stat(&smb_fname->st);
1138 fattr = dos_mode(conn, smb_fname);
1139 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1140 inode = smb_fname->st.st_ex_ino;
1141 if (fattr & aDIR) {
1142 close_file(req, fsp, ERROR_CLOSE);
1143 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1144 goto out;
1147 /* Realloc the size of parameters and data we will return */
1148 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1149 if(*pparams == NULL ) {
1150 reply_nterror(req, NT_STATUS_NO_MEMORY);
1151 goto out;
1153 params = *pparams;
1155 SSVAL(params,0,fsp->fnum);
1156 SSVAL(params,2,fattr);
1157 srv_put_dos_date2(params,4, mtime);
1158 SIVAL(params,8, (uint32)size);
1159 SSVAL(params,12,deny_mode);
1160 SSVAL(params,14,0); /* open_type - file or directory. */
1161 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1163 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1164 smb_action |= EXTENDED_OPLOCK_GRANTED;
1167 SSVAL(params,18,smb_action);
1170 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1172 SIVAL(params,20,inode);
1173 SSVAL(params,24,0); /* Padding. */
1174 if (flags & 8) {
1175 uint32 ea_size = estimate_ea_size(conn, fsp,
1176 fsp->fsp_name->base_name);
1177 SIVAL(params, 26, ea_size);
1178 } else {
1179 SIVAL(params, 26, 0);
1182 /* Send the required number of replies */
1183 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1184 out:
1185 TALLOC_FREE(smb_fname);
1188 /*********************************************************
1189 Routine to check if a given string matches exactly.
1190 as a special case a mask of "." does NOT match. That
1191 is required for correct wildcard semantics
1192 Case can be significant or not.
1193 **********************************************************/
1195 static bool exact_match(bool has_wild,
1196 bool case_sensitive,
1197 const char *str,
1198 const char *mask)
1200 if (mask[0] == '.' && mask[1] == 0) {
1201 return false;
1204 if (has_wild) {
1205 return false;
1208 if (case_sensitive) {
1209 return strcmp(str,mask)==0;
1210 } else {
1211 return StrCaseCmp(str,mask) == 0;
1215 /****************************************************************************
1216 Return the filetype for UNIX extensions.
1217 ****************************************************************************/
1219 static uint32 unix_filetype(mode_t mode)
1221 if(S_ISREG(mode))
1222 return UNIX_TYPE_FILE;
1223 else if(S_ISDIR(mode))
1224 return UNIX_TYPE_DIR;
1225 #ifdef S_ISLNK
1226 else if(S_ISLNK(mode))
1227 return UNIX_TYPE_SYMLINK;
1228 #endif
1229 #ifdef S_ISCHR
1230 else if(S_ISCHR(mode))
1231 return UNIX_TYPE_CHARDEV;
1232 #endif
1233 #ifdef S_ISBLK
1234 else if(S_ISBLK(mode))
1235 return UNIX_TYPE_BLKDEV;
1236 #endif
1237 #ifdef S_ISFIFO
1238 else if(S_ISFIFO(mode))
1239 return UNIX_TYPE_FIFO;
1240 #endif
1241 #ifdef S_ISSOCK
1242 else if(S_ISSOCK(mode))
1243 return UNIX_TYPE_SOCKET;
1244 #endif
1246 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1247 return UNIX_TYPE_UNKNOWN;
1250 /****************************************************************************
1251 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1252 ****************************************************************************/
1254 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1256 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1257 const SMB_STRUCT_STAT *psbuf,
1258 uint32 perms,
1259 enum perm_type ptype,
1260 mode_t *ret_perms)
1262 mode_t ret = 0;
1264 if (perms == SMB_MODE_NO_CHANGE) {
1265 if (!VALID_STAT(*psbuf)) {
1266 return NT_STATUS_INVALID_PARAMETER;
1267 } else {
1268 *ret_perms = psbuf->st_ex_mode;
1269 return NT_STATUS_OK;
1273 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1274 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1275 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1276 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1277 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1278 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1279 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1280 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1281 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1282 #ifdef S_ISVTX
1283 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1284 #endif
1285 #ifdef S_ISGID
1286 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1287 #endif
1288 #ifdef S_ISUID
1289 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1290 #endif
1292 switch (ptype) {
1293 case PERM_NEW_FILE:
1294 /* Apply mode mask */
1295 ret &= lp_create_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_create_mode(SNUM(conn));
1298 break;
1299 case PERM_NEW_DIR:
1300 ret &= lp_dir_mask(SNUM(conn));
1301 /* Add in force bits */
1302 ret |= lp_force_dir_mode(SNUM(conn));
1303 break;
1304 case PERM_EXISTING_FILE:
1305 /* Apply mode mask */
1306 ret &= lp_security_mask(SNUM(conn));
1307 /* Add in force bits */
1308 ret |= lp_force_security_mode(SNUM(conn));
1309 break;
1310 case PERM_EXISTING_DIR:
1311 /* Apply mode mask */
1312 ret &= lp_dir_security_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_security_mode(SNUM(conn));
1315 break;
1318 *ret_perms = ret;
1319 return NT_STATUS_OK;
1322 /****************************************************************************
1323 Needed to show the msdfs symlinks as directories. Modifies psbuf
1324 to be a directory if it's a msdfs link.
1325 ****************************************************************************/
1327 static bool check_msdfs_link(connection_struct *conn,
1328 const char *pathname,
1329 SMB_STRUCT_STAT *psbuf)
1331 int saved_errno = errno;
1332 if(lp_host_msdfs() &&
1333 lp_msdfs_root(SNUM(conn)) &&
1334 is_msdfs_link(conn, pathname, psbuf)) {
1336 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1337 "as a directory\n",
1338 pathname));
1339 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1340 errno = saved_errno;
1341 return true;
1343 errno = saved_errno;
1344 return false;
1348 /****************************************************************************
1349 Get a level dependent lanman2 dir entry.
1350 ****************************************************************************/
1352 struct smbd_dirptr_lanman2_state {
1353 connection_struct *conn;
1354 uint32_t info_level;
1355 bool check_mangled_names;
1356 bool has_wild;
1357 bool got_exact_match;
1360 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1361 void *private_data,
1362 const char *dname,
1363 const char *mask,
1364 char **_fname)
1366 struct smbd_dirptr_lanman2_state *state =
1367 (struct smbd_dirptr_lanman2_state *)private_data;
1368 bool ok;
1369 char mangled_name[13]; /* mangled 8.3 name. */
1370 bool got_match;
1371 const char *fname;
1373 /* Mangle fname if it's an illegal name. */
1374 if (mangle_must_mangle(dname, state->conn->params)) {
1375 ok = name_to_8_3(dname, mangled_name,
1376 true, state->conn->params);
1377 if (!ok) {
1378 return false;
1380 fname = mangled_name;
1381 } else {
1382 fname = dname;
1385 got_match = exact_match(state->has_wild,
1386 state->conn->case_sensitive,
1387 fname, mask);
1388 state->got_exact_match = got_match;
1389 if (!got_match) {
1390 got_match = mask_match(fname, mask,
1391 state->conn->case_sensitive);
1394 if(!got_match && state->check_mangled_names &&
1395 !mangle_is_8_3(fname, false, state->conn->params)) {
1397 * It turns out that NT matches wildcards against
1398 * both long *and* short names. This may explain some
1399 * of the wildcard wierdness from old DOS clients
1400 * that some people have been seeing.... JRA.
1402 /* Force the mangling into 8.3. */
1403 ok = name_to_8_3(fname, mangled_name,
1404 false, state->conn->params);
1405 if (!ok) {
1406 return false;
1409 got_match = exact_match(state->has_wild,
1410 state->conn->case_sensitive,
1411 mangled_name, mask);
1412 state->got_exact_match = got_match;
1413 if (!got_match) {
1414 got_match = mask_match(mangled_name, mask,
1415 state->conn->case_sensitive);
1419 if (!got_match) {
1420 return false;
1423 *_fname = talloc_strdup(ctx, fname);
1424 if (*_fname == NULL) {
1425 return false;
1428 return true;
1431 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1432 void *private_data,
1433 struct smb_filename *smb_fname,
1434 uint32_t *_mode)
1436 struct smbd_dirptr_lanman2_state *state =
1437 (struct smbd_dirptr_lanman2_state *)private_data;
1438 bool ms_dfs_link = false;
1439 uint32_t mode = 0;
1441 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1442 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1443 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1444 "Couldn't lstat [%s] (%s)\n",
1445 smb_fname_str_dbg(smb_fname),
1446 strerror(errno)));
1447 return false;
1449 } else if (!VALID_STAT(smb_fname->st) &&
1450 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1451 /* Needed to show the msdfs symlinks as
1452 * directories */
1454 ms_dfs_link = check_msdfs_link(state->conn,
1455 smb_fname->base_name,
1456 &smb_fname->st);
1457 if (!ms_dfs_link) {
1458 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1459 "Couldn't stat [%s] (%s)\n",
1460 smb_fname_str_dbg(smb_fname),
1461 strerror(errno)));
1462 return false;
1466 if (ms_dfs_link) {
1467 mode = dos_mode_msdfs(state->conn, smb_fname);
1468 } else {
1469 mode = dos_mode(state->conn, smb_fname);
1472 *_mode = mode;
1473 return true;
1476 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1477 connection_struct *conn,
1478 uint16_t flags2,
1479 uint32_t info_level,
1480 struct ea_list *name_list,
1481 bool check_mangled_names,
1482 bool requires_resume_key,
1483 uint32_t mode,
1484 const char *fname,
1485 const struct smb_filename *smb_fname,
1486 int space_remaining,
1487 uint8_t align,
1488 bool do_pad,
1489 char *base_data,
1490 char **ppdata,
1491 char *end_data,
1492 bool *out_of_space,
1493 uint64_t *last_entry_off)
1495 char *p, *q, *pdata = *ppdata;
1496 uint32_t reskey=0;
1497 uint64_t file_size = 0;
1498 uint64_t allocation_size = 0;
1499 uint64_t file_index = 0;
1500 uint32_t len;
1501 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1502 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1503 time_t c_date = (time_t)0;
1504 char *nameptr;
1505 char *last_entry_ptr;
1506 bool was_8_3;
1507 int off;
1508 int pad = 0;
1510 *out_of_space = false;
1512 ZERO_STRUCT(mdate_ts);
1513 ZERO_STRUCT(adate_ts);
1514 ZERO_STRUCT(create_date_ts);
1515 ZERO_STRUCT(cdate_ts);
1517 if (!(mode & aDIR)) {
1518 file_size = get_file_size_stat(&smb_fname->st);
1520 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1522 file_index = get_FileIndex(conn, &smb_fname->st);
1524 mdate_ts = smb_fname->st.st_ex_mtime;
1525 adate_ts = smb_fname->st.st_ex_atime;
1526 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1527 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1529 if (lp_dos_filetime_resolution(SNUM(conn))) {
1530 dos_filetime_timespec(&create_date_ts);
1531 dos_filetime_timespec(&mdate_ts);
1532 dos_filetime_timespec(&adate_ts);
1533 dos_filetime_timespec(&cdate_ts);
1536 create_date = convert_timespec_to_time_t(create_date_ts);
1537 mdate = convert_timespec_to_time_t(mdate_ts);
1538 adate = convert_timespec_to_time_t(adate_ts);
1539 c_date = convert_timespec_to_time_t(cdate_ts);
1541 /* align the record */
1542 SMB_ASSERT(align >= 1);
1544 off = (int)PTR_DIFF(pdata, base_data);
1545 pad = (off + (align-1)) & ~(align-1);
1546 pad -= off;
1548 if (pad && pad > space_remaining) {
1549 *out_of_space = true;
1550 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1551 "for padding (wanted %u, had %d)\n",
1552 (unsigned int)pad,
1553 space_remaining ));
1554 return false; /* Not finished - just out of space */
1557 off += pad;
1558 /* initialize padding to 0 */
1559 if (pad) {
1560 memset(pdata, 0, pad);
1562 space_remaining -= pad;
1564 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1565 space_remaining ));
1567 pdata += pad;
1568 p = pdata;
1569 last_entry_ptr = p;
1571 pad = 0;
1572 off = 0;
1574 switch (info_level) {
1575 case SMB_FIND_INFO_STANDARD:
1576 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1577 if(requires_resume_key) {
1578 SIVAL(p,0,reskey);
1579 p += 4;
1581 srv_put_dos_date2(p,0,create_date);
1582 srv_put_dos_date2(p,4,adate);
1583 srv_put_dos_date2(p,8,mdate);
1584 SIVAL(p,12,(uint32)file_size);
1585 SIVAL(p,16,(uint32)allocation_size);
1586 SSVAL(p,20,mode);
1587 p += 23;
1588 nameptr = p;
1589 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1590 p += ucs2_align(base_data, p, 0);
1592 len = srvstr_push(base_data, flags2, p,
1593 fname, PTR_DIFF(end_data, p),
1594 STR_TERMINATE);
1595 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1596 if (len > 2) {
1597 SCVAL(nameptr, -1, len - 2);
1598 } else {
1599 SCVAL(nameptr, -1, 0);
1601 } else {
1602 if (len > 1) {
1603 SCVAL(nameptr, -1, len - 1);
1604 } else {
1605 SCVAL(nameptr, -1, 0);
1608 p += len;
1609 break;
1611 case SMB_FIND_EA_SIZE:
1612 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1613 if (requires_resume_key) {
1614 SIVAL(p,0,reskey);
1615 p += 4;
1617 srv_put_dos_date2(p,0,create_date);
1618 srv_put_dos_date2(p,4,adate);
1619 srv_put_dos_date2(p,8,mdate);
1620 SIVAL(p,12,(uint32)file_size);
1621 SIVAL(p,16,(uint32)allocation_size);
1622 SSVAL(p,20,mode);
1624 unsigned int ea_size = estimate_ea_size(conn, NULL,
1625 smb_fname->base_name);
1626 SIVAL(p,22,ea_size); /* Extended attributes */
1628 p += 27;
1629 nameptr = p - 1;
1630 len = srvstr_push(base_data, flags2,
1631 p, fname, PTR_DIFF(end_data, p),
1632 STR_TERMINATE | STR_NOALIGN);
1633 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1634 if (len > 2) {
1635 len -= 2;
1636 } else {
1637 len = 0;
1639 } else {
1640 if (len > 1) {
1641 len -= 1;
1642 } else {
1643 len = 0;
1646 SCVAL(nameptr,0,len);
1647 p += len;
1648 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1649 break;
1651 case SMB_FIND_EA_LIST:
1653 struct ea_list *file_list = NULL;
1654 size_t ea_len = 0;
1656 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1657 if (!name_list) {
1658 return false;
1660 if (requires_resume_key) {
1661 SIVAL(p,0,reskey);
1662 p += 4;
1664 srv_put_dos_date2(p,0,create_date);
1665 srv_put_dos_date2(p,4,adate);
1666 srv_put_dos_date2(p,8,mdate);
1667 SIVAL(p,12,(uint32)file_size);
1668 SIVAL(p,16,(uint32)allocation_size);
1669 SSVAL(p,20,mode);
1670 p += 22; /* p now points to the EA area. */
1672 file_list = get_ea_list_from_file(ctx, conn, NULL,
1673 smb_fname->base_name,
1674 &ea_len);
1675 name_list = ea_list_union(name_list, file_list, &ea_len);
1677 /* We need to determine if this entry will fit in the space available. */
1678 /* Max string size is 255 bytes. */
1679 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1680 *out_of_space = true;
1681 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1682 "(wanted %u, had %d)\n",
1683 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1684 space_remaining ));
1685 return False; /* Not finished - just out of space */
1688 /* Push the ea_data followed by the name. */
1689 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1690 nameptr = p;
1691 len = srvstr_push(base_data, flags2,
1692 p + 1, fname, PTR_DIFF(end_data, p+1),
1693 STR_TERMINATE | STR_NOALIGN);
1694 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1695 if (len > 2) {
1696 len -= 2;
1697 } else {
1698 len = 0;
1700 } else {
1701 if (len > 1) {
1702 len -= 1;
1703 } else {
1704 len = 0;
1707 SCVAL(nameptr,0,len);
1708 p += len + 1;
1709 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1710 break;
1713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1714 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1715 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1716 p += 4;
1717 SIVAL(p,0,reskey); p += 4;
1718 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1719 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1720 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1721 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1722 SOFF_T(p,0,file_size); p += 8;
1723 SOFF_T(p,0,allocation_size); p += 8;
1724 SIVAL(p,0,mode); p += 4;
1725 q = p; p += 4; /* q is placeholder for name length. */
1727 unsigned int ea_size = estimate_ea_size(conn, NULL,
1728 smb_fname->base_name);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1730 p += 4;
1732 /* Clear the short name buffer. This is
1733 * IMPORTANT as not doing so will trigger
1734 * a Win2k client bug. JRA.
1736 if (!was_8_3 && check_mangled_names) {
1737 char mangled_name[13]; /* mangled 8.3 name. */
1738 if (!name_to_8_3(fname,mangled_name,True,
1739 conn->params)) {
1740 /* Error - mangle failed ! */
1741 memset(mangled_name,'\0',12);
1743 mangled_name[12] = 0;
1744 len = srvstr_push(base_data, flags2,
1745 p+2, mangled_name, 24,
1746 STR_UPPER|STR_UNICODE);
1747 if (len < 24) {
1748 memset(p + 2 + len,'\0',24 - len);
1750 SSVAL(p, 0, len);
1751 } else {
1752 memset(p,'\0',26);
1754 p += 2 + 24;
1755 len = srvstr_push(base_data, flags2, p,
1756 fname, PTR_DIFF(end_data, p),
1757 STR_TERMINATE_ASCII);
1758 SIVAL(q,0,len);
1759 p += len;
1761 len = PTR_DIFF(p, pdata);
1762 pad = (len + (align-1)) & ~(align-1);
1764 * offset to the next entry, the caller
1765 * will overwrite it for the last entry
1766 * that's why we always include the padding
1768 SIVAL(pdata,0,pad);
1770 * set padding to zero
1772 if (do_pad) {
1773 memset(p, 0, pad - len);
1774 p = pdata + pad;
1775 } else {
1776 p = pdata + len;
1778 break;
1780 case SMB_FIND_FILE_DIRECTORY_INFO:
1781 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1782 p += 4;
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,mode); p += 4;
1791 len = srvstr_push(base_data, flags2,
1792 p + 4, fname, PTR_DIFF(end_data, p+4),
1793 STR_TERMINATE_ASCII);
1794 SIVAL(p,0,len);
1795 p += 4 + len;
1797 len = PTR_DIFF(p, pdata);
1798 pad = (len + (align-1)) & ~(align-1);
1800 * offset to the next entry, the caller
1801 * will overwrite it for the last entry
1802 * that's why we always include the padding
1804 SIVAL(pdata,0,pad);
1806 * set padding to zero
1808 if (do_pad) {
1809 memset(p, 0, pad - len);
1810 p = pdata + pad;
1811 } else {
1812 p = pdata + len;
1814 break;
1816 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1817 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1818 p += 4;
1819 SIVAL(p,0,reskey); p += 4;
1820 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1821 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1824 SOFF_T(p,0,file_size); p += 8;
1825 SOFF_T(p,0,allocation_size); p += 8;
1826 SIVAL(p,0,mode); p += 4;
1827 q = p; p += 4; /* q is placeholder for name length. */
1829 unsigned int ea_size = estimate_ea_size(conn, NULL,
1830 smb_fname->base_name);
1831 SIVAL(p,0,ea_size); /* Extended attributes */
1832 p +=4;
1834 len = srvstr_push(base_data, flags2, p,
1835 fname, PTR_DIFF(end_data, p),
1836 STR_TERMINATE_ASCII);
1837 SIVAL(q, 0, len);
1838 p += len;
1840 len = PTR_DIFF(p, pdata);
1841 pad = (len + (align-1)) & ~(align-1);
1843 * offset to the next entry, the caller
1844 * will overwrite it for the last entry
1845 * that's why we always include the padding
1847 SIVAL(pdata,0,pad);
1849 * set padding to zero
1851 if (do_pad) {
1852 memset(p, 0, pad - len);
1853 p = pdata + pad;
1854 } else {
1855 p = pdata + len;
1857 break;
1859 case SMB_FIND_FILE_NAMES_INFO:
1860 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1861 p += 4;
1862 SIVAL(p,0,reskey); p += 4;
1863 p += 4;
1864 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1865 acl on a dir (tridge) */
1866 len = srvstr_push(base_data, flags2, p,
1867 fname, PTR_DIFF(end_data, p),
1868 STR_TERMINATE_ASCII);
1869 SIVAL(p, -4, len);
1870 p += len;
1872 len = PTR_DIFF(p, pdata);
1873 pad = (len + (align-1)) & ~(align-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1879 SIVAL(pdata,0,pad);
1881 * set padding to zero
1883 if (do_pad) {
1884 memset(p, 0, pad - len);
1885 p = pdata + pad;
1886 } else {
1887 p = pdata + len;
1889 break;
1891 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1893 p += 4;
1894 SIVAL(p,0,reskey); p += 4;
1895 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1896 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1899 SOFF_T(p,0,file_size); p += 8;
1900 SOFF_T(p,0,allocation_size); p += 8;
1901 SIVAL(p,0,mode); p += 4;
1902 q = p; p += 4; /* q is placeholder for name length. */
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1905 smb_fname->base_name);
1906 SIVAL(p,0,ea_size); /* Extended attributes */
1907 p +=4;
1909 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1910 SBVAL(p,0,file_index); p += 8;
1911 len = srvstr_push(base_data, flags2, p,
1912 fname, PTR_DIFF(end_data, p),
1913 STR_TERMINATE_ASCII);
1914 SIVAL(q, 0, len);
1915 p += len;
1917 len = PTR_DIFF(p, pdata);
1918 pad = (len + (align-1)) & ~(align-1);
1920 * offset to the next entry, the caller
1921 * will overwrite it for the last entry
1922 * that's why we always include the padding
1924 SIVAL(pdata,0,pad);
1926 * set padding to zero
1928 if (do_pad) {
1929 memset(p, 0, pad - len);
1930 p = pdata + pad;
1931 } else {
1932 p = pdata + len;
1934 break;
1936 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1937 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1938 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1939 p += 4;
1940 SIVAL(p,0,reskey); p += 4;
1941 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1942 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1945 SOFF_T(p,0,file_size); p += 8;
1946 SOFF_T(p,0,allocation_size); p += 8;
1947 SIVAL(p,0,mode); p += 4;
1948 q = p; p += 4; /* q is placeholder for name length */
1950 unsigned int ea_size = estimate_ea_size(conn, NULL,
1951 smb_fname->base_name);
1952 SIVAL(p,0,ea_size); /* Extended attributes */
1953 p +=4;
1955 /* Clear the short name buffer. This is
1956 * IMPORTANT as not doing so will trigger
1957 * a Win2k client bug. JRA.
1959 if (!was_8_3 && check_mangled_names) {
1960 char mangled_name[13]; /* mangled 8.3 name. */
1961 if (!name_to_8_3(fname,mangled_name,True,
1962 conn->params)) {
1963 /* Error - mangle failed ! */
1964 memset(mangled_name,'\0',12);
1966 mangled_name[12] = 0;
1967 len = srvstr_push(base_data, flags2,
1968 p+2, mangled_name, 24,
1969 STR_UPPER|STR_UNICODE);
1970 SSVAL(p, 0, len);
1971 if (len < 24) {
1972 memset(p + 2 + len,'\0',24 - len);
1974 SSVAL(p, 0, len);
1975 } else {
1976 memset(p,'\0',26);
1978 p += 26;
1979 SSVAL(p,0,0); p += 2; /* Reserved ? */
1980 SBVAL(p,0,file_index); p += 8;
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE_ASCII);
1984 SIVAL(q,0,len);
1985 p += len;
1987 len = PTR_DIFF(p, pdata);
1988 pad = (len + (align-1)) & ~(align-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1994 SIVAL(pdata,0,pad);
1996 * set padding to zero
1998 if (do_pad) {
1999 memset(p, 0, pad - len);
2000 p = pdata + pad;
2001 } else {
2002 p = pdata + len;
2004 break;
2006 /* CIFS UNIX Extension. */
2008 case SMB_FIND_FILE_UNIX:
2009 case SMB_FIND_FILE_UNIX_INFO2:
2010 p+= 4;
2011 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2013 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2015 if (info_level == SMB_FIND_FILE_UNIX) {
2016 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2017 p = store_file_unix_basic(conn, p,
2018 NULL, &smb_fname->st);
2019 len = srvstr_push(base_data, flags2, p,
2020 fname, PTR_DIFF(end_data, p),
2021 STR_TERMINATE);
2022 } else {
2023 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2024 p = store_file_unix_basic_info2(conn, p,
2025 NULL, &smb_fname->st);
2026 nameptr = p;
2027 p += 4;
2028 len = srvstr_push(base_data, flags2, p, fname,
2029 PTR_DIFF(end_data, p), 0);
2030 SIVAL(nameptr, 0, len);
2033 p += len;
2035 len = PTR_DIFF(p, pdata);
2036 pad = (len + (align-1)) & ~(align-1);
2038 * offset to the next entry, the caller
2039 * will overwrite it for the last entry
2040 * that's why we always include the padding
2042 SIVAL(pdata,0,pad);
2044 * set padding to zero
2046 if (do_pad) {
2047 memset(p, 0, pad - len);
2048 p = pdata + pad;
2049 } else {
2050 p = pdata + len;
2052 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2054 break;
2056 default:
2057 return false;
2060 if (PTR_DIFF(p,pdata) > space_remaining) {
2061 *out_of_space = true;
2062 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2063 "(wanted %u, had %d)\n",
2064 (unsigned int)PTR_DIFF(p,pdata),
2065 space_remaining ));
2066 return false; /* Not finished - just out of space */
2069 /* Setup the last entry pointer, as an offset from base_data */
2070 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2071 /* Advance the data pointer to the next slot */
2072 *ppdata = p;
2074 return true;
2077 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2078 connection_struct *conn,
2079 struct dptr_struct *dirptr,
2080 uint16 flags2,
2081 const char *path_mask,
2082 uint32 dirtype,
2083 int info_level,
2084 int requires_resume_key,
2085 bool dont_descend,
2086 bool ask_sharemode,
2087 uint8_t align,
2088 bool do_pad,
2089 char **ppdata,
2090 char *base_data,
2091 char *end_data,
2092 int space_remaining,
2093 bool *out_of_space,
2094 bool *got_exact_match,
2095 int *_last_entry_off,
2096 struct ea_list *name_list)
2098 const char *p;
2099 const char *mask = NULL;
2100 long prev_dirpos = 0;
2101 uint32_t mode = 0;
2102 char *fname = NULL;
2103 struct smb_filename *smb_fname = NULL;
2104 struct smbd_dirptr_lanman2_state state;
2105 bool ok;
2106 uint64_t last_entry_off = 0;
2108 ZERO_STRUCT(state);
2109 state.conn = conn;
2110 state.info_level = info_level;
2111 state.check_mangled_names = lp_manglednames(conn->params);
2112 state.has_wild = dptr_has_wild(dirptr);
2113 state.got_exact_match = false;
2115 *out_of_space = false;
2116 *got_exact_match = false;
2118 p = strrchr_m(path_mask,'/');
2119 if(p != NULL) {
2120 if(p[1] == '\0') {
2121 mask = "*.*";
2122 } else {
2123 mask = p+1;
2125 } else {
2126 mask = path_mask;
2129 ok = smbd_dirptr_get_entry(ctx,
2130 dirptr,
2131 mask,
2132 dirtype,
2133 dont_descend,
2134 ask_sharemode,
2135 smbd_dirptr_lanman2_match_fn,
2136 smbd_dirptr_lanman2_mode_fn,
2137 &state,
2138 &fname,
2139 &smb_fname,
2140 &mode,
2141 &prev_dirpos);
2142 if (!ok) {
2143 return false;
2146 *got_exact_match = state.got_exact_match;
2148 ok = smbd_marshall_dir_entry(ctx,
2149 conn,
2150 flags2,
2151 info_level,
2152 name_list,
2153 state.check_mangled_names,
2154 requires_resume_key,
2155 mode,
2156 fname,
2157 smb_fname,
2158 space_remaining,
2159 align,
2160 do_pad,
2161 base_data,
2162 ppdata,
2163 end_data,
2164 out_of_space,
2165 &last_entry_off);
2166 TALLOC_FREE(fname);
2167 TALLOC_FREE(smb_fname);
2168 if (*out_of_space) {
2169 dptr_SeekDir(dirptr, prev_dirpos);
2170 return false;
2172 if (!ok) {
2173 return false;
2176 *_last_entry_off = last_entry_off;
2177 return true;
2180 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 bool requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 char **ppdata,
2191 char *base_data,
2192 char *end_data,
2193 int space_remaining,
2194 bool *out_of_space,
2195 bool *got_exact_match,
2196 int *last_entry_off,
2197 struct ea_list *name_list)
2199 uint8_t align = 4;
2200 const bool do_pad = true;
2202 if (info_level >= 1 && info_level <= 3) {
2203 /* No alignment on earlier info levels. */
2204 align = 1;
2207 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2208 path_mask, dirtype, info_level,
2209 requires_resume_key, dont_descend, ask_sharemode,
2210 align, do_pad,
2211 ppdata, base_data, end_data,
2212 space_remaining,
2213 out_of_space, got_exact_match,
2214 last_entry_off, name_list);
2217 /****************************************************************************
2218 Reply to a TRANS2_FINDFIRST.
2219 ****************************************************************************/
2221 static void call_trans2findfirst(connection_struct *conn,
2222 struct smb_request *req,
2223 char **pparams, int total_params,
2224 char **ppdata, int total_data,
2225 unsigned int max_data_bytes)
2227 /* We must be careful here that we don't return more than the
2228 allowed number of data bytes. If this means returning fewer than
2229 maxentries then so be it. We assume that the redirector has
2230 enough room for the fixed number of parameter bytes it has
2231 requested. */
2232 struct smb_filename *smb_dname = NULL;
2233 char *params = *pparams;
2234 char *pdata = *ppdata;
2235 char *data_end;
2236 uint32 dirtype;
2237 int maxentries;
2238 uint16 findfirst_flags;
2239 bool close_after_first;
2240 bool close_if_end;
2241 bool requires_resume_key;
2242 int info_level;
2243 char *directory = NULL;
2244 char *mask = NULL;
2245 char *p;
2246 int last_entry_off=0;
2247 int dptr_num = -1;
2248 int numentries = 0;
2249 int i;
2250 bool finished = False;
2251 bool dont_descend = False;
2252 bool out_of_space = False;
2253 int space_remaining;
2254 bool mask_contains_wcard = False;
2255 struct ea_list *ea_list = NULL;
2256 NTSTATUS ntstatus = NT_STATUS_OK;
2257 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2258 TALLOC_CTX *ctx = talloc_tos();
2259 struct dptr_struct *dirptr = NULL;
2260 struct smbd_server_connection *sconn = req->sconn;
2262 if (total_params < 13) {
2263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2264 goto out;
2267 dirtype = SVAL(params,0);
2268 maxentries = SVAL(params,2);
2269 findfirst_flags = SVAL(params,4);
2270 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2271 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2272 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2273 info_level = SVAL(params,6);
2275 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2276 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2277 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2278 info_level, max_data_bytes));
2280 if (!maxentries) {
2281 /* W2K3 seems to treat zero as 1. */
2282 maxentries = 1;
2285 switch (info_level) {
2286 case SMB_FIND_INFO_STANDARD:
2287 case SMB_FIND_EA_SIZE:
2288 case SMB_FIND_EA_LIST:
2289 case SMB_FIND_FILE_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_NAMES_INFO:
2292 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2295 break;
2296 case SMB_FIND_FILE_UNIX:
2297 case SMB_FIND_FILE_UNIX_INFO2:
2298 /* Always use filesystem for UNIX mtime query. */
2299 ask_sharemode = false;
2300 if (!lp_unix_extensions()) {
2301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2302 goto out;
2304 break;
2305 default:
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2307 goto out;
2310 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2311 params+12, total_params - 12,
2312 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2313 if (!NT_STATUS_IS_OK(ntstatus)) {
2314 reply_nterror(req, ntstatus);
2315 goto out;
2318 ntstatus = filename_convert(ctx, conn,
2319 req->flags2 & FLAGS2_DFS_PATHNAMES,
2320 directory,
2321 (UCF_SAVE_LCOMP |
2322 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2323 &mask_contains_wcard,
2324 &smb_dname);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2327 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2328 ERRSRV, ERRbadpath);
2329 goto out;
2331 reply_nterror(req, ntstatus);
2332 goto out;
2335 mask = smb_dname->original_lcomp;
2337 directory = smb_dname->base_name;
2339 p = strrchr_m(directory,'/');
2340 if(p == NULL) {
2341 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2342 if((directory[0] == '.') && (directory[1] == '\0')) {
2343 mask = talloc_strdup(ctx,"*");
2344 if (!mask) {
2345 reply_nterror(req, NT_STATUS_NO_MEMORY);
2346 goto out;
2348 mask_contains_wcard = True;
2350 directory = talloc_strdup(talloc_tos(), "./");
2351 if (!directory) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2355 } else {
2356 *p = 0;
2359 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2361 if (info_level == SMB_FIND_EA_LIST) {
2362 uint32 ea_size;
2364 if (total_data < 4) {
2365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2366 goto out;
2369 ea_size = IVAL(pdata,0);
2370 if (ea_size != total_data) {
2371 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2372 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2374 goto out;
2377 if (!lp_ea_support(SNUM(conn))) {
2378 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2379 goto out;
2382 /* Pull out the list of names. */
2383 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2384 if (!ea_list) {
2385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2386 goto out;
2390 *ppdata = (char *)SMB_REALLOC(
2391 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2392 if(*ppdata == NULL ) {
2393 reply_nterror(req, NT_STATUS_NO_MEMORY);
2394 goto out;
2396 pdata = *ppdata;
2397 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2399 /* Realloc the params space */
2400 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2401 if (*pparams == NULL) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2403 goto out;
2405 params = *pparams;
2407 /* Save the wildcard match and attribs we are using on this directory -
2408 needed as lanman2 assumes these are being saved between calls */
2410 ntstatus = dptr_create(conn,
2411 directory,
2412 False,
2413 True,
2414 req->smbpid,
2415 mask,
2416 mask_contains_wcard,
2417 dirtype,
2418 &dirptr);
2420 if (!NT_STATUS_IS_OK(ntstatus)) {
2421 reply_nterror(req, ntstatus);
2422 goto out;
2425 dptr_num = dptr_dnum(dirptr);
2426 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2428 /* Initialize per TRANS2_FIND_FIRST operation data */
2429 dptr_init_search_op(dirptr);
2431 /* We don't need to check for VOL here as this is returned by
2432 a different TRANS2 call. */
2434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2435 directory,lp_dontdescend(SNUM(conn))));
2436 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2437 dont_descend = True;
2439 p = pdata;
2440 space_remaining = max_data_bytes;
2441 out_of_space = False;
2443 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2444 bool got_exact_match = False;
2446 /* this is a heuristic to avoid seeking the dirptr except when
2447 absolutely necessary. It allows for a filename of about 40 chars */
2448 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2449 out_of_space = True;
2450 finished = False;
2451 } else {
2452 finished = !get_lanman2_dir_entry(ctx,
2453 conn,
2454 dirptr,
2455 req->flags2,
2456 mask,dirtype,info_level,
2457 requires_resume_key,dont_descend,
2458 ask_sharemode,
2459 &p,pdata,data_end,
2460 space_remaining, &out_of_space,
2461 &got_exact_match,
2462 &last_entry_off, ea_list);
2465 if (finished && out_of_space)
2466 finished = False;
2468 if (!finished && !out_of_space)
2469 numentries++;
2472 * As an optimisation if we know we aren't looking
2473 * for a wildcard name (ie. the name matches the wildcard exactly)
2474 * then we can finish on any (first) match.
2475 * This speeds up large directory searches. JRA.
2478 if(got_exact_match)
2479 finished = True;
2481 /* Ensure space_remaining never goes -ve. */
2482 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2483 space_remaining = 0;
2484 out_of_space = true;
2485 } else {
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2490 /* Check if we can close the dirptr */
2491 if(close_after_first || (finished && close_if_end)) {
2492 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2493 dptr_close(sconn, &dptr_num);
2497 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2498 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2499 * the protocol level is less than NT1. Tested with smbclient. JRA.
2500 * This should fix the OS/2 client bug #2335.
2503 if(numentries == 0) {
2504 dptr_close(sconn, &dptr_num);
2505 if (get_Protocol() < PROTOCOL_NT1) {
2506 reply_force_doserror(req, ERRDOS, ERRnofiles);
2507 goto out;
2508 } else {
2509 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2510 ERRDOS, ERRbadfile);
2511 goto out;
2515 /* At this point pdata points to numentries directory entries. */
2517 /* Set up the return parameter block */
2518 SSVAL(params,0,dptr_num);
2519 SSVAL(params,2,numentries);
2520 SSVAL(params,4,finished);
2521 SSVAL(params,6,0); /* Never an EA error */
2522 SSVAL(params,8,last_entry_off);
2524 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2525 max_data_bytes);
2527 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2528 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2529 if (!directory) {
2530 reply_nterror(req, NT_STATUS_NO_MEMORY);
2534 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2535 smb_fn_name(req->cmd),
2536 mask, directory, dirtype, numentries ) );
2539 * Force a name mangle here to ensure that the
2540 * mask as an 8.3 name is top of the mangled cache.
2541 * The reasons for this are subtle. Don't remove
2542 * this code unless you know what you are doing
2543 * (see PR#13758). JRA.
2546 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2547 char mangled_name[13];
2548 name_to_8_3(mask, mangled_name, True, conn->params);
2550 out:
2551 TALLOC_FREE(smb_dname);
2552 return;
2555 /****************************************************************************
2556 Reply to a TRANS2_FINDNEXT.
2557 ****************************************************************************/
2559 static void call_trans2findnext(connection_struct *conn,
2560 struct smb_request *req,
2561 char **pparams, int total_params,
2562 char **ppdata, int total_data,
2563 unsigned int max_data_bytes)
2565 /* We must be careful here that we don't return more than the
2566 allowed number of data bytes. If this means returning fewer than
2567 maxentries then so be it. We assume that the redirector has
2568 enough room for the fixed number of parameter bytes it has
2569 requested. */
2570 char *params = *pparams;
2571 char *pdata = *ppdata;
2572 char *data_end;
2573 int dptr_num;
2574 int maxentries;
2575 uint16 info_level;
2576 uint32 resume_key;
2577 uint16 findnext_flags;
2578 bool close_after_request;
2579 bool close_if_end;
2580 bool requires_resume_key;
2581 bool continue_bit;
2582 bool mask_contains_wcard = False;
2583 char *resume_name = NULL;
2584 const char *mask = NULL;
2585 const char *directory = NULL;
2586 char *p = NULL;
2587 uint16 dirtype;
2588 int numentries = 0;
2589 int i, last_entry_off=0;
2590 bool finished = False;
2591 bool dont_descend = False;
2592 bool out_of_space = False;
2593 int space_remaining;
2594 struct ea_list *ea_list = NULL;
2595 NTSTATUS ntstatus = NT_STATUS_OK;
2596 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2597 TALLOC_CTX *ctx = talloc_tos();
2598 struct dptr_struct *dirptr;
2599 struct smbd_server_connection *sconn = req->sconn;
2601 if (total_params < 13) {
2602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2603 return;
2606 dptr_num = SVAL(params,0);
2607 maxentries = SVAL(params,2);
2608 info_level = SVAL(params,4);
2609 resume_key = IVAL(params,6);
2610 findnext_flags = SVAL(params,10);
2611 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2612 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2613 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2614 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2616 if (!continue_bit) {
2617 /* We only need resume_name if continue_bit is zero. */
2618 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2619 params+12,
2620 total_params - 12, STR_TERMINATE, &ntstatus,
2621 &mask_contains_wcard);
2622 if (!NT_STATUS_IS_OK(ntstatus)) {
2623 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2624 complain (it thinks we're asking for the directory above the shared
2625 path or an invalid name). Catch this as the resume name is only compared, never used in
2626 a file access. JRA. */
2627 srvstr_pull_talloc(ctx, params, req->flags2,
2628 &resume_name, params+12,
2629 total_params - 12,
2630 STR_TERMINATE);
2632 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2633 reply_nterror(req, ntstatus);
2634 return;
2639 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2640 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2641 resume_key = %d resume name = %s continue=%d level = %d\n",
2642 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2643 requires_resume_key, resume_key,
2644 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2646 if (!maxentries) {
2647 /* W2K3 seems to treat zero as 1. */
2648 maxentries = 1;
2651 switch (info_level) {
2652 case SMB_FIND_INFO_STANDARD:
2653 case SMB_FIND_EA_SIZE:
2654 case SMB_FIND_EA_LIST:
2655 case SMB_FIND_FILE_DIRECTORY_INFO:
2656 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2657 case SMB_FIND_FILE_NAMES_INFO:
2658 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2659 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2660 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2661 break;
2662 case SMB_FIND_FILE_UNIX:
2663 case SMB_FIND_FILE_UNIX_INFO2:
2664 /* Always use filesystem for UNIX mtime query. */
2665 ask_sharemode = false;
2666 if (!lp_unix_extensions()) {
2667 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2668 return;
2670 break;
2671 default:
2672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2673 return;
2676 if (info_level == SMB_FIND_EA_LIST) {
2677 uint32 ea_size;
2679 if (total_data < 4) {
2680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2681 return;
2684 ea_size = IVAL(pdata,0);
2685 if (ea_size != total_data) {
2686 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2687 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2689 return;
2692 if (!lp_ea_support(SNUM(conn))) {
2693 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2694 return;
2697 /* Pull out the list of names. */
2698 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2699 if (!ea_list) {
2700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2701 return;
2705 *ppdata = (char *)SMB_REALLOC(
2706 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2707 if(*ppdata == NULL) {
2708 reply_nterror(req, NT_STATUS_NO_MEMORY);
2709 return;
2712 pdata = *ppdata;
2713 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2715 /* Realloc the params space */
2716 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2717 if(*pparams == NULL ) {
2718 reply_nterror(req, NT_STATUS_NO_MEMORY);
2719 return;
2722 params = *pparams;
2724 /* Check that the dptr is valid */
2725 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2726 reply_nterror(req, STATUS_NO_MORE_FILES);
2727 return;
2730 directory = dptr_path(sconn, dptr_num);
2732 /* Get the wildcard mask from the dptr */
2733 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2734 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2735 reply_nterror(req, STATUS_NO_MORE_FILES);
2736 return;
2739 mask = p;
2741 /* Get the attr mask from the dptr */
2742 dirtype = dptr_attr(sconn, dptr_num);
2744 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2745 dptr_num, mask, dirtype,
2746 (long)dirptr,
2747 dptr_TellDir(dirptr)));
2749 /* Initialize per TRANS2_FIND_NEXT operation data */
2750 dptr_init_search_op(dirptr);
2752 /* We don't need to check for VOL here as this is returned by
2753 a different TRANS2 call. */
2755 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2756 directory,lp_dontdescend(SNUM(conn))));
2757 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2758 dont_descend = True;
2760 p = pdata;
2761 space_remaining = max_data_bytes;
2762 out_of_space = False;
2765 * Seek to the correct position. We no longer use the resume key but
2766 * depend on the last file name instead.
2769 if(!continue_bit && resume_name && *resume_name) {
2770 SMB_STRUCT_STAT st;
2772 long current_pos = 0;
2774 * Remember, name_to_8_3 is called by
2775 * get_lanman2_dir_entry(), so the resume name
2776 * could be mangled. Ensure we check the unmangled name.
2779 if (mangle_is_mangled(resume_name, conn->params)) {
2780 char *new_resume_name = NULL;
2781 mangle_lookup_name_from_8_3(ctx,
2782 resume_name,
2783 &new_resume_name,
2784 conn->params);
2785 if (new_resume_name) {
2786 resume_name = new_resume_name;
2791 * Fix for NT redirector problem triggered by resume key indexes
2792 * changing between directory scans. We now return a resume key of 0
2793 * and instead look for the filename to continue from (also given
2794 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2795 * findfirst/findnext (as is usual) then the directory pointer
2796 * should already be at the correct place.
2799 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2800 } /* end if resume_name && !continue_bit */
2802 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2803 bool got_exact_match = False;
2805 /* this is a heuristic to avoid seeking the dirptr except when
2806 absolutely necessary. It allows for a filename of about 40 chars */
2807 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2808 out_of_space = True;
2809 finished = False;
2810 } else {
2811 finished = !get_lanman2_dir_entry(ctx,
2812 conn,
2813 dirptr,
2814 req->flags2,
2815 mask,dirtype,info_level,
2816 requires_resume_key,dont_descend,
2817 ask_sharemode,
2818 &p,pdata,data_end,
2819 space_remaining, &out_of_space,
2820 &got_exact_match,
2821 &last_entry_off, ea_list);
2824 if (finished && out_of_space)
2825 finished = False;
2827 if (!finished && !out_of_space)
2828 numentries++;
2831 * As an optimisation if we know we aren't looking
2832 * for a wildcard name (ie. the name matches the wildcard exactly)
2833 * then we can finish on any (first) match.
2834 * This speeds up large directory searches. JRA.
2837 if(got_exact_match)
2838 finished = True;
2840 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2843 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2844 smb_fn_name(req->cmd),
2845 mask, directory, dirtype, numentries ) );
2847 /* Check if we can close the dirptr */
2848 if(close_after_request || (finished && close_if_end)) {
2849 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2850 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2853 /* Set up the return parameter block */
2854 SSVAL(params,0,numentries);
2855 SSVAL(params,2,finished);
2856 SSVAL(params,4,0); /* Never an EA error */
2857 SSVAL(params,6,last_entry_off);
2859 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2860 max_data_bytes);
2862 return;
2865 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2867 E_md4hash(lp_servicename(SNUM(conn)),objid);
2868 return objid;
2871 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2873 SMB_ASSERT(extended_info != NULL);
2875 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2876 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2877 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2878 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2879 #ifdef SAMBA_VERSION_REVISION
2880 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2881 #endif
2882 extended_info->samba_subversion = 0;
2883 #ifdef SAMBA_VERSION_RC_RELEASE
2884 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2885 #else
2886 #ifdef SAMBA_VERSION_PRE_RELEASE
2887 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2888 #endif
2889 #endif
2890 #ifdef SAMBA_VERSION_VENDOR_PATCH
2891 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2892 #endif
2893 extended_info->samba_gitcommitdate = 0;
2894 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2895 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2896 #endif
2898 memset(extended_info->samba_version_string, 0,
2899 sizeof(extended_info->samba_version_string));
2901 snprintf (extended_info->samba_version_string,
2902 sizeof(extended_info->samba_version_string),
2903 "%s", samba_version_string());
2906 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2907 TALLOC_CTX *mem_ctx,
2908 uint16_t info_level,
2909 uint16_t flags2,
2910 unsigned int max_data_bytes,
2911 char **ppdata,
2912 int *ret_data_len)
2914 char *pdata, *end_data;
2915 int data_len = 0, len;
2916 const char *vname = volume_label(SNUM(conn));
2917 int snum = SNUM(conn);
2918 char *fstype = lp_fstype(SNUM(conn));
2919 uint32 additional_flags = 0;
2920 struct smb_filename smb_fname_dot;
2921 SMB_STRUCT_STAT st;
2923 if (IS_IPC(conn)) {
2924 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2925 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2926 "info level (0x%x) on IPC$.\n",
2927 (unsigned int)info_level));
2928 return NT_STATUS_ACCESS_DENIED;
2932 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2934 ZERO_STRUCT(smb_fname_dot);
2935 smb_fname_dot.base_name = discard_const_p(char, ".");
2937 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2938 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2939 return map_nt_error_from_unix(errno);
2942 st = smb_fname_dot.st;
2944 *ppdata = (char *)SMB_REALLOC(
2945 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2946 if (*ppdata == NULL) {
2947 return NT_STATUS_NO_MEMORY;
2950 pdata = *ppdata;
2951 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2952 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2954 switch (info_level) {
2955 case SMB_INFO_ALLOCATION:
2957 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2958 data_len = 18;
2959 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2960 return map_nt_error_from_unix(errno);
2963 block_size = lp_block_size(snum);
2964 if (bsize < block_size) {
2965 uint64_t factor = block_size/bsize;
2966 bsize = block_size;
2967 dsize /= factor;
2968 dfree /= factor;
2970 if (bsize > block_size) {
2971 uint64_t factor = bsize/block_size;
2972 bsize = block_size;
2973 dsize *= factor;
2974 dfree *= factor;
2976 bytes_per_sector = 512;
2977 sectors_per_unit = bsize/bytes_per_sector;
2979 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2980 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2981 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2983 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2984 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2985 SIVAL(pdata,l1_cUnit,dsize);
2986 SIVAL(pdata,l1_cUnitAvail,dfree);
2987 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2988 break;
2991 case SMB_INFO_VOLUME:
2992 /* Return volume name */
2994 * Add volume serial number - hash of a combination of
2995 * the called hostname and the service name.
2997 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2999 * Win2k3 and previous mess this up by sending a name length
3000 * one byte short. I believe only older clients (OS/2 Win9x) use
3001 * this call so try fixing this by adding a terminating null to
3002 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3004 len = srvstr_push(
3005 pdata, flags2,
3006 pdata+l2_vol_szVolLabel, vname,
3007 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3008 STR_NOALIGN|STR_TERMINATE);
3009 SCVAL(pdata,l2_vol_cch,len);
3010 data_len = l2_vol_szVolLabel + len;
3011 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3012 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3013 len, vname));
3014 break;
3016 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3017 case SMB_FS_ATTRIBUTE_INFORMATION:
3019 additional_flags = 0;
3020 #if defined(HAVE_SYS_QUOTAS)
3021 additional_flags |= FILE_VOLUME_QUOTAS;
3022 #endif
3024 if(lp_nt_acl_support(SNUM(conn))) {
3025 additional_flags |= FILE_PERSISTENT_ACLS;
3028 /* Capabilities are filled in at connection time through STATVFS call */
3029 additional_flags |= conn->fs_capabilities;
3030 additional_flags |= lp_parm_int(conn->params->service,
3031 "share", "fake_fscaps",
3034 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3035 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3036 additional_flags); /* FS ATTRIBUTES */
3038 SIVAL(pdata,4,255); /* Max filename component length */
3039 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3040 and will think we can't do long filenames */
3041 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3042 PTR_DIFF(end_data, pdata+12),
3043 STR_UNICODE);
3044 SIVAL(pdata,8,len);
3045 data_len = 12 + len;
3046 break;
3048 case SMB_QUERY_FS_LABEL_INFO:
3049 case SMB_FS_LABEL_INFORMATION:
3050 len = srvstr_push(pdata, flags2, pdata+4, vname,
3051 PTR_DIFF(end_data, pdata+4), 0);
3052 data_len = 4 + len;
3053 SIVAL(pdata,0,len);
3054 break;
3056 case SMB_QUERY_FS_VOLUME_INFO:
3057 case SMB_FS_VOLUME_INFORMATION:
3060 * Add volume serial number - hash of a combination of
3061 * the called hostname and the service name.
3063 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3064 (str_checksum(get_local_machine_name())<<16));
3066 /* Max label len is 32 characters. */
3067 len = srvstr_push(pdata, flags2, pdata+18, vname,
3068 PTR_DIFF(end_data, pdata+18),
3069 STR_UNICODE);
3070 SIVAL(pdata,12,len);
3071 data_len = 18+len;
3073 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3074 (int)strlen(vname),vname, lp_servicename(snum)));
3075 break;
3077 case SMB_QUERY_FS_SIZE_INFO:
3078 case SMB_FS_SIZE_INFORMATION:
3080 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3081 data_len = 24;
3082 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno);
3085 block_size = lp_block_size(snum);
3086 if (bsize < block_size) {
3087 uint64_t factor = block_size/bsize;
3088 bsize = block_size;
3089 dsize /= factor;
3090 dfree /= factor;
3092 if (bsize > block_size) {
3093 uint64_t factor = bsize/block_size;
3094 bsize = block_size;
3095 dsize *= factor;
3096 dfree *= factor;
3098 bytes_per_sector = 512;
3099 sectors_per_unit = bsize/bytes_per_sector;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3102 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3103 SBIG_UINT(pdata,0,dsize);
3104 SBIG_UINT(pdata,8,dfree);
3105 SIVAL(pdata,16,sectors_per_unit);
3106 SIVAL(pdata,20,bytes_per_sector);
3107 break;
3110 case SMB_FS_FULL_SIZE_INFORMATION:
3112 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3113 data_len = 32;
3114 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3115 return map_nt_error_from_unix(errno);
3117 block_size = lp_block_size(snum);
3118 if (bsize < block_size) {
3119 uint64_t factor = block_size/bsize;
3120 bsize = block_size;
3121 dsize /= factor;
3122 dfree /= factor;
3124 if (bsize > block_size) {
3125 uint64_t factor = bsize/block_size;
3126 bsize = block_size;
3127 dsize *= factor;
3128 dfree *= factor;
3130 bytes_per_sector = 512;
3131 sectors_per_unit = bsize/bytes_per_sector;
3132 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3133 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3134 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3135 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3136 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3137 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3138 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3139 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3140 break;
3143 case SMB_QUERY_FS_DEVICE_INFO:
3144 case SMB_FS_DEVICE_INFORMATION:
3146 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3148 if (!CAN_WRITE(conn)) {
3149 characteristics |= FILE_READ_ONLY_DEVICE;
3151 data_len = 8;
3152 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3153 SIVAL(pdata,4,characteristics);
3154 break;
3157 #ifdef HAVE_SYS_QUOTAS
3158 case SMB_FS_QUOTA_INFORMATION:
3160 * what we have to send --metze:
3162 * Unknown1: 24 NULL bytes
3163 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3164 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3165 * Quota Flags: 2 byte :
3166 * Unknown3: 6 NULL bytes
3168 * 48 bytes total
3170 * details for Quota Flags:
3172 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3173 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3174 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3175 * 0x0001 Enable Quotas: enable quota for this fs
3179 /* we need to fake up a fsp here,
3180 * because its not send in this call
3182 files_struct fsp;
3183 SMB_NTQUOTA_STRUCT quotas;
3185 ZERO_STRUCT(fsp);
3186 ZERO_STRUCT(quotas);
3188 fsp.conn = conn;
3189 fsp.fnum = -1;
3191 /* access check */
3192 if (conn->server_info->utok.uid != sec_initial_uid()) {
3193 DEBUG(0,("set_user_quota: access_denied "
3194 "service [%s] user [%s]\n",
3195 lp_servicename(SNUM(conn)),
3196 conn->server_info->unix_name));
3197 return NT_STATUS_ACCESS_DENIED;
3200 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3201 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3202 return map_nt_error_from_unix(errno);
3205 data_len = 48;
3207 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3208 lp_servicename(SNUM(conn))));
3210 /* Unknown1 24 NULL bytes*/
3211 SBIG_UINT(pdata,0,(uint64_t)0);
3212 SBIG_UINT(pdata,8,(uint64_t)0);
3213 SBIG_UINT(pdata,16,(uint64_t)0);
3215 /* Default Soft Quota 8 bytes */
3216 SBIG_UINT(pdata,24,quotas.softlim);
3218 /* Default Hard Quota 8 bytes */
3219 SBIG_UINT(pdata,32,quotas.hardlim);
3221 /* Quota flag 2 bytes */
3222 SSVAL(pdata,40,quotas.qflags);
3224 /* Unknown3 6 NULL bytes */
3225 SSVAL(pdata,42,0);
3226 SIVAL(pdata,44,0);
3228 break;
3230 #endif /* HAVE_SYS_QUOTAS */
3231 case SMB_FS_OBJECTID_INFORMATION:
3233 unsigned char objid[16];
3234 struct smb_extended_info extended_info;
3235 memcpy(pdata,create_volume_objectid(conn, objid),16);
3236 samba_extended_info_version (&extended_info);
3237 SIVAL(pdata,16,extended_info.samba_magic);
3238 SIVAL(pdata,20,extended_info.samba_version);
3239 SIVAL(pdata,24,extended_info.samba_subversion);
3240 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3241 memcpy(pdata+36,extended_info.samba_version_string,28);
3242 data_len = 64;
3243 break;
3247 * Query the version and capabilities of the CIFS UNIX extensions
3248 * in use.
3251 case SMB_QUERY_CIFS_UNIX_INFO:
3253 bool large_write = lp_min_receive_file_size() &&
3254 !srv_is_signing_active(conn->sconn);
3255 bool large_read = !srv_is_signing_active(conn->sconn);
3256 int encrypt_caps = 0;
3258 if (!lp_unix_extensions()) {
3259 return NT_STATUS_INVALID_LEVEL;
3262 switch (conn->encrypt_level) {
3263 case 0:
3264 encrypt_caps = 0;
3265 break;
3266 case 1:
3267 case Auto:
3268 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3269 break;
3270 case Required:
3271 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3272 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3273 large_write = false;
3274 large_read = false;
3275 break;
3278 data_len = 12;
3279 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3280 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3282 /* We have POSIX ACLs, pathname, encryption,
3283 * large read/write, and locking capability. */
3285 SBIG_UINT(pdata,4,((uint64_t)(
3286 CIFS_UNIX_POSIX_ACLS_CAP|
3287 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3288 CIFS_UNIX_FCNTL_LOCKS_CAP|
3289 CIFS_UNIX_EXTATTR_CAP|
3290 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3291 encrypt_caps|
3292 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3293 (large_write ?
3294 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3295 break;
3298 case SMB_QUERY_POSIX_FS_INFO:
3300 int rc;
3301 vfs_statvfs_struct svfs;
3303 if (!lp_unix_extensions()) {
3304 return NT_STATUS_INVALID_LEVEL;
3307 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3309 if (!rc) {
3310 data_len = 56;
3311 SIVAL(pdata,0,svfs.OptimalTransferSize);
3312 SIVAL(pdata,4,svfs.BlockSize);
3313 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3314 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3315 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3316 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3317 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3318 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3320 #ifdef EOPNOTSUPP
3321 } else if (rc == EOPNOTSUPP) {
3322 return NT_STATUS_INVALID_LEVEL;
3323 #endif /* EOPNOTSUPP */
3324 } else {
3325 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3326 return NT_STATUS_DOS(ERRSRV, ERRerror);
3328 break;
3331 case SMB_QUERY_POSIX_WHOAMI:
3333 uint32_t flags = 0;
3334 uint32_t sid_bytes;
3335 int i;
3337 if (!lp_unix_extensions()) {
3338 return NT_STATUS_INVALID_LEVEL;
3341 if (max_data_bytes < 40) {
3342 return NT_STATUS_BUFFER_TOO_SMALL;
3345 /* We ARE guest if global_sid_Builtin_Guests is
3346 * in our list of SIDs.
3348 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3349 conn->server_info->ptok)) {
3350 flags |= SMB_WHOAMI_GUEST;
3353 /* We are NOT guest if global_sid_Authenticated_Users
3354 * is in our list of SIDs.
3356 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3357 conn->server_info->ptok)) {
3358 flags &= ~SMB_WHOAMI_GUEST;
3361 /* NOTE: 8 bytes for UID/GID, irrespective of native
3362 * platform size. This matches
3363 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3365 data_len = 4 /* flags */
3366 + 4 /* flag mask */
3367 + 8 /* uid */
3368 + 8 /* gid */
3369 + 4 /* ngroups */
3370 + 4 /* num_sids */
3371 + 4 /* SID bytes */
3372 + 4 /* pad/reserved */
3373 + (conn->server_info->utok.ngroups * 8)
3374 /* groups list */
3375 + (conn->server_info->ptok->num_sids *
3376 SID_MAX_SIZE)
3377 /* SID list */;
3379 SIVAL(pdata, 0, flags);
3380 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3381 SBIG_UINT(pdata, 8,
3382 (uint64_t)conn->server_info->utok.uid);
3383 SBIG_UINT(pdata, 16,
3384 (uint64_t)conn->server_info->utok.gid);
3387 if (data_len >= max_data_bytes) {
3388 /* Potential overflow, skip the GIDs and SIDs. */
3390 SIVAL(pdata, 24, 0); /* num_groups */
3391 SIVAL(pdata, 28, 0); /* num_sids */
3392 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3393 SIVAL(pdata, 36, 0); /* reserved */
3395 data_len = 40;
3396 break;
3399 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3400 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3402 /* We walk the SID list twice, but this call is fairly
3403 * infrequent, and I don't expect that it's performance
3404 * sensitive -- jpeach
3406 for (i = 0, sid_bytes = 0;
3407 i < conn->server_info->ptok->num_sids; ++i) {
3408 sid_bytes += ndr_size_dom_sid(
3409 &conn->server_info->ptok->user_sids[i],
3413 /* SID list byte count */
3414 SIVAL(pdata, 32, sid_bytes);
3416 /* 4 bytes pad/reserved - must be zero */
3417 SIVAL(pdata, 36, 0);
3418 data_len = 40;
3420 /* GID list */
3421 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3422 SBIG_UINT(pdata, data_len,
3423 (uint64_t)conn->server_info->utok.groups[i]);
3424 data_len += 8;
3427 /* SID list */
3428 for (i = 0;
3429 i < conn->server_info->ptok->num_sids; ++i) {
3430 int sid_len = ndr_size_dom_sid(
3431 &conn->server_info->ptok->user_sids[i],
3434 sid_linearize(pdata + data_len, sid_len,
3435 &conn->server_info->ptok->user_sids[i]);
3436 data_len += sid_len;
3439 break;
3442 case SMB_MAC_QUERY_FS_INFO:
3444 * Thursby MAC extension... ONLY on NTFS filesystems
3445 * once we do streams then we don't need this
3447 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3448 data_len = 88;
3449 SIVAL(pdata,84,0x100); /* Don't support mac... */
3450 break;
3452 /* drop through */
3453 default:
3454 return NT_STATUS_INVALID_LEVEL;
3457 *ret_data_len = data_len;
3458 return NT_STATUS_OK;
3461 /****************************************************************************
3462 Reply to a TRANS2_QFSINFO (query filesystem info).
3463 ****************************************************************************/
3465 static void call_trans2qfsinfo(connection_struct *conn,
3466 struct smb_request *req,
3467 char **pparams, int total_params,
3468 char **ppdata, int total_data,
3469 unsigned int max_data_bytes)
3471 char *params = *pparams;
3472 uint16_t info_level;
3473 int data_len = 0;
3474 NTSTATUS status;
3476 if (total_params < 2) {
3477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3478 return;
3481 info_level = SVAL(params,0);
3483 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3484 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3485 DEBUG(0,("call_trans2qfsinfo: encryption required "
3486 "and info level 0x%x sent.\n",
3487 (unsigned int)info_level));
3488 exit_server_cleanly("encryption required "
3489 "on connection");
3490 return;
3494 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3496 status = smbd_do_qfsinfo(conn, req,
3497 info_level,
3498 req->flags2,
3499 max_data_bytes,
3500 ppdata, &data_len);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 reply_nterror(req, status);
3503 return;
3506 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3507 max_data_bytes);
3509 DEBUG( 4, ( "%s info_level = %d\n",
3510 smb_fn_name(req->cmd), info_level) );
3512 return;
3515 /****************************************************************************
3516 Reply to a TRANS2_SETFSINFO (set filesystem info).
3517 ****************************************************************************/
3519 static void call_trans2setfsinfo(connection_struct *conn,
3520 struct smb_request *req,
3521 char **pparams, int total_params,
3522 char **ppdata, int total_data,
3523 unsigned int max_data_bytes)
3525 char *pdata = *ppdata;
3526 char *params = *pparams;
3527 uint16 info_level;
3529 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3531 /* */
3532 if (total_params < 4) {
3533 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3534 total_params));
3535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3536 return;
3539 info_level = SVAL(params,2);
3541 if (IS_IPC(conn)) {
3542 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3543 info_level != SMB_SET_CIFS_UNIX_INFO) {
3544 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3545 "info level (0x%x) on IPC$.\n",
3546 (unsigned int)info_level));
3547 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3548 return;
3552 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3553 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3554 DEBUG(0,("call_trans2setfsinfo: encryption required "
3555 "and info level 0x%x sent.\n",
3556 (unsigned int)info_level));
3557 exit_server_cleanly("encryption required "
3558 "on connection");
3559 return;
3563 switch(info_level) {
3564 case SMB_SET_CIFS_UNIX_INFO:
3566 uint16 client_unix_major;
3567 uint16 client_unix_minor;
3568 uint32 client_unix_cap_low;
3569 uint32 client_unix_cap_high;
3571 if (!lp_unix_extensions()) {
3572 reply_nterror(req,
3573 NT_STATUS_INVALID_LEVEL);
3574 return;
3577 /* There should be 12 bytes of capabilities set. */
3578 if (total_data < 8) {
3579 reply_nterror(
3580 req,
3581 NT_STATUS_INVALID_PARAMETER);
3582 return;
3584 client_unix_major = SVAL(pdata,0);
3585 client_unix_minor = SVAL(pdata,2);
3586 client_unix_cap_low = IVAL(pdata,4);
3587 client_unix_cap_high = IVAL(pdata,8);
3588 /* Just print these values for now. */
3589 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3590 cap_low = 0x%x, cap_high = 0x%x\n",
3591 (unsigned int)client_unix_major,
3592 (unsigned int)client_unix_minor,
3593 (unsigned int)client_unix_cap_low,
3594 (unsigned int)client_unix_cap_high ));
3596 /* Here is where we must switch to posix pathname processing... */
3597 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3598 lp_set_posix_pathnames();
3599 mangle_change_to_posix();
3602 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3603 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3604 /* Client that knows how to do posix locks,
3605 * but not posix open/mkdir operations. Set a
3606 * default type for read/write checks. */
3608 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3611 break;
3614 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3616 NTSTATUS status;
3617 size_t param_len = 0;
3618 size_t data_len = total_data;
3620 if (!lp_unix_extensions()) {
3621 reply_nterror(
3622 req,
3623 NT_STATUS_INVALID_LEVEL);
3624 return;
3627 if (lp_smb_encrypt(SNUM(conn)) == false) {
3628 reply_nterror(
3629 req,
3630 NT_STATUS_NOT_SUPPORTED);
3631 return;
3634 if (req->sconn->smb1.echo_handler.trusted_fde) {
3635 DEBUG( 2,("call_trans2setfsinfo: "
3636 "request transport encryption disabled"
3637 "with 'fork echo handler = yes'\n"));
3638 reply_nterror(
3639 req,
3640 NT_STATUS_NOT_SUPPORTED);
3641 return;
3644 DEBUG( 4,("call_trans2setfsinfo: "
3645 "request transport encryption.\n"));
3647 status = srv_request_encryption_setup(conn,
3648 (unsigned char **)ppdata,
3649 &data_len,
3650 (unsigned char **)pparams,
3651 &param_len);
3653 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3654 !NT_STATUS_IS_OK(status)) {
3655 reply_nterror(req, status);
3656 return;
3659 send_trans2_replies(conn, req,
3660 *pparams,
3661 param_len,
3662 *ppdata,
3663 data_len,
3664 max_data_bytes);
3666 if (NT_STATUS_IS_OK(status)) {
3667 /* Server-side transport
3668 * encryption is now *on*. */
3669 status = srv_encryption_start(conn);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 exit_server_cleanly(
3672 "Failure in setting "
3673 "up encrypted transport");
3676 return;
3679 case SMB_FS_QUOTA_INFORMATION:
3681 files_struct *fsp = NULL;
3682 SMB_NTQUOTA_STRUCT quotas;
3684 ZERO_STRUCT(quotas);
3686 /* access check */
3687 if ((conn->server_info->utok.uid != sec_initial_uid())
3688 ||!CAN_WRITE(conn)) {
3689 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3690 lp_servicename(SNUM(conn)),
3691 conn->server_info->unix_name));
3692 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3693 return;
3696 /* note: normaly there're 48 bytes,
3697 * but we didn't use the last 6 bytes for now
3698 * --metze
3700 fsp = file_fsp(req, SVAL(params,0));
3702 if (!check_fsp_ntquota_handle(conn, req,
3703 fsp)) {
3704 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3705 reply_nterror(
3706 req, NT_STATUS_INVALID_HANDLE);
3707 return;
3710 if (total_data < 42) {
3711 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3712 total_data));
3713 reply_nterror(
3714 req,
3715 NT_STATUS_INVALID_PARAMETER);
3716 return;
3719 /* unknown_1 24 NULL bytes in pdata*/
3721 /* the soft quotas 8 bytes (uint64_t)*/
3722 quotas.softlim = (uint64_t)IVAL(pdata,24);
3723 #ifdef LARGE_SMB_OFF_T
3724 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3725 #else /* LARGE_SMB_OFF_T */
3726 if ((IVAL(pdata,28) != 0)&&
3727 ((quotas.softlim != 0xFFFFFFFF)||
3728 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3729 /* more than 32 bits? */
3730 reply_nterror(
3731 req,
3732 NT_STATUS_INVALID_PARAMETER);
3733 return;
3735 #endif /* LARGE_SMB_OFF_T */
3737 /* the hard quotas 8 bytes (uint64_t)*/
3738 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3739 #ifdef LARGE_SMB_OFF_T
3740 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3741 #else /* LARGE_SMB_OFF_T */
3742 if ((IVAL(pdata,36) != 0)&&
3743 ((quotas.hardlim != 0xFFFFFFFF)||
3744 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3745 /* more than 32 bits? */
3746 reply_nterror(
3747 req,
3748 NT_STATUS_INVALID_PARAMETER);
3749 return;
3751 #endif /* LARGE_SMB_OFF_T */
3753 /* quota_flags 2 bytes **/
3754 quotas.qflags = SVAL(pdata,40);
3756 /* unknown_2 6 NULL bytes follow*/
3758 /* now set the quotas */
3759 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3760 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3761 reply_nterror(req, map_nt_error_from_unix(errno));
3762 return;
3765 break;
3767 default:
3768 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3769 info_level));
3770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3771 return;
3772 break;
3776 * sending this reply works fine,
3777 * but I'm not sure it's the same
3778 * like windows do...
3779 * --metze
3781 reply_outbuf(req, 10, 0);
3784 #if defined(HAVE_POSIX_ACLS)
3785 /****************************************************************************
3786 Utility function to count the number of entries in a POSIX acl.
3787 ****************************************************************************/
3789 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3791 unsigned int ace_count = 0;
3792 int entry_id = SMB_ACL_FIRST_ENTRY;
3793 SMB_ACL_ENTRY_T entry;
3795 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3796 /* get_next... */
3797 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3798 entry_id = SMB_ACL_NEXT_ENTRY;
3800 ace_count++;
3802 return ace_count;
3805 /****************************************************************************
3806 Utility function to marshall a POSIX acl into wire format.
3807 ****************************************************************************/
3809 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3811 int entry_id = SMB_ACL_FIRST_ENTRY;
3812 SMB_ACL_ENTRY_T entry;
3814 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3815 SMB_ACL_TAG_T tagtype;
3816 SMB_ACL_PERMSET_T permset;
3817 unsigned char perms = 0;
3818 unsigned int own_grp;
3820 /* get_next... */
3821 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3822 entry_id = SMB_ACL_NEXT_ENTRY;
3825 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3827 return False;
3830 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3832 return False;
3835 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3836 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3837 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3839 SCVAL(pdata,1,perms);
3841 switch (tagtype) {
3842 case SMB_ACL_USER_OBJ:
3843 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3844 own_grp = (unsigned int)pst->st_ex_uid;
3845 SIVAL(pdata,2,own_grp);
3846 SIVAL(pdata,6,0);
3847 break;
3848 case SMB_ACL_USER:
3850 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3851 if (!puid) {
3852 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3853 return False;
3855 own_grp = (unsigned int)*puid;
3856 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3857 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3858 SIVAL(pdata,2,own_grp);
3859 SIVAL(pdata,6,0);
3860 break;
3862 case SMB_ACL_GROUP_OBJ:
3863 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3864 own_grp = (unsigned int)pst->st_ex_gid;
3865 SIVAL(pdata,2,own_grp);
3866 SIVAL(pdata,6,0);
3867 break;
3868 case SMB_ACL_GROUP:
3870 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3871 if (!pgid) {
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3873 return False;
3875 own_grp = (unsigned int)*pgid;
3876 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3877 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3878 SIVAL(pdata,2,own_grp);
3879 SIVAL(pdata,6,0);
3880 break;
3882 case SMB_ACL_MASK:
3883 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3884 SIVAL(pdata,2,0xFFFFFFFF);
3885 SIVAL(pdata,6,0xFFFFFFFF);
3886 break;
3887 case SMB_ACL_OTHER:
3888 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3889 SIVAL(pdata,2,0xFFFFFFFF);
3890 SIVAL(pdata,6,0xFFFFFFFF);
3891 break;
3892 default:
3893 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3894 return False;
3896 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3899 return True;
3901 #endif
3903 /****************************************************************************
3904 Store the FILE_UNIX_BASIC info.
3905 ****************************************************************************/
3907 static char *store_file_unix_basic(connection_struct *conn,
3908 char *pdata,
3909 files_struct *fsp,
3910 const SMB_STRUCT_STAT *psbuf)
3912 uint64_t file_index = get_FileIndex(conn, psbuf);
3914 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3915 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3917 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3918 pdata += 8;
3920 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3921 pdata += 8;
3923 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3925 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3926 pdata += 24;
3928 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3929 SIVAL(pdata,4,0);
3930 pdata += 8;
3932 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3933 SIVAL(pdata,4,0);
3934 pdata += 8;
3936 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3937 pdata += 4;
3939 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3940 SIVAL(pdata,4,0);
3941 pdata += 8;
3943 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3944 SIVAL(pdata,4,0);
3945 pdata += 8;
3947 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3948 pdata += 8;
3950 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3951 SIVAL(pdata,4,0);
3952 pdata += 8;
3954 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3955 SIVAL(pdata,4,0);
3956 pdata += 8;
3958 return pdata;
3961 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3962 * the chflags(2) (or equivalent) flags.
3964 * XXX: this really should be behind the VFS interface. To do this, we would
3965 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3966 * Each VFS module could then implement its own mapping as appropriate for the
3967 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3969 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3970 info2_flags_map[] =
3972 #ifdef UF_NODUMP
3973 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3974 #endif
3976 #ifdef UF_IMMUTABLE
3977 { UF_IMMUTABLE, EXT_IMMUTABLE },
3978 #endif
3980 #ifdef UF_APPEND
3981 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3982 #endif
3984 #ifdef UF_HIDDEN
3985 { UF_HIDDEN, EXT_HIDDEN },
3986 #endif
3988 /* Do not remove. We need to guarantee that this array has at least one
3989 * entry to build on HP-UX.
3991 { 0, 0 }
3995 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3996 uint32 *smb_fflags, uint32 *smb_fmask)
3998 int i;
4000 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4001 *smb_fmask |= info2_flags_map[i].smb_fflag;
4002 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4003 *smb_fflags |= info2_flags_map[i].smb_fflag;
4008 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4009 const uint32 smb_fflags,
4010 const uint32 smb_fmask,
4011 int *stat_fflags)
4013 uint32 max_fmask = 0;
4014 int i;
4016 *stat_fflags = psbuf->st_ex_flags;
4018 /* For each flags requested in smb_fmask, check the state of the
4019 * corresponding flag in smb_fflags and set or clear the matching
4020 * stat flag.
4023 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4024 max_fmask |= info2_flags_map[i].smb_fflag;
4025 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4026 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4027 *stat_fflags |= info2_flags_map[i].stat_fflag;
4028 } else {
4029 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4034 /* If smb_fmask is asking to set any bits that are not supported by
4035 * our flag mappings, we should fail.
4037 if ((smb_fmask & max_fmask) != smb_fmask) {
4038 return False;
4041 return True;
4045 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4046 * of file flags and birth (create) time.
4048 static char *store_file_unix_basic_info2(connection_struct *conn,
4049 char *pdata,
4050 files_struct *fsp,
4051 const SMB_STRUCT_STAT *psbuf)
4053 uint32 file_flags = 0;
4054 uint32 flags_mask = 0;
4056 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4058 /* Create (birth) time 64 bit */
4059 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4060 pdata += 8;
4062 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4063 SIVAL(pdata, 0, file_flags); /* flags */
4064 SIVAL(pdata, 4, flags_mask); /* mask */
4065 pdata += 8;
4067 return pdata;
4070 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4071 const struct stream_struct *streams,
4072 char *data,
4073 unsigned int max_data_bytes,
4074 unsigned int *data_size)
4076 unsigned int i;
4077 unsigned int ofs = 0;
4079 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4080 unsigned int next_offset;
4081 size_t namelen;
4082 smb_ucs2_t *namebuf;
4084 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4085 streams[i].name, &namelen) ||
4086 namelen <= 2)
4088 return NT_STATUS_INVALID_PARAMETER;
4092 * name_buf is now null-terminated, we need to marshall as not
4093 * terminated
4096 namelen -= 2;
4098 SIVAL(data, ofs+4, namelen);
4099 SOFF_T(data, ofs+8, streams[i].size);
4100 SOFF_T(data, ofs+16, streams[i].alloc_size);
4101 memcpy(data+ofs+24, namebuf, namelen);
4102 TALLOC_FREE(namebuf);
4104 next_offset = ofs + 24 + namelen;
4106 if (i == num_streams-1) {
4107 SIVAL(data, ofs, 0);
4109 else {
4110 unsigned int align = ndr_align_size(next_offset, 8);
4112 memset(data+next_offset, 0, align);
4113 next_offset += align;
4115 SIVAL(data, ofs, next_offset - ofs);
4116 ofs = next_offset;
4119 ofs = next_offset;
4122 *data_size = ofs;
4124 return NT_STATUS_OK;
4127 /****************************************************************************
4128 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4129 ****************************************************************************/
4131 static void call_trans2qpipeinfo(connection_struct *conn,
4132 struct smb_request *req,
4133 unsigned int tran_call,
4134 char **pparams, int total_params,
4135 char **ppdata, int total_data,
4136 unsigned int max_data_bytes)
4138 char *params = *pparams;
4139 char *pdata = *ppdata;
4140 unsigned int data_size = 0;
4141 unsigned int param_size = 2;
4142 uint16 info_level;
4143 files_struct *fsp;
4145 if (!params) {
4146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4147 return;
4150 if (total_params < 4) {
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 return;
4155 fsp = file_fsp(req, SVAL(params,0));
4156 if (!fsp_is_np(fsp)) {
4157 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4158 return;
4161 info_level = SVAL(params,2);
4163 *pparams = (char *)SMB_REALLOC(*pparams,2);
4164 if (*pparams == NULL) {
4165 reply_nterror(req, NT_STATUS_NO_MEMORY);
4166 return;
4168 params = *pparams;
4169 SSVAL(params,0,0);
4170 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4171 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4172 if (*ppdata == NULL ) {
4173 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 return;
4176 pdata = *ppdata;
4178 switch (info_level) {
4179 case SMB_FILE_STANDARD_INFORMATION:
4180 memset(pdata,0,24);
4181 SOFF_T(pdata,0,4096LL);
4182 SIVAL(pdata,16,1);
4183 SIVAL(pdata,20,1);
4184 data_size = 24;
4185 break;
4187 default:
4188 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4189 return;
4192 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4193 max_data_bytes);
4195 return;
4198 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4199 TALLOC_CTX *mem_ctx,
4200 uint16_t info_level,
4201 files_struct *fsp,
4202 struct smb_filename *smb_fname,
4203 bool delete_pending,
4204 struct timespec write_time_ts,
4205 struct ea_list *ea_list,
4206 int lock_data_count,
4207 char *lock_data,
4208 uint16_t flags2,
4209 unsigned int max_data_bytes,
4210 char **ppdata,
4211 unsigned int *pdata_size)
4213 char *pdata = *ppdata;
4214 char *dstart, *dend;
4215 unsigned int data_size;
4216 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4217 time_t create_time, mtime, atime, c_time;
4218 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4219 char *p;
4220 char *base_name;
4221 char *dos_fname;
4222 int mode;
4223 int nlink;
4224 NTSTATUS status;
4225 uint64_t file_size = 0;
4226 uint64_t pos = 0;
4227 uint64_t allocation_size = 0;
4228 uint64_t file_index = 0;
4229 uint32_t access_mask = 0;
4231 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4232 return NT_STATUS_INVALID_LEVEL;
4235 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4236 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4237 info_level, max_data_bytes));
4239 mode = dos_mode(conn, smb_fname);
4240 nlink = psbuf->st_ex_nlink;
4242 if (nlink && (mode&aDIR)) {
4243 nlink = 1;
4246 if ((nlink > 0) && delete_pending) {
4247 nlink -= 1;
4250 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4251 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4252 if (*ppdata == NULL) {
4253 return NT_STATUS_NO_MEMORY;
4255 pdata = *ppdata;
4256 dstart = pdata;
4257 dend = dstart + data_size - 1;
4259 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4260 update_stat_ex_mtime(psbuf, write_time_ts);
4263 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4264 mtime_ts = psbuf->st_ex_mtime;
4265 atime_ts = psbuf->st_ex_atime;
4266 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4268 if (lp_dos_filetime_resolution(SNUM(conn))) {
4269 dos_filetime_timespec(&create_time_ts);
4270 dos_filetime_timespec(&mtime_ts);
4271 dos_filetime_timespec(&atime_ts);
4272 dos_filetime_timespec(&ctime_ts);
4275 create_time = convert_timespec_to_time_t(create_time_ts);
4276 mtime = convert_timespec_to_time_t(mtime_ts);
4277 atime = convert_timespec_to_time_t(atime_ts);
4278 c_time = convert_timespec_to_time_t(ctime_ts);
4280 p = strrchr_m(smb_fname->base_name,'/');
4281 if (!p)
4282 base_name = smb_fname->base_name;
4283 else
4284 base_name = p+1;
4286 /* NT expects the name to be in an exact form of the *full*
4287 filename. See the trans2 torture test */
4288 if (ISDOT(base_name)) {
4289 dos_fname = talloc_strdup(mem_ctx, "\\");
4290 if (!dos_fname) {
4291 return NT_STATUS_NO_MEMORY;
4293 } else {
4294 dos_fname = talloc_asprintf(mem_ctx,
4295 "\\%s",
4296 smb_fname->base_name);
4297 if (!dos_fname) {
4298 return NT_STATUS_NO_MEMORY;
4300 if (is_ntfs_stream_smb_fname(smb_fname)) {
4301 dos_fname = talloc_asprintf(dos_fname, "%s",
4302 smb_fname->stream_name);
4303 if (!dos_fname) {
4304 return NT_STATUS_NO_MEMORY;
4308 string_replace(dos_fname, '/', '\\');
4311 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4313 if (!fsp) {
4314 /* Do we have this path open ? */
4315 files_struct *fsp1;
4316 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4317 fsp1 = file_find_di_first(fileid);
4318 if (fsp1 && fsp1->initial_allocation_size) {
4319 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4323 if (!(mode & aDIR)) {
4324 file_size = get_file_size_stat(psbuf);
4327 if (fsp) {
4328 pos = fsp->fh->position_information;
4331 if (fsp) {
4332 access_mask = fsp->access_mask;
4333 } else {
4334 /* GENERIC_EXECUTE mapping from Windows */
4335 access_mask = 0x12019F;
4338 /* This should be an index number - looks like
4339 dev/ino to me :-)
4341 I think this causes us to fail the IFSKIT
4342 BasicFileInformationTest. -tpot */
4343 file_index = get_FileIndex(conn, psbuf);
4345 switch (info_level) {
4346 case SMB_INFO_STANDARD:
4347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4348 data_size = 22;
4349 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4350 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4351 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4352 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4353 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4354 SSVAL(pdata,l1_attrFile,mode);
4355 break;
4357 case SMB_INFO_QUERY_EA_SIZE:
4359 unsigned int ea_size =
4360 estimate_ea_size(conn, fsp,
4361 smb_fname->base_name);
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4363 data_size = 26;
4364 srv_put_dos_date2(pdata,0,create_time);
4365 srv_put_dos_date2(pdata,4,atime);
4366 srv_put_dos_date2(pdata,8,mtime); /* write time */
4367 SIVAL(pdata,12,(uint32)file_size);
4368 SIVAL(pdata,16,(uint32)allocation_size);
4369 SSVAL(pdata,20,mode);
4370 SIVAL(pdata,22,ea_size);
4371 break;
4374 case SMB_INFO_IS_NAME_VALID:
4375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4376 if (fsp) {
4377 /* os/2 needs this ? really ?*/
4378 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4380 /* This is only reached for qpathinfo */
4381 data_size = 0;
4382 break;
4384 case SMB_INFO_QUERY_EAS_FROM_LIST:
4386 size_t total_ea_len = 0;
4387 struct ea_list *ea_file_list = NULL;
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4391 ea_file_list =
4392 get_ea_list_from_file(mem_ctx, conn, fsp,
4393 smb_fname->base_name,
4394 &total_ea_len);
4395 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4397 if (!ea_list || (total_ea_len > data_size)) {
4398 data_size = 4;
4399 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4400 break;
4403 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4404 break;
4407 case SMB_INFO_QUERY_ALL_EAS:
4409 /* We have data_size bytes to put EA's into. */
4410 size_t total_ea_len = 0;
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4414 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4415 smb_fname->base_name,
4416 &total_ea_len);
4417 if (!ea_list || (total_ea_len > data_size)) {
4418 data_size = 4;
4419 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4420 break;
4423 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4424 break;
4427 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4429 /* This is FileFullEaInformation - 0xF which maps to
4430 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4432 /* We have data_size bytes to put EA's into. */
4433 size_t total_ea_len = 0;
4434 struct ea_list *ea_file_list = NULL;
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4438 /*TODO: add filtering and index handling */
4440 ea_file_list =
4441 get_ea_list_from_file(mem_ctx, conn, fsp,
4442 smb_fname->base_name,
4443 &total_ea_len);
4444 if (!ea_file_list) {
4445 return NT_STATUS_NO_EAS_ON_FILE;
4448 status = fill_ea_chained_buffer(mem_ctx,
4449 pdata,
4450 data_size,
4451 &data_size,
4452 conn, ea_file_list);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 return status;
4456 break;
4459 case SMB_FILE_BASIC_INFORMATION:
4460 case SMB_QUERY_FILE_BASIC_INFO:
4462 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4464 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4465 } else {
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4467 data_size = 40;
4468 SIVAL(pdata,36,0);
4470 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4471 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4472 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4473 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4474 SIVAL(pdata,32,mode);
4476 DEBUG(5,("SMB_QFBI - "));
4477 DEBUG(5,("create: %s ", ctime(&create_time)));
4478 DEBUG(5,("access: %s ", ctime(&atime)));
4479 DEBUG(5,("write: %s ", ctime(&mtime)));
4480 DEBUG(5,("change: %s ", ctime(&c_time)));
4481 DEBUG(5,("mode: %x\n", mode));
4482 break;
4484 case SMB_FILE_STANDARD_INFORMATION:
4485 case SMB_QUERY_FILE_STANDARD_INFO:
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4488 data_size = 24;
4489 SOFF_T(pdata,0,allocation_size);
4490 SOFF_T(pdata,8,file_size);
4491 SIVAL(pdata,16,nlink);
4492 SCVAL(pdata,20,delete_pending?1:0);
4493 SCVAL(pdata,21,(mode&aDIR)?1:0);
4494 SSVAL(pdata,22,0); /* Padding. */
4495 break;
4497 case SMB_FILE_EA_INFORMATION:
4498 case SMB_QUERY_FILE_EA_INFO:
4500 unsigned int ea_size =
4501 estimate_ea_size(conn, fsp, smb_fname->base_name);
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4503 data_size = 4;
4504 SIVAL(pdata,0,ea_size);
4505 break;
4508 /* Get the 8.3 name - used if NT SMB was negotiated. */
4509 case SMB_QUERY_FILE_ALT_NAME_INFO:
4510 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4512 int len;
4513 char mangled_name[13];
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4515 if (!name_to_8_3(base_name,mangled_name,
4516 True,conn->params)) {
4517 return NT_STATUS_NO_MEMORY;
4519 len = srvstr_push(dstart, flags2,
4520 pdata+4, mangled_name,
4521 PTR_DIFF(dend, pdata+4),
4522 STR_UNICODE);
4523 data_size = 4 + len;
4524 SIVAL(pdata,0,len);
4525 break;
4528 case SMB_QUERY_FILE_NAME_INFO:
4530 int len;
4532 this must be *exactly* right for ACLs on mapped drives to work
4534 len = srvstr_push(dstart, flags2,
4535 pdata+4, dos_fname,
4536 PTR_DIFF(dend, pdata+4),
4537 STR_UNICODE);
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4539 data_size = 4 + len;
4540 SIVAL(pdata,0,len);
4541 break;
4544 case SMB_FILE_ALLOCATION_INFORMATION:
4545 case SMB_QUERY_FILE_ALLOCATION_INFO:
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4547 data_size = 8;
4548 SOFF_T(pdata,0,allocation_size);
4549 break;
4551 case SMB_FILE_END_OF_FILE_INFORMATION:
4552 case SMB_QUERY_FILE_END_OF_FILEINFO:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4554 data_size = 8;
4555 SOFF_T(pdata,0,file_size);
4556 break;
4558 case SMB_QUERY_FILE_ALL_INFO:
4559 case SMB_FILE_ALL_INFORMATION:
4561 int len;
4562 unsigned int ea_size =
4563 estimate_ea_size(conn, fsp, smb_fname->base_name);
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4565 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4566 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4567 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4568 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4569 SIVAL(pdata,32,mode);
4570 SIVAL(pdata,36,0); /* padding. */
4571 pdata += 40;
4572 SOFF_T(pdata,0,allocation_size);
4573 SOFF_T(pdata,8,file_size);
4574 SIVAL(pdata,16,nlink);
4575 SCVAL(pdata,20,delete_pending);
4576 SCVAL(pdata,21,(mode&aDIR)?1:0);
4577 SSVAL(pdata,22,0);
4578 pdata += 24;
4579 SIVAL(pdata,0,ea_size);
4580 pdata += 4; /* EA info */
4581 len = srvstr_push(dstart, flags2,
4582 pdata+4, dos_fname,
4583 PTR_DIFF(dend, pdata+4),
4584 STR_UNICODE);
4585 SIVAL(pdata,0,len);
4586 pdata += 4 + len;
4587 data_size = PTR_DIFF(pdata,(*ppdata));
4588 break;
4591 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4593 int len;
4594 unsigned int ea_size =
4595 estimate_ea_size(conn, fsp, smb_fname->base_name);
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4597 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4598 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4599 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4600 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4601 SIVAL(pdata, 0x20, mode);
4602 SIVAL(pdata, 0x24, 0); /* padding. */
4603 SBVAL(pdata, 0x28, allocation_size);
4604 SBVAL(pdata, 0x30, file_size);
4605 SIVAL(pdata, 0x38, nlink);
4606 SCVAL(pdata, 0x3C, delete_pending);
4607 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4608 SSVAL(pdata, 0x3E, 0); /* padding */
4609 SBVAL(pdata, 0x40, file_index);
4610 SIVAL(pdata, 0x48, ea_size);
4611 SIVAL(pdata, 0x4C, access_mask);
4612 SBVAL(pdata, 0x50, pos);
4613 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4614 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4616 pdata += 0x60;
4618 len = srvstr_push(dstart, flags2,
4619 pdata+4, dos_fname,
4620 PTR_DIFF(dend, pdata+4),
4621 STR_UNICODE);
4622 SIVAL(pdata,0,len);
4623 pdata += 4 + len;
4624 data_size = PTR_DIFF(pdata,(*ppdata));
4625 break;
4627 case SMB_FILE_INTERNAL_INFORMATION:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4630 SBVAL(pdata, 0, file_index);
4631 data_size = 8;
4632 break;
4634 case SMB_FILE_ACCESS_INFORMATION:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4636 SIVAL(pdata, 0, access_mask);
4637 data_size = 4;
4638 break;
4640 case SMB_FILE_NAME_INFORMATION:
4641 /* Pathname with leading '\'. */
4643 size_t byte_len;
4644 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4646 SIVAL(pdata,0,byte_len);
4647 data_size = 4 + byte_len;
4648 break;
4651 case SMB_FILE_DISPOSITION_INFORMATION:
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4653 data_size = 1;
4654 SCVAL(pdata,0,delete_pending);
4655 break;
4657 case SMB_FILE_POSITION_INFORMATION:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4659 data_size = 8;
4660 SOFF_T(pdata,0,pos);
4661 break;
4663 case SMB_FILE_MODE_INFORMATION:
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4665 SIVAL(pdata,0,mode);
4666 data_size = 4;
4667 break;
4669 case SMB_FILE_ALIGNMENT_INFORMATION:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4671 SIVAL(pdata,0,0); /* No alignment needed. */
4672 data_size = 4;
4673 break;
4676 * NT4 server just returns "invalid query" to this - if we try
4677 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4678 * want this. JRA.
4680 /* The first statement above is false - verified using Thursby
4681 * client against NT4 -- gcolley.
4683 case SMB_QUERY_FILE_STREAM_INFO:
4684 case SMB_FILE_STREAM_INFORMATION: {
4685 unsigned int num_streams;
4686 struct stream_struct *streams;
4688 DEBUG(10,("smbd_do_qfilepathinfo: "
4689 "SMB_FILE_STREAM_INFORMATION\n"));
4691 if (is_ntfs_stream_smb_fname(smb_fname)) {
4692 return NT_STATUS_INVALID_PARAMETER;
4695 status = SMB_VFS_STREAMINFO(
4696 conn, fsp, smb_fname->base_name, talloc_tos(),
4697 &num_streams, &streams);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 DEBUG(10, ("could not get stream info: %s\n",
4701 nt_errstr(status)));
4702 return status;
4705 status = marshall_stream_info(num_streams, streams,
4706 pdata, max_data_bytes,
4707 &data_size);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 DEBUG(10, ("marshall_stream_info failed: %s\n",
4711 nt_errstr(status)));
4712 return status;
4715 TALLOC_FREE(streams);
4717 break;
4719 case SMB_QUERY_COMPRESSION_INFO:
4720 case SMB_FILE_COMPRESSION_INFORMATION:
4721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4722 SOFF_T(pdata,0,file_size);
4723 SIVAL(pdata,8,0); /* ??? */
4724 SIVAL(pdata,12,0); /* ??? */
4725 data_size = 16;
4726 break;
4728 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4730 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4731 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4732 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4733 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4734 SOFF_T(pdata,32,allocation_size);
4735 SOFF_T(pdata,40,file_size);
4736 SIVAL(pdata,48,mode);
4737 SIVAL(pdata,52,0); /* ??? */
4738 data_size = 56;
4739 break;
4741 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4743 SIVAL(pdata,0,mode);
4744 SIVAL(pdata,4,0);
4745 data_size = 8;
4746 break;
4749 * CIFS UNIX Extensions.
4752 case SMB_QUERY_FILE_UNIX_BASIC:
4754 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4755 data_size = PTR_DIFF(pdata,(*ppdata));
4757 DEBUG(4,("smbd_do_qfilepathinfo: "
4758 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4759 dump_data(4, (uint8_t *)(*ppdata), data_size);
4761 break;
4763 case SMB_QUERY_FILE_UNIX_INFO2:
4765 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4766 data_size = PTR_DIFF(pdata,(*ppdata));
4769 int i;
4770 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4772 for (i=0; i<100; i++)
4773 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4774 DEBUG(4,("\n"));
4777 break;
4779 case SMB_QUERY_FILE_UNIX_LINK:
4781 int len;
4782 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4784 if (!buffer) {
4785 return NT_STATUS_NO_MEMORY;
4788 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4789 #ifdef S_ISLNK
4790 if(!S_ISLNK(psbuf->st_ex_mode)) {
4791 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4793 #else
4794 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4795 #endif
4796 len = SMB_VFS_READLINK(conn,
4797 smb_fname->base_name,
4798 buffer, PATH_MAX);
4799 if (len == -1) {
4800 return map_nt_error_from_unix(errno);
4802 buffer[len] = 0;
4803 len = srvstr_push(dstart, flags2,
4804 pdata, buffer,
4805 PTR_DIFF(dend, pdata),
4806 STR_TERMINATE);
4807 pdata += len;
4808 data_size = PTR_DIFF(pdata,(*ppdata));
4810 break;
4813 #if defined(HAVE_POSIX_ACLS)
4814 case SMB_QUERY_POSIX_ACL:
4816 SMB_ACL_T file_acl = NULL;
4817 SMB_ACL_T def_acl = NULL;
4818 uint16 num_file_acls = 0;
4819 uint16 num_def_acls = 0;
4821 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4822 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4823 } else {
4824 file_acl =
4825 SMB_VFS_SYS_ACL_GET_FILE(conn,
4826 smb_fname->base_name,
4827 SMB_ACL_TYPE_ACCESS);
4830 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4831 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4832 "not implemented on "
4833 "filesystem containing %s\n",
4834 smb_fname->base_name));
4835 return NT_STATUS_NOT_IMPLEMENTED;
4838 if (S_ISDIR(psbuf->st_ex_mode)) {
4839 if (fsp && fsp->is_directory) {
4840 def_acl =
4841 SMB_VFS_SYS_ACL_GET_FILE(
4842 conn,
4843 fsp->fsp_name->base_name,
4844 SMB_ACL_TYPE_DEFAULT);
4845 } else {
4846 def_acl =
4847 SMB_VFS_SYS_ACL_GET_FILE(
4848 conn,
4849 smb_fname->base_name,
4850 SMB_ACL_TYPE_DEFAULT);
4852 def_acl = free_empty_sys_acl(conn, def_acl);
4855 num_file_acls = count_acl_entries(conn, file_acl);
4856 num_def_acls = count_acl_entries(conn, def_acl);
4858 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4859 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4860 data_size,
4861 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4862 SMB_POSIX_ACL_HEADER_SIZE) ));
4863 if (file_acl) {
4864 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4866 if (def_acl) {
4867 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4869 return NT_STATUS_BUFFER_TOO_SMALL;
4872 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4873 SSVAL(pdata,2,num_file_acls);
4874 SSVAL(pdata,4,num_def_acls);
4875 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4876 if (file_acl) {
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4879 if (def_acl) {
4880 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4882 return NT_STATUS_INTERNAL_ERROR;
4884 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4885 if (file_acl) {
4886 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4888 if (def_acl) {
4889 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4891 return NT_STATUS_INTERNAL_ERROR;
4894 if (file_acl) {
4895 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4897 if (def_acl) {
4898 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4900 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4901 break;
4903 #endif
4906 case SMB_QUERY_POSIX_LOCK:
4908 uint64_t count;
4909 uint64_t offset;
4910 uint64_t smblctx;
4911 enum brl_type lock_type;
4913 /* We need an open file with a real fd for this. */
4914 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4915 return NT_STATUS_INVALID_LEVEL;
4918 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4919 return NT_STATUS_INVALID_PARAMETER;
4922 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4923 case POSIX_LOCK_TYPE_READ:
4924 lock_type = READ_LOCK;
4925 break;
4926 case POSIX_LOCK_TYPE_WRITE:
4927 lock_type = WRITE_LOCK;
4928 break;
4929 case POSIX_LOCK_TYPE_UNLOCK:
4930 default:
4931 /* There's no point in asking for an unlock... */
4932 return NT_STATUS_INVALID_PARAMETER;
4935 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4936 #if defined(HAVE_LONGLONG)
4937 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4938 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4939 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4940 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4941 #else /* HAVE_LONGLONG */
4942 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4943 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4944 #endif /* HAVE_LONGLONG */
4946 status = query_lock(fsp,
4947 &smblctx,
4948 &count,
4949 &offset,
4950 &lock_type,
4951 POSIX_LOCK);
4953 if (ERROR_WAS_LOCK_DENIED(status)) {
4954 /* Here we need to report who has it locked... */
4955 data_size = POSIX_LOCK_DATA_SIZE;
4957 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4958 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4959 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4960 #if defined(HAVE_LONGLONG)
4961 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4962 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4963 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4964 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4965 #else /* HAVE_LONGLONG */
4966 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4967 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4968 #endif /* HAVE_LONGLONG */
4970 } else if (NT_STATUS_IS_OK(status)) {
4971 /* For success we just return a copy of what we sent
4972 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4973 data_size = POSIX_LOCK_DATA_SIZE;
4974 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4975 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4976 } else {
4977 return status;
4979 break;
4982 default:
4983 return NT_STATUS_INVALID_LEVEL;
4986 *pdata_size = data_size;
4987 return NT_STATUS_OK;
4990 /****************************************************************************
4991 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4992 file name or file id).
4993 ****************************************************************************/
4995 static void call_trans2qfilepathinfo(connection_struct *conn,
4996 struct smb_request *req,
4997 unsigned int tran_call,
4998 char **pparams, int total_params,
4999 char **ppdata, int total_data,
5000 unsigned int max_data_bytes)
5002 char *params = *pparams;
5003 char *pdata = *ppdata;
5004 uint16 info_level;
5005 unsigned int data_size = 0;
5006 unsigned int param_size = 2;
5007 struct smb_filename *smb_fname = NULL;
5008 bool delete_pending = False;
5009 struct timespec write_time_ts;
5010 files_struct *fsp = NULL;
5011 struct file_id fileid;
5012 struct ea_list *ea_list = NULL;
5013 int lock_data_count = 0;
5014 char *lock_data = NULL;
5015 NTSTATUS status = NT_STATUS_OK;
5017 if (!params) {
5018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5019 return;
5022 ZERO_STRUCT(write_time_ts);
5024 if (tran_call == TRANSACT2_QFILEINFO) {
5025 if (total_params < 4) {
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 return;
5030 if (IS_IPC(conn)) {
5031 call_trans2qpipeinfo(conn, req, tran_call,
5032 pparams, total_params,
5033 ppdata, total_data,
5034 max_data_bytes);
5035 return;
5038 fsp = file_fsp(req, SVAL(params,0));
5039 info_level = SVAL(params,2);
5041 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5043 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5044 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5045 return;
5048 /* Initial check for valid fsp ptr. */
5049 if (!check_fsp_open(conn, req, fsp)) {
5050 return;
5053 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5054 &smb_fname);
5055 if (!NT_STATUS_IS_OK(status)) {
5056 reply_nterror(req, status);
5057 return;
5060 if(fsp->fake_file_handle) {
5062 * This is actually for the QUOTA_FAKE_FILE --metze
5065 /* We know this name is ok, it's already passed the checks. */
5067 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5069 * This is actually a QFILEINFO on a directory
5070 * handle (returned from an NT SMB). NT5.0 seems
5071 * to do this call. JRA.
5074 if (INFO_LEVEL_IS_UNIX(info_level)) {
5075 /* Always do lstat for UNIX calls. */
5076 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5077 DEBUG(3,("call_trans2qfilepathinfo: "
5078 "SMB_VFS_LSTAT of %s failed "
5079 "(%s)\n",
5080 smb_fname_str_dbg(smb_fname),
5081 strerror(errno)));
5082 reply_nterror(req,
5083 map_nt_error_from_unix(errno));
5084 return;
5086 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5087 DEBUG(3,("call_trans2qfilepathinfo: "
5088 "SMB_VFS_STAT of %s failed (%s)\n",
5089 smb_fname_str_dbg(smb_fname),
5090 strerror(errno)));
5091 reply_nterror(req,
5092 map_nt_error_from_unix(errno));
5093 return;
5096 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5097 get_file_infos(fileid, &delete_pending, &write_time_ts);
5098 } else {
5100 * Original code - this is an open file.
5102 if (!check_fsp(conn, req, fsp)) {
5103 return;
5106 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5107 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5108 fsp->fnum, strerror(errno)));
5109 reply_nterror(req,
5110 map_nt_error_from_unix(errno));
5111 return;
5113 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5114 get_file_infos(fileid, &delete_pending, &write_time_ts);
5117 } else {
5118 char *fname = NULL;
5120 /* qpathinfo */
5121 if (total_params < 7) {
5122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5123 return;
5126 info_level = SVAL(params,0);
5128 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5130 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5131 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5132 return;
5135 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5136 total_params - 6,
5137 STR_TERMINATE, &status);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 reply_nterror(req, status);
5140 return;
5143 status = filename_convert(req,
5144 conn,
5145 req->flags2 & FLAGS2_DFS_PATHNAMES,
5146 fname,
5148 NULL,
5149 &smb_fname);
5150 if (!NT_STATUS_IS_OK(status)) {
5151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5152 reply_botherror(req,
5153 NT_STATUS_PATH_NOT_COVERED,
5154 ERRSRV, ERRbadpath);
5155 return;
5157 reply_nterror(req, status);
5158 return;
5161 /* If this is a stream, check if there is a delete_pending. */
5162 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5163 && is_ntfs_stream_smb_fname(smb_fname)) {
5164 struct smb_filename *smb_fname_base = NULL;
5166 /* Create an smb_filename with stream_name == NULL. */
5167 status =
5168 create_synthetic_smb_fname(talloc_tos(),
5169 smb_fname->base_name,
5170 NULL, NULL,
5171 &smb_fname_base);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 reply_nterror(req, status);
5174 return;
5177 if (INFO_LEVEL_IS_UNIX(info_level)) {
5178 /* Always do lstat for UNIX calls. */
5179 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5180 DEBUG(3,("call_trans2qfilepathinfo: "
5181 "SMB_VFS_LSTAT of %s failed "
5182 "(%s)\n",
5183 smb_fname_str_dbg(smb_fname_base),
5184 strerror(errno)));
5185 TALLOC_FREE(smb_fname_base);
5186 reply_nterror(req,
5187 map_nt_error_from_unix(errno));
5188 return;
5190 } else {
5191 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5192 DEBUG(3,("call_trans2qfilepathinfo: "
5193 "fileinfo of %s failed "
5194 "(%s)\n",
5195 smb_fname_str_dbg(smb_fname_base),
5196 strerror(errno)));
5197 TALLOC_FREE(smb_fname_base);
5198 reply_nterror(req,
5199 map_nt_error_from_unix(errno));
5200 return;
5204 fileid = vfs_file_id_from_sbuf(conn,
5205 &smb_fname_base->st);
5206 TALLOC_FREE(smb_fname_base);
5207 get_file_infos(fileid, &delete_pending, NULL);
5208 if (delete_pending) {
5209 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5210 return;
5214 if (INFO_LEVEL_IS_UNIX(info_level)) {
5215 /* Always do lstat for UNIX calls. */
5216 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5217 DEBUG(3,("call_trans2qfilepathinfo: "
5218 "SMB_VFS_LSTAT of %s failed (%s)\n",
5219 smb_fname_str_dbg(smb_fname),
5220 strerror(errno)));
5221 reply_nterror(req,
5222 map_nt_error_from_unix(errno));
5223 return;
5226 } else {
5227 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5228 DEBUG(3,("call_trans2qfilepathinfo: "
5229 "SMB_VFS_STAT of %s failed (%s)\n",
5230 smb_fname_str_dbg(smb_fname),
5231 strerror(errno)));
5232 reply_nterror(req,
5233 map_nt_error_from_unix(errno));
5234 return;
5238 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5239 get_file_infos(fileid, &delete_pending, &write_time_ts);
5240 if (delete_pending) {
5241 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5242 return;
5246 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5247 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5248 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5250 /* Pull out any data sent here before we realloc. */
5251 switch (info_level) {
5252 case SMB_INFO_QUERY_EAS_FROM_LIST:
5254 /* Pull any EA list from the data portion. */
5255 uint32 ea_size;
5257 if (total_data < 4) {
5258 reply_nterror(
5259 req, NT_STATUS_INVALID_PARAMETER);
5260 return;
5262 ea_size = IVAL(pdata,0);
5264 if (total_data > 0 && ea_size != total_data) {
5265 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5266 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5267 reply_nterror(
5268 req, NT_STATUS_INVALID_PARAMETER);
5269 return;
5272 if (!lp_ea_support(SNUM(conn))) {
5273 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5274 return;
5277 /* Pull out the list of names. */
5278 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5279 if (!ea_list) {
5280 reply_nterror(
5281 req, NT_STATUS_INVALID_PARAMETER);
5282 return;
5284 break;
5287 case SMB_QUERY_POSIX_LOCK:
5289 if (fsp == NULL || fsp->fh->fd == -1) {
5290 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5291 return;
5294 if (total_data != POSIX_LOCK_DATA_SIZE) {
5295 reply_nterror(
5296 req, NT_STATUS_INVALID_PARAMETER);
5297 return;
5300 /* Copy the lock range data. */
5301 lock_data = (char *)TALLOC_MEMDUP(
5302 req, pdata, total_data);
5303 if (!lock_data) {
5304 reply_nterror(req, NT_STATUS_NO_MEMORY);
5305 return;
5307 lock_data_count = total_data;
5309 default:
5310 break;
5313 *pparams = (char *)SMB_REALLOC(*pparams,2);
5314 if (*pparams == NULL) {
5315 reply_nterror(req, NT_STATUS_NO_MEMORY);
5316 return;
5318 params = *pparams;
5319 SSVAL(params,0,0);
5322 * draft-leach-cifs-v1-spec-02.txt
5323 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5324 * says:
5326 * The requested information is placed in the Data portion of the
5327 * transaction response. For the information levels greater than 0x100,
5328 * the transaction response has 1 parameter word which should be
5329 * ignored by the client.
5331 * However Windows only follows this rule for the IS_NAME_VALID call.
5333 switch (info_level) {
5334 case SMB_INFO_IS_NAME_VALID:
5335 param_size = 0;
5336 break;
5339 if ((info_level & 0xFF00) == 0xFF00) {
5341 * We use levels that start with 0xFF00
5342 * internally to represent SMB2 specific levels
5344 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5345 return;
5348 status = smbd_do_qfilepathinfo(conn, req, info_level,
5349 fsp, smb_fname,
5350 delete_pending, write_time_ts,
5351 ea_list,
5352 lock_data_count, lock_data,
5353 req->flags2, max_data_bytes,
5354 ppdata, &data_size);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 reply_nterror(req, status);
5357 return;
5360 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5361 max_data_bytes);
5363 return;
5366 /****************************************************************************
5367 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5368 code.
5369 ****************************************************************************/
5371 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5372 connection_struct *conn,
5373 struct smb_request *req,
5374 bool overwrite_if_exists,
5375 const struct smb_filename *smb_fname_old,
5376 struct smb_filename *smb_fname_new)
5378 NTSTATUS status = NT_STATUS_OK;
5380 /* source must already exist. */
5381 if (!VALID_STAT(smb_fname_old->st)) {
5382 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5385 if (VALID_STAT(smb_fname_new->st)) {
5386 if (overwrite_if_exists) {
5387 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5388 return NT_STATUS_FILE_IS_A_DIRECTORY;
5390 status = unlink_internals(conn,
5391 req,
5392 FILE_ATTRIBUTE_NORMAL,
5393 smb_fname_new,
5394 false);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 return status;
5398 } else {
5399 /* Disallow if newname already exists. */
5400 return NT_STATUS_OBJECT_NAME_COLLISION;
5404 /* No links from a directory. */
5405 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5406 return NT_STATUS_FILE_IS_A_DIRECTORY;
5409 /* Setting a hardlink to/from a stream isn't currently supported. */
5410 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5411 is_ntfs_stream_smb_fname(smb_fname_new)) {
5412 return NT_STATUS_INVALID_PARAMETER;
5415 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5416 smb_fname_old->base_name, smb_fname_new->base_name));
5418 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5419 smb_fname_new->base_name) != 0) {
5420 status = map_nt_error_from_unix(errno);
5421 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5422 nt_errstr(status), smb_fname_old->base_name,
5423 smb_fname_new->base_name));
5425 return status;
5428 /****************************************************************************
5429 Deal with setting the time from any of the setfilepathinfo functions.
5430 ****************************************************************************/
5432 NTSTATUS smb_set_file_time(connection_struct *conn,
5433 files_struct *fsp,
5434 const struct smb_filename *smb_fname,
5435 struct smb_file_time *ft,
5436 bool setting_write_time)
5438 struct smb_filename smb_fname_base;
5439 uint32 action =
5440 FILE_NOTIFY_CHANGE_LAST_ACCESS
5441 |FILE_NOTIFY_CHANGE_LAST_WRITE
5442 |FILE_NOTIFY_CHANGE_CREATION;
5444 if (!VALID_STAT(smb_fname->st)) {
5445 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5448 /* get some defaults (no modifications) if any info is zero or -1. */
5449 if (null_timespec(ft->create_time)) {
5450 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5453 if (null_timespec(ft->atime)) {
5454 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5457 if (null_timespec(ft->mtime)) {
5458 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5461 if (!setting_write_time) {
5462 /* ft->mtime comes from change time, not write time. */
5463 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5466 /* Ensure the resolution is the correct for
5467 * what we can store on this filesystem. */
5469 round_timespec(conn->ts_res, &ft->create_time);
5470 round_timespec(conn->ts_res, &ft->ctime);
5471 round_timespec(conn->ts_res, &ft->atime);
5472 round_timespec(conn->ts_res, &ft->mtime);
5474 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5475 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5476 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5477 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5478 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5479 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5480 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5483 if (setting_write_time) {
5485 * This was a Windows setfileinfo on an open file.
5486 * NT does this a lot. We also need to
5487 * set the time here, as it can be read by
5488 * FindFirst/FindNext and with the patch for bug #2045
5489 * in smbd/fileio.c it ensures that this timestamp is
5490 * kept sticky even after a write. We save the request
5491 * away and will set it on file close and after a write. JRA.
5494 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5495 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5497 if (fsp != NULL) {
5498 if (fsp->base_fsp) {
5499 set_sticky_write_time_fsp(fsp->base_fsp,
5500 ft->mtime);
5501 } else {
5502 set_sticky_write_time_fsp(fsp, ft->mtime);
5504 } else {
5505 set_sticky_write_time_path(
5506 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5507 ft->mtime);
5511 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5513 /* Always call ntimes on the base, even if a stream was passed in. */
5514 smb_fname_base = *smb_fname;
5515 smb_fname_base.stream_name = NULL;
5517 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5518 return map_nt_error_from_unix(errno);
5521 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5522 smb_fname->base_name);
5523 return NT_STATUS_OK;
5526 /****************************************************************************
5527 Deal with setting the dosmode from any of the setfilepathinfo functions.
5528 ****************************************************************************/
5530 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5531 const struct smb_filename *smb_fname,
5532 uint32 dosmode)
5534 struct smb_filename *smb_fname_base = NULL;
5535 NTSTATUS status;
5537 if (!VALID_STAT(smb_fname->st)) {
5538 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5541 /* Always operate on the base_name, even if a stream was passed in. */
5542 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5543 NULL, &smb_fname->st,
5544 &smb_fname_base);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 return status;
5549 if (dosmode) {
5550 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5551 dosmode |= aDIR;
5552 } else {
5553 dosmode &= ~aDIR;
5557 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5559 /* check the mode isn't different, before changing it */
5560 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5561 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5562 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5563 (unsigned int)dosmode));
5565 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5566 false)) {
5567 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5568 "%s failed (%s)\n",
5569 smb_fname_str_dbg(smb_fname_base),
5570 strerror(errno)));
5571 status = map_nt_error_from_unix(errno);
5572 goto out;
5575 status = NT_STATUS_OK;
5576 out:
5577 TALLOC_FREE(smb_fname_base);
5578 return status;
5581 /****************************************************************************
5582 Deal with setting the size from any of the setfilepathinfo functions.
5583 ****************************************************************************/
5585 static NTSTATUS smb_set_file_size(connection_struct *conn,
5586 struct smb_request *req,
5587 files_struct *fsp,
5588 const struct smb_filename *smb_fname,
5589 const SMB_STRUCT_STAT *psbuf,
5590 SMB_OFF_T size,
5591 bool fail_after_createfile)
5593 NTSTATUS status = NT_STATUS_OK;
5594 struct smb_filename *smb_fname_tmp = NULL;
5595 files_struct *new_fsp = NULL;
5597 if (!VALID_STAT(*psbuf)) {
5598 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5601 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5603 if (size == get_file_size_stat(psbuf)) {
5604 return NT_STATUS_OK;
5607 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5608 smb_fname_str_dbg(smb_fname), (double)size));
5610 if (fsp && fsp->fh->fd != -1) {
5611 /* Handle based call. */
5612 if (vfs_set_filelen(fsp, size) == -1) {
5613 return map_nt_error_from_unix(errno);
5615 trigger_write_time_update_immediate(fsp);
5616 return NT_STATUS_OK;
5619 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5620 if (!NT_STATUS_IS_OK(status)) {
5621 return status;
5624 smb_fname_tmp->st = *psbuf;
5626 status = SMB_VFS_CREATE_FILE(
5627 conn, /* conn */
5628 req, /* req */
5629 0, /* root_dir_fid */
5630 smb_fname_tmp, /* fname */
5631 FILE_WRITE_DATA, /* access_mask */
5632 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5633 FILE_SHARE_DELETE),
5634 FILE_OPEN, /* create_disposition*/
5635 0, /* create_options */
5636 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5637 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5638 0, /* allocation_size */
5639 0, /* private_flags */
5640 NULL, /* sd */
5641 NULL, /* ea_list */
5642 &new_fsp, /* result */
5643 NULL); /* pinfo */
5645 TALLOC_FREE(smb_fname_tmp);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 /* NB. We check for open_was_deferred in the caller. */
5649 return status;
5652 /* See RAW-SFILEINFO-END-OF-FILE */
5653 if (fail_after_createfile) {
5654 close_file(req, new_fsp,NORMAL_CLOSE);
5655 return NT_STATUS_INVALID_LEVEL;
5658 if (vfs_set_filelen(new_fsp, size) == -1) {
5659 status = map_nt_error_from_unix(errno);
5660 close_file(req, new_fsp,NORMAL_CLOSE);
5661 return status;
5664 trigger_write_time_update_immediate(new_fsp);
5665 close_file(req, new_fsp,NORMAL_CLOSE);
5666 return NT_STATUS_OK;
5669 /****************************************************************************
5670 Deal with SMB_INFO_SET_EA.
5671 ****************************************************************************/
5673 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5674 const char *pdata,
5675 int total_data,
5676 files_struct *fsp,
5677 const struct smb_filename *smb_fname)
5679 struct ea_list *ea_list = NULL;
5680 TALLOC_CTX *ctx = NULL;
5681 NTSTATUS status = NT_STATUS_OK;
5683 if (total_data < 10) {
5685 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5686 length. They seem to have no effect. Bug #3212. JRA */
5688 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5689 /* We're done. We only get EA info in this call. */
5690 return NT_STATUS_OK;
5693 return NT_STATUS_INVALID_PARAMETER;
5696 if (IVAL(pdata,0) > total_data) {
5697 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5698 IVAL(pdata,0), (unsigned int)total_data));
5699 return NT_STATUS_INVALID_PARAMETER;
5702 ctx = talloc_tos();
5703 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5704 if (!ea_list) {
5705 return NT_STATUS_INVALID_PARAMETER;
5707 status = set_ea(conn, fsp, smb_fname, ea_list);
5709 return status;
5712 /****************************************************************************
5713 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5714 ****************************************************************************/
5716 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5717 const char *pdata,
5718 int total_data,
5719 files_struct *fsp)
5721 struct ea_list *ea_list = NULL;
5722 NTSTATUS status;
5724 if (!fsp) {
5725 return NT_STATUS_INVALID_HANDLE;
5728 if (!lp_ea_support(SNUM(conn))) {
5729 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5730 "EA's not supported.\n",
5731 (unsigned int)total_data));
5732 return NT_STATUS_EAS_NOT_SUPPORTED;
5735 if (total_data < 10) {
5736 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5737 "too small.\n",
5738 (unsigned int)total_data));
5739 return NT_STATUS_INVALID_PARAMETER;
5742 ea_list = read_nttrans_ea_list(talloc_tos(),
5743 pdata,
5744 total_data);
5746 if (!ea_list) {
5747 return NT_STATUS_INVALID_PARAMETER;
5749 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5751 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5752 smb_fname_str_dbg(fsp->fsp_name),
5753 nt_errstr(status) ));
5755 return status;
5759 /****************************************************************************
5760 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5761 ****************************************************************************/
5763 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5764 const char *pdata,
5765 int total_data,
5766 files_struct *fsp,
5767 struct smb_filename *smb_fname)
5769 NTSTATUS status = NT_STATUS_OK;
5770 bool delete_on_close;
5771 uint32 dosmode = 0;
5773 if (total_data < 1) {
5774 return NT_STATUS_INVALID_PARAMETER;
5777 if (fsp == NULL) {
5778 return NT_STATUS_INVALID_HANDLE;
5781 delete_on_close = (CVAL(pdata,0) ? True : False);
5782 dosmode = dos_mode(conn, smb_fname);
5784 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5785 "delete_on_close = %u\n",
5786 smb_fname_str_dbg(smb_fname),
5787 (unsigned int)dosmode,
5788 (unsigned int)delete_on_close ));
5790 if (delete_on_close) {
5791 status = can_set_delete_on_close(fsp, dosmode);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 return status;
5797 /* The set is across all open files on this dev/inode pair. */
5798 if (!set_delete_on_close(fsp, delete_on_close,
5799 &conn->server_info->utok)) {
5800 return NT_STATUS_ACCESS_DENIED;
5802 return NT_STATUS_OK;
5805 /****************************************************************************
5806 Deal with SMB_FILE_POSITION_INFORMATION.
5807 ****************************************************************************/
5809 static NTSTATUS smb_file_position_information(connection_struct *conn,
5810 const char *pdata,
5811 int total_data,
5812 files_struct *fsp)
5814 uint64_t position_information;
5816 if (total_data < 8) {
5817 return NT_STATUS_INVALID_PARAMETER;
5820 if (fsp == NULL) {
5821 /* Ignore on pathname based set. */
5822 return NT_STATUS_OK;
5825 position_information = (uint64_t)IVAL(pdata,0);
5826 #ifdef LARGE_SMB_OFF_T
5827 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5828 #else /* LARGE_SMB_OFF_T */
5829 if (IVAL(pdata,4) != 0) {
5830 /* more than 32 bits? */
5831 return NT_STATUS_INVALID_PARAMETER;
5833 #endif /* LARGE_SMB_OFF_T */
5835 DEBUG(10,("smb_file_position_information: Set file position "
5836 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5837 (double)position_information));
5838 fsp->fh->position_information = position_information;
5839 return NT_STATUS_OK;
5842 /****************************************************************************
5843 Deal with SMB_FILE_MODE_INFORMATION.
5844 ****************************************************************************/
5846 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5847 const char *pdata,
5848 int total_data)
5850 uint32 mode;
5852 if (total_data < 4) {
5853 return NT_STATUS_INVALID_PARAMETER;
5855 mode = IVAL(pdata,0);
5856 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5857 return NT_STATUS_INVALID_PARAMETER;
5859 return NT_STATUS_OK;
5862 /****************************************************************************
5863 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5864 ****************************************************************************/
5866 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5867 struct smb_request *req,
5868 const char *pdata,
5869 int total_data,
5870 const struct smb_filename *smb_fname)
5872 char *link_target = NULL;
5873 const char *newname = smb_fname->base_name;
5874 TALLOC_CTX *ctx = talloc_tos();
5876 /* Set a symbolic link. */
5877 /* Don't allow this if follow links is false. */
5879 if (total_data == 0) {
5880 return NT_STATUS_INVALID_PARAMETER;
5883 if (!lp_symlinks(SNUM(conn))) {
5884 return NT_STATUS_ACCESS_DENIED;
5887 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5888 total_data, STR_TERMINATE);
5890 if (!link_target) {
5891 return NT_STATUS_INVALID_PARAMETER;
5894 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5895 newname, link_target ));
5897 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5898 return map_nt_error_from_unix(errno);
5901 return NT_STATUS_OK;
5904 /****************************************************************************
5905 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5906 ****************************************************************************/
5908 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5909 struct smb_request *req,
5910 const char *pdata, int total_data,
5911 struct smb_filename *smb_fname_new)
5913 char *oldname = NULL;
5914 struct smb_filename *smb_fname_old = NULL;
5915 TALLOC_CTX *ctx = talloc_tos();
5916 NTSTATUS status = NT_STATUS_OK;
5918 /* Set a hard link. */
5919 if (total_data == 0) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5924 total_data, STR_TERMINATE, &status);
5925 if (!NT_STATUS_IS_OK(status)) {
5926 return status;
5929 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5930 smb_fname_str_dbg(smb_fname_new), oldname));
5932 status = filename_convert(ctx,
5933 conn,
5934 req->flags2 & FLAGS2_DFS_PATHNAMES,
5935 oldname,
5937 NULL,
5938 &smb_fname_old);
5939 if (!NT_STATUS_IS_OK(status)) {
5940 return status;
5943 return hardlink_internals(ctx, conn, req, false,
5944 smb_fname_old, smb_fname_new);
5947 /****************************************************************************
5948 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5949 ****************************************************************************/
5951 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5952 struct smb_request *req,
5953 const char *pdata,
5954 int total_data,
5955 files_struct *fsp,
5956 struct smb_filename *smb_fname_src)
5958 bool overwrite;
5959 uint32_t len;
5960 char *newname = NULL;
5961 struct smb_filename *smb_fname_dst = NULL;
5962 NTSTATUS status = NT_STATUS_OK;
5963 TALLOC_CTX *ctx = talloc_tos();
5965 if (!fsp) {
5966 return NT_STATUS_INVALID_HANDLE;
5969 if (total_data < 20) {
5970 return NT_STATUS_INVALID_PARAMETER;
5973 overwrite = (CVAL(pdata,0) ? True : False);
5974 len = IVAL(pdata,16);
5976 if (len > (total_data - 20) || (len == 0)) {
5977 return NT_STATUS_INVALID_PARAMETER;
5980 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5981 &pdata[20], len, STR_TERMINATE,
5982 &status);
5983 if (!NT_STATUS_IS_OK(status)) {
5984 return status;
5987 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5988 newname));
5990 status = filename_convert(ctx,
5991 conn,
5992 req->flags2 & FLAGS2_DFS_PATHNAMES,
5993 newname,
5995 NULL,
5996 &smb_fname_dst);
5997 if (!NT_STATUS_IS_OK(status)) {
5998 return status;
6001 if (fsp->base_fsp) {
6002 /* newname must be a stream name. */
6003 if (newname[0] != ':') {
6004 return NT_STATUS_NOT_SUPPORTED;
6007 /* Create an smb_fname to call rename_internals_fsp() with. */
6008 status = create_synthetic_smb_fname(talloc_tos(),
6009 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6010 &smb_fname_dst);
6011 if (!NT_STATUS_IS_OK(status)) {
6012 goto out;
6016 * Set the original last component, since
6017 * rename_internals_fsp() requires it.
6019 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6020 newname);
6021 if (smb_fname_dst->original_lcomp == NULL) {
6022 status = NT_STATUS_NO_MEMORY;
6023 goto out;
6028 DEBUG(10,("smb2_file_rename_information: "
6029 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6030 fsp->fnum, fsp_str_dbg(fsp),
6031 smb_fname_str_dbg(smb_fname_dst)));
6032 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6033 overwrite);
6035 out:
6036 TALLOC_FREE(smb_fname_dst);
6037 return status;
6040 static NTSTATUS smb_file_link_information(connection_struct *conn,
6041 struct smb_request *req,
6042 const char *pdata,
6043 int total_data,
6044 files_struct *fsp,
6045 struct smb_filename *smb_fname_src)
6047 bool overwrite;
6048 uint32_t len;
6049 char *newname = NULL;
6050 struct smb_filename *smb_fname_dst = NULL;
6051 NTSTATUS status = NT_STATUS_OK;
6052 TALLOC_CTX *ctx = talloc_tos();
6054 if (!fsp) {
6055 return NT_STATUS_INVALID_HANDLE;
6058 if (total_data < 20) {
6059 return NT_STATUS_INVALID_PARAMETER;
6062 overwrite = (CVAL(pdata,0) ? true : false);
6063 len = IVAL(pdata,16);
6065 if (len > (total_data - 20) || (len == 0)) {
6066 return NT_STATUS_INVALID_PARAMETER;
6069 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6070 &pdata[20], len, STR_TERMINATE,
6071 &status);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 return status;
6076 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6077 newname));
6079 status = filename_convert(ctx,
6080 conn,
6081 req->flags2 & FLAGS2_DFS_PATHNAMES,
6082 newname,
6084 NULL,
6085 &smb_fname_dst);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 return status;
6090 if (fsp->base_fsp) {
6091 /* No stream names. */
6092 return NT_STATUS_NOT_SUPPORTED;
6095 DEBUG(10,("smb_file_link_information: "
6096 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6097 fsp->fnum, fsp_str_dbg(fsp),
6098 smb_fname_str_dbg(smb_fname_dst)));
6099 status = hardlink_internals(ctx,
6100 conn,
6101 req,
6102 overwrite,
6103 fsp->fsp_name,
6104 smb_fname_dst);
6106 TALLOC_FREE(smb_fname_dst);
6107 return status;
6110 /****************************************************************************
6111 Deal with SMB_FILE_RENAME_INFORMATION.
6112 ****************************************************************************/
6114 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6115 struct smb_request *req,
6116 const char *pdata,
6117 int total_data,
6118 files_struct *fsp,
6119 struct smb_filename *smb_fname_src)
6121 bool overwrite;
6122 uint32 root_fid;
6123 uint32 len;
6124 char *newname = NULL;
6125 struct smb_filename *smb_fname_dst = NULL;
6126 bool dest_has_wcard = False;
6127 NTSTATUS status = NT_STATUS_OK;
6128 char *p;
6129 TALLOC_CTX *ctx = talloc_tos();
6131 if (total_data < 13) {
6132 return NT_STATUS_INVALID_PARAMETER;
6135 overwrite = (CVAL(pdata,0) ? True : False);
6136 root_fid = IVAL(pdata,4);
6137 len = IVAL(pdata,8);
6139 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6144 len, 0, &status,
6145 &dest_has_wcard);
6146 if (!NT_STATUS_IS_OK(status)) {
6147 return status;
6150 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6151 newname));
6153 status = resolve_dfspath_wcard(ctx, conn,
6154 req->flags2 & FLAGS2_DFS_PATHNAMES,
6155 newname,
6156 true,
6157 &newname,
6158 &dest_has_wcard);
6159 if (!NT_STATUS_IS_OK(status)) {
6160 return status;
6163 /* Check the new name has no '/' characters. */
6164 if (strchr_m(newname, '/')) {
6165 return NT_STATUS_NOT_SUPPORTED;
6168 if (fsp && fsp->base_fsp) {
6169 /* newname must be a stream name. */
6170 if (newname[0] != ':') {
6171 return NT_STATUS_NOT_SUPPORTED;
6174 /* Create an smb_fname to call rename_internals_fsp() with. */
6175 status = create_synthetic_smb_fname(talloc_tos(),
6176 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6177 &smb_fname_dst);
6178 if (!NT_STATUS_IS_OK(status)) {
6179 goto out;
6183 * Set the original last component, since
6184 * rename_internals_fsp() requires it.
6186 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6187 newname);
6188 if (smb_fname_dst->original_lcomp == NULL) {
6189 status = NT_STATUS_NO_MEMORY;
6190 goto out;
6193 } else {
6195 * Build up an smb_fname_dst based on the filename passed in.
6196 * We basically just strip off the last component, and put on
6197 * the newname instead.
6199 char *base_name = NULL;
6201 /* newname must *not* be a stream name. */
6202 if (newname[0] == ':') {
6203 return NT_STATUS_NOT_SUPPORTED;
6207 * Strip off the last component (filename) of the path passed
6208 * in.
6210 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6211 if (!base_name) {
6212 return NT_STATUS_NO_MEMORY;
6214 p = strrchr_m(base_name, '/');
6215 if (p) {
6216 p[1] = '\0';
6217 } else {
6218 base_name = talloc_strdup(ctx, "./");
6219 if (!base_name) {
6220 return NT_STATUS_NO_MEMORY;
6223 /* Append the new name. */
6224 base_name = talloc_asprintf_append(base_name,
6225 "%s",
6226 newname);
6227 if (!base_name) {
6228 return NT_STATUS_NO_MEMORY;
6231 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6232 (UCF_SAVE_LCOMP |
6233 (dest_has_wcard ?
6234 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6235 0)));
6237 /* If an error we expect this to be
6238 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6240 if (!NT_STATUS_IS_OK(status)) {
6241 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6242 status)) {
6243 goto out;
6245 /* Create an smb_fname to call rename_internals_fsp() */
6246 status = create_synthetic_smb_fname(ctx,
6247 base_name, NULL,
6248 NULL,
6249 &smb_fname_dst);
6250 if (!NT_STATUS_IS_OK(status)) {
6251 goto out;
6256 if (fsp) {
6257 DEBUG(10,("smb_file_rename_information: "
6258 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6259 fsp->fnum, fsp_str_dbg(fsp),
6260 smb_fname_str_dbg(smb_fname_dst)));
6261 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6262 overwrite);
6263 } else {
6264 DEBUG(10,("smb_file_rename_information: "
6265 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6266 smb_fname_str_dbg(smb_fname_src),
6267 smb_fname_str_dbg(smb_fname_dst)));
6268 status = rename_internals(ctx, conn, req, smb_fname_src,
6269 smb_fname_dst, 0, overwrite, false,
6270 dest_has_wcard,
6271 FILE_WRITE_ATTRIBUTES);
6273 out:
6274 TALLOC_FREE(smb_fname_dst);
6275 return status;
6278 /****************************************************************************
6279 Deal with SMB_SET_POSIX_ACL.
6280 ****************************************************************************/
6282 #if defined(HAVE_POSIX_ACLS)
6283 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6284 const char *pdata,
6285 int total_data,
6286 files_struct *fsp,
6287 const struct smb_filename *smb_fname)
6289 uint16 posix_acl_version;
6290 uint16 num_file_acls;
6291 uint16 num_def_acls;
6292 bool valid_file_acls = True;
6293 bool valid_def_acls = True;
6295 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6296 return NT_STATUS_INVALID_PARAMETER;
6298 posix_acl_version = SVAL(pdata,0);
6299 num_file_acls = SVAL(pdata,2);
6300 num_def_acls = SVAL(pdata,4);
6302 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6303 valid_file_acls = False;
6304 num_file_acls = 0;
6307 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6308 valid_def_acls = False;
6309 num_def_acls = 0;
6312 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6313 return NT_STATUS_INVALID_PARAMETER;
6316 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6317 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6322 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6323 (unsigned int)num_file_acls,
6324 (unsigned int)num_def_acls));
6326 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6327 smb_fname->base_name, num_file_acls,
6328 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6329 return map_nt_error_from_unix(errno);
6332 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6333 smb_fname->base_name, &smb_fname->st, num_def_acls,
6334 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6335 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6336 return map_nt_error_from_unix(errno);
6338 return NT_STATUS_OK;
6340 #endif
6342 /****************************************************************************
6343 Deal with SMB_SET_POSIX_LOCK.
6344 ****************************************************************************/
6346 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6347 struct smb_request *req,
6348 const char *pdata,
6349 int total_data,
6350 files_struct *fsp)
6352 uint64_t count;
6353 uint64_t offset;
6354 uint64_t smblctx;
6355 bool blocking_lock = False;
6356 enum brl_type lock_type;
6358 NTSTATUS status = NT_STATUS_OK;
6360 if (fsp == NULL || fsp->fh->fd == -1) {
6361 return NT_STATUS_INVALID_HANDLE;
6364 if (total_data != POSIX_LOCK_DATA_SIZE) {
6365 return NT_STATUS_INVALID_PARAMETER;
6368 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6369 case POSIX_LOCK_TYPE_READ:
6370 lock_type = READ_LOCK;
6371 break;
6372 case POSIX_LOCK_TYPE_WRITE:
6373 /* Return the right POSIX-mappable error code for files opened read-only. */
6374 if (!fsp->can_write) {
6375 return NT_STATUS_INVALID_HANDLE;
6377 lock_type = WRITE_LOCK;
6378 break;
6379 case POSIX_LOCK_TYPE_UNLOCK:
6380 lock_type = UNLOCK_LOCK;
6381 break;
6382 default:
6383 return NT_STATUS_INVALID_PARAMETER;
6386 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6387 blocking_lock = False;
6388 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6389 blocking_lock = True;
6390 } else {
6391 return NT_STATUS_INVALID_PARAMETER;
6394 if (!lp_blocking_locks(SNUM(conn))) {
6395 blocking_lock = False;
6398 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6399 #if defined(HAVE_LONGLONG)
6400 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6401 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6402 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6403 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6404 #else /* HAVE_LONGLONG */
6405 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6406 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6407 #endif /* HAVE_LONGLONG */
6409 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6410 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6411 fsp_str_dbg(fsp),
6412 (unsigned int)lock_type,
6413 (unsigned long long)smblctx,
6414 (double)count,
6415 (double)offset ));
6417 if (lock_type == UNLOCK_LOCK) {
6418 status = do_unlock(req->sconn->msg_ctx,
6419 fsp,
6420 smblctx,
6421 count,
6422 offset,
6423 POSIX_LOCK);
6424 } else {
6425 uint64_t block_smblctx;
6427 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6428 fsp,
6429 smblctx,
6430 count,
6431 offset,
6432 lock_type,
6433 POSIX_LOCK,
6434 blocking_lock,
6435 &status,
6436 &block_smblctx,
6437 NULL);
6439 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6441 * A blocking lock was requested. Package up
6442 * this smb into a queued request and push it
6443 * onto the blocking lock queue.
6445 if(push_blocking_lock_request(br_lck,
6446 req,
6447 fsp,
6448 -1, /* infinite timeout. */
6450 smblctx,
6451 lock_type,
6452 POSIX_LOCK,
6453 offset,
6454 count,
6455 block_smblctx)) {
6456 TALLOC_FREE(br_lck);
6457 return status;
6460 TALLOC_FREE(br_lck);
6463 return status;
6466 /****************************************************************************
6467 Deal with SMB_SET_FILE_BASIC_INFO.
6468 ****************************************************************************/
6470 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6471 const char *pdata,
6472 int total_data,
6473 files_struct *fsp,
6474 const struct smb_filename *smb_fname)
6476 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6477 struct smb_file_time ft;
6478 uint32 dosmode = 0;
6479 NTSTATUS status = NT_STATUS_OK;
6481 ZERO_STRUCT(ft);
6483 if (total_data < 36) {
6484 return NT_STATUS_INVALID_PARAMETER;
6487 /* Set the attributes */
6488 dosmode = IVAL(pdata,32);
6489 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6490 if (!NT_STATUS_IS_OK(status)) {
6491 return status;
6494 /* create time */
6495 ft.create_time = interpret_long_date(pdata);
6497 /* access time */
6498 ft.atime = interpret_long_date(pdata+8);
6500 /* write time. */
6501 ft.mtime = interpret_long_date(pdata+16);
6503 /* change time. */
6504 ft.ctime = interpret_long_date(pdata+24);
6506 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6507 smb_fname_str_dbg(smb_fname)));
6509 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6510 true);
6513 /****************************************************************************
6514 Deal with SMB_INFO_STANDARD.
6515 ****************************************************************************/
6517 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6518 const char *pdata,
6519 int total_data,
6520 files_struct *fsp,
6521 const struct smb_filename *smb_fname)
6523 struct smb_file_time ft;
6525 ZERO_STRUCT(ft);
6527 if (total_data < 12) {
6528 return NT_STATUS_INVALID_PARAMETER;
6531 /* create time */
6532 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6533 /* access time */
6534 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6535 /* write time */
6536 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6538 DEBUG(10,("smb_set_info_standard: file %s\n",
6539 smb_fname_str_dbg(smb_fname)));
6541 return smb_set_file_time(conn,
6542 fsp,
6543 smb_fname,
6544 &ft,
6545 true);
6548 /****************************************************************************
6549 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6550 ****************************************************************************/
6552 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6553 struct smb_request *req,
6554 const char *pdata,
6555 int total_data,
6556 files_struct *fsp,
6557 struct smb_filename *smb_fname)
6559 uint64_t allocation_size = 0;
6560 NTSTATUS status = NT_STATUS_OK;
6561 files_struct *new_fsp = NULL;
6563 if (!VALID_STAT(smb_fname->st)) {
6564 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6567 if (total_data < 8) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 allocation_size = (uint64_t)IVAL(pdata,0);
6572 #ifdef LARGE_SMB_OFF_T
6573 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6574 #else /* LARGE_SMB_OFF_T */
6575 if (IVAL(pdata,4) != 0) {
6576 /* more than 32 bits? */
6577 return NT_STATUS_INVALID_PARAMETER;
6579 #endif /* LARGE_SMB_OFF_T */
6581 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6582 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6583 (double)allocation_size));
6585 if (allocation_size) {
6586 allocation_size = smb_roundup(conn, allocation_size);
6589 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6590 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6591 (double)allocation_size));
6593 if (fsp && fsp->fh->fd != -1) {
6594 /* Open file handle. */
6595 /* Only change if needed. */
6596 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6597 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6598 return map_nt_error_from_unix(errno);
6601 /* But always update the time. */
6603 * This is equivalent to a write. Ensure it's seen immediately
6604 * if there are no pending writes.
6606 trigger_write_time_update_immediate(fsp);
6607 return NT_STATUS_OK;
6610 /* Pathname or stat or directory file. */
6611 status = SMB_VFS_CREATE_FILE(
6612 conn, /* conn */
6613 req, /* req */
6614 0, /* root_dir_fid */
6615 smb_fname, /* fname */
6616 FILE_WRITE_DATA, /* access_mask */
6617 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6618 FILE_SHARE_DELETE),
6619 FILE_OPEN, /* create_disposition*/
6620 0, /* create_options */
6621 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6622 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6623 0, /* allocation_size */
6624 0, /* private_flags */
6625 NULL, /* sd */
6626 NULL, /* ea_list */
6627 &new_fsp, /* result */
6628 NULL); /* pinfo */
6630 if (!NT_STATUS_IS_OK(status)) {
6631 /* NB. We check for open_was_deferred in the caller. */
6632 return status;
6635 /* Only change if needed. */
6636 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6637 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6638 status = map_nt_error_from_unix(errno);
6639 close_file(req, new_fsp, NORMAL_CLOSE);
6640 return status;
6644 /* Changing the allocation size should set the last mod time. */
6646 * This is equivalent to a write. Ensure it's seen immediately
6647 * if there are no pending writes.
6649 trigger_write_time_update_immediate(new_fsp);
6651 close_file(req, new_fsp, NORMAL_CLOSE);
6652 return NT_STATUS_OK;
6655 /****************************************************************************
6656 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6657 ****************************************************************************/
6659 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6660 struct smb_request *req,
6661 const char *pdata,
6662 int total_data,
6663 files_struct *fsp,
6664 const struct smb_filename *smb_fname,
6665 bool fail_after_createfile)
6667 SMB_OFF_T size;
6669 if (total_data < 8) {
6670 return NT_STATUS_INVALID_PARAMETER;
6673 size = IVAL(pdata,0);
6674 #ifdef LARGE_SMB_OFF_T
6675 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6676 #else /* LARGE_SMB_OFF_T */
6677 if (IVAL(pdata,4) != 0) {
6678 /* more than 32 bits? */
6679 return NT_STATUS_INVALID_PARAMETER;
6681 #endif /* LARGE_SMB_OFF_T */
6682 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6683 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6684 (double)size));
6686 return smb_set_file_size(conn, req,
6687 fsp,
6688 smb_fname,
6689 &smb_fname->st,
6690 size,
6691 fail_after_createfile);
6694 /****************************************************************************
6695 Allow a UNIX info mknod.
6696 ****************************************************************************/
6698 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6699 const char *pdata,
6700 int total_data,
6701 const struct smb_filename *smb_fname)
6703 uint32 file_type = IVAL(pdata,56);
6704 #if defined(HAVE_MAKEDEV)
6705 uint32 dev_major = IVAL(pdata,60);
6706 uint32 dev_minor = IVAL(pdata,68);
6707 #endif
6708 SMB_DEV_T dev = (SMB_DEV_T)0;
6709 uint32 raw_unixmode = IVAL(pdata,84);
6710 NTSTATUS status;
6711 mode_t unixmode;
6713 if (total_data < 100) {
6714 return NT_STATUS_INVALID_PARAMETER;
6717 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6718 PERM_NEW_FILE, &unixmode);
6719 if (!NT_STATUS_IS_OK(status)) {
6720 return status;
6723 #if defined(HAVE_MAKEDEV)
6724 dev = makedev(dev_major, dev_minor);
6725 #endif
6727 switch (file_type) {
6728 #if defined(S_IFIFO)
6729 case UNIX_TYPE_FIFO:
6730 unixmode |= S_IFIFO;
6731 break;
6732 #endif
6733 #if defined(S_IFSOCK)
6734 case UNIX_TYPE_SOCKET:
6735 unixmode |= S_IFSOCK;
6736 break;
6737 #endif
6738 #if defined(S_IFCHR)
6739 case UNIX_TYPE_CHARDEV:
6740 unixmode |= S_IFCHR;
6741 break;
6742 #endif
6743 #if defined(S_IFBLK)
6744 case UNIX_TYPE_BLKDEV:
6745 unixmode |= S_IFBLK;
6746 break;
6747 #endif
6748 default:
6749 return NT_STATUS_INVALID_PARAMETER;
6752 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6753 "%.0f mode 0%o for file %s\n", (double)dev,
6754 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6756 /* Ok - do the mknod. */
6757 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6758 return map_nt_error_from_unix(errno);
6761 /* If any of the other "set" calls fail we
6762 * don't want to end up with a half-constructed mknod.
6765 if (lp_inherit_perms(SNUM(conn))) {
6766 char *parent;
6767 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6768 &parent, NULL)) {
6769 return NT_STATUS_NO_MEMORY;
6771 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6772 unixmode);
6773 TALLOC_FREE(parent);
6776 return NT_STATUS_OK;
6779 /****************************************************************************
6780 Deal with SMB_SET_FILE_UNIX_BASIC.
6781 ****************************************************************************/
6783 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6784 struct smb_request *req,
6785 const char *pdata,
6786 int total_data,
6787 files_struct *fsp,
6788 const struct smb_filename *smb_fname)
6790 struct smb_file_time ft;
6791 uint32 raw_unixmode;
6792 mode_t unixmode;
6793 SMB_OFF_T size = 0;
6794 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6795 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6796 NTSTATUS status = NT_STATUS_OK;
6797 bool delete_on_fail = False;
6798 enum perm_type ptype;
6799 files_struct *all_fsps = NULL;
6800 bool modify_mtime = true;
6801 struct file_id id;
6802 SMB_STRUCT_STAT sbuf;
6804 ZERO_STRUCT(ft);
6806 if (total_data < 100) {
6807 return NT_STATUS_INVALID_PARAMETER;
6810 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6811 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6812 size=IVAL(pdata,0); /* first 8 Bytes are size */
6813 #ifdef LARGE_SMB_OFF_T
6814 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6815 #else /* LARGE_SMB_OFF_T */
6816 if (IVAL(pdata,4) != 0) {
6817 /* more than 32 bits? */
6818 return NT_STATUS_INVALID_PARAMETER;
6820 #endif /* LARGE_SMB_OFF_T */
6823 ft.atime = interpret_long_date(pdata+24); /* access_time */
6824 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6825 set_owner = (uid_t)IVAL(pdata,40);
6826 set_grp = (gid_t)IVAL(pdata,48);
6827 raw_unixmode = IVAL(pdata,84);
6829 if (VALID_STAT(smb_fname->st)) {
6830 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6831 ptype = PERM_EXISTING_DIR;
6832 } else {
6833 ptype = PERM_EXISTING_FILE;
6835 } else {
6836 ptype = PERM_NEW_FILE;
6839 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6840 ptype, &unixmode);
6841 if (!NT_STATUS_IS_OK(status)) {
6842 return status;
6845 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6846 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6847 smb_fname_str_dbg(smb_fname), (double)size,
6848 (unsigned int)set_owner, (unsigned int)set_grp,
6849 (int)raw_unixmode));
6851 sbuf = smb_fname->st;
6853 if (!VALID_STAT(sbuf)) {
6854 struct smb_filename *smb_fname_tmp = NULL;
6856 * The only valid use of this is to create character and block
6857 * devices, and named pipes. This is deprecated (IMHO) and
6858 * a new info level should be used for mknod. JRA.
6861 status = smb_unix_mknod(conn,
6862 pdata,
6863 total_data,
6864 smb_fname);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 return status;
6869 status = copy_smb_filename(talloc_tos(), smb_fname,
6870 &smb_fname_tmp);
6871 if (!NT_STATUS_IS_OK(status)) {
6872 return status;
6875 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6876 status = map_nt_error_from_unix(errno);
6877 TALLOC_FREE(smb_fname_tmp);
6878 SMB_VFS_UNLINK(conn, smb_fname);
6879 return status;
6882 sbuf = smb_fname_tmp->st;
6883 TALLOC_FREE(smb_fname_tmp);
6885 /* Ensure we don't try and change anything else. */
6886 raw_unixmode = SMB_MODE_NO_CHANGE;
6887 size = get_file_size_stat(&sbuf);
6888 ft.atime = sbuf.st_ex_atime;
6889 ft.mtime = sbuf.st_ex_mtime;
6891 * We continue here as we might want to change the
6892 * owner uid/gid.
6894 delete_on_fail = True;
6897 #if 1
6898 /* Horrible backwards compatibility hack as an old server bug
6899 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6900 * */
6902 if (!size) {
6903 size = get_file_size_stat(&sbuf);
6905 #endif
6908 * Deal with the UNIX specific mode set.
6911 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6912 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6913 "setting mode 0%o for file %s\n",
6914 (unsigned int)unixmode,
6915 smb_fname_str_dbg(smb_fname)));
6916 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6917 return map_nt_error_from_unix(errno);
6922 * Deal with the UNIX specific uid set.
6925 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6926 (sbuf.st_ex_uid != set_owner)) {
6927 int ret;
6929 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6930 "changing owner %u for path %s\n",
6931 (unsigned int)set_owner,
6932 smb_fname_str_dbg(smb_fname)));
6934 if (S_ISLNK(sbuf.st_ex_mode)) {
6935 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6936 set_owner, (gid_t)-1);
6937 } else {
6938 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6939 set_owner, (gid_t)-1);
6942 if (ret != 0) {
6943 status = map_nt_error_from_unix(errno);
6944 if (delete_on_fail) {
6945 SMB_VFS_UNLINK(conn, smb_fname);
6947 return status;
6952 * Deal with the UNIX specific gid set.
6955 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6956 (sbuf.st_ex_gid != set_grp)) {
6957 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6958 "changing group %u for file %s\n",
6959 (unsigned int)set_owner,
6960 smb_fname_str_dbg(smb_fname)));
6961 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6962 set_grp) != 0) {
6963 status = map_nt_error_from_unix(errno);
6964 if (delete_on_fail) {
6965 SMB_VFS_UNLINK(conn, smb_fname);
6967 return status;
6971 /* Deal with any size changes. */
6973 status = smb_set_file_size(conn, req,
6974 fsp,
6975 smb_fname,
6976 &sbuf,
6977 size,
6978 false);
6979 if (!NT_STATUS_IS_OK(status)) {
6980 return status;
6983 /* Deal with any time changes. */
6984 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6985 /* No change, don't cancel anything. */
6986 return status;
6989 id = vfs_file_id_from_sbuf(conn, &sbuf);
6990 for(all_fsps = file_find_di_first(id); all_fsps;
6991 all_fsps = file_find_di_next(all_fsps)) {
6993 * We're setting the time explicitly for UNIX.
6994 * Cancel any pending changes over all handles.
6996 all_fsps->update_write_time_on_close = false;
6997 TALLOC_FREE(all_fsps->update_write_time_event);
7001 * Override the "setting_write_time"
7002 * parameter here as it almost does what
7003 * we need. Just remember if we modified
7004 * mtime and send the notify ourselves.
7006 if (null_timespec(ft.mtime)) {
7007 modify_mtime = false;
7010 status = smb_set_file_time(conn,
7011 fsp,
7012 smb_fname,
7013 &ft,
7014 false);
7015 if (modify_mtime) {
7016 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7017 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7019 return status;
7022 /****************************************************************************
7023 Deal with SMB_SET_FILE_UNIX_INFO2.
7024 ****************************************************************************/
7026 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7027 struct smb_request *req,
7028 const char *pdata,
7029 int total_data,
7030 files_struct *fsp,
7031 const struct smb_filename *smb_fname)
7033 NTSTATUS status;
7034 uint32 smb_fflags;
7035 uint32 smb_fmask;
7037 if (total_data < 116) {
7038 return NT_STATUS_INVALID_PARAMETER;
7041 /* Start by setting all the fields that are common between UNIX_BASIC
7042 * and UNIX_INFO2.
7044 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7045 fsp, smb_fname);
7046 if (!NT_STATUS_IS_OK(status)) {
7047 return status;
7050 smb_fflags = IVAL(pdata, 108);
7051 smb_fmask = IVAL(pdata, 112);
7053 /* NB: We should only attempt to alter the file flags if the client
7054 * sends a non-zero mask.
7056 if (smb_fmask != 0) {
7057 int stat_fflags = 0;
7059 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7060 smb_fmask, &stat_fflags)) {
7061 /* Client asked to alter a flag we don't understand. */
7062 return NT_STATUS_INVALID_PARAMETER;
7065 if (fsp && fsp->fh->fd != -1) {
7066 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7067 return NT_STATUS_NOT_SUPPORTED;
7068 } else {
7069 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7070 stat_fflags) != 0) {
7071 return map_nt_error_from_unix(errno);
7076 /* XXX: need to add support for changing the create_time here. You
7077 * can do this for paths on Darwin with setattrlist(2). The right way
7078 * to hook this up is probably by extending the VFS utimes interface.
7081 return NT_STATUS_OK;
7084 /****************************************************************************
7085 Create a directory with POSIX semantics.
7086 ****************************************************************************/
7088 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7089 struct smb_request *req,
7090 char **ppdata,
7091 int total_data,
7092 struct smb_filename *smb_fname,
7093 int *pdata_return_size)
7095 NTSTATUS status = NT_STATUS_OK;
7096 uint32 raw_unixmode = 0;
7097 uint32 mod_unixmode = 0;
7098 mode_t unixmode = (mode_t)0;
7099 files_struct *fsp = NULL;
7100 uint16 info_level_return = 0;
7101 int info;
7102 char *pdata = *ppdata;
7104 if (total_data < 18) {
7105 return NT_STATUS_INVALID_PARAMETER;
7108 raw_unixmode = IVAL(pdata,8);
7109 /* Next 4 bytes are not yet defined. */
7111 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7112 PERM_NEW_DIR, &unixmode);
7113 if (!NT_STATUS_IS_OK(status)) {
7114 return status;
7117 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7119 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7120 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7122 status = SMB_VFS_CREATE_FILE(
7123 conn, /* conn */
7124 req, /* req */
7125 0, /* root_dir_fid */
7126 smb_fname, /* fname */
7127 FILE_READ_ATTRIBUTES, /* access_mask */
7128 FILE_SHARE_NONE, /* share_access */
7129 FILE_CREATE, /* create_disposition*/
7130 FILE_DIRECTORY_FILE, /* create_options */
7131 mod_unixmode, /* file_attributes */
7132 0, /* oplock_request */
7133 0, /* allocation_size */
7134 0, /* private_flags */
7135 NULL, /* sd */
7136 NULL, /* ea_list */
7137 &fsp, /* result */
7138 &info); /* pinfo */
7140 if (NT_STATUS_IS_OK(status)) {
7141 close_file(req, fsp, NORMAL_CLOSE);
7144 info_level_return = SVAL(pdata,16);
7146 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7147 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7148 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7149 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7150 } else {
7151 *pdata_return_size = 12;
7154 /* Realloc the data size */
7155 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7156 if (*ppdata == NULL) {
7157 *pdata_return_size = 0;
7158 return NT_STATUS_NO_MEMORY;
7160 pdata = *ppdata;
7162 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7163 SSVAL(pdata,2,0); /* No fnum. */
7164 SIVAL(pdata,4,info); /* Was directory created. */
7166 switch (info_level_return) {
7167 case SMB_QUERY_FILE_UNIX_BASIC:
7168 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7169 SSVAL(pdata,10,0); /* Padding. */
7170 store_file_unix_basic(conn, pdata + 12, fsp,
7171 &smb_fname->st);
7172 break;
7173 case SMB_QUERY_FILE_UNIX_INFO2:
7174 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7175 SSVAL(pdata,10,0); /* Padding. */
7176 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7177 &smb_fname->st);
7178 break;
7179 default:
7180 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7181 SSVAL(pdata,10,0); /* Padding. */
7182 break;
7185 return status;
7188 /****************************************************************************
7189 Open/Create a file with POSIX semantics.
7190 ****************************************************************************/
7192 static NTSTATUS smb_posix_open(connection_struct *conn,
7193 struct smb_request *req,
7194 char **ppdata,
7195 int total_data,
7196 struct smb_filename *smb_fname,
7197 int *pdata_return_size)
7199 bool extended_oplock_granted = False;
7200 char *pdata = *ppdata;
7201 uint32 flags = 0;
7202 uint32 wire_open_mode = 0;
7203 uint32 raw_unixmode = 0;
7204 uint32 mod_unixmode = 0;
7205 uint32 create_disp = 0;
7206 uint32 access_mask = 0;
7207 uint32 create_options = 0;
7208 NTSTATUS status = NT_STATUS_OK;
7209 mode_t unixmode = (mode_t)0;
7210 files_struct *fsp = NULL;
7211 int oplock_request = 0;
7212 int info = 0;
7213 uint16 info_level_return = 0;
7215 if (total_data < 18) {
7216 return NT_STATUS_INVALID_PARAMETER;
7219 flags = IVAL(pdata,0);
7220 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7221 if (oplock_request) {
7222 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7225 wire_open_mode = IVAL(pdata,4);
7227 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7228 return smb_posix_mkdir(conn, req,
7229 ppdata,
7230 total_data,
7231 smb_fname,
7232 pdata_return_size);
7235 switch (wire_open_mode & SMB_ACCMODE) {
7236 case SMB_O_RDONLY:
7237 access_mask = FILE_READ_DATA;
7238 break;
7239 case SMB_O_WRONLY:
7240 access_mask = FILE_WRITE_DATA;
7241 break;
7242 case SMB_O_RDWR:
7243 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7244 break;
7245 default:
7246 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7247 (unsigned int)wire_open_mode ));
7248 return NT_STATUS_INVALID_PARAMETER;
7251 wire_open_mode &= ~SMB_ACCMODE;
7253 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7254 create_disp = FILE_CREATE;
7255 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7256 create_disp = FILE_OVERWRITE_IF;
7257 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7258 create_disp = FILE_OPEN_IF;
7259 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7260 create_disp = FILE_OPEN;
7261 } else {
7262 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7263 (unsigned int)wire_open_mode ));
7264 return NT_STATUS_INVALID_PARAMETER;
7267 raw_unixmode = IVAL(pdata,8);
7268 /* Next 4 bytes are not yet defined. */
7270 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7271 (VALID_STAT(smb_fname->st) ?
7272 PERM_EXISTING_FILE : PERM_NEW_FILE),
7273 &unixmode);
7275 if (!NT_STATUS_IS_OK(status)) {
7276 return status;
7279 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7281 if (wire_open_mode & SMB_O_SYNC) {
7282 create_options |= FILE_WRITE_THROUGH;
7284 if (wire_open_mode & SMB_O_APPEND) {
7285 access_mask |= FILE_APPEND_DATA;
7287 if (wire_open_mode & SMB_O_DIRECT) {
7288 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7291 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7292 smb_fname_str_dbg(smb_fname),
7293 (unsigned int)wire_open_mode,
7294 (unsigned int)unixmode ));
7296 status = SMB_VFS_CREATE_FILE(
7297 conn, /* conn */
7298 req, /* req */
7299 0, /* root_dir_fid */
7300 smb_fname, /* fname */
7301 access_mask, /* access_mask */
7302 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7303 FILE_SHARE_DELETE),
7304 create_disp, /* create_disposition*/
7305 FILE_NON_DIRECTORY_FILE, /* create_options */
7306 mod_unixmode, /* file_attributes */
7307 oplock_request, /* oplock_request */
7308 0, /* allocation_size */
7309 0, /* private_flags */
7310 NULL, /* sd */
7311 NULL, /* ea_list */
7312 &fsp, /* result */
7313 &info); /* pinfo */
7315 if (!NT_STATUS_IS_OK(status)) {
7316 return status;
7319 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7320 extended_oplock_granted = True;
7323 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7324 extended_oplock_granted = True;
7327 info_level_return = SVAL(pdata,16);
7329 /* Allocate the correct return size. */
7331 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7332 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7333 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7334 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7335 } else {
7336 *pdata_return_size = 12;
7339 /* Realloc the data size */
7340 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7341 if (*ppdata == NULL) {
7342 close_file(req, fsp, ERROR_CLOSE);
7343 *pdata_return_size = 0;
7344 return NT_STATUS_NO_MEMORY;
7346 pdata = *ppdata;
7348 if (extended_oplock_granted) {
7349 if (flags & REQUEST_BATCH_OPLOCK) {
7350 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7351 } else {
7352 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7354 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7355 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7356 } else {
7357 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7360 SSVAL(pdata,2,fsp->fnum);
7361 SIVAL(pdata,4,info); /* Was file created etc. */
7363 switch (info_level_return) {
7364 case SMB_QUERY_FILE_UNIX_BASIC:
7365 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7366 SSVAL(pdata,10,0); /* padding. */
7367 store_file_unix_basic(conn, pdata + 12, fsp,
7368 &smb_fname->st);
7369 break;
7370 case SMB_QUERY_FILE_UNIX_INFO2:
7371 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7372 SSVAL(pdata,10,0); /* padding. */
7373 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7374 &smb_fname->st);
7375 break;
7376 default:
7377 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7378 SSVAL(pdata,10,0); /* padding. */
7379 break;
7381 return NT_STATUS_OK;
7384 /****************************************************************************
7385 Delete a file with POSIX semantics.
7386 ****************************************************************************/
7388 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7389 struct smb_request *req,
7390 const char *pdata,
7391 int total_data,
7392 struct smb_filename *smb_fname)
7394 NTSTATUS status = NT_STATUS_OK;
7395 files_struct *fsp = NULL;
7396 uint16 flags = 0;
7397 char del = 1;
7398 int info = 0;
7399 int create_options = 0;
7400 int i;
7401 struct share_mode_lock *lck = NULL;
7403 if (total_data < 2) {
7404 return NT_STATUS_INVALID_PARAMETER;
7407 flags = SVAL(pdata,0);
7409 if (!VALID_STAT(smb_fname->st)) {
7410 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7413 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7414 !VALID_STAT_OF_DIR(smb_fname->st)) {
7415 return NT_STATUS_NOT_A_DIRECTORY;
7418 DEBUG(10,("smb_posix_unlink: %s %s\n",
7419 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7420 smb_fname_str_dbg(smb_fname)));
7422 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7423 create_options |= FILE_DIRECTORY_FILE;
7426 status = SMB_VFS_CREATE_FILE(
7427 conn, /* conn */
7428 req, /* req */
7429 0, /* root_dir_fid */
7430 smb_fname, /* fname */
7431 DELETE_ACCESS, /* access_mask */
7432 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7433 FILE_SHARE_DELETE),
7434 FILE_OPEN, /* create_disposition*/
7435 create_options, /* create_options */
7436 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7437 0, /* oplock_request */
7438 0, /* allocation_size */
7439 0, /* private_flags */
7440 NULL, /* sd */
7441 NULL, /* ea_list */
7442 &fsp, /* result */
7443 &info); /* pinfo */
7445 if (!NT_STATUS_IS_OK(status)) {
7446 return status;
7450 * Don't lie to client. If we can't really delete due to
7451 * non-POSIX opens return SHARING_VIOLATION.
7454 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7455 NULL);
7456 if (lck == NULL) {
7457 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7458 "lock for file %s\n", fsp_str_dbg(fsp)));
7459 close_file(req, fsp, NORMAL_CLOSE);
7460 return NT_STATUS_INVALID_PARAMETER;
7464 * See if others still have the file open. If this is the case, then
7465 * don't delete. If all opens are POSIX delete we can set the delete
7466 * on close disposition.
7468 for (i=0; i<lck->num_share_modes; i++) {
7469 struct share_mode_entry *e = &lck->share_modes[i];
7470 if (is_valid_share_mode_entry(e)) {
7471 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7472 continue;
7474 /* Fail with sharing violation. */
7475 close_file(req, fsp, NORMAL_CLOSE);
7476 TALLOC_FREE(lck);
7477 return NT_STATUS_SHARING_VIOLATION;
7482 * Set the delete on close.
7484 status = smb_set_file_disposition_info(conn,
7485 &del,
7487 fsp,
7488 smb_fname);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 close_file(req, fsp, NORMAL_CLOSE);
7492 TALLOC_FREE(lck);
7493 return status;
7495 TALLOC_FREE(lck);
7496 return close_file(req, fsp, NORMAL_CLOSE);
7499 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7500 struct smb_request *req,
7501 TALLOC_CTX *mem_ctx,
7502 uint16_t info_level,
7503 files_struct *fsp,
7504 struct smb_filename *smb_fname,
7505 char **ppdata, int total_data,
7506 int *ret_data_size)
7508 char *pdata = *ppdata;
7509 NTSTATUS status = NT_STATUS_OK;
7510 int data_return_size = 0;
7512 *ret_data_size = 0;
7514 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7515 return NT_STATUS_INVALID_LEVEL;
7518 if (!CAN_WRITE(conn)) {
7519 /* Allow POSIX opens. The open path will deny
7520 * any non-readonly opens. */
7521 if (info_level != SMB_POSIX_PATH_OPEN) {
7522 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7526 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7527 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7528 fsp ? fsp->fnum : -1, info_level, total_data));
7530 switch (info_level) {
7532 case SMB_INFO_STANDARD:
7534 status = smb_set_info_standard(conn,
7535 pdata,
7536 total_data,
7537 fsp,
7538 smb_fname);
7539 break;
7542 case SMB_INFO_SET_EA:
7544 status = smb_info_set_ea(conn,
7545 pdata,
7546 total_data,
7547 fsp,
7548 smb_fname);
7549 break;
7552 case SMB_SET_FILE_BASIC_INFO:
7553 case SMB_FILE_BASIC_INFORMATION:
7555 status = smb_set_file_basic_info(conn,
7556 pdata,
7557 total_data,
7558 fsp,
7559 smb_fname);
7560 break;
7563 case SMB_FILE_ALLOCATION_INFORMATION:
7564 case SMB_SET_FILE_ALLOCATION_INFO:
7566 status = smb_set_file_allocation_info(conn, req,
7567 pdata,
7568 total_data,
7569 fsp,
7570 smb_fname);
7571 break;
7574 case SMB_FILE_END_OF_FILE_INFORMATION:
7575 case SMB_SET_FILE_END_OF_FILE_INFO:
7578 * XP/Win7 both fail after the createfile with
7579 * SMB_SET_FILE_END_OF_FILE_INFO but not
7580 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7581 * The level is known here, so pass it down
7582 * appropriately.
7584 bool should_fail =
7585 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7587 status = smb_set_file_end_of_file_info(conn, req,
7588 pdata,
7589 total_data,
7590 fsp,
7591 smb_fname,
7592 should_fail);
7593 break;
7596 case SMB_FILE_DISPOSITION_INFORMATION:
7597 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7599 #if 0
7600 /* JRA - We used to just ignore this on a path ?
7601 * Shouldn't this be invalid level on a pathname
7602 * based call ?
7604 if (tran_call != TRANSACT2_SETFILEINFO) {
7605 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7607 #endif
7608 status = smb_set_file_disposition_info(conn,
7609 pdata,
7610 total_data,
7611 fsp,
7612 smb_fname);
7613 break;
7616 case SMB_FILE_POSITION_INFORMATION:
7618 status = smb_file_position_information(conn,
7619 pdata,
7620 total_data,
7621 fsp);
7622 break;
7625 case SMB_FILE_FULL_EA_INFORMATION:
7627 status = smb_set_file_full_ea_info(conn,
7628 pdata,
7629 total_data,
7630 fsp);
7631 break;
7634 /* From tridge Samba4 :
7635 * MODE_INFORMATION in setfileinfo (I have no
7636 * idea what "mode information" on a file is - it takes a value of 0,
7637 * 2, 4 or 6. What could it be?).
7640 case SMB_FILE_MODE_INFORMATION:
7642 status = smb_file_mode_information(conn,
7643 pdata,
7644 total_data);
7645 break;
7649 * CIFS UNIX extensions.
7652 case SMB_SET_FILE_UNIX_BASIC:
7654 status = smb_set_file_unix_basic(conn, req,
7655 pdata,
7656 total_data,
7657 fsp,
7658 smb_fname);
7659 break;
7662 case SMB_SET_FILE_UNIX_INFO2:
7664 status = smb_set_file_unix_info2(conn, req,
7665 pdata,
7666 total_data,
7667 fsp,
7668 smb_fname);
7669 break;
7672 case SMB_SET_FILE_UNIX_LINK:
7674 if (fsp) {
7675 /* We must have a pathname for this. */
7676 return NT_STATUS_INVALID_LEVEL;
7678 status = smb_set_file_unix_link(conn, req, pdata,
7679 total_data, smb_fname);
7680 break;
7683 case SMB_SET_FILE_UNIX_HLINK:
7685 if (fsp) {
7686 /* We must have a pathname for this. */
7687 return NT_STATUS_INVALID_LEVEL;
7689 status = smb_set_file_unix_hlink(conn, req,
7690 pdata, total_data,
7691 smb_fname);
7692 break;
7695 case SMB_FILE_RENAME_INFORMATION:
7697 status = smb_file_rename_information(conn, req,
7698 pdata, total_data,
7699 fsp, smb_fname);
7700 break;
7703 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7705 /* SMB2 rename information. */
7706 status = smb2_file_rename_information(conn, req,
7707 pdata, total_data,
7708 fsp, smb_fname);
7709 break;
7712 case SMB_FILE_LINK_INFORMATION:
7714 status = smb_file_link_information(conn, req,
7715 pdata, total_data,
7716 fsp, smb_fname);
7717 break;
7720 #if defined(HAVE_POSIX_ACLS)
7721 case SMB_SET_POSIX_ACL:
7723 status = smb_set_posix_acl(conn,
7724 pdata,
7725 total_data,
7726 fsp,
7727 smb_fname);
7728 break;
7730 #endif
7732 case SMB_SET_POSIX_LOCK:
7734 if (!fsp) {
7735 return NT_STATUS_INVALID_LEVEL;
7737 status = smb_set_posix_lock(conn, req,
7738 pdata, total_data, fsp);
7739 break;
7742 case SMB_POSIX_PATH_OPEN:
7744 if (fsp) {
7745 /* We must have a pathname for this. */
7746 return NT_STATUS_INVALID_LEVEL;
7749 status = smb_posix_open(conn, req,
7750 ppdata,
7751 total_data,
7752 smb_fname,
7753 &data_return_size);
7754 break;
7757 case SMB_POSIX_PATH_UNLINK:
7759 if (fsp) {
7760 /* We must have a pathname for this. */
7761 return NT_STATUS_INVALID_LEVEL;
7764 status = smb_posix_unlink(conn, req,
7765 pdata,
7766 total_data,
7767 smb_fname);
7768 break;
7771 default:
7772 return NT_STATUS_INVALID_LEVEL;
7775 if (!NT_STATUS_IS_OK(status)) {
7776 return status;
7779 *ret_data_size = data_return_size;
7780 return NT_STATUS_OK;
7783 /****************************************************************************
7784 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7785 ****************************************************************************/
7787 static void call_trans2setfilepathinfo(connection_struct *conn,
7788 struct smb_request *req,
7789 unsigned int tran_call,
7790 char **pparams, int total_params,
7791 char **ppdata, int total_data,
7792 unsigned int max_data_bytes)
7794 char *params = *pparams;
7795 char *pdata = *ppdata;
7796 uint16 info_level;
7797 struct smb_filename *smb_fname = NULL;
7798 files_struct *fsp = NULL;
7799 NTSTATUS status = NT_STATUS_OK;
7800 int data_return_size = 0;
7802 if (!params) {
7803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7804 return;
7807 if (tran_call == TRANSACT2_SETFILEINFO) {
7808 if (total_params < 4) {
7809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7810 return;
7813 fsp = file_fsp(req, SVAL(params,0));
7814 /* Basic check for non-null fsp. */
7815 if (!check_fsp_open(conn, req, fsp)) {
7816 return;
7818 info_level = SVAL(params,2);
7820 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7821 &smb_fname);
7822 if (!NT_STATUS_IS_OK(status)) {
7823 reply_nterror(req, status);
7824 return;
7827 if(fsp->is_directory || fsp->fh->fd == -1) {
7829 * This is actually a SETFILEINFO on a directory
7830 * handle (returned from an NT SMB). NT5.0 seems
7831 * to do this call. JRA.
7833 if (INFO_LEVEL_IS_UNIX(info_level)) {
7834 /* Always do lstat for UNIX calls. */
7835 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7836 DEBUG(3,("call_trans2setfilepathinfo: "
7837 "SMB_VFS_LSTAT of %s failed "
7838 "(%s)\n",
7839 smb_fname_str_dbg(smb_fname),
7840 strerror(errno)));
7841 reply_nterror(req, map_nt_error_from_unix(errno));
7842 return;
7844 } else {
7845 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7846 DEBUG(3,("call_trans2setfilepathinfo: "
7847 "fileinfo of %s failed (%s)\n",
7848 smb_fname_str_dbg(smb_fname),
7849 strerror(errno)));
7850 reply_nterror(req, map_nt_error_from_unix(errno));
7851 return;
7854 } else if (fsp->print_file) {
7856 * Doing a DELETE_ON_CLOSE should cancel a print job.
7858 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7859 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7861 DEBUG(3,("call_trans2setfilepathinfo: "
7862 "Cancelling print job (%s)\n",
7863 fsp_str_dbg(fsp)));
7865 SSVAL(params,0,0);
7866 send_trans2_replies(conn, req, params, 2,
7867 *ppdata, 0,
7868 max_data_bytes);
7869 return;
7870 } else {
7871 reply_nterror(req,
7872 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7873 return;
7875 } else {
7877 * Original code - this is an open file.
7879 if (!check_fsp(conn, req, fsp)) {
7880 return;
7883 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7884 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7885 "of fnum %d failed (%s)\n", fsp->fnum,
7886 strerror(errno)));
7887 reply_nterror(req, map_nt_error_from_unix(errno));
7888 return;
7891 } else {
7892 char *fname = NULL;
7894 /* set path info */
7895 if (total_params < 7) {
7896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7897 return;
7900 info_level = SVAL(params,0);
7901 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7902 total_params - 6, STR_TERMINATE,
7903 &status);
7904 if (!NT_STATUS_IS_OK(status)) {
7905 reply_nterror(req, status);
7906 return;
7909 status = filename_convert(req, conn,
7910 req->flags2 & FLAGS2_DFS_PATHNAMES,
7911 fname,
7913 NULL,
7914 &smb_fname);
7915 if (!NT_STATUS_IS_OK(status)) {
7916 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7917 reply_botherror(req,
7918 NT_STATUS_PATH_NOT_COVERED,
7919 ERRSRV, ERRbadpath);
7920 return;
7922 reply_nterror(req, status);
7923 return;
7926 if (INFO_LEVEL_IS_UNIX(info_level)) {
7928 * For CIFS UNIX extensions the target name may not exist.
7931 /* Always do lstat for UNIX calls. */
7932 SMB_VFS_LSTAT(conn, smb_fname);
7934 } else if (!VALID_STAT(smb_fname->st) &&
7935 SMB_VFS_STAT(conn, smb_fname)) {
7936 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7937 "%s failed (%s)\n",
7938 smb_fname_str_dbg(smb_fname),
7939 strerror(errno)));
7940 reply_nterror(req, map_nt_error_from_unix(errno));
7941 return;
7945 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7946 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7947 fsp ? fsp->fnum : -1, info_level,total_data));
7949 /* Realloc the parameter size */
7950 *pparams = (char *)SMB_REALLOC(*pparams,2);
7951 if (*pparams == NULL) {
7952 reply_nterror(req, NT_STATUS_NO_MEMORY);
7953 return;
7955 params = *pparams;
7957 SSVAL(params,0,0);
7959 status = smbd_do_setfilepathinfo(conn, req, req,
7960 info_level,
7961 fsp,
7962 smb_fname,
7963 ppdata, total_data,
7964 &data_return_size);
7965 if (!NT_STATUS_IS_OK(status)) {
7966 if (open_was_deferred(req->mid)) {
7967 /* We have re-scheduled this call. */
7968 return;
7970 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
7971 /* We have re-scheduled this call. */
7972 return;
7974 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7975 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7976 ERRSRV, ERRbadpath);
7977 return;
7979 if (info_level == SMB_POSIX_PATH_OPEN) {
7980 reply_openerror(req, status);
7981 return;
7984 reply_nterror(req, status);
7985 return;
7988 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7989 max_data_bytes);
7991 return;
7994 /****************************************************************************
7995 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7996 ****************************************************************************/
7998 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7999 char **pparams, int total_params,
8000 char **ppdata, int total_data,
8001 unsigned int max_data_bytes)
8003 struct smb_filename *smb_dname = NULL;
8004 char *params = *pparams;
8005 char *pdata = *ppdata;
8006 char *directory = NULL;
8007 NTSTATUS status = NT_STATUS_OK;
8008 struct ea_list *ea_list = NULL;
8009 TALLOC_CTX *ctx = talloc_tos();
8011 if (!CAN_WRITE(conn)) {
8012 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8013 return;
8016 if (total_params < 5) {
8017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8018 return;
8021 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8022 total_params - 4, STR_TERMINATE,
8023 &status);
8024 if (!NT_STATUS_IS_OK(status)) {
8025 reply_nterror(req, status);
8026 return;
8029 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8031 status = filename_convert(ctx,
8032 conn,
8033 req->flags2 & FLAGS2_DFS_PATHNAMES,
8034 directory,
8036 NULL,
8037 &smb_dname);
8039 if (!NT_STATUS_IS_OK(status)) {
8040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8041 reply_botherror(req,
8042 NT_STATUS_PATH_NOT_COVERED,
8043 ERRSRV, ERRbadpath);
8044 return;
8046 reply_nterror(req, status);
8047 return;
8051 * OS/2 workplace shell seems to send SET_EA requests of "null"
8052 * length (4 bytes containing IVAL 4).
8053 * They seem to have no effect. Bug #3212. JRA.
8056 if (total_data && (total_data != 4)) {
8057 /* Any data in this call is an EA list. */
8058 if (total_data < 10) {
8059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8060 goto out;
8063 if (IVAL(pdata,0) > total_data) {
8064 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8065 IVAL(pdata,0), (unsigned int)total_data));
8066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8067 goto out;
8070 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8071 total_data - 4);
8072 if (!ea_list) {
8073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8074 goto out;
8077 if (!lp_ea_support(SNUM(conn))) {
8078 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8079 goto out;
8082 /* If total_data == 4 Windows doesn't care what values
8083 * are placed in that field, it just ignores them.
8084 * The System i QNTC IBM SMB client puts bad values here,
8085 * so ignore them. */
8087 status = create_directory(conn, req, smb_dname);
8089 if (!NT_STATUS_IS_OK(status)) {
8090 reply_nterror(req, status);
8091 goto out;
8094 /* Try and set any given EA. */
8095 if (ea_list) {
8096 status = set_ea(conn, NULL, smb_dname, ea_list);
8097 if (!NT_STATUS_IS_OK(status)) {
8098 reply_nterror(req, status);
8099 goto out;
8103 /* Realloc the parameter and data sizes */
8104 *pparams = (char *)SMB_REALLOC(*pparams,2);
8105 if(*pparams == NULL) {
8106 reply_nterror(req, NT_STATUS_NO_MEMORY);
8107 goto out;
8109 params = *pparams;
8111 SSVAL(params,0,0);
8113 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8115 out:
8116 TALLOC_FREE(smb_dname);
8117 return;
8120 /****************************************************************************
8121 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8122 We don't actually do this - we just send a null response.
8123 ****************************************************************************/
8125 static void call_trans2findnotifyfirst(connection_struct *conn,
8126 struct smb_request *req,
8127 char **pparams, int total_params,
8128 char **ppdata, int total_data,
8129 unsigned int max_data_bytes)
8131 char *params = *pparams;
8132 uint16 info_level;
8134 if (total_params < 6) {
8135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8136 return;
8139 info_level = SVAL(params,4);
8140 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8142 switch (info_level) {
8143 case 1:
8144 case 2:
8145 break;
8146 default:
8147 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8148 return;
8151 /* Realloc the parameter and data sizes */
8152 *pparams = (char *)SMB_REALLOC(*pparams,6);
8153 if (*pparams == NULL) {
8154 reply_nterror(req, NT_STATUS_NO_MEMORY);
8155 return;
8157 params = *pparams;
8159 SSVAL(params,0,fnf_handle);
8160 SSVAL(params,2,0); /* No changes */
8161 SSVAL(params,4,0); /* No EA errors */
8163 fnf_handle++;
8165 if(fnf_handle == 0)
8166 fnf_handle = 257;
8168 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8170 return;
8173 /****************************************************************************
8174 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8175 changes). Currently this does nothing.
8176 ****************************************************************************/
8178 static void call_trans2findnotifynext(connection_struct *conn,
8179 struct smb_request *req,
8180 char **pparams, int total_params,
8181 char **ppdata, int total_data,
8182 unsigned int max_data_bytes)
8184 char *params = *pparams;
8186 DEBUG(3,("call_trans2findnotifynext\n"));
8188 /* Realloc the parameter and data sizes */
8189 *pparams = (char *)SMB_REALLOC(*pparams,4);
8190 if (*pparams == NULL) {
8191 reply_nterror(req, NT_STATUS_NO_MEMORY);
8192 return;
8194 params = *pparams;
8196 SSVAL(params,0,0); /* No changes */
8197 SSVAL(params,2,0); /* No EA errors */
8199 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8201 return;
8204 /****************************************************************************
8205 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8206 ****************************************************************************/
8208 static void call_trans2getdfsreferral(connection_struct *conn,
8209 struct smb_request *req,
8210 char **pparams, int total_params,
8211 char **ppdata, int total_data,
8212 unsigned int max_data_bytes)
8214 char *params = *pparams;
8215 char *pathname = NULL;
8216 int reply_size = 0;
8217 int max_referral_level;
8218 NTSTATUS status = NT_STATUS_OK;
8219 TALLOC_CTX *ctx = talloc_tos();
8221 DEBUG(10,("call_trans2getdfsreferral\n"));
8223 if (total_params < 3) {
8224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8225 return;
8228 max_referral_level = SVAL(params,0);
8230 if(!lp_host_msdfs()) {
8231 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8232 return;
8235 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8236 total_params - 2, STR_TERMINATE);
8237 if (!pathname) {
8238 reply_nterror(req, NT_STATUS_NOT_FOUND);
8239 return;
8241 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8242 ppdata,&status)) < 0) {
8243 reply_nterror(req, status);
8244 return;
8247 SSVAL(req->inbuf, smb_flg2,
8248 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8249 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8251 return;
8254 #define LMCAT_SPL 0x53
8255 #define LMFUNC_GETJOBID 0x60
8257 /****************************************************************************
8258 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8259 ****************************************************************************/
8261 static void call_trans2ioctl(connection_struct *conn,
8262 struct smb_request *req,
8263 char **pparams, int total_params,
8264 char **ppdata, int total_data,
8265 unsigned int max_data_bytes)
8267 char *pdata = *ppdata;
8268 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8270 /* check for an invalid fid before proceeding */
8272 if (!fsp) {
8273 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8274 return;
8277 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8278 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8279 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8280 if (*ppdata == NULL) {
8281 reply_nterror(req, NT_STATUS_NO_MEMORY);
8282 return;
8284 pdata = *ppdata;
8286 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8287 CAN ACCEPT THIS IN UNICODE. JRA. */
8289 /* Job number */
8290 if (fsp->print_file) {
8291 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8292 } else {
8293 SSVAL(pdata, 0, 0);
8295 srvstr_push(pdata, req->flags2, pdata + 2,
8296 global_myname(), 15,
8297 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8298 srvstr_push(pdata, req->flags2, pdata+18,
8299 lp_servicename(SNUM(conn)), 13,
8300 STR_ASCII|STR_TERMINATE); /* Service name */
8301 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8302 max_data_bytes);
8303 return;
8306 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8307 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8310 /****************************************************************************
8311 Reply to a SMBfindclose (stop trans2 directory search).
8312 ****************************************************************************/
8314 void reply_findclose(struct smb_request *req)
8316 int dptr_num;
8317 struct smbd_server_connection *sconn = req->sconn;
8319 START_PROFILE(SMBfindclose);
8321 if (req->wct < 1) {
8322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8323 END_PROFILE(SMBfindclose);
8324 return;
8327 dptr_num = SVALS(req->vwv+0, 0);
8329 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8331 dptr_close(sconn, &dptr_num);
8333 reply_outbuf(req, 0, 0);
8335 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8337 END_PROFILE(SMBfindclose);
8338 return;
8341 /****************************************************************************
8342 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8343 ****************************************************************************/
8345 void reply_findnclose(struct smb_request *req)
8347 int dptr_num;
8349 START_PROFILE(SMBfindnclose);
8351 if (req->wct < 1) {
8352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8353 END_PROFILE(SMBfindnclose);
8354 return;
8357 dptr_num = SVAL(req->vwv+0, 0);
8359 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8361 /* We never give out valid handles for a
8362 findnotifyfirst - so any dptr_num is ok here.
8363 Just ignore it. */
8365 reply_outbuf(req, 0, 0);
8367 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8369 END_PROFILE(SMBfindnclose);
8370 return;
8373 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8374 struct trans_state *state)
8376 if (get_Protocol() >= PROTOCOL_NT1) {
8377 req->flags2 |= 0x40; /* IS_LONG_NAME */
8378 SSVAL(req->inbuf,smb_flg2,req->flags2);
8381 if (conn->encrypt_level == Required && !req->encrypted) {
8382 if (state->call != TRANSACT2_QFSINFO &&
8383 state->call != TRANSACT2_SETFSINFO) {
8384 DEBUG(0,("handle_trans2: encryption required "
8385 "with call 0x%x\n",
8386 (unsigned int)state->call));
8387 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8388 return;
8392 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8394 /* Now we must call the relevant TRANS2 function */
8395 switch(state->call) {
8396 case TRANSACT2_OPEN:
8398 START_PROFILE(Trans2_open);
8399 call_trans2open(conn, req,
8400 &state->param, state->total_param,
8401 &state->data, state->total_data,
8402 state->max_data_return);
8403 END_PROFILE(Trans2_open);
8404 break;
8407 case TRANSACT2_FINDFIRST:
8409 START_PROFILE(Trans2_findfirst);
8410 call_trans2findfirst(conn, req,
8411 &state->param, state->total_param,
8412 &state->data, state->total_data,
8413 state->max_data_return);
8414 END_PROFILE(Trans2_findfirst);
8415 break;
8418 case TRANSACT2_FINDNEXT:
8420 START_PROFILE(Trans2_findnext);
8421 call_trans2findnext(conn, req,
8422 &state->param, state->total_param,
8423 &state->data, state->total_data,
8424 state->max_data_return);
8425 END_PROFILE(Trans2_findnext);
8426 break;
8429 case TRANSACT2_QFSINFO:
8431 START_PROFILE(Trans2_qfsinfo);
8432 call_trans2qfsinfo(conn, req,
8433 &state->param, state->total_param,
8434 &state->data, state->total_data,
8435 state->max_data_return);
8436 END_PROFILE(Trans2_qfsinfo);
8437 break;
8440 case TRANSACT2_SETFSINFO:
8442 START_PROFILE(Trans2_setfsinfo);
8443 call_trans2setfsinfo(conn, req,
8444 &state->param, state->total_param,
8445 &state->data, state->total_data,
8446 state->max_data_return);
8447 END_PROFILE(Trans2_setfsinfo);
8448 break;
8451 case TRANSACT2_QPATHINFO:
8452 case TRANSACT2_QFILEINFO:
8454 START_PROFILE(Trans2_qpathinfo);
8455 call_trans2qfilepathinfo(conn, req, state->call,
8456 &state->param, state->total_param,
8457 &state->data, state->total_data,
8458 state->max_data_return);
8459 END_PROFILE(Trans2_qpathinfo);
8460 break;
8463 case TRANSACT2_SETPATHINFO:
8464 case TRANSACT2_SETFILEINFO:
8466 START_PROFILE(Trans2_setpathinfo);
8467 call_trans2setfilepathinfo(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_setpathinfo);
8472 break;
8475 case TRANSACT2_FINDNOTIFYFIRST:
8477 START_PROFILE(Trans2_findnotifyfirst);
8478 call_trans2findnotifyfirst(conn, req,
8479 &state->param, state->total_param,
8480 &state->data, state->total_data,
8481 state->max_data_return);
8482 END_PROFILE(Trans2_findnotifyfirst);
8483 break;
8486 case TRANSACT2_FINDNOTIFYNEXT:
8488 START_PROFILE(Trans2_findnotifynext);
8489 call_trans2findnotifynext(conn, req,
8490 &state->param, state->total_param,
8491 &state->data, state->total_data,
8492 state->max_data_return);
8493 END_PROFILE(Trans2_findnotifynext);
8494 break;
8497 case TRANSACT2_MKDIR:
8499 START_PROFILE(Trans2_mkdir);
8500 call_trans2mkdir(conn, req,
8501 &state->param, state->total_param,
8502 &state->data, state->total_data,
8503 state->max_data_return);
8504 END_PROFILE(Trans2_mkdir);
8505 break;
8508 case TRANSACT2_GET_DFS_REFERRAL:
8510 START_PROFILE(Trans2_get_dfs_referral);
8511 call_trans2getdfsreferral(conn, req,
8512 &state->param, state->total_param,
8513 &state->data, state->total_data,
8514 state->max_data_return);
8515 END_PROFILE(Trans2_get_dfs_referral);
8516 break;
8519 case TRANSACT2_IOCTL:
8521 START_PROFILE(Trans2_ioctl);
8522 call_trans2ioctl(conn, req,
8523 &state->param, state->total_param,
8524 &state->data, state->total_data,
8525 state->max_data_return);
8526 END_PROFILE(Trans2_ioctl);
8527 break;
8530 default:
8531 /* Error in request */
8532 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8533 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8537 /****************************************************************************
8538 Reply to a SMBtrans2.
8539 ****************************************************************************/
8541 void reply_trans2(struct smb_request *req)
8543 connection_struct *conn = req->conn;
8544 unsigned int dsoff;
8545 unsigned int dscnt;
8546 unsigned int psoff;
8547 unsigned int pscnt;
8548 unsigned int tran_call;
8549 struct trans_state *state;
8550 NTSTATUS result;
8552 START_PROFILE(SMBtrans2);
8554 if (req->wct < 14) {
8555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8556 END_PROFILE(SMBtrans2);
8557 return;
8560 dsoff = SVAL(req->vwv+12, 0);
8561 dscnt = SVAL(req->vwv+11, 0);
8562 psoff = SVAL(req->vwv+10, 0);
8563 pscnt = SVAL(req->vwv+9, 0);
8564 tran_call = SVAL(req->vwv+14, 0);
8566 result = allow_new_trans(conn->pending_trans, req->mid);
8567 if (!NT_STATUS_IS_OK(result)) {
8568 DEBUG(2, ("Got invalid trans2 request: %s\n",
8569 nt_errstr(result)));
8570 reply_nterror(req, result);
8571 END_PROFILE(SMBtrans2);
8572 return;
8575 if (IS_IPC(conn)) {
8576 switch (tran_call) {
8577 /* List the allowed trans2 calls on IPC$ */
8578 case TRANSACT2_OPEN:
8579 case TRANSACT2_GET_DFS_REFERRAL:
8580 case TRANSACT2_QFILEINFO:
8581 case TRANSACT2_QFSINFO:
8582 case TRANSACT2_SETFSINFO:
8583 break;
8584 default:
8585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8586 END_PROFILE(SMBtrans2);
8587 return;
8591 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8592 DEBUG(0, ("talloc failed\n"));
8593 reply_nterror(req, NT_STATUS_NO_MEMORY);
8594 END_PROFILE(SMBtrans2);
8595 return;
8598 state->cmd = SMBtrans2;
8600 state->mid = req->mid;
8601 state->vuid = req->vuid;
8602 state->setup_count = SVAL(req->vwv+13, 0);
8603 state->setup = NULL;
8604 state->total_param = SVAL(req->vwv+0, 0);
8605 state->param = NULL;
8606 state->total_data = SVAL(req->vwv+1, 0);
8607 state->data = NULL;
8608 state->max_param_return = SVAL(req->vwv+2, 0);
8609 state->max_data_return = SVAL(req->vwv+3, 0);
8610 state->max_setup_return = SVAL(req->vwv+4, 0);
8611 state->close_on_completion = BITSETW(req->vwv+5, 0);
8612 state->one_way = BITSETW(req->vwv+5, 1);
8614 state->call = tran_call;
8616 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8617 is so as a sanity check */
8618 if (state->setup_count != 1) {
8620 * Need to have rc=0 for ioctl to get job id for OS/2.
8621 * Network printing will fail if function is not successful.
8622 * Similar function in reply.c will be used if protocol
8623 * is LANMAN1.0 instead of LM1.2X002.
8624 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8625 * outbuf doesn't have to be set(only job id is used).
8627 if ( (state->setup_count == 4)
8628 && (tran_call == TRANSACT2_IOCTL)
8629 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8630 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8631 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8632 } else {
8633 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8634 DEBUG(2,("Transaction is %d\n",tran_call));
8635 TALLOC_FREE(state);
8636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8637 END_PROFILE(SMBtrans2);
8638 return;
8642 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8643 goto bad_param;
8645 if (state->total_data) {
8647 if (trans_oob(state->total_data, 0, dscnt)
8648 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8649 goto bad_param;
8652 /* Can't use talloc here, the core routines do realloc on the
8653 * params and data. */
8654 state->data = (char *)SMB_MALLOC(state->total_data);
8655 if (state->data == NULL) {
8656 DEBUG(0,("reply_trans2: data malloc fail for %u "
8657 "bytes !\n", (unsigned int)state->total_data));
8658 TALLOC_FREE(state);
8659 reply_nterror(req, NT_STATUS_NO_MEMORY);
8660 END_PROFILE(SMBtrans2);
8661 return;
8664 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8667 if (state->total_param) {
8669 if (trans_oob(state->total_param, 0, pscnt)
8670 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8671 goto bad_param;
8674 /* Can't use talloc here, the core routines do realloc on the
8675 * params and data. */
8676 state->param = (char *)SMB_MALLOC(state->total_param);
8677 if (state->param == NULL) {
8678 DEBUG(0,("reply_trans: param malloc fail for %u "
8679 "bytes !\n", (unsigned int)state->total_param));
8680 SAFE_FREE(state->data);
8681 TALLOC_FREE(state);
8682 reply_nterror(req, NT_STATUS_NO_MEMORY);
8683 END_PROFILE(SMBtrans2);
8684 return;
8687 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8690 state->received_data = dscnt;
8691 state->received_param = pscnt;
8693 if ((state->received_param == state->total_param) &&
8694 (state->received_data == state->total_data)) {
8696 handle_trans2(conn, req, state);
8698 SAFE_FREE(state->data);
8699 SAFE_FREE(state->param);
8700 TALLOC_FREE(state);
8701 END_PROFILE(SMBtrans2);
8702 return;
8705 DLIST_ADD(conn->pending_trans, state);
8707 /* We need to send an interim response then receive the rest
8708 of the parameter/data bytes */
8709 reply_outbuf(req, 0, 0);
8710 show_msg((char *)req->outbuf);
8711 END_PROFILE(SMBtrans2);
8712 return;
8714 bad_param:
8716 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8717 SAFE_FREE(state->data);
8718 SAFE_FREE(state->param);
8719 TALLOC_FREE(state);
8720 END_PROFILE(SMBtrans2);
8721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8725 /****************************************************************************
8726 Reply to a SMBtranss2
8727 ****************************************************************************/
8729 void reply_transs2(struct smb_request *req)
8731 connection_struct *conn = req->conn;
8732 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8733 struct trans_state *state;
8735 START_PROFILE(SMBtranss2);
8737 show_msg((char *)req->inbuf);
8739 if (req->wct < 8) {
8740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8741 END_PROFILE(SMBtranss2);
8742 return;
8745 for (state = conn->pending_trans; state != NULL;
8746 state = state->next) {
8747 if (state->mid == req->mid) {
8748 break;
8752 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8754 END_PROFILE(SMBtranss2);
8755 return;
8758 /* Revise state->total_param and state->total_data in case they have
8759 changed downwards */
8761 if (SVAL(req->vwv+0, 0) < state->total_param)
8762 state->total_param = SVAL(req->vwv+0, 0);
8763 if (SVAL(req->vwv+1, 0) < state->total_data)
8764 state->total_data = SVAL(req->vwv+1, 0);
8766 pcnt = SVAL(req->vwv+2, 0);
8767 poff = SVAL(req->vwv+3, 0);
8768 pdisp = SVAL(req->vwv+4, 0);
8770 dcnt = SVAL(req->vwv+5, 0);
8771 doff = SVAL(req->vwv+6, 0);
8772 ddisp = SVAL(req->vwv+7, 0);
8774 state->received_param += pcnt;
8775 state->received_data += dcnt;
8777 if ((state->received_data > state->total_data) ||
8778 (state->received_param > state->total_param))
8779 goto bad_param;
8781 if (pcnt) {
8782 if (trans_oob(state->total_param, pdisp, pcnt)
8783 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8784 goto bad_param;
8786 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8789 if (dcnt) {
8790 if (trans_oob(state->total_data, ddisp, dcnt)
8791 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8792 goto bad_param;
8794 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8797 if ((state->received_param < state->total_param) ||
8798 (state->received_data < state->total_data)) {
8799 END_PROFILE(SMBtranss2);
8800 return;
8803 handle_trans2(conn, req, state);
8805 DLIST_REMOVE(conn->pending_trans, state);
8806 SAFE_FREE(state->data);
8807 SAFE_FREE(state->param);
8808 TALLOC_FREE(state);
8810 END_PROFILE(SMBtranss2);
8811 return;
8813 bad_param:
8815 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8816 DLIST_REMOVE(conn->pending_trans, state);
8817 SAFE_FREE(state->data);
8818 SAFE_FREE(state->param);
8819 TALLOC_FREE(state);
8820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8821 END_PROFILE(SMBtranss2);
8822 return;