Fix bug #7339 - MSDFS is non-functional in 3.5.x
[Samba/ekacnet.git] / source3 / smbd / trans2.c
blob06b454ab3970f6a4d37f3be755ae920cb495df7f
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
57 return val;
60 /****************************************************************************
61 Utility functions for dealing with extended attributes.
62 ****************************************************************************/
64 /****************************************************************************
65 Refuse to allow clients to overwrite our private xattrs.
66 ****************************************************************************/
68 static bool samba_private_attr_name(const char *unix_ea_name)
70 static const char * const prohibited_ea_names[] = {
71 SAMBA_POSIX_INHERITANCE_EA_NAME,
72 SAMBA_XATTR_DOS_ATTRIB,
73 SAMBA_XATTR_MARKER,
74 XATTR_NTACL_NAME,
75 NULL
78 int i;
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
82 return true;
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
86 return true;
88 return false;
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
101 char *val = NULL;
102 ssize_t sizeret;
104 again:
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 if (!val) {
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 } else {
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
118 attr_size = 65536;
119 goto again;
122 if (sizeret == -1) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
129 pea->flags = 0;
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 } else {
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
136 TALLOC_FREE(val);
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
141 return NT_STATUS_OK;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
152 char *p;
153 char **names, **tmp;
154 size_t num_names;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
158 if (pnames) {
159 *pnames = NULL;
161 *pnum_names = 0;
162 return NT_STATUS_OK;
166 * TALLOC the result early to get the talloc hierarchy right.
169 names = TALLOC_ARRAY(mem_ctx, char *, 1);
170 if (names == NULL) {
171 DEBUG(0, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY;
175 while (ea_namelist_size <= 65536) {
177 ea_namelist = TALLOC_REALLOC_ARRAY(
178 names, ea_namelist, char, ea_namelist_size);
179 if (ea_namelist == NULL) {
180 DEBUG(0, ("talloc failed\n"));
181 TALLOC_FREE(names);
182 return NT_STATUS_NO_MEMORY;
185 if (fsp && fsp->fh->fd != -1) {
186 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 ea_namelist_size);
188 } else {
189 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
190 ea_namelist_size);
193 if ((sizeret == -1) && (errno == ERANGE)) {
194 ea_namelist_size *= 2;
196 else {
197 break;
201 if (sizeret == -1) {
202 TALLOC_FREE(names);
203 return map_nt_error_from_unix(errno);
206 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
207 (unsigned int)sizeret));
209 if (sizeret == 0) {
210 TALLOC_FREE(names);
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * Ensure the result is 0-terminated
222 if (ea_namelist[sizeret-1] != '\0') {
223 TALLOC_FREE(names);
224 return NT_STATUS_INTERNAL_ERROR;
228 * count the names
230 num_names = 0;
232 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
233 num_names += 1;
236 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
237 if (tmp == NULL) {
238 DEBUG(0, ("talloc failed\n"));
239 TALLOC_FREE(names);
240 return NT_STATUS_NO_MEMORY;
243 names = tmp;
244 num_names = 0;
246 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
247 names[num_names++] = p;
250 if (pnames) {
251 *pnames = names;
252 } else {
253 TALLOC_FREE(names);
255 *pnum_names = num_names;
256 return NT_STATUS_OK;
259 /****************************************************************************
260 Return a linked list of the total EA's. Plus the total size
261 ****************************************************************************/
263 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
264 const char *fname, size_t *pea_total_len)
266 /* Get a list of all xattrs. Max namesize is 64k. */
267 size_t i, num_names;
268 char **names;
269 struct ea_list *ea_list_head = NULL;
270 NTSTATUS status;
272 *pea_total_len = 0;
274 if (!lp_ea_support(SNUM(conn))) {
275 return NULL;
278 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
279 &names, &num_names);
281 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
282 return NULL;
285 for (i=0; i<num_names; i++) {
286 struct ea_list *listp;
287 fstring dos_ea_name;
289 if (strnequal(names[i], "system.", 7)
290 || samba_private_attr_name(names[i]))
291 continue;
293 listp = TALLOC_P(mem_ctx, struct ea_list);
294 if (listp == NULL) {
295 return NULL;
298 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
299 fname, names[i],
300 &listp->ea))) {
301 return NULL;
304 push_ascii_fstring(dos_ea_name, listp->ea.name);
306 *pea_total_len +=
307 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
309 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
310 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
311 (unsigned int)listp->ea.value.length));
313 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
317 /* Add on 4 for total length. */
318 if (*pea_total_len) {
319 *pea_total_len += 4;
322 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
323 (unsigned int)*pea_total_len));
325 return ea_list_head;
328 /****************************************************************************
329 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
330 that was filled.
331 ****************************************************************************/
333 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
334 connection_struct *conn, struct ea_list *ea_list)
336 unsigned int ret_data_size = 4;
337 char *p = pdata;
339 SMB_ASSERT(total_data_size >= 4);
341 if (!lp_ea_support(SNUM(conn))) {
342 SIVAL(pdata,4,0);
343 return 4;
346 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
347 size_t dos_namelen;
348 fstring dos_ea_name;
349 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
350 dos_namelen = strlen(dos_ea_name);
351 if (dos_namelen > 255 || dos_namelen == 0) {
352 break;
354 if (ea_list->ea.value.length > 65535) {
355 break;
357 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
358 break;
361 /* We know we have room. */
362 SCVAL(p,0,ea_list->ea.flags);
363 SCVAL(p,1,dos_namelen);
364 SSVAL(p,2,ea_list->ea.value.length);
365 fstrcpy(p+4, dos_ea_name);
366 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
368 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
369 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
372 ret_data_size = PTR_DIFF(p, pdata);
373 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
374 SIVAL(pdata,0,ret_data_size);
375 return ret_data_size;
378 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
379 char *pdata,
380 unsigned int total_data_size,
381 unsigned int *ret_data_size,
382 connection_struct *conn,
383 struct ea_list *ea_list)
385 uint8_t *p = (uint8_t *)pdata;
386 uint8_t *last_start = NULL;
388 *ret_data_size = 0;
390 if (!lp_ea_support(SNUM(conn))) {
391 return NT_STATUS_NO_EAS_ON_FILE;
394 for (; ea_list; ea_list = ea_list->next) {
395 size_t dos_namelen;
396 fstring dos_ea_name;
397 size_t this_size;
399 if (last_start) {
400 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
402 last_start = p;
404 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
405 dos_namelen = strlen(dos_ea_name);
406 if (dos_namelen > 255 || dos_namelen == 0) {
407 return NT_STATUS_INTERNAL_ERROR;
409 if (ea_list->ea.value.length > 65535) {
410 return NT_STATUS_INTERNAL_ERROR;
413 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
415 if (ea_list->next) {
416 size_t pad = 4 - (this_size % 4);
417 this_size += pad;
420 if (this_size > total_data_size) {
421 return NT_STATUS_INFO_LENGTH_MISMATCH;
424 /* We know we have room. */
425 SIVAL(p, 0x00, 0); /* next offset */
426 SCVAL(p, 0x04, ea_list->ea.flags);
427 SCVAL(p, 0x05, dos_namelen);
428 SSVAL(p, 0x06, ea_list->ea.value.length);
429 fstrcpy((char *)(p+0x08), dos_ea_name);
430 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
432 total_data_size -= this_size;
433 p += this_size;
436 *ret_data_size = PTR_DIFF(p, pdata);
437 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
438 return NT_STATUS_OK;
441 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
443 size_t total_ea_len = 0;
444 TALLOC_CTX *mem_ctx = NULL;
446 if (!lp_ea_support(SNUM(conn))) {
447 return 0;
449 mem_ctx = talloc_tos();
450 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
451 return total_ea_len;
454 /****************************************************************************
455 Ensure the EA name is case insensitive by matching any existing EA name.
456 ****************************************************************************/
458 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
460 size_t total_ea_len;
461 TALLOC_CTX *mem_ctx = talloc_tos();
462 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
464 for (; ea_list; ea_list = ea_list->next) {
465 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
466 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
467 &unix_ea_name[5], ea_list->ea.name));
468 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
469 break;
474 /****************************************************************************
475 Set or delete an extended attribute.
476 ****************************************************************************/
478 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
479 const struct smb_filename *smb_fname, struct ea_list *ea_list)
481 char *fname = NULL;
483 if (!lp_ea_support(SNUM(conn))) {
484 return NT_STATUS_EAS_NOT_SUPPORTED;
487 /* For now setting EAs on streams isn't supported. */
488 fname = smb_fname->base_name;
490 for (;ea_list; ea_list = ea_list->next) {
491 int ret;
492 fstring unix_ea_name;
494 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
495 fstrcat(unix_ea_name, ea_list->ea.name);
497 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
499 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
501 if (samba_private_attr_name(unix_ea_name)) {
502 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
503 return NT_STATUS_ACCESS_DENIED;
506 if (ea_list->ea.value.length == 0) {
507 /* Remove the attribute. */
508 if (fsp && (fsp->fh->fd != -1)) {
509 DEBUG(10,("set_ea: deleting ea name %s on "
510 "file %s by file descriptor.\n",
511 unix_ea_name, fsp_str_dbg(fsp)));
512 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
513 } else {
514 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
515 unix_ea_name, fname));
516 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
518 #ifdef ENOATTR
519 /* Removing a non existent attribute always succeeds. */
520 if (ret == -1 && errno == ENOATTR) {
521 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
522 unix_ea_name));
523 ret = 0;
525 #endif
526 } else {
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: setting ea name %s on file "
529 "%s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
532 ea_list->ea.value.data, ea_list->ea.value.length, 0);
533 } else {
534 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
535 unix_ea_name, fname));
536 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
537 ea_list->ea.value.data, ea_list->ea.value.length, 0);
541 if (ret == -1) {
542 #ifdef ENOTSUP
543 if (errno == ENOTSUP) {
544 return NT_STATUS_EAS_NOT_SUPPORTED;
546 #endif
547 return map_nt_error_from_unix(errno);
551 return NT_STATUS_OK;
553 /****************************************************************************
554 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
555 ****************************************************************************/
557 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
559 struct ea_list *ea_list_head = NULL;
560 size_t converted_size, offset = 0;
562 while (offset + 2 < data_size) {
563 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
564 unsigned int namelen = CVAL(pdata,offset);
566 offset++; /* Go past the namelen byte. */
568 /* integer wrap paranioa. */
569 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
570 (offset > data_size) || (namelen > data_size) ||
571 (offset + namelen >= data_size)) {
572 break;
574 /* Ensure the name is null terminated. */
575 if (pdata[offset + namelen] != '\0') {
576 return NULL;
578 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
579 &converted_size)) {
580 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
581 "failed: %s", strerror(errno)));
583 if (!eal->ea.name) {
584 return NULL;
587 offset += (namelen + 1); /* Go past the name + terminating zero. */
588 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
589 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
592 return ea_list_head;
595 /****************************************************************************
596 Read one EA list entry from the buffer.
597 ****************************************************************************/
599 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
601 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
602 uint16 val_len;
603 unsigned int namelen;
604 size_t converted_size;
606 if (!eal) {
607 return NULL;
610 if (data_size < 6) {
611 return NULL;
614 eal->ea.flags = CVAL(pdata,0);
615 namelen = CVAL(pdata,1);
616 val_len = SVAL(pdata,2);
618 if (4 + namelen + 1 + val_len > data_size) {
619 return NULL;
622 /* Ensure the name is null terminated. */
623 if (pdata[namelen + 4] != '\0') {
624 return NULL;
626 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
627 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
628 strerror(errno)));
630 if (!eal->ea.name) {
631 return NULL;
634 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
635 if (!eal->ea.value.data) {
636 return NULL;
639 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
641 /* Ensure we're null terminated just in case we print the value. */
642 eal->ea.value.data[val_len] = '\0';
643 /* But don't count the null. */
644 eal->ea.value.length--;
646 if (pbytes_used) {
647 *pbytes_used = 4 + namelen + 1 + val_len;
650 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
651 dump_data(10, eal->ea.value.data, eal->ea.value.length);
653 return eal;
656 /****************************************************************************
657 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
658 ****************************************************************************/
660 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
662 struct ea_list *ea_list_head = NULL;
663 size_t offset = 0;
664 size_t bytes_used = 0;
666 while (offset < data_size) {
667 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
669 if (!eal) {
670 return NULL;
673 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
674 offset += bytes_used;
677 return ea_list_head;
680 /****************************************************************************
681 Count the total EA size needed.
682 ****************************************************************************/
684 static size_t ea_list_size(struct ea_list *ealist)
686 fstring dos_ea_name;
687 struct ea_list *listp;
688 size_t ret = 0;
690 for (listp = ealist; listp; listp = listp->next) {
691 push_ascii_fstring(dos_ea_name, listp->ea.name);
692 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
694 /* Add on 4 for total length. */
695 if (ret) {
696 ret += 4;
699 return ret;
702 /****************************************************************************
703 Return a union of EA's from a file list and a list of names.
704 The TALLOC context for the two lists *MUST* be identical as we steal
705 memory from one list to add to another. JRA.
706 ****************************************************************************/
708 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
710 struct ea_list *nlistp, *flistp;
712 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
713 for (flistp = file_list; flistp; flistp = flistp->next) {
714 if (strequal(nlistp->ea.name, flistp->ea.name)) {
715 break;
719 if (flistp) {
720 /* Copy the data from this entry. */
721 nlistp->ea.flags = flistp->ea.flags;
722 nlistp->ea.value = flistp->ea.value;
723 } else {
724 /* Null entry. */
725 nlistp->ea.flags = 0;
726 ZERO_STRUCT(nlistp->ea.value);
730 *total_ea_len = ea_list_size(name_list);
731 return name_list;
734 /****************************************************************************
735 Send the required number of replies back.
736 We assume all fields other than the data fields are
737 set correctly for the type of call.
738 HACK ! Always assumes smb_setup field is zero.
739 ****************************************************************************/
741 void send_trans2_replies(connection_struct *conn,
742 struct smb_request *req,
743 const char *params,
744 int paramsize,
745 const char *pdata,
746 int datasize,
747 int max_data_bytes)
749 /* As we are using a protocol > LANMAN1 then the max_send
750 variable must have been set in the sessetupX call.
751 This takes precedence over the max_xmit field in the
752 global struct. These different max_xmit variables should
753 be merged as this is now too confusing */
755 int data_to_send = datasize;
756 int params_to_send = paramsize;
757 int useable_space;
758 const char *pp = params;
759 const char *pd = pdata;
760 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
761 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
762 int data_alignment_offset = 0;
763 bool overflow = False;
764 struct smbd_server_connection *sconn = smbd_server_conn;
765 int max_send = sconn->smb1.sessions.max_send;
767 /* Modify the data_to_send and datasize and set the error if
768 we're trying to send more than max_data_bytes. We still send
769 the part of the packet(s) that fit. Strange, but needed
770 for OS/2. */
772 if (max_data_bytes > 0 && datasize > max_data_bytes) {
773 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
774 max_data_bytes, datasize ));
775 datasize = data_to_send = max_data_bytes;
776 overflow = True;
779 /* If there genuinely are no parameters or data to send just send the empty packet */
781 if(params_to_send == 0 && data_to_send == 0) {
782 reply_outbuf(req, 10, 0);
783 show_msg((char *)req->outbuf);
784 if (!srv_send_smb(smbd_server_fd(),
785 (char *)req->outbuf,
786 true, req->seqnum+1,
787 IS_CONN_ENCRYPTED(conn),
788 &req->pcd)) {
789 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
791 TALLOC_FREE(req->outbuf);
792 return;
795 /* When sending params and data ensure that both are nicely aligned */
796 /* Only do this alignment when there is also data to send - else
797 can cause NT redirector problems. */
799 if (((params_to_send % 4) != 0) && (data_to_send != 0))
800 data_alignment_offset = 4 - (params_to_send % 4);
802 /* Space is bufsize minus Netbios over TCP header minus SMB header */
803 /* The alignment_offset is to align the param bytes on an even byte
804 boundary. NT 4.0 Beta needs this to work correctly. */
806 useable_space = max_send - (smb_size
807 + 2 * 10 /* wct */
808 + alignment_offset
809 + data_alignment_offset);
811 if (useable_space < 0) {
812 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
813 "= %d!!!", useable_space));
814 exit_server_cleanly("send_trans2_replies: Not enough space");
817 while (params_to_send || data_to_send) {
818 /* Calculate whether we will totally or partially fill this packet */
820 total_sent_thistime = params_to_send + data_to_send;
822 /* We can never send more than useable_space */
824 * Note that 'useable_space' does not include the alignment offsets,
825 * but we must include the alignment offsets in the calculation of
826 * the length of the data we send over the wire, as the alignment offsets
827 * are sent here. Fix from Marc_Jacobsen@hp.com.
830 total_sent_thistime = MIN(total_sent_thistime, useable_space);
832 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
833 + data_alignment_offset);
836 * We might have SMBtrans2s in req which was transferred to
837 * the outbuf, fix that.
839 SCVAL(req->outbuf, smb_com, SMBtrans2);
841 /* Set total params and data to be sent */
842 SSVAL(req->outbuf,smb_tprcnt,paramsize);
843 SSVAL(req->outbuf,smb_tdrcnt,datasize);
845 /* Calculate how many parameters and data we can fit into
846 * this packet. Parameters get precedence
849 params_sent_thistime = MIN(params_to_send,useable_space);
850 data_sent_thistime = useable_space - params_sent_thistime;
851 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
853 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
855 /* smb_proff is the offset from the start of the SMB header to the
856 parameter bytes, however the first 4 bytes of outbuf are
857 the Netbios over TCP header. Thus use smb_base() to subtract
858 them from the calculation */
860 SSVAL(req->outbuf,smb_proff,
861 ((smb_buf(req->outbuf)+alignment_offset)
862 - smb_base(req->outbuf)));
864 if(params_sent_thistime == 0)
865 SSVAL(req->outbuf,smb_prdisp,0);
866 else
867 /* Absolute displacement of param bytes sent in this packet */
868 SSVAL(req->outbuf,smb_prdisp,pp - params);
870 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
871 if(data_sent_thistime == 0) {
872 SSVAL(req->outbuf,smb_droff,0);
873 SSVAL(req->outbuf,smb_drdisp, 0);
874 } else {
875 /* The offset of the data bytes is the offset of the
876 parameter bytes plus the number of parameters being sent this time */
877 SSVAL(req->outbuf, smb_droff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf))
880 + params_sent_thistime + data_alignment_offset);
881 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
884 /* Initialize the padding for alignment */
886 if (alignment_offset != 0) {
887 memset(smb_buf(req->outbuf), 0, alignment_offset);
890 /* Copy the param bytes into the packet */
892 if(params_sent_thistime) {
893 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
894 params_sent_thistime);
897 /* Copy in the data bytes */
898 if(data_sent_thistime) {
899 if (data_alignment_offset != 0) {
900 memset((smb_buf(req->outbuf)+alignment_offset+
901 params_sent_thistime), 0,
902 data_alignment_offset);
904 memcpy(smb_buf(req->outbuf)+alignment_offset
905 +params_sent_thistime+data_alignment_offset,
906 pd,data_sent_thistime);
909 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
910 params_sent_thistime, data_sent_thistime, useable_space));
911 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
912 params_to_send, data_to_send, paramsize, datasize));
914 if (overflow) {
915 error_packet_set((char *)req->outbuf,
916 ERRDOS,ERRbufferoverflow,
917 STATUS_BUFFER_OVERFLOW,
918 __LINE__,__FILE__);
921 /* Send the packet */
922 show_msg((char *)req->outbuf);
923 if (!srv_send_smb(smbd_server_fd(),
924 (char *)req->outbuf,
925 true, req->seqnum+1,
926 IS_CONN_ENCRYPTED(conn),
927 &req->pcd))
928 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
930 TALLOC_FREE(req->outbuf);
932 pp += params_sent_thistime;
933 pd += data_sent_thistime;
935 params_to_send -= params_sent_thistime;
936 data_to_send -= data_sent_thistime;
938 /* Sanity check */
939 if(params_to_send < 0 || data_to_send < 0) {
940 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
941 params_to_send, data_to_send));
942 return;
946 return;
949 /****************************************************************************
950 Reply to a TRANSACT2_OPEN.
951 ****************************************************************************/
953 static void call_trans2open(connection_struct *conn,
954 struct smb_request *req,
955 char **pparams, int total_params,
956 char **ppdata, int total_data,
957 unsigned int max_data_bytes)
959 struct smb_filename *smb_fname = NULL;
960 char *params = *pparams;
961 char *pdata = *ppdata;
962 int deny_mode;
963 int32 open_attr;
964 bool oplock_request;
965 #if 0
966 bool return_additional_info;
967 int16 open_sattr;
968 time_t open_time;
969 #endif
970 int open_ofun;
971 uint32 open_size;
972 char *pname;
973 char *fname = NULL;
974 SMB_OFF_T size=0;
975 int fattr=0,mtime=0;
976 SMB_INO_T inode = 0;
977 int smb_action = 0;
978 files_struct *fsp;
979 struct ea_list *ea_list = NULL;
980 uint16 flags = 0;
981 NTSTATUS status;
982 uint32 access_mask;
983 uint32 share_mode;
984 uint32 create_disposition;
985 uint32 create_options = 0;
986 uint32_t private_flags = 0;
987 TALLOC_CTX *ctx = talloc_tos();
990 * Ensure we have enough parameters to perform the operation.
993 if (total_params < 29) {
994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
995 goto out;
998 flags = SVAL(params, 0);
999 deny_mode = SVAL(params, 2);
1000 open_attr = SVAL(params,6);
1001 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1002 if (oplock_request) {
1003 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1006 #if 0
1007 return_additional_info = BITSETW(params,0);
1008 open_sattr = SVAL(params, 4);
1009 open_time = make_unix_date3(params+8);
1010 #endif
1011 open_ofun = SVAL(params,12);
1012 open_size = IVAL(params,14);
1013 pname = &params[28];
1015 if (IS_IPC(conn)) {
1016 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1017 goto out;
1020 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1021 total_params - 28, STR_TERMINATE,
1022 &status);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 reply_nterror(req, status);
1025 goto out;
1028 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1029 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1030 (unsigned int)open_ofun, open_size));
1032 status = filename_convert(ctx,
1033 conn,
1034 req->flags2 & FLAGS2_DFS_PATHNAMES,
1035 fname,
1037 NULL,
1038 &smb_fname);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1041 reply_botherror(req,
1042 NT_STATUS_PATH_NOT_COVERED,
1043 ERRSRV, ERRbadpath);
1044 goto out;
1046 reply_nterror(req, status);
1047 goto out;
1050 if (open_ofun == 0) {
1051 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1052 goto out;
1055 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1056 &access_mask, &share_mode,
1057 &create_disposition,
1058 &create_options,
1059 &private_flags)) {
1060 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1061 goto out;
1064 /* Any data in this call is an EA list. */
1065 if (total_data && (total_data != 4)) {
1066 if (total_data < 10) {
1067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1068 goto out;
1071 if (IVAL(pdata,0) > total_data) {
1072 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1073 IVAL(pdata,0), (unsigned int)total_data));
1074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1075 goto out;
1078 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1079 total_data - 4);
1080 if (!ea_list) {
1081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1082 goto out;
1085 if (!lp_ea_support(SNUM(conn))) {
1086 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1087 goto out;
1091 status = SMB_VFS_CREATE_FILE(
1092 conn, /* conn */
1093 req, /* req */
1094 0, /* root_dir_fid */
1095 smb_fname, /* fname */
1096 access_mask, /* access_mask */
1097 share_mode, /* share_access */
1098 create_disposition, /* create_disposition*/
1099 create_options, /* create_options */
1100 open_attr, /* file_attributes */
1101 oplock_request, /* oplock_request */
1102 open_size, /* allocation_size */
1103 private_flags,
1104 NULL, /* sd */
1105 ea_list, /* ea_list */
1106 &fsp, /* result */
1107 &smb_action); /* psbuf */
1109 if (!NT_STATUS_IS_OK(status)) {
1110 if (open_was_deferred(req->mid)) {
1111 /* We have re-scheduled this call. */
1112 goto out;
1114 reply_openerror(req, status);
1115 goto out;
1118 size = get_file_size_stat(&smb_fname->st);
1119 fattr = dos_mode(conn, smb_fname);
1120 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1121 inode = smb_fname->st.st_ex_ino;
1122 if (fattr & aDIR) {
1123 close_file(req, fsp, ERROR_CLOSE);
1124 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1125 goto out;
1128 /* Realloc the size of parameters and data we will return */
1129 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1130 if(*pparams == NULL ) {
1131 reply_nterror(req, NT_STATUS_NO_MEMORY);
1132 goto out;
1134 params = *pparams;
1136 SSVAL(params,0,fsp->fnum);
1137 SSVAL(params,2,fattr);
1138 srv_put_dos_date2(params,4, mtime);
1139 SIVAL(params,8, (uint32)size);
1140 SSVAL(params,12,deny_mode);
1141 SSVAL(params,14,0); /* open_type - file or directory. */
1142 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1144 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1145 smb_action |= EXTENDED_OPLOCK_GRANTED;
1148 SSVAL(params,18,smb_action);
1151 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1153 SIVAL(params,20,inode);
1154 SSVAL(params,24,0); /* Padding. */
1155 if (flags & 8) {
1156 uint32 ea_size = estimate_ea_size(conn, fsp,
1157 fsp->fsp_name->base_name);
1158 SIVAL(params, 26, ea_size);
1159 } else {
1160 SIVAL(params, 26, 0);
1163 /* Send the required number of replies */
1164 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1165 out:
1166 TALLOC_FREE(smb_fname);
1169 /*********************************************************
1170 Routine to check if a given string matches exactly.
1171 as a special case a mask of "." does NOT match. That
1172 is required for correct wildcard semantics
1173 Case can be significant or not.
1174 **********************************************************/
1176 static bool exact_match(bool has_wild,
1177 bool case_sensitive,
1178 const char *str,
1179 const char *mask)
1181 if (mask[0] == '.' && mask[1] == 0) {
1182 return false;
1185 if (has_wild) {
1186 return false;
1189 if (case_sensitive) {
1190 return strcmp(str,mask)==0;
1191 } else {
1192 return StrCaseCmp(str,mask) == 0;
1196 /****************************************************************************
1197 Return the filetype for UNIX extensions.
1198 ****************************************************************************/
1200 static uint32 unix_filetype(mode_t mode)
1202 if(S_ISREG(mode))
1203 return UNIX_TYPE_FILE;
1204 else if(S_ISDIR(mode))
1205 return UNIX_TYPE_DIR;
1206 #ifdef S_ISLNK
1207 else if(S_ISLNK(mode))
1208 return UNIX_TYPE_SYMLINK;
1209 #endif
1210 #ifdef S_ISCHR
1211 else if(S_ISCHR(mode))
1212 return UNIX_TYPE_CHARDEV;
1213 #endif
1214 #ifdef S_ISBLK
1215 else if(S_ISBLK(mode))
1216 return UNIX_TYPE_BLKDEV;
1217 #endif
1218 #ifdef S_ISFIFO
1219 else if(S_ISFIFO(mode))
1220 return UNIX_TYPE_FIFO;
1221 #endif
1222 #ifdef S_ISSOCK
1223 else if(S_ISSOCK(mode))
1224 return UNIX_TYPE_SOCKET;
1225 #endif
1227 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1228 return UNIX_TYPE_UNKNOWN;
1231 /****************************************************************************
1232 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1233 ****************************************************************************/
1235 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1237 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1238 const SMB_STRUCT_STAT *psbuf,
1239 uint32 perms,
1240 enum perm_type ptype,
1241 mode_t *ret_perms)
1243 mode_t ret = 0;
1245 if (perms == SMB_MODE_NO_CHANGE) {
1246 if (!VALID_STAT(*psbuf)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1248 } else {
1249 *ret_perms = psbuf->st_ex_mode;
1250 return NT_STATUS_OK;
1254 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1255 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1256 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1257 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1258 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1259 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1260 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1261 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1262 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1263 #ifdef S_ISVTX
1264 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1265 #endif
1266 #ifdef S_ISGID
1267 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1268 #endif
1269 #ifdef S_ISUID
1270 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1271 #endif
1273 switch (ptype) {
1274 case PERM_NEW_FILE:
1275 /* Apply mode mask */
1276 ret &= lp_create_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_create_mode(SNUM(conn));
1279 break;
1280 case PERM_NEW_DIR:
1281 ret &= lp_dir_mask(SNUM(conn));
1282 /* Add in force bits */
1283 ret |= lp_force_dir_mode(SNUM(conn));
1284 break;
1285 case PERM_EXISTING_FILE:
1286 /* Apply mode mask */
1287 ret &= lp_security_mask(SNUM(conn));
1288 /* Add in force bits */
1289 ret |= lp_force_security_mode(SNUM(conn));
1290 break;
1291 case PERM_EXISTING_DIR:
1292 /* Apply mode mask */
1293 ret &= lp_dir_security_mask(SNUM(conn));
1294 /* Add in force bits */
1295 ret |= lp_force_dir_security_mode(SNUM(conn));
1296 break;
1299 *ret_perms = ret;
1300 return NT_STATUS_OK;
1303 /****************************************************************************
1304 Needed to show the msdfs symlinks as directories. Modifies psbuf
1305 to be a directory if it's a msdfs link.
1306 ****************************************************************************/
1308 static bool check_msdfs_link(connection_struct *conn,
1309 const char *pathname,
1310 SMB_STRUCT_STAT *psbuf)
1312 int saved_errno = errno;
1313 if(lp_host_msdfs() &&
1314 lp_msdfs_root(SNUM(conn)) &&
1315 is_msdfs_link(conn, pathname, psbuf)) {
1317 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1318 "as a directory\n",
1319 pathname));
1320 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1321 errno = saved_errno;
1322 return true;
1324 errno = saved_errno;
1325 return false;
1329 /****************************************************************************
1330 Get a level dependent lanman2 dir entry.
1331 ****************************************************************************/
1333 struct smbd_dirptr_lanman2_state {
1334 connection_struct *conn;
1335 uint32_t info_level;
1336 bool check_mangled_names;
1337 bool has_wild;
1338 bool got_exact_match;
1341 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1342 void *private_data,
1343 const char *dname,
1344 const char *mask,
1345 char **_fname)
1347 struct smbd_dirptr_lanman2_state *state =
1348 (struct smbd_dirptr_lanman2_state *)private_data;
1349 bool ok;
1350 char mangled_name[13]; /* mangled 8.3 name. */
1351 bool got_match;
1352 const char *fname;
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname, state->conn->params)) {
1356 ok = name_to_8_3(dname, mangled_name,
1357 true, state->conn->params);
1358 if (!ok) {
1359 return false;
1361 fname = mangled_name;
1362 } else {
1363 fname = dname;
1366 got_match = exact_match(state->has_wild,
1367 state->conn->case_sensitive,
1368 fname, mask);
1369 state->got_exact_match = got_match;
1370 if (!got_match) {
1371 got_match = mask_match(fname, mask,
1372 state->conn->case_sensitive);
1375 if(!got_match && state->check_mangled_names &&
1376 !mangle_is_8_3(fname, false, state->conn->params)) {
1378 * It turns out that NT matches wildcards against
1379 * both long *and* short names. This may explain some
1380 * of the wildcard wierdness from old DOS clients
1381 * that some people have been seeing.... JRA.
1383 /* Force the mangling into 8.3. */
1384 ok = name_to_8_3(fname, mangled_name,
1385 false, state->conn->params);
1386 if (!ok) {
1387 return false;
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1392 mangled_name, mask);
1393 state->got_exact_match = got_match;
1394 if (!got_match) {
1395 got_match = mask_match(mangled_name, mask,
1396 state->conn->case_sensitive);
1400 if (!got_match) {
1401 return false;
1404 *_fname = talloc_strdup(ctx, fname);
1405 if (*_fname == NULL) {
1406 return false;
1409 return true;
1412 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1413 void *private_data,
1414 struct smb_filename *smb_fname,
1415 uint32_t *_mode)
1417 struct smbd_dirptr_lanman2_state *state =
1418 (struct smbd_dirptr_lanman2_state *)private_data;
1419 bool ms_dfs_link = false;
1420 uint32_t mode = 0;
1422 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1423 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1424 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1425 "Couldn't lstat [%s] (%s)\n",
1426 smb_fname_str_dbg(smb_fname),
1427 strerror(errno)));
1428 return false;
1430 } else if (!VALID_STAT(smb_fname->st) &&
1431 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1432 /* Needed to show the msdfs symlinks as
1433 * directories */
1435 ms_dfs_link = check_msdfs_link(state->conn,
1436 smb_fname->base_name,
1437 &smb_fname->st);
1438 if (!ms_dfs_link) {
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't stat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname),
1442 strerror(errno)));
1443 return false;
1447 if (ms_dfs_link) {
1448 mode = dos_mode_msdfs(state->conn, smb_fname);
1449 } else {
1450 mode = dos_mode(state->conn, smb_fname);
1453 *_mode = mode;
1454 return true;
1457 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1458 connection_struct *conn,
1459 uint16_t flags2,
1460 uint32_t info_level,
1461 struct ea_list *name_list,
1462 bool check_mangled_names,
1463 bool requires_resume_key,
1464 uint32_t mode,
1465 const char *fname,
1466 const struct smb_filename *smb_fname,
1467 uint64_t space_remaining,
1468 uint8_t align,
1469 bool do_pad,
1470 char *base_data,
1471 char **ppdata,
1472 char *end_data,
1473 bool *out_of_space,
1474 uint64_t *last_entry_off)
1476 char *p, *q, *pdata = *ppdata;
1477 uint32_t reskey=0;
1478 uint64_t file_size = 0;
1479 uint64_t allocation_size = 0;
1480 uint32_t len;
1481 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1482 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1483 time_t c_date = (time_t)0;
1484 char *nameptr;
1485 char *last_entry_ptr;
1486 bool was_8_3;
1487 off_t off;
1488 off_t pad = 0;
1490 *out_of_space = false;
1492 ZERO_STRUCT(mdate_ts);
1493 ZERO_STRUCT(adate_ts);
1494 ZERO_STRUCT(create_date_ts);
1495 ZERO_STRUCT(cdate_ts);
1497 if (!(mode & aDIR)) {
1498 file_size = get_file_size_stat(&smb_fname->st);
1500 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1502 mdate_ts = smb_fname->st.st_ex_mtime;
1503 adate_ts = smb_fname->st.st_ex_atime;
1504 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1505 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1507 if (lp_dos_filetime_resolution(SNUM(conn))) {
1508 dos_filetime_timespec(&create_date_ts);
1509 dos_filetime_timespec(&mdate_ts);
1510 dos_filetime_timespec(&adate_ts);
1511 dos_filetime_timespec(&cdate_ts);
1514 create_date = convert_timespec_to_time_t(create_date_ts);
1515 mdate = convert_timespec_to_time_t(mdate_ts);
1516 adate = convert_timespec_to_time_t(adate_ts);
1517 c_date = convert_timespec_to_time_t(cdate_ts);
1519 /* align the record */
1520 off = PTR_DIFF(pdata, base_data);
1521 pad = (off + (align-1)) & ~(align-1);
1522 pad -= off;
1523 off += pad;
1524 /* initialize padding to 0 */
1525 if (pad) {
1526 memset(pdata, 0, pad);
1528 space_remaining -= pad;
1530 pdata += pad;
1531 p = pdata;
1532 last_entry_ptr = p;
1534 pad = 0;
1535 off = 0;
1537 switch (info_level) {
1538 case SMB_FIND_INFO_STANDARD:
1539 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1540 if(requires_resume_key) {
1541 SIVAL(p,0,reskey);
1542 p += 4;
1544 srv_put_dos_date2(p,0,create_date);
1545 srv_put_dos_date2(p,4,adate);
1546 srv_put_dos_date2(p,8,mdate);
1547 SIVAL(p,12,(uint32)file_size);
1548 SIVAL(p,16,(uint32)allocation_size);
1549 SSVAL(p,20,mode);
1550 p += 23;
1551 nameptr = p;
1552 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1553 p += ucs2_align(base_data, p, 0);
1555 len = srvstr_push(base_data, flags2, p,
1556 fname, PTR_DIFF(end_data, p),
1557 STR_TERMINATE);
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1559 if (len > 2) {
1560 SCVAL(nameptr, -1, len - 2);
1561 } else {
1562 SCVAL(nameptr, -1, 0);
1564 } else {
1565 if (len > 1) {
1566 SCVAL(nameptr, -1, len - 1);
1567 } else {
1568 SCVAL(nameptr, -1, 0);
1571 p += len;
1572 break;
1574 case SMB_FIND_EA_SIZE:
1575 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1576 if (requires_resume_key) {
1577 SIVAL(p,0,reskey);
1578 p += 4;
1580 srv_put_dos_date2(p,0,create_date);
1581 srv_put_dos_date2(p,4,adate);
1582 srv_put_dos_date2(p,8,mdate);
1583 SIVAL(p,12,(uint32)file_size);
1584 SIVAL(p,16,(uint32)allocation_size);
1585 SSVAL(p,20,mode);
1587 unsigned int ea_size = estimate_ea_size(conn, NULL,
1588 smb_fname->base_name);
1589 SIVAL(p,22,ea_size); /* Extended attributes */
1591 p += 27;
1592 nameptr = p - 1;
1593 len = srvstr_push(base_data, flags2,
1594 p, fname, PTR_DIFF(end_data, p),
1595 STR_TERMINATE | STR_NOALIGN);
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 if (len > 2) {
1598 len -= 2;
1599 } else {
1600 len = 0;
1602 } else {
1603 if (len > 1) {
1604 len -= 1;
1605 } else {
1606 len = 0;
1609 SCVAL(nameptr,0,len);
1610 p += len;
1611 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1612 break;
1614 case SMB_FIND_EA_LIST:
1616 struct ea_list *file_list = NULL;
1617 size_t ea_len = 0;
1619 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1620 if (!name_list) {
1621 return false;
1623 if (requires_resume_key) {
1624 SIVAL(p,0,reskey);
1625 p += 4;
1627 srv_put_dos_date2(p,0,create_date);
1628 srv_put_dos_date2(p,4,adate);
1629 srv_put_dos_date2(p,8,mdate);
1630 SIVAL(p,12,(uint32)file_size);
1631 SIVAL(p,16,(uint32)allocation_size);
1632 SSVAL(p,20,mode);
1633 p += 22; /* p now points to the EA area. */
1635 file_list = get_ea_list_from_file(ctx, conn, NULL,
1636 smb_fname->base_name,
1637 &ea_len);
1638 name_list = ea_list_union(name_list, file_list, &ea_len);
1640 /* We need to determine if this entry will fit in the space available. */
1641 /* Max string size is 255 bytes. */
1642 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1643 *out_of_space = true;
1644 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1645 return False; /* Not finished - just out of space */
1648 /* Push the ea_data followed by the name. */
1649 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1650 nameptr = p;
1651 len = srvstr_push(base_data, flags2,
1652 p + 1, fname, PTR_DIFF(end_data, p+1),
1653 STR_TERMINATE | STR_NOALIGN);
1654 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1655 if (len > 2) {
1656 len -= 2;
1657 } else {
1658 len = 0;
1660 } else {
1661 if (len > 1) {
1662 len -= 1;
1663 } else {
1664 len = 0;
1667 SCVAL(nameptr,0,len);
1668 p += len + 1;
1669 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1670 break;
1673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1675 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1676 p += 4;
1677 SIVAL(p,0,reskey); p += 4;
1678 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1679 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1680 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1681 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1682 SOFF_T(p,0,file_size); p += 8;
1683 SOFF_T(p,0,allocation_size); p += 8;
1684 SIVAL(p,0,mode); p += 4;
1685 q = p; p += 4; /* q is placeholder for name length. */
1687 unsigned int ea_size = estimate_ea_size(conn, NULL,
1688 smb_fname->base_name);
1689 SIVAL(p,0,ea_size); /* Extended attributes */
1690 p += 4;
1692 /* Clear the short name buffer. This is
1693 * IMPORTANT as not doing so will trigger
1694 * a Win2k client bug. JRA.
1696 if (!was_8_3 && check_mangled_names) {
1697 char mangled_name[13]; /* mangled 8.3 name. */
1698 if (!name_to_8_3(fname,mangled_name,True,
1699 conn->params)) {
1700 /* Error - mangle failed ! */
1701 memset(mangled_name,'\0',12);
1703 mangled_name[12] = 0;
1704 len = srvstr_push(base_data, flags2,
1705 p+2, mangled_name, 24,
1706 STR_UPPER|STR_UNICODE);
1707 if (len < 24) {
1708 memset(p + 2 + len,'\0',24 - len);
1710 SSVAL(p, 0, len);
1711 } else {
1712 memset(p,'\0',26);
1714 p += 2 + 24;
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1718 SIVAL(q,0,len);
1719 p += len;
1721 len = PTR_DIFF(p, pdata);
1722 pad = (len + (align-1)) & ~(align-1);
1724 * offset to the next entry, the caller
1725 * will overwrite it for the last entry
1726 * that's why we always include the padding
1728 SIVAL(pdata,0,pad);
1730 * set padding to zero
1732 if (do_pad) {
1733 memset(p, 0, pad - len);
1734 p = pdata + pad;
1735 } else {
1736 p = pdata + len;
1738 break;
1740 case SMB_FIND_FILE_DIRECTORY_INFO:
1741 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1742 p += 4;
1743 SIVAL(p,0,reskey); p += 4;
1744 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1745 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1746 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1747 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1748 SOFF_T(p,0,file_size); p += 8;
1749 SOFF_T(p,0,allocation_size); p += 8;
1750 SIVAL(p,0,mode); p += 4;
1751 len = srvstr_push(base_data, flags2,
1752 p + 4, fname, PTR_DIFF(end_data, p+4),
1753 STR_TERMINATE_ASCII);
1754 SIVAL(p,0,len);
1755 p += 4 + len;
1757 len = PTR_DIFF(p, pdata);
1758 pad = (len + (align-1)) & ~(align-1);
1760 * offset to the next entry, the caller
1761 * will overwrite it for the last entry
1762 * that's why we always include the padding
1764 SIVAL(pdata,0,pad);
1766 * set padding to zero
1768 if (do_pad) {
1769 memset(p, 0, pad - len);
1770 p = pdata + pad;
1771 } else {
1772 p = pdata + len;
1774 break;
1776 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1777 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1778 p += 4;
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1781 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1782 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1783 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,mode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length. */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL,
1790 smb_fname->base_name);
1791 SIVAL(p,0,ea_size); /* Extended attributes */
1792 p +=4;
1794 len = srvstr_push(base_data, flags2, p,
1795 fname, PTR_DIFF(end_data, p),
1796 STR_TERMINATE_ASCII);
1797 SIVAL(q, 0, len);
1798 p += len;
1800 len = PTR_DIFF(p, pdata);
1801 pad = (len + (align-1)) & ~(align-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1807 SIVAL(pdata,0,pad);
1809 * set padding to zero
1811 if (do_pad) {
1812 memset(p, 0, pad - len);
1813 p = pdata + pad;
1814 } else {
1815 p = pdata + len;
1817 break;
1819 case SMB_FIND_FILE_NAMES_INFO:
1820 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1821 p += 4;
1822 SIVAL(p,0,reskey); p += 4;
1823 p += 4;
1824 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1825 acl on a dir (tridge) */
1826 len = srvstr_push(base_data, flags2, p,
1827 fname, PTR_DIFF(end_data, p),
1828 STR_TERMINATE_ASCII);
1829 SIVAL(p, -4, len);
1830 p += len;
1832 len = PTR_DIFF(p, pdata);
1833 pad = (len + (align-1)) & ~(align-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1839 SIVAL(pdata,0,pad);
1841 * set padding to zero
1843 if (do_pad) {
1844 memset(p, 0, pad - len);
1845 p = pdata + pad;
1846 } else {
1847 p = pdata + len;
1849 break;
1851 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1852 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1853 p += 4;
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,mode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname->base_name);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1867 p +=4;
1869 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1870 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1871 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1875 SIVAL(q, 0, len);
1876 p += len;
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1885 SIVAL(pdata,0,pad);
1887 * set padding to zero
1889 if (do_pad) {
1890 memset(p, 0, pad - len);
1891 p = pdata + pad;
1892 } else {
1893 p = pdata + len;
1895 break;
1897 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1899 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1900 p += 4;
1901 SIVAL(p,0,reskey); p += 4;
1902 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1906 SOFF_T(p,0,file_size); p += 8;
1907 SOFF_T(p,0,allocation_size); p += 8;
1908 SIVAL(p,0,mode); p += 4;
1909 q = p; p += 4; /* q is placeholder for name length */
1911 unsigned int ea_size = estimate_ea_size(conn, NULL,
1912 smb_fname->base_name);
1913 SIVAL(p,0,ea_size); /* Extended attributes */
1914 p +=4;
1916 /* Clear the short name buffer. This is
1917 * IMPORTANT as not doing so will trigger
1918 * a Win2k client bug. JRA.
1920 if (!was_8_3 && check_mangled_names) {
1921 char mangled_name[13]; /* mangled 8.3 name. */
1922 if (!name_to_8_3(fname,mangled_name,True,
1923 conn->params)) {
1924 /* Error - mangle failed ! */
1925 memset(mangled_name,'\0',12);
1927 mangled_name[12] = 0;
1928 len = srvstr_push(base_data, flags2,
1929 p+2, mangled_name, 24,
1930 STR_UPPER|STR_UNICODE);
1931 SSVAL(p, 0, len);
1932 if (len < 24) {
1933 memset(p + 2 + len,'\0',24 - len);
1935 SSVAL(p, 0, len);
1936 } else {
1937 memset(p,'\0',26);
1939 p += 26;
1940 SSVAL(p,0,0); p += 2; /* Reserved ? */
1941 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1942 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1943 len = srvstr_push(base_data, flags2, p,
1944 fname, PTR_DIFF(end_data, p),
1945 STR_TERMINATE_ASCII);
1946 SIVAL(q,0,len);
1947 p += len;
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1956 SIVAL(pdata,0,pad);
1958 * set padding to zero
1960 if (do_pad) {
1961 memset(p, 0, pad - len);
1962 p = pdata + pad;
1963 } else {
1964 p = pdata + len;
1966 break;
1968 /* CIFS UNIX Extension. */
1970 case SMB_FIND_FILE_UNIX:
1971 case SMB_FIND_FILE_UNIX_INFO2:
1972 p+= 4;
1973 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1975 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (info_level == SMB_FIND_FILE_UNIX) {
1978 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1979 p = store_file_unix_basic(conn, p,
1980 NULL, &smb_fname->st);
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE);
1984 } else {
1985 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1986 p = store_file_unix_basic_info2(conn, p,
1987 NULL, &smb_fname->st);
1988 nameptr = p;
1989 p += 4;
1990 len = srvstr_push(base_data, flags2, p, fname,
1991 PTR_DIFF(end_data, p), 0);
1992 SIVAL(nameptr, 0, len);
1995 p += len;
1997 len = PTR_DIFF(p, pdata);
1998 pad = (len + (align-1)) & ~(align-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2004 SIVAL(pdata,0,pad);
2006 * set padding to zero
2008 if (do_pad) {
2009 memset(p, 0, pad - len);
2010 p = pdata + pad;
2011 } else {
2012 p = pdata + len;
2014 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2016 break;
2018 default:
2019 return false;
2022 if (PTR_DIFF(p,pdata) > space_remaining) {
2023 *out_of_space = true;
2024 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2025 return false; /* Not finished - just out of space */
2028 /* Setup the last entry pointer, as an offset from base_data */
2029 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2030 /* Advance the data pointer to the next slot */
2031 *ppdata = p;
2033 return true;
2036 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2037 connection_struct *conn,
2038 struct dptr_struct *dirptr,
2039 uint16 flags2,
2040 const char *path_mask,
2041 uint32 dirtype,
2042 int info_level,
2043 int requires_resume_key,
2044 bool dont_descend,
2045 bool ask_sharemode,
2046 uint8_t align,
2047 bool do_pad,
2048 char **ppdata,
2049 char *base_data,
2050 char *end_data,
2051 int space_remaining,
2052 bool *out_of_space,
2053 bool *got_exact_match,
2054 int *_last_entry_off,
2055 struct ea_list *name_list)
2057 const char *p;
2058 const char *mask = NULL;
2059 long prev_dirpos = 0;
2060 uint32_t mode = 0;
2061 char *fname = NULL;
2062 struct smb_filename *smb_fname = NULL;
2063 struct smbd_dirptr_lanman2_state state;
2064 bool ok;
2065 uint64_t last_entry_off = 0;
2067 ZERO_STRUCT(state);
2068 state.conn = conn;
2069 state.info_level = info_level;
2070 state.check_mangled_names = lp_manglednames(conn->params);
2071 state.has_wild = dptr_has_wild(dirptr);
2072 state.got_exact_match = false;
2074 *out_of_space = false;
2075 *got_exact_match = false;
2077 p = strrchr_m(path_mask,'/');
2078 if(p != NULL) {
2079 if(p[1] == '\0') {
2080 mask = "*.*";
2081 } else {
2082 mask = p+1;
2084 } else {
2085 mask = path_mask;
2088 ok = smbd_dirptr_get_entry(ctx,
2089 dirptr,
2090 mask,
2091 dirtype,
2092 dont_descend,
2093 ask_sharemode,
2094 smbd_dirptr_lanman2_match_fn,
2095 smbd_dirptr_lanman2_mode_fn,
2096 &state,
2097 &fname,
2098 &smb_fname,
2099 &mode,
2100 &prev_dirpos);
2101 if (!ok) {
2102 return false;
2105 *got_exact_match = state.got_exact_match;
2107 ok = smbd_marshall_dir_entry(ctx,
2108 conn,
2109 flags2,
2110 info_level,
2111 name_list,
2112 state.check_mangled_names,
2113 requires_resume_key,
2114 mode,
2115 fname,
2116 smb_fname,
2117 space_remaining,
2118 align,
2119 do_pad,
2120 base_data,
2121 ppdata,
2122 end_data,
2123 out_of_space,
2124 &last_entry_off);
2125 TALLOC_FREE(fname);
2126 TALLOC_FREE(smb_fname);
2127 if (*out_of_space) {
2128 dptr_SeekDir(dirptr, prev_dirpos);
2129 return false;
2131 if (!ok) {
2132 return false;
2135 *_last_entry_off = last_entry_off;
2136 return true;
2139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2140 connection_struct *conn,
2141 struct dptr_struct *dirptr,
2142 uint16 flags2,
2143 const char *path_mask,
2144 uint32 dirtype,
2145 int info_level,
2146 bool requires_resume_key,
2147 bool dont_descend,
2148 bool ask_sharemode,
2149 char **ppdata,
2150 char *base_data,
2151 char *end_data,
2152 int space_remaining,
2153 bool *out_of_space,
2154 bool *got_exact_match,
2155 int *last_entry_off,
2156 struct ea_list *name_list)
2158 uint8_t align = 4;
2159 const bool do_pad = true;
2161 if (info_level >= 1 && info_level <= 3) {
2162 /* No alignment on earlier info levels. */
2163 align = 1;
2166 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2167 path_mask, dirtype, info_level,
2168 requires_resume_key, dont_descend, ask_sharemode,
2169 align, do_pad,
2170 ppdata, base_data, end_data,
2171 space_remaining,
2172 out_of_space, got_exact_match,
2173 last_entry_off, name_list);
2176 /****************************************************************************
2177 Reply to a TRANS2_FINDFIRST.
2178 ****************************************************************************/
2180 static void call_trans2findfirst(connection_struct *conn,
2181 struct smb_request *req,
2182 char **pparams, int total_params,
2183 char **ppdata, int total_data,
2184 unsigned int max_data_bytes)
2186 /* We must be careful here that we don't return more than the
2187 allowed number of data bytes. If this means returning fewer than
2188 maxentries then so be it. We assume that the redirector has
2189 enough room for the fixed number of parameter bytes it has
2190 requested. */
2191 struct smb_filename *smb_dname = NULL;
2192 char *params = *pparams;
2193 char *pdata = *ppdata;
2194 char *data_end;
2195 uint32 dirtype;
2196 int maxentries;
2197 uint16 findfirst_flags;
2198 bool close_after_first;
2199 bool close_if_end;
2200 bool requires_resume_key;
2201 int info_level;
2202 char *directory = NULL;
2203 char *mask = NULL;
2204 char *p;
2205 int last_entry_off=0;
2206 int dptr_num = -1;
2207 int numentries = 0;
2208 int i;
2209 bool finished = False;
2210 bool dont_descend = False;
2211 bool out_of_space = False;
2212 int space_remaining;
2213 bool mask_contains_wcard = False;
2214 struct ea_list *ea_list = NULL;
2215 NTSTATUS ntstatus = NT_STATUS_OK;
2216 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2217 TALLOC_CTX *ctx = talloc_tos();
2218 struct dptr_struct *dirptr = NULL;
2219 struct smbd_server_connection *sconn = smbd_server_conn;
2221 if (total_params < 13) {
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2223 goto out;
2226 dirtype = SVAL(params,0);
2227 maxentries = SVAL(params,2);
2228 findfirst_flags = SVAL(params,4);
2229 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2230 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2231 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2232 info_level = SVAL(params,6);
2234 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2235 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2236 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2237 info_level, max_data_bytes));
2239 if (!maxentries) {
2240 /* W2K3 seems to treat zero as 1. */
2241 maxentries = 1;
2244 switch (info_level) {
2245 case SMB_FIND_INFO_STANDARD:
2246 case SMB_FIND_EA_SIZE:
2247 case SMB_FIND_EA_LIST:
2248 case SMB_FIND_FILE_DIRECTORY_INFO:
2249 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2250 case SMB_FIND_FILE_NAMES_INFO:
2251 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2254 break;
2255 case SMB_FIND_FILE_UNIX:
2256 case SMB_FIND_FILE_UNIX_INFO2:
2257 /* Always use filesystem for UNIX mtime query. */
2258 ask_sharemode = false;
2259 if (!lp_unix_extensions()) {
2260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2261 goto out;
2263 break;
2264 default:
2265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2266 goto out;
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2270 params+12, total_params - 12,
2271 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 reply_nterror(req, ntstatus);
2274 goto out;
2277 ntstatus = filename_convert(ctx, conn,
2278 req->flags2 & FLAGS2_DFS_PATHNAMES,
2279 directory,
2280 (UCF_SAVE_LCOMP |
2281 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2282 &mask_contains_wcard,
2283 &smb_dname);
2284 if (!NT_STATUS_IS_OK(ntstatus)) {
2285 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2286 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2287 ERRSRV, ERRbadpath);
2288 goto out;
2290 reply_nterror(req, ntstatus);
2291 goto out;
2294 mask = smb_dname->original_lcomp;
2296 directory = smb_dname->base_name;
2298 p = strrchr_m(directory,'/');
2299 if(p == NULL) {
2300 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2301 if((directory[0] == '.') && (directory[1] == '\0')) {
2302 mask = talloc_strdup(ctx,"*");
2303 if (!mask) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2305 goto out;
2307 mask_contains_wcard = True;
2309 directory = talloc_strdup(talloc_tos(), "./");
2310 if (!directory) {
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 goto out;
2314 } else {
2315 *p = 0;
2318 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2320 if (info_level == SMB_FIND_EA_LIST) {
2321 uint32 ea_size;
2323 if (total_data < 4) {
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 goto out;
2328 ea_size = IVAL(pdata,0);
2329 if (ea_size != total_data) {
2330 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 goto out;
2336 if (!lp_ea_support(SNUM(conn))) {
2337 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2338 goto out;
2341 /* Pull out the list of names. */
2342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2343 if (!ea_list) {
2344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2345 goto out;
2349 *ppdata = (char *)SMB_REALLOC(
2350 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2351 if(*ppdata == NULL ) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2355 pdata = *ppdata;
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2360 if (*pparams == NULL) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 goto out;
2364 params = *pparams;
2366 /* Save the wildcard match and attribs we are using on this directory -
2367 needed as lanman2 assumes these are being saved between calls */
2369 ntstatus = dptr_create(conn,
2370 directory,
2371 False,
2372 True,
2373 req->smbpid,
2374 mask,
2375 mask_contains_wcard,
2376 dirtype,
2377 &dirptr);
2379 if (!NT_STATUS_IS_OK(ntstatus)) {
2380 reply_nterror(req, ntstatus);
2381 goto out;
2384 dptr_num = dptr_dnum(dirptr);
2385 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2387 /* Initialize per TRANS2_FIND_FIRST operation data */
2388 dptr_init_search_op(dirptr);
2390 /* We don't need to check for VOL here as this is returned by
2391 a different TRANS2 call. */
2393 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2394 directory,lp_dontdescend(SNUM(conn))));
2395 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2396 dont_descend = True;
2398 p = pdata;
2399 space_remaining = max_data_bytes;
2400 out_of_space = False;
2402 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2403 bool got_exact_match = False;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2408 out_of_space = True;
2409 finished = False;
2410 } else {
2411 finished = !get_lanman2_dir_entry(ctx,
2412 conn,
2413 dirptr,
2414 req->flags2,
2415 mask,dirtype,info_level,
2416 requires_resume_key,dont_descend,
2417 ask_sharemode,
2418 &p,pdata,data_end,
2419 space_remaining, &out_of_space,
2420 &got_exact_match,
2421 &last_entry_off, ea_list);
2424 if (finished && out_of_space)
2425 finished = False;
2427 if (!finished && !out_of_space)
2428 numentries++;
2431 * As an optimisation if we know we aren't looking
2432 * for a wildcard name (ie. the name matches the wildcard exactly)
2433 * then we can finish on any (first) match.
2434 * This speeds up large directory searches. JRA.
2437 if(got_exact_match)
2438 finished = True;
2440 /* Ensure space_remaining never goes -ve. */
2441 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2442 space_remaining = 0;
2443 out_of_space = true;
2444 } else {
2445 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2449 /* Check if we can close the dirptr */
2450 if(close_after_first || (finished && close_if_end)) {
2451 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2452 dptr_close(sconn, &dptr_num);
2456 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2457 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2458 * the protocol level is less than NT1. Tested with smbclient. JRA.
2459 * This should fix the OS/2 client bug #2335.
2462 if(numentries == 0) {
2463 dptr_close(sconn, &dptr_num);
2464 if (get_Protocol() < PROTOCOL_NT1) {
2465 reply_force_doserror(req, ERRDOS, ERRnofiles);
2466 goto out;
2467 } else {
2468 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2469 ERRDOS, ERRbadfile);
2470 goto out;
2474 /* At this point pdata points to numentries directory entries. */
2476 /* Set up the return parameter block */
2477 SSVAL(params,0,dptr_num);
2478 SSVAL(params,2,numentries);
2479 SSVAL(params,4,finished);
2480 SSVAL(params,6,0); /* Never an EA error */
2481 SSVAL(params,8,last_entry_off);
2483 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2484 max_data_bytes);
2486 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2487 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2488 if (!directory) {
2489 reply_nterror(req, NT_STATUS_NO_MEMORY);
2493 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req->cmd),
2495 mask, directory, dirtype, numentries ) );
2498 * Force a name mangle here to ensure that the
2499 * mask as an 8.3 name is top of the mangled cache.
2500 * The reasons for this are subtle. Don't remove
2501 * this code unless you know what you are doing
2502 * (see PR#13758). JRA.
2505 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2506 char mangled_name[13];
2507 name_to_8_3(mask, mangled_name, True, conn->params);
2509 out:
2510 TALLOC_FREE(smb_dname);
2511 return;
2514 /****************************************************************************
2515 Reply to a TRANS2_FINDNEXT.
2516 ****************************************************************************/
2518 static void call_trans2findnext(connection_struct *conn,
2519 struct smb_request *req,
2520 char **pparams, int total_params,
2521 char **ppdata, int total_data,
2522 unsigned int max_data_bytes)
2524 /* We must be careful here that we don't return more than the
2525 allowed number of data bytes. If this means returning fewer than
2526 maxentries then so be it. We assume that the redirector has
2527 enough room for the fixed number of parameter bytes it has
2528 requested. */
2529 char *params = *pparams;
2530 char *pdata = *ppdata;
2531 char *data_end;
2532 int dptr_num;
2533 int maxentries;
2534 uint16 info_level;
2535 uint32 resume_key;
2536 uint16 findnext_flags;
2537 bool close_after_request;
2538 bool close_if_end;
2539 bool requires_resume_key;
2540 bool continue_bit;
2541 bool mask_contains_wcard = False;
2542 char *resume_name = NULL;
2543 const char *mask = NULL;
2544 const char *directory = NULL;
2545 char *p = NULL;
2546 uint16 dirtype;
2547 int numentries = 0;
2548 int i, last_entry_off=0;
2549 bool finished = False;
2550 bool dont_descend = False;
2551 bool out_of_space = False;
2552 int space_remaining;
2553 struct ea_list *ea_list = NULL;
2554 NTSTATUS ntstatus = NT_STATUS_OK;
2555 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2556 TALLOC_CTX *ctx = talloc_tos();
2557 struct dptr_struct *dirptr;
2558 struct smbd_server_connection *sconn = smbd_server_conn;
2560 if (total_params < 13) {
2561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2562 return;
2565 dptr_num = SVAL(params,0);
2566 maxentries = SVAL(params,2);
2567 info_level = SVAL(params,4);
2568 resume_key = IVAL(params,6);
2569 findnext_flags = SVAL(params,10);
2570 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2571 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2572 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2573 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2575 if (!continue_bit) {
2576 /* We only need resume_name if continue_bit is zero. */
2577 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2578 params+12,
2579 total_params - 12, STR_TERMINATE, &ntstatus,
2580 &mask_contains_wcard);
2581 if (!NT_STATUS_IS_OK(ntstatus)) {
2582 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2583 complain (it thinks we're asking for the directory above the shared
2584 path or an invalid name). Catch this as the resume name is only compared, never used in
2585 a file access. JRA. */
2586 srvstr_pull_talloc(ctx, params, req->flags2,
2587 &resume_name, params+12,
2588 total_params - 12,
2589 STR_TERMINATE);
2591 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2592 reply_nterror(req, ntstatus);
2593 return;
2598 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2599 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2600 resume_key = %d resume name = %s continue=%d level = %d\n",
2601 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2602 requires_resume_key, resume_key,
2603 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2605 if (!maxentries) {
2606 /* W2K3 seems to treat zero as 1. */
2607 maxentries = 1;
2610 switch (info_level) {
2611 case SMB_FIND_INFO_STANDARD:
2612 case SMB_FIND_EA_SIZE:
2613 case SMB_FIND_EA_LIST:
2614 case SMB_FIND_FILE_DIRECTORY_INFO:
2615 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2616 case SMB_FIND_FILE_NAMES_INFO:
2617 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2618 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2619 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2620 break;
2621 case SMB_FIND_FILE_UNIX:
2622 case SMB_FIND_FILE_UNIX_INFO2:
2623 /* Always use filesystem for UNIX mtime query. */
2624 ask_sharemode = false;
2625 if (!lp_unix_extensions()) {
2626 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2627 return;
2629 break;
2630 default:
2631 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2632 return;
2635 if (info_level == SMB_FIND_EA_LIST) {
2636 uint32 ea_size;
2638 if (total_data < 4) {
2639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2640 return;
2643 ea_size = IVAL(pdata,0);
2644 if (ea_size != total_data) {
2645 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2646 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 return;
2651 if (!lp_ea_support(SNUM(conn))) {
2652 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2653 return;
2656 /* Pull out the list of names. */
2657 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2658 if (!ea_list) {
2659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 return;
2664 *ppdata = (char *)SMB_REALLOC(
2665 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2666 if(*ppdata == NULL) {
2667 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 return;
2671 pdata = *ppdata;
2672 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2674 /* Realloc the params space */
2675 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2676 if(*pparams == NULL ) {
2677 reply_nterror(req, NT_STATUS_NO_MEMORY);
2678 return;
2681 params = *pparams;
2683 /* Check that the dptr is valid */
2684 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2685 reply_nterror(req, STATUS_NO_MORE_FILES);
2686 return;
2689 directory = dptr_path(sconn, dptr_num);
2691 /* Get the wildcard mask from the dptr */
2692 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2693 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2694 reply_nterror(req, STATUS_NO_MORE_FILES);
2695 return;
2698 mask = p;
2700 /* Get the attr mask from the dptr */
2701 dirtype = dptr_attr(sconn, dptr_num);
2703 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2704 dptr_num, mask, dirtype,
2705 (long)dirptr,
2706 dptr_TellDir(dirptr)));
2708 /* Initialize per TRANS2_FIND_NEXT operation data */
2709 dptr_init_search_op(dirptr);
2711 /* We don't need to check for VOL here as this is returned by
2712 a different TRANS2 call. */
2714 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2715 directory,lp_dontdescend(SNUM(conn))));
2716 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2717 dont_descend = True;
2719 p = pdata;
2720 space_remaining = max_data_bytes;
2721 out_of_space = False;
2724 * Seek to the correct position. We no longer use the resume key but
2725 * depend on the last file name instead.
2728 if(!continue_bit && resume_name && *resume_name) {
2729 SMB_STRUCT_STAT st;
2731 long current_pos = 0;
2733 * Remember, name_to_8_3 is called by
2734 * get_lanman2_dir_entry(), so the resume name
2735 * could be mangled. Ensure we check the unmangled name.
2738 if (mangle_is_mangled(resume_name, conn->params)) {
2739 char *new_resume_name = NULL;
2740 mangle_lookup_name_from_8_3(ctx,
2741 resume_name,
2742 &new_resume_name,
2743 conn->params);
2744 if (new_resume_name) {
2745 resume_name = new_resume_name;
2750 * Fix for NT redirector problem triggered by resume key indexes
2751 * changing between directory scans. We now return a resume key of 0
2752 * and instead look for the filename to continue from (also given
2753 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2754 * findfirst/findnext (as is usual) then the directory pointer
2755 * should already be at the correct place.
2758 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2759 } /* end if resume_name && !continue_bit */
2761 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2762 bool got_exact_match = False;
2764 /* this is a heuristic to avoid seeking the dirptr except when
2765 absolutely necessary. It allows for a filename of about 40 chars */
2766 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2767 out_of_space = True;
2768 finished = False;
2769 } else {
2770 finished = !get_lanman2_dir_entry(ctx,
2771 conn,
2772 dirptr,
2773 req->flags2,
2774 mask,dirtype,info_level,
2775 requires_resume_key,dont_descend,
2776 ask_sharemode,
2777 &p,pdata,data_end,
2778 space_remaining, &out_of_space,
2779 &got_exact_match,
2780 &last_entry_off, ea_list);
2783 if (finished && out_of_space)
2784 finished = False;
2786 if (!finished && !out_of_space)
2787 numentries++;
2790 * As an optimisation if we know we aren't looking
2791 * for a wildcard name (ie. the name matches the wildcard exactly)
2792 * then we can finish on any (first) match.
2793 * This speeds up large directory searches. JRA.
2796 if(got_exact_match)
2797 finished = True;
2799 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2802 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2803 smb_fn_name(req->cmd),
2804 mask, directory, dirtype, numentries ) );
2806 /* Check if we can close the dirptr */
2807 if(close_after_request || (finished && close_if_end)) {
2808 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2809 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2812 /* Set up the return parameter block */
2813 SSVAL(params,0,numentries);
2814 SSVAL(params,2,finished);
2815 SSVAL(params,4,0); /* Never an EA error */
2816 SSVAL(params,6,last_entry_off);
2818 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2819 max_data_bytes);
2821 return;
2824 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2826 E_md4hash(lp_servicename(SNUM(conn)),objid);
2827 return objid;
2830 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2832 SMB_ASSERT(extended_info != NULL);
2834 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2835 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2836 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2837 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2838 #ifdef SAMBA_VERSION_REVISION
2839 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2840 #endif
2841 extended_info->samba_subversion = 0;
2842 #ifdef SAMBA_VERSION_RC_RELEASE
2843 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2844 #else
2845 #ifdef SAMBA_VERSION_PRE_RELEASE
2846 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2847 #endif
2848 #endif
2849 #ifdef SAMBA_VERSION_VENDOR_PATCH
2850 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2851 #endif
2852 extended_info->samba_gitcommitdate = 0;
2853 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2854 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2855 #endif
2857 memset(extended_info->samba_version_string, 0,
2858 sizeof(extended_info->samba_version_string));
2860 snprintf (extended_info->samba_version_string,
2861 sizeof(extended_info->samba_version_string),
2862 "%s", samba_version_string());
2865 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2866 TALLOC_CTX *mem_ctx,
2867 uint16_t info_level,
2868 uint16_t flags2,
2869 unsigned int max_data_bytes,
2870 char **ppdata,
2871 int *ret_data_len)
2873 char *pdata, *end_data;
2874 int data_len = 0, len;
2875 const char *vname = volume_label(SNUM(conn));
2876 int snum = SNUM(conn);
2877 char *fstype = lp_fstype(SNUM(conn));
2878 uint32 additional_flags = 0;
2879 struct smb_filename smb_fname_dot;
2880 SMB_STRUCT_STAT st;
2882 if (IS_IPC(conn)) {
2883 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2884 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2885 "info level (0x%x) on IPC$.\n",
2886 (unsigned int)info_level));
2887 return NT_STATUS_ACCESS_DENIED;
2891 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2893 ZERO_STRUCT(smb_fname_dot);
2894 smb_fname_dot.base_name = discard_const_p(char, ".");
2896 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2897 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2898 return map_nt_error_from_unix(errno);
2901 st = smb_fname_dot.st;
2903 *ppdata = (char *)SMB_REALLOC(
2904 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2905 if (*ppdata == NULL) {
2906 return NT_STATUS_NO_MEMORY;
2909 pdata = *ppdata;
2910 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2911 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2913 switch (info_level) {
2914 case SMB_INFO_ALLOCATION:
2916 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2917 data_len = 18;
2918 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2919 return map_nt_error_from_unix(errno);
2922 block_size = lp_block_size(snum);
2923 if (bsize < block_size) {
2924 uint64_t factor = block_size/bsize;
2925 bsize = block_size;
2926 dsize /= factor;
2927 dfree /= factor;
2929 if (bsize > block_size) {
2930 uint64_t factor = bsize/block_size;
2931 bsize = block_size;
2932 dsize *= factor;
2933 dfree *= factor;
2935 bytes_per_sector = 512;
2936 sectors_per_unit = bsize/bytes_per_sector;
2938 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2939 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2940 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2942 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2943 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2944 SIVAL(pdata,l1_cUnit,dsize);
2945 SIVAL(pdata,l1_cUnitAvail,dfree);
2946 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2947 break;
2950 case SMB_INFO_VOLUME:
2951 /* Return volume name */
2953 * Add volume serial number - hash of a combination of
2954 * the called hostname and the service name.
2956 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2958 * Win2k3 and previous mess this up by sending a name length
2959 * one byte short. I believe only older clients (OS/2 Win9x) use
2960 * this call so try fixing this by adding a terminating null to
2961 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2963 len = srvstr_push(
2964 pdata, flags2,
2965 pdata+l2_vol_szVolLabel, vname,
2966 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2967 STR_NOALIGN|STR_TERMINATE);
2968 SCVAL(pdata,l2_vol_cch,len);
2969 data_len = l2_vol_szVolLabel + len;
2970 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2971 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2972 len, vname));
2973 break;
2975 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2976 case SMB_FS_ATTRIBUTE_INFORMATION:
2978 additional_flags = 0;
2979 #if defined(HAVE_SYS_QUOTAS)
2980 additional_flags |= FILE_VOLUME_QUOTAS;
2981 #endif
2983 if(lp_nt_acl_support(SNUM(conn))) {
2984 additional_flags |= FILE_PERSISTENT_ACLS;
2987 /* Capabilities are filled in at connection time through STATVFS call */
2988 additional_flags |= conn->fs_capabilities;
2989 additional_flags |= lp_parm_int(conn->params->service,
2990 "share", "fake_fscaps",
2993 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2994 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2995 additional_flags); /* FS ATTRIBUTES */
2997 SIVAL(pdata,4,255); /* Max filename component length */
2998 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2999 and will think we can't do long filenames */
3000 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3001 PTR_DIFF(end_data, pdata+12),
3002 STR_UNICODE);
3003 SIVAL(pdata,8,len);
3004 data_len = 12 + len;
3005 break;
3007 case SMB_QUERY_FS_LABEL_INFO:
3008 case SMB_FS_LABEL_INFORMATION:
3009 len = srvstr_push(pdata, flags2, pdata+4, vname,
3010 PTR_DIFF(end_data, pdata+4), 0);
3011 data_len = 4 + len;
3012 SIVAL(pdata,0,len);
3013 break;
3015 case SMB_QUERY_FS_VOLUME_INFO:
3016 case SMB_FS_VOLUME_INFORMATION:
3019 * Add volume serial number - hash of a combination of
3020 * the called hostname and the service name.
3022 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3023 (str_checksum(get_local_machine_name())<<16));
3025 /* Max label len is 32 characters. */
3026 len = srvstr_push(pdata, flags2, pdata+18, vname,
3027 PTR_DIFF(end_data, pdata+18),
3028 STR_UNICODE);
3029 SIVAL(pdata,12,len);
3030 data_len = 18+len;
3032 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3033 (int)strlen(vname),vname, lp_servicename(snum)));
3034 break;
3036 case SMB_QUERY_FS_SIZE_INFO:
3037 case SMB_FS_SIZE_INFORMATION:
3039 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3040 data_len = 24;
3041 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3042 return map_nt_error_from_unix(errno);
3044 block_size = lp_block_size(snum);
3045 if (bsize < block_size) {
3046 uint64_t factor = block_size/bsize;
3047 bsize = block_size;
3048 dsize /= factor;
3049 dfree /= factor;
3051 if (bsize > block_size) {
3052 uint64_t factor = bsize/block_size;
3053 bsize = block_size;
3054 dsize *= factor;
3055 dfree *= factor;
3057 bytes_per_sector = 512;
3058 sectors_per_unit = bsize/bytes_per_sector;
3059 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3060 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3061 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3062 SBIG_UINT(pdata,0,dsize);
3063 SBIG_UINT(pdata,8,dfree);
3064 SIVAL(pdata,16,sectors_per_unit);
3065 SIVAL(pdata,20,bytes_per_sector);
3066 break;
3069 case SMB_FS_FULL_SIZE_INFORMATION:
3071 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3072 data_len = 32;
3073 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3074 return map_nt_error_from_unix(errno);
3076 block_size = lp_block_size(snum);
3077 if (bsize < block_size) {
3078 uint64_t factor = block_size/bsize;
3079 bsize = block_size;
3080 dsize /= factor;
3081 dfree /= factor;
3083 if (bsize > block_size) {
3084 uint64_t factor = bsize/block_size;
3085 bsize = block_size;
3086 dsize *= factor;
3087 dfree *= factor;
3089 bytes_per_sector = 512;
3090 sectors_per_unit = bsize/bytes_per_sector;
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3092 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3093 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3094 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3095 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3096 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3097 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3098 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3099 break;
3102 case SMB_QUERY_FS_DEVICE_INFO:
3103 case SMB_FS_DEVICE_INFORMATION:
3104 data_len = 8;
3105 SIVAL(pdata,0,0); /* dev type */
3106 SIVAL(pdata,4,0); /* characteristics */
3107 break;
3109 #ifdef HAVE_SYS_QUOTAS
3110 case SMB_FS_QUOTA_INFORMATION:
3112 * what we have to send --metze:
3114 * Unknown1: 24 NULL bytes
3115 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3116 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3117 * Quota Flags: 2 byte :
3118 * Unknown3: 6 NULL bytes
3120 * 48 bytes total
3122 * details for Quota Flags:
3124 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3125 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3126 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3127 * 0x0001 Enable Quotas: enable quota for this fs
3131 /* we need to fake up a fsp here,
3132 * because its not send in this call
3134 files_struct fsp;
3135 SMB_NTQUOTA_STRUCT quotas;
3137 ZERO_STRUCT(fsp);
3138 ZERO_STRUCT(quotas);
3140 fsp.conn = conn;
3141 fsp.fnum = -1;
3143 /* access check */
3144 if (conn->server_info->utok.uid != sec_initial_uid()) {
3145 DEBUG(0,("set_user_quota: access_denied "
3146 "service [%s] user [%s]\n",
3147 lp_servicename(SNUM(conn)),
3148 conn->server_info->unix_name));
3149 return NT_STATUS_ACCESS_DENIED;
3152 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3153 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3154 return map_nt_error_from_unix(errno);
3157 data_len = 48;
3159 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3160 lp_servicename(SNUM(conn))));
3162 /* Unknown1 24 NULL bytes*/
3163 SBIG_UINT(pdata,0,(uint64_t)0);
3164 SBIG_UINT(pdata,8,(uint64_t)0);
3165 SBIG_UINT(pdata,16,(uint64_t)0);
3167 /* Default Soft Quota 8 bytes */
3168 SBIG_UINT(pdata,24,quotas.softlim);
3170 /* Default Hard Quota 8 bytes */
3171 SBIG_UINT(pdata,32,quotas.hardlim);
3173 /* Quota flag 2 bytes */
3174 SSVAL(pdata,40,quotas.qflags);
3176 /* Unknown3 6 NULL bytes */
3177 SSVAL(pdata,42,0);
3178 SIVAL(pdata,44,0);
3180 break;
3182 #endif /* HAVE_SYS_QUOTAS */
3183 case SMB_FS_OBJECTID_INFORMATION:
3185 unsigned char objid[16];
3186 struct smb_extended_info extended_info;
3187 memcpy(pdata,create_volume_objectid(conn, objid),16);
3188 samba_extended_info_version (&extended_info);
3189 SIVAL(pdata,16,extended_info.samba_magic);
3190 SIVAL(pdata,20,extended_info.samba_version);
3191 SIVAL(pdata,24,extended_info.samba_subversion);
3192 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3193 memcpy(pdata+36,extended_info.samba_version_string,28);
3194 data_len = 64;
3195 break;
3199 * Query the version and capabilities of the CIFS UNIX extensions
3200 * in use.
3203 case SMB_QUERY_CIFS_UNIX_INFO:
3205 bool large_write = lp_min_receive_file_size() &&
3206 !srv_is_signing_active(smbd_server_conn);
3207 bool large_read = !srv_is_signing_active(smbd_server_conn);
3208 int encrypt_caps = 0;
3210 if (!lp_unix_extensions()) {
3211 return NT_STATUS_INVALID_LEVEL;
3214 switch (conn->encrypt_level) {
3215 case 0:
3216 encrypt_caps = 0;
3217 break;
3218 case 1:
3219 case Auto:
3220 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3221 break;
3222 case Required:
3223 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3224 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3225 large_write = false;
3226 large_read = false;
3227 break;
3230 data_len = 12;
3231 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3232 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3234 /* We have POSIX ACLs, pathname, encryption,
3235 * large read/write, and locking capability. */
3237 SBIG_UINT(pdata,4,((uint64_t)(
3238 CIFS_UNIX_POSIX_ACLS_CAP|
3239 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3240 CIFS_UNIX_FCNTL_LOCKS_CAP|
3241 CIFS_UNIX_EXTATTR_CAP|
3242 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3243 encrypt_caps|
3244 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3245 (large_write ?
3246 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3247 break;
3250 case SMB_QUERY_POSIX_FS_INFO:
3252 int rc;
3253 vfs_statvfs_struct svfs;
3255 if (!lp_unix_extensions()) {
3256 return NT_STATUS_INVALID_LEVEL;
3259 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3261 if (!rc) {
3262 data_len = 56;
3263 SIVAL(pdata,0,svfs.OptimalTransferSize);
3264 SIVAL(pdata,4,svfs.BlockSize);
3265 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3266 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3267 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3268 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3269 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3270 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3271 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3272 #ifdef EOPNOTSUPP
3273 } else if (rc == EOPNOTSUPP) {
3274 return NT_STATUS_INVALID_LEVEL;
3275 #endif /* EOPNOTSUPP */
3276 } else {
3277 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3278 return NT_STATUS_DOS(ERRSRV, ERRerror);
3280 break;
3283 case SMB_QUERY_POSIX_WHOAMI:
3285 uint32_t flags = 0;
3286 uint32_t sid_bytes;
3287 int i;
3289 if (!lp_unix_extensions()) {
3290 return NT_STATUS_INVALID_LEVEL;
3293 if (max_data_bytes < 40) {
3294 return NT_STATUS_BUFFER_TOO_SMALL;
3297 /* We ARE guest if global_sid_Builtin_Guests is
3298 * in our list of SIDs.
3300 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3301 conn->server_info->ptok)) {
3302 flags |= SMB_WHOAMI_GUEST;
3305 /* We are NOT guest if global_sid_Authenticated_Users
3306 * is in our list of SIDs.
3308 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3309 conn->server_info->ptok)) {
3310 flags &= ~SMB_WHOAMI_GUEST;
3313 /* NOTE: 8 bytes for UID/GID, irrespective of native
3314 * platform size. This matches
3315 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3317 data_len = 4 /* flags */
3318 + 4 /* flag mask */
3319 + 8 /* uid */
3320 + 8 /* gid */
3321 + 4 /* ngroups */
3322 + 4 /* num_sids */
3323 + 4 /* SID bytes */
3324 + 4 /* pad/reserved */
3325 + (conn->server_info->utok.ngroups * 8)
3326 /* groups list */
3327 + (conn->server_info->ptok->num_sids *
3328 SID_MAX_SIZE)
3329 /* SID list */;
3331 SIVAL(pdata, 0, flags);
3332 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3333 SBIG_UINT(pdata, 8,
3334 (uint64_t)conn->server_info->utok.uid);
3335 SBIG_UINT(pdata, 16,
3336 (uint64_t)conn->server_info->utok.gid);
3339 if (data_len >= max_data_bytes) {
3340 /* Potential overflow, skip the GIDs and SIDs. */
3342 SIVAL(pdata, 24, 0); /* num_groups */
3343 SIVAL(pdata, 28, 0); /* num_sids */
3344 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3345 SIVAL(pdata, 36, 0); /* reserved */
3347 data_len = 40;
3348 break;
3351 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3352 SIVAL(pdata, 28, conn->server_info->num_sids);
3354 /* We walk the SID list twice, but this call is fairly
3355 * infrequent, and I don't expect that it's performance
3356 * sensitive -- jpeach
3358 for (i = 0, sid_bytes = 0;
3359 i < conn->server_info->ptok->num_sids; ++i) {
3360 sid_bytes += ndr_size_dom_sid(
3361 &conn->server_info->ptok->user_sids[i],
3362 NULL,
3366 /* SID list byte count */
3367 SIVAL(pdata, 32, sid_bytes);
3369 /* 4 bytes pad/reserved - must be zero */
3370 SIVAL(pdata, 36, 0);
3371 data_len = 40;
3373 /* GID list */
3374 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3375 SBIG_UINT(pdata, data_len,
3376 (uint64_t)conn->server_info->utok.groups[i]);
3377 data_len += 8;
3380 /* SID list */
3381 for (i = 0;
3382 i < conn->server_info->ptok->num_sids; ++i) {
3383 int sid_len = ndr_size_dom_sid(
3384 &conn->server_info->ptok->user_sids[i],
3385 NULL,
3388 sid_linearize(pdata + data_len, sid_len,
3389 &conn->server_info->ptok->user_sids[i]);
3390 data_len += sid_len;
3393 break;
3396 case SMB_MAC_QUERY_FS_INFO:
3398 * Thursby MAC extension... ONLY on NTFS filesystems
3399 * once we do streams then we don't need this
3401 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3402 data_len = 88;
3403 SIVAL(pdata,84,0x100); /* Don't support mac... */
3404 break;
3406 /* drop through */
3407 default:
3408 return NT_STATUS_INVALID_LEVEL;
3411 *ret_data_len = data_len;
3412 return NT_STATUS_OK;
3415 /****************************************************************************
3416 Reply to a TRANS2_QFSINFO (query filesystem info).
3417 ****************************************************************************/
3419 static void call_trans2qfsinfo(connection_struct *conn,
3420 struct smb_request *req,
3421 char **pparams, int total_params,
3422 char **ppdata, int total_data,
3423 unsigned int max_data_bytes)
3425 char *params = *pparams;
3426 uint16_t info_level;
3427 int data_len = 0;
3428 NTSTATUS status;
3430 if (total_params < 2) {
3431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3432 return;
3435 info_level = SVAL(params,0);
3437 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3438 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3439 DEBUG(0,("call_trans2qfsinfo: encryption required "
3440 "and info level 0x%x sent.\n",
3441 (unsigned int)info_level));
3442 exit_server_cleanly("encryption required "
3443 "on connection");
3444 return;
3448 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3450 status = smbd_do_qfsinfo(conn, req,
3451 info_level,
3452 req->flags2,
3453 max_data_bytes,
3454 ppdata, &data_len);
3455 if (!NT_STATUS_IS_OK(status)) {
3456 reply_nterror(req, status);
3457 return;
3460 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3461 max_data_bytes);
3463 DEBUG( 4, ( "%s info_level = %d\n",
3464 smb_fn_name(req->cmd), info_level) );
3466 return;
3469 /****************************************************************************
3470 Reply to a TRANS2_SETFSINFO (set filesystem info).
3471 ****************************************************************************/
3473 static void call_trans2setfsinfo(connection_struct *conn,
3474 struct smb_request *req,
3475 char **pparams, int total_params,
3476 char **ppdata, int total_data,
3477 unsigned int max_data_bytes)
3479 char *pdata = *ppdata;
3480 char *params = *pparams;
3481 uint16 info_level;
3483 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3485 /* */
3486 if (total_params < 4) {
3487 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3488 total_params));
3489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3490 return;
3493 info_level = SVAL(params,2);
3495 if (IS_IPC(conn)) {
3496 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3497 info_level != SMB_SET_CIFS_UNIX_INFO) {
3498 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3499 "info level (0x%x) on IPC$.\n",
3500 (unsigned int)info_level));
3501 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3502 return;
3506 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3507 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3508 DEBUG(0,("call_trans2setfsinfo: encryption required "
3509 "and info level 0x%x sent.\n",
3510 (unsigned int)info_level));
3511 exit_server_cleanly("encryption required "
3512 "on connection");
3513 return;
3517 switch(info_level) {
3518 case SMB_SET_CIFS_UNIX_INFO:
3520 uint16 client_unix_major;
3521 uint16 client_unix_minor;
3522 uint32 client_unix_cap_low;
3523 uint32 client_unix_cap_high;
3525 if (!lp_unix_extensions()) {
3526 reply_nterror(req,
3527 NT_STATUS_INVALID_LEVEL);
3528 return;
3531 /* There should be 12 bytes of capabilities set. */
3532 if (total_data < 8) {
3533 reply_nterror(
3534 req,
3535 NT_STATUS_INVALID_PARAMETER);
3536 return;
3538 client_unix_major = SVAL(pdata,0);
3539 client_unix_minor = SVAL(pdata,2);
3540 client_unix_cap_low = IVAL(pdata,4);
3541 client_unix_cap_high = IVAL(pdata,8);
3542 /* Just print these values for now. */
3543 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3544 cap_low = 0x%x, cap_high = 0x%x\n",
3545 (unsigned int)client_unix_major,
3546 (unsigned int)client_unix_minor,
3547 (unsigned int)client_unix_cap_low,
3548 (unsigned int)client_unix_cap_high ));
3550 /* Here is where we must switch to posix pathname processing... */
3551 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3552 lp_set_posix_pathnames();
3553 mangle_change_to_posix();
3556 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3557 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3558 /* Client that knows how to do posix locks,
3559 * but not posix open/mkdir operations. Set a
3560 * default type for read/write checks. */
3562 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3565 break;
3568 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3570 NTSTATUS status;
3571 size_t param_len = 0;
3572 size_t data_len = total_data;
3574 if (!lp_unix_extensions()) {
3575 reply_nterror(
3576 req,
3577 NT_STATUS_INVALID_LEVEL);
3578 return;
3581 if (lp_smb_encrypt(SNUM(conn)) == false) {
3582 reply_nterror(
3583 req,
3584 NT_STATUS_NOT_SUPPORTED);
3585 return;
3588 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3589 DEBUG( 2,("call_trans2setfsinfo: "
3590 "request transport encryption disabled"
3591 "with 'fork echo handler = yes'\n"));
3592 reply_nterror(
3593 req,
3594 NT_STATUS_NOT_SUPPORTED);
3595 return;
3598 DEBUG( 4,("call_trans2setfsinfo: "
3599 "request transport encryption.\n"));
3601 status = srv_request_encryption_setup(conn,
3602 (unsigned char **)ppdata,
3603 &data_len,
3604 (unsigned char **)pparams,
3605 &param_len);
3607 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3608 !NT_STATUS_IS_OK(status)) {
3609 reply_nterror(req, status);
3610 return;
3613 send_trans2_replies(conn, req,
3614 *pparams,
3615 param_len,
3616 *ppdata,
3617 data_len,
3618 max_data_bytes);
3620 if (NT_STATUS_IS_OK(status)) {
3621 /* Server-side transport
3622 * encryption is now *on*. */
3623 status = srv_encryption_start(conn);
3624 if (!NT_STATUS_IS_OK(status)) {
3625 exit_server_cleanly(
3626 "Failure in setting "
3627 "up encrypted transport");
3630 return;
3633 case SMB_FS_QUOTA_INFORMATION:
3635 files_struct *fsp = NULL;
3636 SMB_NTQUOTA_STRUCT quotas;
3638 ZERO_STRUCT(quotas);
3640 /* access check */
3641 if ((conn->server_info->utok.uid != sec_initial_uid())
3642 ||!CAN_WRITE(conn)) {
3643 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3644 lp_servicename(SNUM(conn)),
3645 conn->server_info->unix_name));
3646 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3647 return;
3650 /* note: normaly there're 48 bytes,
3651 * but we didn't use the last 6 bytes for now
3652 * --metze
3654 fsp = file_fsp(req, SVAL(params,0));
3656 if (!check_fsp_ntquota_handle(conn, req,
3657 fsp)) {
3658 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3659 reply_nterror(
3660 req, NT_STATUS_INVALID_HANDLE);
3661 return;
3664 if (total_data < 42) {
3665 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3666 total_data));
3667 reply_nterror(
3668 req,
3669 NT_STATUS_INVALID_PARAMETER);
3670 return;
3673 /* unknown_1 24 NULL bytes in pdata*/
3675 /* the soft quotas 8 bytes (uint64_t)*/
3676 quotas.softlim = (uint64_t)IVAL(pdata,24);
3677 #ifdef LARGE_SMB_OFF_T
3678 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3679 #else /* LARGE_SMB_OFF_T */
3680 if ((IVAL(pdata,28) != 0)&&
3681 ((quotas.softlim != 0xFFFFFFFF)||
3682 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3683 /* more than 32 bits? */
3684 reply_nterror(
3685 req,
3686 NT_STATUS_INVALID_PARAMETER);
3687 return;
3689 #endif /* LARGE_SMB_OFF_T */
3691 /* the hard quotas 8 bytes (uint64_t)*/
3692 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3693 #ifdef LARGE_SMB_OFF_T
3694 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3695 #else /* LARGE_SMB_OFF_T */
3696 if ((IVAL(pdata,36) != 0)&&
3697 ((quotas.hardlim != 0xFFFFFFFF)||
3698 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3699 /* more than 32 bits? */
3700 reply_nterror(
3701 req,
3702 NT_STATUS_INVALID_PARAMETER);
3703 return;
3705 #endif /* LARGE_SMB_OFF_T */
3707 /* quota_flags 2 bytes **/
3708 quotas.qflags = SVAL(pdata,40);
3710 /* unknown_2 6 NULL bytes follow*/
3712 /* now set the quotas */
3713 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3714 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3715 reply_nterror(req, map_nt_error_from_unix(errno));
3716 return;
3719 break;
3721 default:
3722 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3723 info_level));
3724 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3725 return;
3726 break;
3730 * sending this reply works fine,
3731 * but I'm not sure it's the same
3732 * like windows do...
3733 * --metze
3735 reply_outbuf(req, 10, 0);
3738 #if defined(HAVE_POSIX_ACLS)
3739 /****************************************************************************
3740 Utility function to count the number of entries in a POSIX acl.
3741 ****************************************************************************/
3743 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3745 unsigned int ace_count = 0;
3746 int entry_id = SMB_ACL_FIRST_ENTRY;
3747 SMB_ACL_ENTRY_T entry;
3749 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3750 /* get_next... */
3751 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3752 entry_id = SMB_ACL_NEXT_ENTRY;
3754 ace_count++;
3756 return ace_count;
3759 /****************************************************************************
3760 Utility function to marshall a POSIX acl into wire format.
3761 ****************************************************************************/
3763 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3765 int entry_id = SMB_ACL_FIRST_ENTRY;
3766 SMB_ACL_ENTRY_T entry;
3768 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3769 SMB_ACL_TAG_T tagtype;
3770 SMB_ACL_PERMSET_T permset;
3771 unsigned char perms = 0;
3772 unsigned int own_grp;
3774 /* get_next... */
3775 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3776 entry_id = SMB_ACL_NEXT_ENTRY;
3779 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3780 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3781 return False;
3784 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3785 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3786 return False;
3789 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3790 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3791 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3793 SCVAL(pdata,1,perms);
3795 switch (tagtype) {
3796 case SMB_ACL_USER_OBJ:
3797 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3798 own_grp = (unsigned int)pst->st_ex_uid;
3799 SIVAL(pdata,2,own_grp);
3800 SIVAL(pdata,6,0);
3801 break;
3802 case SMB_ACL_USER:
3804 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3805 if (!puid) {
3806 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3807 return False;
3809 own_grp = (unsigned int)*puid;
3810 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3811 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3812 SIVAL(pdata,2,own_grp);
3813 SIVAL(pdata,6,0);
3814 break;
3816 case SMB_ACL_GROUP_OBJ:
3817 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3818 own_grp = (unsigned int)pst->st_ex_gid;
3819 SIVAL(pdata,2,own_grp);
3820 SIVAL(pdata,6,0);
3821 break;
3822 case SMB_ACL_GROUP:
3824 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3825 if (!pgid) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3827 return False;
3829 own_grp = (unsigned int)*pgid;
3830 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3831 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3832 SIVAL(pdata,2,own_grp);
3833 SIVAL(pdata,6,0);
3834 break;
3836 case SMB_ACL_MASK:
3837 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3838 SIVAL(pdata,2,0xFFFFFFFF);
3839 SIVAL(pdata,6,0xFFFFFFFF);
3840 break;
3841 case SMB_ACL_OTHER:
3842 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3843 SIVAL(pdata,2,0xFFFFFFFF);
3844 SIVAL(pdata,6,0xFFFFFFFF);
3845 break;
3846 default:
3847 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3848 return False;
3850 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3853 return True;
3855 #endif
3857 /****************************************************************************
3858 Store the FILE_UNIX_BASIC info.
3859 ****************************************************************************/
3861 static char *store_file_unix_basic(connection_struct *conn,
3862 char *pdata,
3863 files_struct *fsp,
3864 const SMB_STRUCT_STAT *psbuf)
3866 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3867 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3869 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3870 pdata += 8;
3872 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3873 pdata += 8;
3875 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3876 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3877 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3878 pdata += 24;
3880 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3881 SIVAL(pdata,4,0);
3882 pdata += 8;
3884 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3885 SIVAL(pdata,4,0);
3886 pdata += 8;
3888 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3889 pdata += 4;
3891 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3892 SIVAL(pdata,4,0);
3893 pdata += 8;
3895 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3896 SIVAL(pdata,4,0);
3897 pdata += 8;
3899 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3900 pdata += 8;
3902 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3903 SIVAL(pdata,4,0);
3904 pdata += 8;
3906 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3907 SIVAL(pdata,4,0);
3908 pdata += 8;
3910 return pdata;
3913 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3914 * the chflags(2) (or equivalent) flags.
3916 * XXX: this really should be behind the VFS interface. To do this, we would
3917 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3918 * Each VFS module could then implement its own mapping as appropriate for the
3919 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3921 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3922 info2_flags_map[] =
3924 #ifdef UF_NODUMP
3925 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3926 #endif
3928 #ifdef UF_IMMUTABLE
3929 { UF_IMMUTABLE, EXT_IMMUTABLE },
3930 #endif
3932 #ifdef UF_APPEND
3933 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3934 #endif
3936 #ifdef UF_HIDDEN
3937 { UF_HIDDEN, EXT_HIDDEN },
3938 #endif
3940 /* Do not remove. We need to guarantee that this array has at least one
3941 * entry to build on HP-UX.
3943 { 0, 0 }
3947 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3948 uint32 *smb_fflags, uint32 *smb_fmask)
3950 int i;
3952 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3953 *smb_fmask |= info2_flags_map[i].smb_fflag;
3954 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3955 *smb_fflags |= info2_flags_map[i].smb_fflag;
3960 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3961 const uint32 smb_fflags,
3962 const uint32 smb_fmask,
3963 int *stat_fflags)
3965 uint32 max_fmask = 0;
3966 int i;
3968 *stat_fflags = psbuf->st_ex_flags;
3970 /* For each flags requested in smb_fmask, check the state of the
3971 * corresponding flag in smb_fflags and set or clear the matching
3972 * stat flag.
3975 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3976 max_fmask |= info2_flags_map[i].smb_fflag;
3977 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3978 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3979 *stat_fflags |= info2_flags_map[i].stat_fflag;
3980 } else {
3981 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3986 /* If smb_fmask is asking to set any bits that are not supported by
3987 * our flag mappings, we should fail.
3989 if ((smb_fmask & max_fmask) != smb_fmask) {
3990 return False;
3993 return True;
3997 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3998 * of file flags and birth (create) time.
4000 static char *store_file_unix_basic_info2(connection_struct *conn,
4001 char *pdata,
4002 files_struct *fsp,
4003 const SMB_STRUCT_STAT *psbuf)
4005 uint32 file_flags = 0;
4006 uint32 flags_mask = 0;
4008 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4010 /* Create (birth) time 64 bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4012 pdata += 8;
4014 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4015 SIVAL(pdata, 0, file_flags); /* flags */
4016 SIVAL(pdata, 4, flags_mask); /* mask */
4017 pdata += 8;
4019 return pdata;
4022 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4023 const struct stream_struct *streams,
4024 char *data,
4025 unsigned int max_data_bytes,
4026 unsigned int *data_size)
4028 unsigned int i;
4029 unsigned int ofs = 0;
4031 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4032 unsigned int next_offset;
4033 size_t namelen;
4034 smb_ucs2_t *namebuf;
4036 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4037 streams[i].name, &namelen) ||
4038 namelen <= 2)
4040 return NT_STATUS_INVALID_PARAMETER;
4044 * name_buf is now null-terminated, we need to marshall as not
4045 * terminated
4048 namelen -= 2;
4050 SIVAL(data, ofs+4, namelen);
4051 SOFF_T(data, ofs+8, streams[i].size);
4052 SOFF_T(data, ofs+16, streams[i].alloc_size);
4053 memcpy(data+ofs+24, namebuf, namelen);
4054 TALLOC_FREE(namebuf);
4056 next_offset = ofs + 24 + namelen;
4058 if (i == num_streams-1) {
4059 SIVAL(data, ofs, 0);
4061 else {
4062 unsigned int align = ndr_align_size(next_offset, 8);
4064 memset(data+next_offset, 0, align);
4065 next_offset += align;
4067 SIVAL(data, ofs, next_offset - ofs);
4068 ofs = next_offset;
4071 ofs = next_offset;
4074 *data_size = ofs;
4076 return NT_STATUS_OK;
4079 /****************************************************************************
4080 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4081 ****************************************************************************/
4083 static void call_trans2qpipeinfo(connection_struct *conn,
4084 struct smb_request *req,
4085 unsigned int tran_call,
4086 char **pparams, int total_params,
4087 char **ppdata, int total_data,
4088 unsigned int max_data_bytes)
4090 char *params = *pparams;
4091 char *pdata = *ppdata;
4092 unsigned int data_size = 0;
4093 unsigned int param_size = 2;
4094 uint16 info_level;
4095 files_struct *fsp;
4097 if (!params) {
4098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4099 return;
4102 if (total_params < 4) {
4103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4104 return;
4107 fsp = file_fsp(req, SVAL(params,0));
4108 if (!fsp_is_np(fsp)) {
4109 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4110 return;
4113 info_level = SVAL(params,2);
4115 *pparams = (char *)SMB_REALLOC(*pparams,2);
4116 if (*pparams == NULL) {
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 return;
4120 params = *pparams;
4121 SSVAL(params,0,0);
4122 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4123 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4124 if (*ppdata == NULL ) {
4125 reply_nterror(req, NT_STATUS_NO_MEMORY);
4126 return;
4128 pdata = *ppdata;
4130 switch (info_level) {
4131 case SMB_FILE_STANDARD_INFORMATION:
4132 memset(pdata,0,24);
4133 SOFF_T(pdata,0,4096LL);
4134 SIVAL(pdata,16,1);
4135 SIVAL(pdata,20,1);
4136 data_size = 24;
4137 break;
4139 default:
4140 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4141 return;
4144 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4145 max_data_bytes);
4147 return;
4150 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4151 TALLOC_CTX *mem_ctx,
4152 uint16_t info_level,
4153 files_struct *fsp,
4154 struct smb_filename *smb_fname,
4155 bool delete_pending,
4156 struct timespec write_time_ts,
4157 bool ms_dfs_link,
4158 struct ea_list *ea_list,
4159 int lock_data_count,
4160 char *lock_data,
4161 uint16_t flags2,
4162 unsigned int max_data_bytes,
4163 char **ppdata,
4164 unsigned int *pdata_size)
4166 char *pdata = *ppdata;
4167 char *dstart, *dend;
4168 unsigned int data_size;
4169 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4170 time_t create_time, mtime, atime, c_time;
4171 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4172 char *p;
4173 char *base_name;
4174 char *dos_fname;
4175 int mode;
4176 int nlink;
4177 NTSTATUS status;
4178 uint64_t file_size = 0;
4179 uint64_t pos = 0;
4180 uint64_t allocation_size = 0;
4181 uint64_t file_index = 0;
4182 uint32_t access_mask = 0;
4184 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4185 return NT_STATUS_INVALID_LEVEL;
4188 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4189 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4190 info_level, max_data_bytes));
4192 if (ms_dfs_link) {
4193 mode = dos_mode_msdfs(conn, smb_fname);
4194 } else {
4195 mode = dos_mode(conn, smb_fname);
4198 nlink = psbuf->st_ex_nlink;
4200 if (nlink && (mode&aDIR)) {
4201 nlink = 1;
4204 if ((nlink > 0) && delete_pending) {
4205 nlink -= 1;
4208 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4209 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4210 if (*ppdata == NULL) {
4211 return NT_STATUS_NO_MEMORY;
4213 pdata = *ppdata;
4214 dstart = pdata;
4215 dend = dstart + data_size - 1;
4217 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4218 update_stat_ex_mtime(psbuf, write_time_ts);
4221 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4222 mtime_ts = psbuf->st_ex_mtime;
4223 atime_ts = psbuf->st_ex_atime;
4224 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4226 if (lp_dos_filetime_resolution(SNUM(conn))) {
4227 dos_filetime_timespec(&create_time_ts);
4228 dos_filetime_timespec(&mtime_ts);
4229 dos_filetime_timespec(&atime_ts);
4230 dos_filetime_timespec(&ctime_ts);
4233 create_time = convert_timespec_to_time_t(create_time_ts);
4234 mtime = convert_timespec_to_time_t(mtime_ts);
4235 atime = convert_timespec_to_time_t(atime_ts);
4236 c_time = convert_timespec_to_time_t(ctime_ts);
4238 p = strrchr_m(smb_fname->base_name,'/');
4239 if (!p)
4240 base_name = smb_fname->base_name;
4241 else
4242 base_name = p+1;
4244 /* NT expects the name to be in an exact form of the *full*
4245 filename. See the trans2 torture test */
4246 if (ISDOT(base_name)) {
4247 dos_fname = talloc_strdup(mem_ctx, "\\");
4248 if (!dos_fname) {
4249 return NT_STATUS_NO_MEMORY;
4251 } else {
4252 dos_fname = talloc_asprintf(mem_ctx,
4253 "\\%s",
4254 smb_fname->base_name);
4255 if (!dos_fname) {
4256 return NT_STATUS_NO_MEMORY;
4258 if (is_ntfs_stream_smb_fname(smb_fname)) {
4259 dos_fname = talloc_asprintf(dos_fname, "%s",
4260 smb_fname->stream_name);
4261 if (!dos_fname) {
4262 return NT_STATUS_NO_MEMORY;
4266 string_replace(dos_fname, '/', '\\');
4269 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4271 if (!fsp) {
4272 /* Do we have this path open ? */
4273 files_struct *fsp1;
4274 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4275 fsp1 = file_find_di_first(fileid);
4276 if (fsp1 && fsp1->initial_allocation_size) {
4277 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4281 if (!(mode & aDIR)) {
4282 file_size = get_file_size_stat(psbuf);
4285 if (fsp) {
4286 pos = fsp->fh->position_information;
4289 if (fsp) {
4290 access_mask = fsp->access_mask;
4291 } else {
4292 /* GENERIC_EXECUTE mapping from Windows */
4293 access_mask = 0x12019F;
4296 /* This should be an index number - looks like
4297 dev/ino to me :-)
4299 I think this causes us to fail the IFSKIT
4300 BasicFileInformationTest. -tpot */
4301 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4302 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4304 switch (info_level) {
4305 case SMB_INFO_STANDARD:
4306 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4307 data_size = 22;
4308 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4309 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4310 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4311 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4312 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4313 SSVAL(pdata,l1_attrFile,mode);
4314 break;
4316 case SMB_INFO_QUERY_EA_SIZE:
4318 unsigned int ea_size =
4319 estimate_ea_size(conn, fsp,
4320 smb_fname->base_name);
4321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4322 data_size = 26;
4323 srv_put_dos_date2(pdata,0,create_time);
4324 srv_put_dos_date2(pdata,4,atime);
4325 srv_put_dos_date2(pdata,8,mtime); /* write time */
4326 SIVAL(pdata,12,(uint32)file_size);
4327 SIVAL(pdata,16,(uint32)allocation_size);
4328 SSVAL(pdata,20,mode);
4329 SIVAL(pdata,22,ea_size);
4330 break;
4333 case SMB_INFO_IS_NAME_VALID:
4334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4335 if (fsp) {
4336 /* os/2 needs this ? really ?*/
4337 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4339 /* This is only reached for qpathinfo */
4340 data_size = 0;
4341 break;
4343 case SMB_INFO_QUERY_EAS_FROM_LIST:
4345 size_t total_ea_len = 0;
4346 struct ea_list *ea_file_list = NULL;
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4350 ea_file_list =
4351 get_ea_list_from_file(mem_ctx, conn, fsp,
4352 smb_fname->base_name,
4353 &total_ea_len);
4354 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4356 if (!ea_list || (total_ea_len > data_size)) {
4357 data_size = 4;
4358 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4359 break;
4362 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4363 break;
4366 case SMB_INFO_QUERY_ALL_EAS:
4368 /* We have data_size bytes to put EA's into. */
4369 size_t total_ea_len = 0;
4371 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4373 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4374 smb_fname->base_name,
4375 &total_ea_len);
4376 if (!ea_list || (total_ea_len > data_size)) {
4377 data_size = 4;
4378 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4379 break;
4382 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4383 break;
4386 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4388 /* This is FileFullEaInformation - 0xF which maps to
4389 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4391 /* We have data_size bytes to put EA's into. */
4392 size_t total_ea_len = 0;
4393 struct ea_list *ea_file_list = NULL;
4395 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4397 /*TODO: add filtering and index handling */
4399 ea_file_list =
4400 get_ea_list_from_file(mem_ctx, conn, fsp,
4401 smb_fname->base_name,
4402 &total_ea_len);
4403 if (!ea_file_list) {
4404 return NT_STATUS_NO_EAS_ON_FILE;
4407 status = fill_ea_chained_buffer(mem_ctx,
4408 pdata,
4409 data_size,
4410 &data_size,
4411 conn, ea_file_list);
4412 if (!NT_STATUS_IS_OK(status)) {
4413 return status;
4415 break;
4418 case SMB_FILE_BASIC_INFORMATION:
4419 case SMB_QUERY_FILE_BASIC_INFO:
4421 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4423 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4424 } else {
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4426 data_size = 40;
4427 SIVAL(pdata,36,0);
4429 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4430 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4431 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4432 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4433 SIVAL(pdata,32,mode);
4435 DEBUG(5,("SMB_QFBI - "));
4436 DEBUG(5,("create: %s ", ctime(&create_time)));
4437 DEBUG(5,("access: %s ", ctime(&atime)));
4438 DEBUG(5,("write: %s ", ctime(&mtime)));
4439 DEBUG(5,("change: %s ", ctime(&c_time)));
4440 DEBUG(5,("mode: %x\n", mode));
4441 break;
4443 case SMB_FILE_STANDARD_INFORMATION:
4444 case SMB_QUERY_FILE_STANDARD_INFO:
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4447 data_size = 24;
4448 SOFF_T(pdata,0,allocation_size);
4449 SOFF_T(pdata,8,file_size);
4450 SIVAL(pdata,16,nlink);
4451 SCVAL(pdata,20,delete_pending?1:0);
4452 SCVAL(pdata,21,(mode&aDIR)?1:0);
4453 SSVAL(pdata,22,0); /* Padding. */
4454 break;
4456 case SMB_FILE_EA_INFORMATION:
4457 case SMB_QUERY_FILE_EA_INFO:
4459 unsigned int ea_size =
4460 estimate_ea_size(conn, fsp, smb_fname->base_name);
4461 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4462 data_size = 4;
4463 SIVAL(pdata,0,ea_size);
4464 break;
4467 /* Get the 8.3 name - used if NT SMB was negotiated. */
4468 case SMB_QUERY_FILE_ALT_NAME_INFO:
4469 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4471 int len;
4472 char mangled_name[13];
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4474 if (!name_to_8_3(base_name,mangled_name,
4475 True,conn->params)) {
4476 return NT_STATUS_NO_MEMORY;
4478 len = srvstr_push(dstart, flags2,
4479 pdata+4, mangled_name,
4480 PTR_DIFF(dend, pdata+4),
4481 STR_UNICODE);
4482 data_size = 4 + len;
4483 SIVAL(pdata,0,len);
4484 break;
4487 case SMB_QUERY_FILE_NAME_INFO:
4489 int len;
4491 this must be *exactly* right for ACLs on mapped drives to work
4493 len = srvstr_push(dstart, flags2,
4494 pdata+4, dos_fname,
4495 PTR_DIFF(dend, pdata+4),
4496 STR_UNICODE);
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4498 data_size = 4 + len;
4499 SIVAL(pdata,0,len);
4500 break;
4503 case SMB_FILE_ALLOCATION_INFORMATION:
4504 case SMB_QUERY_FILE_ALLOCATION_INFO:
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4506 data_size = 8;
4507 SOFF_T(pdata,0,allocation_size);
4508 break;
4510 case SMB_FILE_END_OF_FILE_INFORMATION:
4511 case SMB_QUERY_FILE_END_OF_FILEINFO:
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4513 data_size = 8;
4514 SOFF_T(pdata,0,file_size);
4515 break;
4517 case SMB_QUERY_FILE_ALL_INFO:
4518 case SMB_FILE_ALL_INFORMATION:
4520 int len;
4521 unsigned int ea_size =
4522 estimate_ea_size(conn, fsp, smb_fname->base_name);
4523 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4524 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4525 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4526 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4527 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4528 SIVAL(pdata,32,mode);
4529 SIVAL(pdata,36,0); /* padding. */
4530 pdata += 40;
4531 SOFF_T(pdata,0,allocation_size);
4532 SOFF_T(pdata,8,file_size);
4533 SIVAL(pdata,16,nlink);
4534 SCVAL(pdata,20,delete_pending);
4535 SCVAL(pdata,21,(mode&aDIR)?1:0);
4536 SSVAL(pdata,22,0);
4537 pdata += 24;
4538 SIVAL(pdata,0,ea_size);
4539 pdata += 4; /* EA info */
4540 len = srvstr_push(dstart, flags2,
4541 pdata+4, dos_fname,
4542 PTR_DIFF(dend, pdata+4),
4543 STR_UNICODE);
4544 SIVAL(pdata,0,len);
4545 pdata += 4 + len;
4546 data_size = PTR_DIFF(pdata,(*ppdata));
4547 break;
4550 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4552 int len;
4553 unsigned int ea_size =
4554 estimate_ea_size(conn, fsp, smb_fname->base_name);
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4556 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4557 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4558 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4559 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4560 SIVAL(pdata, 0x20, mode);
4561 SIVAL(pdata, 0x24, 0); /* padding. */
4562 SBVAL(pdata, 0x28, allocation_size);
4563 SBVAL(pdata, 0x30, file_size);
4564 SIVAL(pdata, 0x38, nlink);
4565 SCVAL(pdata, 0x3C, delete_pending);
4566 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4567 SSVAL(pdata, 0x3E, 0); /* padding */
4568 SBVAL(pdata, 0x40, file_index);
4569 SIVAL(pdata, 0x48, ea_size);
4570 SIVAL(pdata, 0x4C, access_mask);
4571 SBVAL(pdata, 0x50, pos);
4572 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4573 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4575 pdata += 0x60;
4577 len = srvstr_push(dstart, flags2,
4578 pdata+4, dos_fname,
4579 PTR_DIFF(dend, pdata+4),
4580 STR_UNICODE);
4581 SIVAL(pdata,0,len);
4582 pdata += 4 + len;
4583 data_size = PTR_DIFF(pdata,(*ppdata));
4584 break;
4586 case SMB_FILE_INTERNAL_INFORMATION:
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4589 SBVAL(pdata, 0, file_index);
4590 data_size = 8;
4591 break;
4593 case SMB_FILE_ACCESS_INFORMATION:
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4595 SIVAL(pdata, 0, access_mask);
4596 data_size = 4;
4597 break;
4599 case SMB_FILE_NAME_INFORMATION:
4600 /* Pathname with leading '\'. */
4602 size_t byte_len;
4603 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4605 SIVAL(pdata,0,byte_len);
4606 data_size = 4 + byte_len;
4607 break;
4610 case SMB_FILE_DISPOSITION_INFORMATION:
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4612 data_size = 1;
4613 SCVAL(pdata,0,delete_pending);
4614 break;
4616 case SMB_FILE_POSITION_INFORMATION:
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4618 data_size = 8;
4619 SOFF_T(pdata,0,pos);
4620 break;
4622 case SMB_FILE_MODE_INFORMATION:
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4624 SIVAL(pdata,0,mode);
4625 data_size = 4;
4626 break;
4628 case SMB_FILE_ALIGNMENT_INFORMATION:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4630 SIVAL(pdata,0,0); /* No alignment needed. */
4631 data_size = 4;
4632 break;
4635 * NT4 server just returns "invalid query" to this - if we try
4636 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4637 * want this. JRA.
4639 /* The first statement above is false - verified using Thursby
4640 * client against NT4 -- gcolley.
4642 case SMB_QUERY_FILE_STREAM_INFO:
4643 case SMB_FILE_STREAM_INFORMATION: {
4644 unsigned int num_streams;
4645 struct stream_struct *streams;
4647 DEBUG(10,("smbd_do_qfilepathinfo: "
4648 "SMB_FILE_STREAM_INFORMATION\n"));
4650 if (is_ntfs_stream_smb_fname(smb_fname)) {
4651 return NT_STATUS_INVALID_PARAMETER;
4654 status = SMB_VFS_STREAMINFO(
4655 conn, fsp, smb_fname->base_name, talloc_tos(),
4656 &num_streams, &streams);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 DEBUG(10, ("could not get stream info: %s\n",
4660 nt_errstr(status)));
4661 return status;
4664 status = marshall_stream_info(num_streams, streams,
4665 pdata, max_data_bytes,
4666 &data_size);
4668 if (!NT_STATUS_IS_OK(status)) {
4669 DEBUG(10, ("marshall_stream_info failed: %s\n",
4670 nt_errstr(status)));
4671 return status;
4674 TALLOC_FREE(streams);
4676 break;
4678 case SMB_QUERY_COMPRESSION_INFO:
4679 case SMB_FILE_COMPRESSION_INFORMATION:
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4681 SOFF_T(pdata,0,file_size);
4682 SIVAL(pdata,8,0); /* ??? */
4683 SIVAL(pdata,12,0); /* ??? */
4684 data_size = 16;
4685 break;
4687 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4689 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4690 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4691 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4692 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4693 SOFF_T(pdata,32,allocation_size);
4694 SOFF_T(pdata,40,file_size);
4695 SIVAL(pdata,48,mode);
4696 SIVAL(pdata,52,0); /* ??? */
4697 data_size = 56;
4698 break;
4700 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4702 SIVAL(pdata,0,mode);
4703 SIVAL(pdata,4,0);
4704 data_size = 8;
4705 break;
4708 * CIFS UNIX Extensions.
4711 case SMB_QUERY_FILE_UNIX_BASIC:
4713 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4714 data_size = PTR_DIFF(pdata,(*ppdata));
4717 int i;
4718 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4720 for (i=0; i<100; i++)
4721 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4722 DEBUG(4,("\n"));
4725 break;
4727 case SMB_QUERY_FILE_UNIX_INFO2:
4729 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4730 data_size = PTR_DIFF(pdata,(*ppdata));
4733 int i;
4734 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4736 for (i=0; i<100; i++)
4737 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4738 DEBUG(4,("\n"));
4741 break;
4743 case SMB_QUERY_FILE_UNIX_LINK:
4745 int len;
4746 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4748 if (!buffer) {
4749 return NT_STATUS_NO_MEMORY;
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4753 #ifdef S_ISLNK
4754 if(!S_ISLNK(psbuf->st_ex_mode)) {
4755 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4757 #else
4758 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4759 #endif
4760 len = SMB_VFS_READLINK(conn,
4761 smb_fname->base_name,
4762 buffer, PATH_MAX);
4763 if (len == -1) {
4764 return map_nt_error_from_unix(errno);
4766 buffer[len] = 0;
4767 len = srvstr_push(dstart, flags2,
4768 pdata, buffer,
4769 PTR_DIFF(dend, pdata),
4770 STR_TERMINATE);
4771 pdata += len;
4772 data_size = PTR_DIFF(pdata,(*ppdata));
4774 break;
4777 #if defined(HAVE_POSIX_ACLS)
4778 case SMB_QUERY_POSIX_ACL:
4780 SMB_ACL_T file_acl = NULL;
4781 SMB_ACL_T def_acl = NULL;
4782 uint16 num_file_acls = 0;
4783 uint16 num_def_acls = 0;
4785 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4786 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4787 } else {
4788 file_acl =
4789 SMB_VFS_SYS_ACL_GET_FILE(conn,
4790 smb_fname->base_name,
4791 SMB_ACL_TYPE_ACCESS);
4794 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4795 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4796 "not implemented on "
4797 "filesystem containing %s\n",
4798 smb_fname->base_name));
4799 return NT_STATUS_NOT_IMPLEMENTED;
4802 if (S_ISDIR(psbuf->st_ex_mode)) {
4803 if (fsp && fsp->is_directory) {
4804 def_acl =
4805 SMB_VFS_SYS_ACL_GET_FILE(
4806 conn,
4807 fsp->fsp_name->base_name,
4808 SMB_ACL_TYPE_DEFAULT);
4809 } else {
4810 def_acl =
4811 SMB_VFS_SYS_ACL_GET_FILE(
4812 conn,
4813 smb_fname->base_name,
4814 SMB_ACL_TYPE_DEFAULT);
4816 def_acl = free_empty_sys_acl(conn, def_acl);
4819 num_file_acls = count_acl_entries(conn, file_acl);
4820 num_def_acls = count_acl_entries(conn, def_acl);
4822 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4823 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4824 data_size,
4825 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4826 SMB_POSIX_ACL_HEADER_SIZE) ));
4827 if (file_acl) {
4828 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4830 if (def_acl) {
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4833 return NT_STATUS_BUFFER_TOO_SMALL;
4836 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4837 SSVAL(pdata,2,num_file_acls);
4838 SSVAL(pdata,4,num_def_acls);
4839 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4840 if (file_acl) {
4841 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4843 if (def_acl) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4846 return NT_STATUS_INTERNAL_ERROR;
4848 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4849 if (file_acl) {
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4852 if (def_acl) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4855 return NT_STATUS_INTERNAL_ERROR;
4858 if (file_acl) {
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4861 if (def_acl) {
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4864 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4865 break;
4867 #endif
4870 case SMB_QUERY_POSIX_LOCK:
4872 uint64_t count;
4873 uint64_t offset;
4874 uint32 lock_pid;
4875 enum brl_type lock_type;
4877 /* We need an open file with a real fd for this. */
4878 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4879 return NT_STATUS_INVALID_LEVEL;
4882 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4883 return NT_STATUS_INVALID_PARAMETER;
4886 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4887 case POSIX_LOCK_TYPE_READ:
4888 lock_type = READ_LOCK;
4889 break;
4890 case POSIX_LOCK_TYPE_WRITE:
4891 lock_type = WRITE_LOCK;
4892 break;
4893 case POSIX_LOCK_TYPE_UNLOCK:
4894 default:
4895 /* There's no point in asking for an unlock... */
4896 return NT_STATUS_INVALID_PARAMETER;
4899 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4900 #if defined(HAVE_LONGLONG)
4901 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4902 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4903 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4904 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4905 #else /* HAVE_LONGLONG */
4906 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4907 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4908 #endif /* HAVE_LONGLONG */
4910 status = query_lock(fsp,
4911 &lock_pid,
4912 &count,
4913 &offset,
4914 &lock_type,
4915 POSIX_LOCK);
4917 if (ERROR_WAS_LOCK_DENIED(status)) {
4918 /* Here we need to report who has it locked... */
4919 data_size = POSIX_LOCK_DATA_SIZE;
4921 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4922 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4923 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4924 #if defined(HAVE_LONGLONG)
4925 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4926 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4927 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4928 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4929 #else /* HAVE_LONGLONG */
4930 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4931 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4932 #endif /* HAVE_LONGLONG */
4934 } else if (NT_STATUS_IS_OK(status)) {
4935 /* For success we just return a copy of what we sent
4936 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4937 data_size = POSIX_LOCK_DATA_SIZE;
4938 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4939 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4940 } else {
4941 return status;
4943 break;
4946 default:
4947 return NT_STATUS_INVALID_LEVEL;
4950 *pdata_size = data_size;
4951 return NT_STATUS_OK;
4954 /****************************************************************************
4955 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4956 file name or file id).
4957 ****************************************************************************/
4959 static void call_trans2qfilepathinfo(connection_struct *conn,
4960 struct smb_request *req,
4961 unsigned int tran_call,
4962 char **pparams, int total_params,
4963 char **ppdata, int total_data,
4964 unsigned int max_data_bytes)
4966 char *params = *pparams;
4967 char *pdata = *ppdata;
4968 uint16 info_level;
4969 unsigned int data_size = 0;
4970 unsigned int param_size = 2;
4971 struct smb_filename *smb_fname = NULL;
4972 bool delete_pending = False;
4973 struct timespec write_time_ts;
4974 files_struct *fsp = NULL;
4975 struct file_id fileid;
4976 struct ea_list *ea_list = NULL;
4977 int lock_data_count = 0;
4978 char *lock_data = NULL;
4979 bool ms_dfs_link = false;
4980 NTSTATUS status = NT_STATUS_OK;
4982 if (!params) {
4983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4984 return;
4987 ZERO_STRUCT(write_time_ts);
4989 if (tran_call == TRANSACT2_QFILEINFO) {
4990 if (total_params < 4) {
4991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4992 return;
4995 if (IS_IPC(conn)) {
4996 call_trans2qpipeinfo(conn, req, tran_call,
4997 pparams, total_params,
4998 ppdata, total_data,
4999 max_data_bytes);
5000 return;
5003 fsp = file_fsp(req, SVAL(params,0));
5004 info_level = SVAL(params,2);
5006 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5008 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5009 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5010 return;
5013 /* Initial check for valid fsp ptr. */
5014 if (!check_fsp_open(conn, req, fsp)) {
5015 return;
5018 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5019 &smb_fname);
5020 if (!NT_STATUS_IS_OK(status)) {
5021 reply_nterror(req, status);
5022 return;
5025 if(fsp->fake_file_handle) {
5027 * This is actually for the QUOTA_FAKE_FILE --metze
5030 /* We know this name is ok, it's already passed the checks. */
5032 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5034 * This is actually a QFILEINFO on a directory
5035 * handle (returned from an NT SMB). NT5.0 seems
5036 * to do this call. JRA.
5039 if (INFO_LEVEL_IS_UNIX(info_level)) {
5040 /* Always do lstat for UNIX calls. */
5041 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5042 DEBUG(3,("call_trans2qfilepathinfo: "
5043 "SMB_VFS_LSTAT of %s failed "
5044 "(%s)\n",
5045 smb_fname_str_dbg(smb_fname),
5046 strerror(errno)));
5047 reply_nterror(req,
5048 map_nt_error_from_unix(errno));
5049 return;
5051 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5052 DEBUG(3,("call_trans2qfilepathinfo: "
5053 "SMB_VFS_STAT of %s failed (%s)\n",
5054 smb_fname_str_dbg(smb_fname),
5055 strerror(errno)));
5056 reply_nterror(req,
5057 map_nt_error_from_unix(errno));
5058 return;
5061 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5062 get_file_infos(fileid, &delete_pending, &write_time_ts);
5063 } else {
5065 * Original code - this is an open file.
5067 if (!check_fsp(conn, req, fsp)) {
5068 return;
5071 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5072 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5073 fsp->fnum, strerror(errno)));
5074 reply_nterror(req,
5075 map_nt_error_from_unix(errno));
5076 return;
5078 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5079 get_file_infos(fileid, &delete_pending, &write_time_ts);
5082 } else {
5083 char *fname = NULL;
5085 /* qpathinfo */
5086 if (total_params < 7) {
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 return;
5091 info_level = SVAL(params,0);
5093 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5095 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5096 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5097 return;
5100 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5101 total_params - 6,
5102 STR_TERMINATE, &status);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 reply_nterror(req, status);
5105 return;
5108 status = filename_convert(req,
5109 conn,
5110 req->flags2 & FLAGS2_DFS_PATHNAMES,
5111 fname,
5113 NULL,
5114 &smb_fname);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5117 reply_botherror(req,
5118 NT_STATUS_PATH_NOT_COVERED,
5119 ERRSRV, ERRbadpath);
5120 return;
5122 reply_nterror(req, status);
5123 return;
5126 /* If this is a stream, check if there is a delete_pending. */
5127 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5128 && is_ntfs_stream_smb_fname(smb_fname)) {
5129 struct smb_filename *smb_fname_base = NULL;
5131 /* Create an smb_filename with stream_name == NULL. */
5132 status =
5133 create_synthetic_smb_fname(talloc_tos(),
5134 smb_fname->base_name,
5135 NULL, NULL,
5136 &smb_fname_base);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 reply_nterror(req, status);
5139 return;
5142 if (INFO_LEVEL_IS_UNIX(info_level)) {
5143 /* Always do lstat for UNIX calls. */
5144 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5145 DEBUG(3,("call_trans2qfilepathinfo: "
5146 "SMB_VFS_LSTAT of %s failed "
5147 "(%s)\n",
5148 smb_fname_str_dbg(smb_fname_base),
5149 strerror(errno)));
5150 TALLOC_FREE(smb_fname_base);
5151 reply_nterror(req,
5152 map_nt_error_from_unix(errno));
5153 return;
5155 } else {
5156 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5157 DEBUG(3,("call_trans2qfilepathinfo: "
5158 "fileinfo of %s failed "
5159 "(%s)\n",
5160 smb_fname_str_dbg(smb_fname_base),
5161 strerror(errno)));
5162 TALLOC_FREE(smb_fname_base);
5163 reply_nterror(req,
5164 map_nt_error_from_unix(errno));
5165 return;
5169 fileid = vfs_file_id_from_sbuf(conn,
5170 &smb_fname_base->st);
5171 TALLOC_FREE(smb_fname_base);
5172 get_file_infos(fileid, &delete_pending, NULL);
5173 if (delete_pending) {
5174 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5175 return;
5179 if (INFO_LEVEL_IS_UNIX(info_level)) {
5180 /* Always do lstat for UNIX calls. */
5181 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5182 DEBUG(3,("call_trans2qfilepathinfo: "
5183 "SMB_VFS_LSTAT of %s failed (%s)\n",
5184 smb_fname_str_dbg(smb_fname),
5185 strerror(errno)));
5186 reply_nterror(req,
5187 map_nt_error_from_unix(errno));
5188 return;
5191 } else if (!VALID_STAT(smb_fname->st) &&
5192 SMB_VFS_STAT(conn, smb_fname) &&
5193 (info_level != SMB_INFO_IS_NAME_VALID)) {
5194 ms_dfs_link = check_msdfs_link(conn,
5195 smb_fname->base_name,
5196 &smb_fname->st);
5198 if (!ms_dfs_link) {
5199 DEBUG(3,("call_trans2qfilepathinfo: "
5200 "SMB_VFS_STAT of %s failed (%s)\n",
5201 smb_fname_str_dbg(smb_fname),
5202 strerror(errno)));
5203 reply_nterror(req,
5204 map_nt_error_from_unix(errno));
5205 return;
5209 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5210 get_file_infos(fileid, &delete_pending, &write_time_ts);
5211 if (delete_pending) {
5212 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5213 return;
5217 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5218 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5219 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5221 /* Pull out any data sent here before we realloc. */
5222 switch (info_level) {
5223 case SMB_INFO_QUERY_EAS_FROM_LIST:
5225 /* Pull any EA list from the data portion. */
5226 uint32 ea_size;
5228 if (total_data < 4) {
5229 reply_nterror(
5230 req, NT_STATUS_INVALID_PARAMETER);
5231 return;
5233 ea_size = IVAL(pdata,0);
5235 if (total_data > 0 && ea_size != total_data) {
5236 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5237 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5238 reply_nterror(
5239 req, NT_STATUS_INVALID_PARAMETER);
5240 return;
5243 if (!lp_ea_support(SNUM(conn))) {
5244 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5245 return;
5248 /* Pull out the list of names. */
5249 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5250 if (!ea_list) {
5251 reply_nterror(
5252 req, NT_STATUS_INVALID_PARAMETER);
5253 return;
5255 break;
5258 case SMB_QUERY_POSIX_LOCK:
5260 if (fsp == NULL || fsp->fh->fd == -1) {
5261 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5262 return;
5265 if (total_data != POSIX_LOCK_DATA_SIZE) {
5266 reply_nterror(
5267 req, NT_STATUS_INVALID_PARAMETER);
5268 return;
5271 /* Copy the lock range data. */
5272 lock_data = (char *)TALLOC_MEMDUP(
5273 req, pdata, total_data);
5274 if (!lock_data) {
5275 reply_nterror(req, NT_STATUS_NO_MEMORY);
5276 return;
5278 lock_data_count = total_data;
5280 default:
5281 break;
5284 *pparams = (char *)SMB_REALLOC(*pparams,2);
5285 if (*pparams == NULL) {
5286 reply_nterror(req, NT_STATUS_NO_MEMORY);
5287 return;
5289 params = *pparams;
5290 SSVAL(params,0,0);
5293 * draft-leach-cifs-v1-spec-02.txt
5294 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5295 * says:
5297 * The requested information is placed in the Data portion of the
5298 * transaction response. For the information levels greater than 0x100,
5299 * the transaction response has 1 parameter word which should be
5300 * ignored by the client.
5302 * However Windows only follows this rule for the IS_NAME_VALID call.
5304 switch (info_level) {
5305 case SMB_INFO_IS_NAME_VALID:
5306 param_size = 0;
5307 break;
5310 if ((info_level & 0xFF00) == 0xFF00) {
5312 * We use levels that start with 0xFF00
5313 * internally to represent SMB2 specific levels
5315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5316 return;
5319 status = smbd_do_qfilepathinfo(conn, req, info_level,
5320 fsp, smb_fname,
5321 delete_pending, write_time_ts,
5322 ms_dfs_link, ea_list,
5323 lock_data_count, lock_data,
5324 req->flags2, max_data_bytes,
5325 ppdata, &data_size);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 reply_nterror(req, status);
5328 return;
5331 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5332 max_data_bytes);
5334 return;
5337 /****************************************************************************
5338 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5339 code.
5340 ****************************************************************************/
5342 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5343 connection_struct *conn,
5344 const struct smb_filename *smb_fname_old,
5345 const struct smb_filename *smb_fname_new)
5347 NTSTATUS status = NT_STATUS_OK;
5349 /* source must already exist. */
5350 if (!VALID_STAT(smb_fname_old->st)) {
5351 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5354 /* Disallow if newname already exists. */
5355 if (VALID_STAT(smb_fname_new->st)) {
5356 return NT_STATUS_OBJECT_NAME_COLLISION;
5359 /* No links from a directory. */
5360 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5361 return NT_STATUS_FILE_IS_A_DIRECTORY;
5364 /* Setting a hardlink to/from a stream isn't currently supported. */
5365 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5366 is_ntfs_stream_smb_fname(smb_fname_new)) {
5367 return NT_STATUS_INVALID_PARAMETER;
5370 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5371 smb_fname_old->base_name, smb_fname_new->base_name));
5373 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5374 smb_fname_new->base_name) != 0) {
5375 status = map_nt_error_from_unix(errno);
5376 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5377 nt_errstr(status), smb_fname_old->base_name,
5378 smb_fname_new->base_name));
5380 return status;
5383 /****************************************************************************
5384 Deal with setting the time from any of the setfilepathinfo functions.
5385 ****************************************************************************/
5387 NTSTATUS smb_set_file_time(connection_struct *conn,
5388 files_struct *fsp,
5389 const struct smb_filename *smb_fname,
5390 struct smb_file_time *ft,
5391 bool setting_write_time)
5393 struct smb_filename smb_fname_base;
5394 uint32 action =
5395 FILE_NOTIFY_CHANGE_LAST_ACCESS
5396 |FILE_NOTIFY_CHANGE_LAST_WRITE
5397 |FILE_NOTIFY_CHANGE_CREATION;
5399 if (!VALID_STAT(smb_fname->st)) {
5400 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5403 /* get some defaults (no modifications) if any info is zero or -1. */
5404 if (null_timespec(ft->create_time)) {
5405 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5408 if (null_timespec(ft->atime)) {
5409 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5412 if (null_timespec(ft->mtime)) {
5413 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5416 if (!setting_write_time) {
5417 /* ft->mtime comes from change time, not write time. */
5418 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5421 /* Ensure the resolution is the correct for
5422 * what we can store on this filesystem. */
5424 round_timespec(conn->ts_res, &ft->create_time);
5425 round_timespec(conn->ts_res, &ft->ctime);
5426 round_timespec(conn->ts_res, &ft->atime);
5427 round_timespec(conn->ts_res, &ft->mtime);
5429 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5430 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5431 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5432 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5433 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5434 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5435 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5436 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5438 if (setting_write_time) {
5440 * This was a Windows setfileinfo on an open file.
5441 * NT does this a lot. We also need to
5442 * set the time here, as it can be read by
5443 * FindFirst/FindNext and with the patch for bug #2045
5444 * in smbd/fileio.c it ensures that this timestamp is
5445 * kept sticky even after a write. We save the request
5446 * away and will set it on file close and after a write. JRA.
5449 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5450 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5452 if (fsp != NULL) {
5453 if (fsp->base_fsp) {
5454 set_sticky_write_time_fsp(fsp->base_fsp,
5455 ft->mtime);
5456 } else {
5457 set_sticky_write_time_fsp(fsp, ft->mtime);
5459 } else {
5460 set_sticky_write_time_path(
5461 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5462 ft->mtime);
5466 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5468 /* Always call ntimes on the base, even if a stream was passed in. */
5469 smb_fname_base = *smb_fname;
5470 smb_fname_base.stream_name = NULL;
5472 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5473 return map_nt_error_from_unix(errno);
5476 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5477 smb_fname->base_name);
5478 return NT_STATUS_OK;
5481 /****************************************************************************
5482 Deal with setting the dosmode from any of the setfilepathinfo functions.
5483 ****************************************************************************/
5485 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5486 const struct smb_filename *smb_fname,
5487 uint32 dosmode)
5489 struct smb_filename *smb_fname_base = NULL;
5490 NTSTATUS status;
5492 if (!VALID_STAT(smb_fname->st)) {
5493 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5496 /* Always operate on the base_name, even if a stream was passed in. */
5497 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5498 NULL, &smb_fname->st,
5499 &smb_fname_base);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 return status;
5504 if (dosmode) {
5505 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5506 dosmode |= aDIR;
5507 } else {
5508 dosmode &= ~aDIR;
5512 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5514 /* check the mode isn't different, before changing it */
5515 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5516 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5517 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5518 (unsigned int)dosmode));
5520 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5521 false)) {
5522 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5523 "%s failed (%s)\n",
5524 smb_fname_str_dbg(smb_fname_base),
5525 strerror(errno)));
5526 status = map_nt_error_from_unix(errno);
5527 goto out;
5530 status = NT_STATUS_OK;
5531 out:
5532 TALLOC_FREE(smb_fname_base);
5533 return status;
5536 /****************************************************************************
5537 Deal with setting the size from any of the setfilepathinfo functions.
5538 ****************************************************************************/
5540 static NTSTATUS smb_set_file_size(connection_struct *conn,
5541 struct smb_request *req,
5542 files_struct *fsp,
5543 const struct smb_filename *smb_fname,
5544 const SMB_STRUCT_STAT *psbuf,
5545 SMB_OFF_T size,
5546 bool fail_after_createfile)
5548 NTSTATUS status = NT_STATUS_OK;
5549 struct smb_filename *smb_fname_tmp = NULL;
5550 files_struct *new_fsp = NULL;
5552 if (!VALID_STAT(*psbuf)) {
5553 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5556 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5558 if (size == get_file_size_stat(psbuf)) {
5559 return NT_STATUS_OK;
5562 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5563 smb_fname_str_dbg(smb_fname), (double)size));
5565 if (fsp && fsp->fh->fd != -1) {
5566 /* Handle based call. */
5567 if (vfs_set_filelen(fsp, size) == -1) {
5568 return map_nt_error_from_unix(errno);
5570 trigger_write_time_update_immediate(fsp);
5571 return NT_STATUS_OK;
5574 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5575 if (!NT_STATUS_IS_OK(status)) {
5576 return status;
5579 smb_fname_tmp->st = *psbuf;
5581 status = SMB_VFS_CREATE_FILE(
5582 conn, /* conn */
5583 req, /* req */
5584 0, /* root_dir_fid */
5585 smb_fname_tmp, /* fname */
5586 FILE_WRITE_DATA, /* access_mask */
5587 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5588 FILE_SHARE_DELETE),
5589 FILE_OPEN, /* create_disposition*/
5590 0, /* create_options */
5591 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5592 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5593 0, /* allocation_size */
5594 0, /* private_flags */
5595 NULL, /* sd */
5596 NULL, /* ea_list */
5597 &new_fsp, /* result */
5598 NULL); /* pinfo */
5600 TALLOC_FREE(smb_fname_tmp);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 /* NB. We check for open_was_deferred in the caller. */
5604 return status;
5607 /* See RAW-SFILEINFO-END-OF-FILE */
5608 if (fail_after_createfile) {
5609 close_file(req, new_fsp,NORMAL_CLOSE);
5610 return NT_STATUS_INVALID_LEVEL;
5613 if (vfs_set_filelen(new_fsp, size) == -1) {
5614 status = map_nt_error_from_unix(errno);
5615 close_file(req, new_fsp,NORMAL_CLOSE);
5616 return status;
5619 trigger_write_time_update_immediate(new_fsp);
5620 close_file(req, new_fsp,NORMAL_CLOSE);
5621 return NT_STATUS_OK;
5624 /****************************************************************************
5625 Deal with SMB_INFO_SET_EA.
5626 ****************************************************************************/
5628 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5629 const char *pdata,
5630 int total_data,
5631 files_struct *fsp,
5632 const struct smb_filename *smb_fname)
5634 struct ea_list *ea_list = NULL;
5635 TALLOC_CTX *ctx = NULL;
5636 NTSTATUS status = NT_STATUS_OK;
5638 if (total_data < 10) {
5640 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5641 length. They seem to have no effect. Bug #3212. JRA */
5643 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5644 /* We're done. We only get EA info in this call. */
5645 return NT_STATUS_OK;
5648 return NT_STATUS_INVALID_PARAMETER;
5651 if (IVAL(pdata,0) > total_data) {
5652 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5653 IVAL(pdata,0), (unsigned int)total_data));
5654 return NT_STATUS_INVALID_PARAMETER;
5657 ctx = talloc_tos();
5658 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5659 if (!ea_list) {
5660 return NT_STATUS_INVALID_PARAMETER;
5662 status = set_ea(conn, fsp, smb_fname, ea_list);
5664 return status;
5667 /****************************************************************************
5668 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5669 ****************************************************************************/
5671 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5672 const char *pdata,
5673 int total_data,
5674 files_struct *fsp)
5676 struct ea_list *ea_list = NULL;
5677 NTSTATUS status;
5679 if (!fsp) {
5680 return NT_STATUS_INVALID_HANDLE;
5683 if (!lp_ea_support(SNUM(conn))) {
5684 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5685 "EA's not supported.\n",
5686 (unsigned int)total_data));
5687 return NT_STATUS_EAS_NOT_SUPPORTED;
5690 if (total_data < 10) {
5691 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5692 "too small.\n",
5693 (unsigned int)total_data));
5694 return NT_STATUS_INVALID_PARAMETER;
5697 ea_list = read_nttrans_ea_list(talloc_tos(),
5698 pdata,
5699 total_data);
5701 if (!ea_list) {
5702 return NT_STATUS_INVALID_PARAMETER;
5704 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5706 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5707 smb_fname_str_dbg(fsp->fsp_name),
5708 nt_errstr(status) ));
5710 return status;
5714 /****************************************************************************
5715 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5716 ****************************************************************************/
5718 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5719 const char *pdata,
5720 int total_data,
5721 files_struct *fsp,
5722 struct smb_filename *smb_fname)
5724 NTSTATUS status = NT_STATUS_OK;
5725 bool delete_on_close;
5726 uint32 dosmode = 0;
5728 if (total_data < 1) {
5729 return NT_STATUS_INVALID_PARAMETER;
5732 if (fsp == NULL) {
5733 return NT_STATUS_INVALID_HANDLE;
5736 delete_on_close = (CVAL(pdata,0) ? True : False);
5737 dosmode = dos_mode(conn, smb_fname);
5739 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5740 "delete_on_close = %u\n",
5741 smb_fname_str_dbg(smb_fname),
5742 (unsigned int)dosmode,
5743 (unsigned int)delete_on_close ));
5745 if (delete_on_close) {
5746 status = can_set_delete_on_close(fsp, dosmode);
5747 if (!NT_STATUS_IS_OK(status)) {
5748 return status;
5752 /* The set is across all open files on this dev/inode pair. */
5753 if (!set_delete_on_close(fsp, delete_on_close,
5754 &conn->server_info->utok)) {
5755 return NT_STATUS_ACCESS_DENIED;
5757 return NT_STATUS_OK;
5760 /****************************************************************************
5761 Deal with SMB_FILE_POSITION_INFORMATION.
5762 ****************************************************************************/
5764 static NTSTATUS smb_file_position_information(connection_struct *conn,
5765 const char *pdata,
5766 int total_data,
5767 files_struct *fsp)
5769 uint64_t position_information;
5771 if (total_data < 8) {
5772 return NT_STATUS_INVALID_PARAMETER;
5775 if (fsp == NULL) {
5776 /* Ignore on pathname based set. */
5777 return NT_STATUS_OK;
5780 position_information = (uint64_t)IVAL(pdata,0);
5781 #ifdef LARGE_SMB_OFF_T
5782 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5783 #else /* LARGE_SMB_OFF_T */
5784 if (IVAL(pdata,4) != 0) {
5785 /* more than 32 bits? */
5786 return NT_STATUS_INVALID_PARAMETER;
5788 #endif /* LARGE_SMB_OFF_T */
5790 DEBUG(10,("smb_file_position_information: Set file position "
5791 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5792 (double)position_information));
5793 fsp->fh->position_information = position_information;
5794 return NT_STATUS_OK;
5797 /****************************************************************************
5798 Deal with SMB_FILE_MODE_INFORMATION.
5799 ****************************************************************************/
5801 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5802 const char *pdata,
5803 int total_data)
5805 uint32 mode;
5807 if (total_data < 4) {
5808 return NT_STATUS_INVALID_PARAMETER;
5810 mode = IVAL(pdata,0);
5811 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5812 return NT_STATUS_INVALID_PARAMETER;
5814 return NT_STATUS_OK;
5817 /****************************************************************************
5818 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5819 ****************************************************************************/
5821 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5822 struct smb_request *req,
5823 const char *pdata,
5824 int total_data,
5825 const struct smb_filename *smb_fname)
5827 char *link_target = NULL;
5828 const char *newname = smb_fname->base_name;
5829 TALLOC_CTX *ctx = talloc_tos();
5831 /* Set a symbolic link. */
5832 /* Don't allow this if follow links is false. */
5834 if (total_data == 0) {
5835 return NT_STATUS_INVALID_PARAMETER;
5838 if (!lp_symlinks(SNUM(conn))) {
5839 return NT_STATUS_ACCESS_DENIED;
5842 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5843 total_data, STR_TERMINATE);
5845 if (!link_target) {
5846 return NT_STATUS_INVALID_PARAMETER;
5849 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5850 newname, link_target ));
5852 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5853 return map_nt_error_from_unix(errno);
5856 return NT_STATUS_OK;
5859 /****************************************************************************
5860 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5861 ****************************************************************************/
5863 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5864 struct smb_request *req,
5865 const char *pdata, int total_data,
5866 const struct smb_filename *smb_fname_new)
5868 char *oldname = NULL;
5869 struct smb_filename *smb_fname_old = NULL;
5870 TALLOC_CTX *ctx = talloc_tos();
5871 NTSTATUS status = NT_STATUS_OK;
5873 /* Set a hard link. */
5874 if (total_data == 0) {
5875 return NT_STATUS_INVALID_PARAMETER;
5878 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5879 total_data, STR_TERMINATE, &status);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 return status;
5884 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5885 smb_fname_str_dbg(smb_fname_new), oldname));
5887 status = filename_convert(ctx,
5888 conn,
5889 req->flags2 & FLAGS2_DFS_PATHNAMES,
5890 oldname,
5892 NULL,
5893 &smb_fname_old);
5894 if (!NT_STATUS_IS_OK(status)) {
5895 return status;
5898 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5901 /****************************************************************************
5902 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5903 ****************************************************************************/
5905 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5906 struct smb_request *req,
5907 const char *pdata,
5908 int total_data,
5909 files_struct *fsp,
5910 struct smb_filename *smb_fname_src)
5912 bool overwrite;
5913 uint32_t len;
5914 char *newname = NULL;
5915 struct smb_filename *smb_fname_dst = NULL;
5916 NTSTATUS status = NT_STATUS_OK;
5917 TALLOC_CTX *ctx = talloc_tos();
5919 if (!fsp) {
5920 return NT_STATUS_INVALID_HANDLE;
5923 if (total_data < 20) {
5924 return NT_STATUS_INVALID_PARAMETER;
5927 overwrite = (CVAL(pdata,0) ? True : False);
5928 len = IVAL(pdata,16);
5930 if (len > (total_data - 20) || (len == 0)) {
5931 return NT_STATUS_INVALID_PARAMETER;
5934 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5935 &pdata[20], len, STR_TERMINATE,
5936 &status);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 return status;
5941 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5942 newname));
5944 status = filename_convert(ctx,
5945 conn,
5946 req->flags2 & FLAGS2_DFS_PATHNAMES,
5947 newname,
5949 NULL,
5950 &smb_fname_dst);
5951 if (!NT_STATUS_IS_OK(status)) {
5952 return status;
5955 if (fsp && fsp->base_fsp) {
5956 /* newname must be a stream name. */
5957 if (newname[0] != ':') {
5958 return NT_STATUS_NOT_SUPPORTED;
5961 /* Create an smb_fname to call rename_internals_fsp() with. */
5962 status = create_synthetic_smb_fname(talloc_tos(),
5963 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5964 &smb_fname_dst);
5965 if (!NT_STATUS_IS_OK(status)) {
5966 goto out;
5970 * Set the original last component, since
5971 * rename_internals_fsp() requires it.
5973 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5974 newname);
5975 if (smb_fname_dst->original_lcomp == NULL) {
5976 status = NT_STATUS_NO_MEMORY;
5977 goto out;
5982 DEBUG(10,("smb2_file_rename_information: "
5983 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5984 fsp->fnum, fsp_str_dbg(fsp),
5985 smb_fname_str_dbg(smb_fname_dst)));
5986 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5987 overwrite);
5989 out:
5990 TALLOC_FREE(smb_fname_dst);
5991 return status;
5995 /****************************************************************************
5996 Deal with SMB_FILE_RENAME_INFORMATION.
5997 ****************************************************************************/
5999 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6000 struct smb_request *req,
6001 const char *pdata,
6002 int total_data,
6003 files_struct *fsp,
6004 struct smb_filename *smb_fname_src)
6006 bool overwrite;
6007 uint32 root_fid;
6008 uint32 len;
6009 char *newname = NULL;
6010 struct smb_filename *smb_fname_dst = NULL;
6011 bool dest_has_wcard = False;
6012 NTSTATUS status = NT_STATUS_OK;
6013 char *p;
6014 TALLOC_CTX *ctx = talloc_tos();
6016 if (total_data < 13) {
6017 return NT_STATUS_INVALID_PARAMETER;
6020 overwrite = (CVAL(pdata,0) ? True : False);
6021 root_fid = IVAL(pdata,4);
6022 len = IVAL(pdata,8);
6024 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6025 return NT_STATUS_INVALID_PARAMETER;
6028 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6029 len, 0, &status,
6030 &dest_has_wcard);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 return status;
6035 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6036 newname));
6038 status = resolve_dfspath_wcard(ctx, conn,
6039 req->flags2 & FLAGS2_DFS_PATHNAMES,
6040 newname,
6041 true,
6042 &newname,
6043 &dest_has_wcard);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 return status;
6048 /* Check the new name has no '/' characters. */
6049 if (strchr_m(newname, '/')) {
6050 return NT_STATUS_NOT_SUPPORTED;
6053 if (fsp && fsp->base_fsp) {
6054 /* newname must be a stream name. */
6055 if (newname[0] != ':') {
6056 return NT_STATUS_NOT_SUPPORTED;
6059 /* Create an smb_fname to call rename_internals_fsp() with. */
6060 status = create_synthetic_smb_fname(talloc_tos(),
6061 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6062 &smb_fname_dst);
6063 if (!NT_STATUS_IS_OK(status)) {
6064 goto out;
6068 * Set the original last component, since
6069 * rename_internals_fsp() requires it.
6071 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6072 newname);
6073 if (smb_fname_dst->original_lcomp == NULL) {
6074 status = NT_STATUS_NO_MEMORY;
6075 goto out;
6078 } else {
6080 * Build up an smb_fname_dst based on the filename passed in.
6081 * We basically just strip off the last component, and put on
6082 * the newname instead.
6084 char *base_name = NULL;
6086 /* newname must *not* be a stream name. */
6087 if (newname[0] == ':') {
6088 return NT_STATUS_NOT_SUPPORTED;
6092 * Strip off the last component (filename) of the path passed
6093 * in.
6095 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6096 if (!base_name) {
6097 return NT_STATUS_NO_MEMORY;
6099 p = strrchr_m(base_name, '/');
6100 if (p) {
6101 p[1] = '\0';
6102 } else {
6103 base_name = talloc_strdup(ctx, "./");
6104 if (!base_name) {
6105 return NT_STATUS_NO_MEMORY;
6108 /* Append the new name. */
6109 base_name = talloc_asprintf_append(base_name,
6110 "%s",
6111 newname);
6112 if (!base_name) {
6113 return NT_STATUS_NO_MEMORY;
6116 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6117 (UCF_SAVE_LCOMP |
6118 (dest_has_wcard ?
6119 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6120 0)));
6122 /* If an error we expect this to be
6123 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6125 if (!NT_STATUS_IS_OK(status)) {
6126 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6127 status)) {
6128 goto out;
6130 /* Create an smb_fname to call rename_internals_fsp() */
6131 status = create_synthetic_smb_fname(ctx,
6132 base_name, NULL,
6133 NULL,
6134 &smb_fname_dst);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 goto out;
6141 if (fsp) {
6142 DEBUG(10,("smb_file_rename_information: "
6143 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6144 fsp->fnum, fsp_str_dbg(fsp),
6145 smb_fname_str_dbg(smb_fname_dst)));
6146 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6147 overwrite);
6148 } else {
6149 DEBUG(10,("smb_file_rename_information: "
6150 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6151 smb_fname_str_dbg(smb_fname_src),
6152 smb_fname_str_dbg(smb_fname_dst)));
6153 status = rename_internals(ctx, conn, req, smb_fname_src,
6154 smb_fname_dst, 0, overwrite, false,
6155 dest_has_wcard,
6156 FILE_WRITE_ATTRIBUTES);
6158 out:
6159 TALLOC_FREE(smb_fname_dst);
6160 return status;
6163 /****************************************************************************
6164 Deal with SMB_SET_POSIX_ACL.
6165 ****************************************************************************/
6167 #if defined(HAVE_POSIX_ACLS)
6168 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6169 const char *pdata,
6170 int total_data,
6171 files_struct *fsp,
6172 const struct smb_filename *smb_fname)
6174 uint16 posix_acl_version;
6175 uint16 num_file_acls;
6176 uint16 num_def_acls;
6177 bool valid_file_acls = True;
6178 bool valid_def_acls = True;
6180 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6181 return NT_STATUS_INVALID_PARAMETER;
6183 posix_acl_version = SVAL(pdata,0);
6184 num_file_acls = SVAL(pdata,2);
6185 num_def_acls = SVAL(pdata,4);
6187 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6188 valid_file_acls = False;
6189 num_file_acls = 0;
6192 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6193 valid_def_acls = False;
6194 num_def_acls = 0;
6197 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6198 return NT_STATUS_INVALID_PARAMETER;
6201 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6202 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6203 return NT_STATUS_INVALID_PARAMETER;
6206 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6207 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6208 (unsigned int)num_file_acls,
6209 (unsigned int)num_def_acls));
6211 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6212 smb_fname->base_name, num_file_acls,
6213 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6214 return map_nt_error_from_unix(errno);
6217 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6218 smb_fname->base_name, &smb_fname->st, num_def_acls,
6219 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6220 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6221 return map_nt_error_from_unix(errno);
6223 return NT_STATUS_OK;
6225 #endif
6227 /****************************************************************************
6228 Deal with SMB_SET_POSIX_LOCK.
6229 ****************************************************************************/
6231 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6232 struct smb_request *req,
6233 const char *pdata,
6234 int total_data,
6235 files_struct *fsp)
6237 uint64_t count;
6238 uint64_t offset;
6239 uint32 lock_pid;
6240 bool blocking_lock = False;
6241 enum brl_type lock_type;
6243 NTSTATUS status = NT_STATUS_OK;
6245 if (fsp == NULL || fsp->fh->fd == -1) {
6246 return NT_STATUS_INVALID_HANDLE;
6249 if (total_data != POSIX_LOCK_DATA_SIZE) {
6250 return NT_STATUS_INVALID_PARAMETER;
6253 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6254 case POSIX_LOCK_TYPE_READ:
6255 lock_type = READ_LOCK;
6256 break;
6257 case POSIX_LOCK_TYPE_WRITE:
6258 /* Return the right POSIX-mappable error code for files opened read-only. */
6259 if (!fsp->can_write) {
6260 return NT_STATUS_INVALID_HANDLE;
6262 lock_type = WRITE_LOCK;
6263 break;
6264 case POSIX_LOCK_TYPE_UNLOCK:
6265 lock_type = UNLOCK_LOCK;
6266 break;
6267 default:
6268 return NT_STATUS_INVALID_PARAMETER;
6271 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6272 blocking_lock = False;
6273 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6274 blocking_lock = True;
6275 } else {
6276 return NT_STATUS_INVALID_PARAMETER;
6279 if (!lp_blocking_locks(SNUM(conn))) {
6280 blocking_lock = False;
6283 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6284 #if defined(HAVE_LONGLONG)
6285 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6286 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6287 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6288 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6289 #else /* HAVE_LONGLONG */
6290 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6291 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6292 #endif /* HAVE_LONGLONG */
6294 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6295 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6296 fsp_str_dbg(fsp),
6297 (unsigned int)lock_type,
6298 (unsigned int)lock_pid,
6299 (double)count,
6300 (double)offset ));
6302 if (lock_type == UNLOCK_LOCK) {
6303 status = do_unlock(smbd_messaging_context(),
6304 fsp,
6305 lock_pid,
6306 count,
6307 offset,
6308 POSIX_LOCK);
6309 } else {
6310 uint32 block_smbpid;
6312 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6313 fsp,
6314 lock_pid,
6315 count,
6316 offset,
6317 lock_type,
6318 POSIX_LOCK,
6319 blocking_lock,
6320 &status,
6321 &block_smbpid,
6322 NULL);
6324 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6326 * A blocking lock was requested. Package up
6327 * this smb into a queued request and push it
6328 * onto the blocking lock queue.
6330 if(push_blocking_lock_request(br_lck,
6331 req,
6332 fsp,
6333 -1, /* infinite timeout. */
6335 lock_pid,
6336 lock_type,
6337 POSIX_LOCK,
6338 offset,
6339 count,
6340 block_smbpid)) {
6341 TALLOC_FREE(br_lck);
6342 return status;
6345 TALLOC_FREE(br_lck);
6348 return status;
6351 /****************************************************************************
6352 Deal with SMB_SET_FILE_BASIC_INFO.
6353 ****************************************************************************/
6355 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6356 const char *pdata,
6357 int total_data,
6358 files_struct *fsp,
6359 const struct smb_filename *smb_fname)
6361 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6362 struct smb_file_time ft;
6363 uint32 dosmode = 0;
6364 NTSTATUS status = NT_STATUS_OK;
6366 ZERO_STRUCT(ft);
6368 if (total_data < 36) {
6369 return NT_STATUS_INVALID_PARAMETER;
6372 /* Set the attributes */
6373 dosmode = IVAL(pdata,32);
6374 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6375 if (!NT_STATUS_IS_OK(status)) {
6376 return status;
6379 /* create time */
6380 ft.create_time = interpret_long_date(pdata);
6382 /* access time */
6383 ft.atime = interpret_long_date(pdata+8);
6385 /* write time. */
6386 ft.mtime = interpret_long_date(pdata+16);
6388 /* change time. */
6389 ft.ctime = interpret_long_date(pdata+24);
6391 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6392 smb_fname_str_dbg(smb_fname)));
6394 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6395 true);
6398 /****************************************************************************
6399 Deal with SMB_INFO_STANDARD.
6400 ****************************************************************************/
6402 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6403 const char *pdata,
6404 int total_data,
6405 files_struct *fsp,
6406 const struct smb_filename *smb_fname)
6408 struct smb_file_time ft;
6410 ZERO_STRUCT(ft);
6412 if (total_data < 12) {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 /* create time */
6417 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6418 /* access time */
6419 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6420 /* write time */
6421 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6423 DEBUG(10,("smb_set_info_standard: file %s\n",
6424 smb_fname_str_dbg(smb_fname)));
6426 return smb_set_file_time(conn,
6427 fsp,
6428 smb_fname,
6429 &ft,
6430 true);
6433 /****************************************************************************
6434 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6435 ****************************************************************************/
6437 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6438 struct smb_request *req,
6439 const char *pdata,
6440 int total_data,
6441 files_struct *fsp,
6442 struct smb_filename *smb_fname)
6444 uint64_t allocation_size = 0;
6445 NTSTATUS status = NT_STATUS_OK;
6446 files_struct *new_fsp = NULL;
6448 if (!VALID_STAT(smb_fname->st)) {
6449 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6452 if (total_data < 8) {
6453 return NT_STATUS_INVALID_PARAMETER;
6456 allocation_size = (uint64_t)IVAL(pdata,0);
6457 #ifdef LARGE_SMB_OFF_T
6458 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6459 #else /* LARGE_SMB_OFF_T */
6460 if (IVAL(pdata,4) != 0) {
6461 /* more than 32 bits? */
6462 return NT_STATUS_INVALID_PARAMETER;
6464 #endif /* LARGE_SMB_OFF_T */
6466 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6467 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6468 (double)allocation_size));
6470 if (allocation_size) {
6471 allocation_size = smb_roundup(conn, allocation_size);
6474 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6475 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6476 (double)allocation_size));
6478 if (fsp && fsp->fh->fd != -1) {
6479 /* Open file handle. */
6480 /* Only change if needed. */
6481 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6482 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6483 return map_nt_error_from_unix(errno);
6486 /* But always update the time. */
6488 * This is equivalent to a write. Ensure it's seen immediately
6489 * if there are no pending writes.
6491 trigger_write_time_update_immediate(fsp);
6492 return NT_STATUS_OK;
6495 /* Pathname or stat or directory file. */
6496 status = SMB_VFS_CREATE_FILE(
6497 conn, /* conn */
6498 req, /* req */
6499 0, /* root_dir_fid */
6500 smb_fname, /* fname */
6501 FILE_WRITE_DATA, /* access_mask */
6502 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6503 FILE_SHARE_DELETE),
6504 FILE_OPEN, /* create_disposition*/
6505 0, /* create_options */
6506 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6507 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6508 0, /* allocation_size */
6509 0, /* private_flags */
6510 NULL, /* sd */
6511 NULL, /* ea_list */
6512 &new_fsp, /* result */
6513 NULL); /* pinfo */
6515 if (!NT_STATUS_IS_OK(status)) {
6516 /* NB. We check for open_was_deferred in the caller. */
6517 return status;
6520 /* Only change if needed. */
6521 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6522 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6523 status = map_nt_error_from_unix(errno);
6524 close_file(req, new_fsp, NORMAL_CLOSE);
6525 return status;
6529 /* Changing the allocation size should set the last mod time. */
6531 * This is equivalent to a write. Ensure it's seen immediately
6532 * if there are no pending writes.
6534 trigger_write_time_update_immediate(new_fsp);
6536 close_file(req, new_fsp, NORMAL_CLOSE);
6537 return NT_STATUS_OK;
6540 /****************************************************************************
6541 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6542 ****************************************************************************/
6544 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6545 struct smb_request *req,
6546 const char *pdata,
6547 int total_data,
6548 files_struct *fsp,
6549 const struct smb_filename *smb_fname,
6550 bool fail_after_createfile)
6552 SMB_OFF_T size;
6554 if (total_data < 8) {
6555 return NT_STATUS_INVALID_PARAMETER;
6558 size = IVAL(pdata,0);
6559 #ifdef LARGE_SMB_OFF_T
6560 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6561 #else /* LARGE_SMB_OFF_T */
6562 if (IVAL(pdata,4) != 0) {
6563 /* more than 32 bits? */
6564 return NT_STATUS_INVALID_PARAMETER;
6566 #endif /* LARGE_SMB_OFF_T */
6567 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6568 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6569 (double)size));
6571 return smb_set_file_size(conn, req,
6572 fsp,
6573 smb_fname,
6574 &smb_fname->st,
6575 size,
6576 fail_after_createfile);
6579 /****************************************************************************
6580 Allow a UNIX info mknod.
6581 ****************************************************************************/
6583 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6584 const char *pdata,
6585 int total_data,
6586 const struct smb_filename *smb_fname)
6588 uint32 file_type = IVAL(pdata,56);
6589 #if defined(HAVE_MAKEDEV)
6590 uint32 dev_major = IVAL(pdata,60);
6591 uint32 dev_minor = IVAL(pdata,68);
6592 #endif
6593 SMB_DEV_T dev = (SMB_DEV_T)0;
6594 uint32 raw_unixmode = IVAL(pdata,84);
6595 NTSTATUS status;
6596 mode_t unixmode;
6598 if (total_data < 100) {
6599 return NT_STATUS_INVALID_PARAMETER;
6602 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6603 PERM_NEW_FILE, &unixmode);
6604 if (!NT_STATUS_IS_OK(status)) {
6605 return status;
6608 #if defined(HAVE_MAKEDEV)
6609 dev = makedev(dev_major, dev_minor);
6610 #endif
6612 switch (file_type) {
6613 #if defined(S_IFIFO)
6614 case UNIX_TYPE_FIFO:
6615 unixmode |= S_IFIFO;
6616 break;
6617 #endif
6618 #if defined(S_IFSOCK)
6619 case UNIX_TYPE_SOCKET:
6620 unixmode |= S_IFSOCK;
6621 break;
6622 #endif
6623 #if defined(S_IFCHR)
6624 case UNIX_TYPE_CHARDEV:
6625 unixmode |= S_IFCHR;
6626 break;
6627 #endif
6628 #if defined(S_IFBLK)
6629 case UNIX_TYPE_BLKDEV:
6630 unixmode |= S_IFBLK;
6631 break;
6632 #endif
6633 default:
6634 return NT_STATUS_INVALID_PARAMETER;
6637 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6638 "%.0f mode 0%o for file %s\n", (double)dev,
6639 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6641 /* Ok - do the mknod. */
6642 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6643 return map_nt_error_from_unix(errno);
6646 /* If any of the other "set" calls fail we
6647 * don't want to end up with a half-constructed mknod.
6650 if (lp_inherit_perms(SNUM(conn))) {
6651 char *parent;
6652 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6653 &parent, NULL)) {
6654 return NT_STATUS_NO_MEMORY;
6656 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6657 unixmode);
6658 TALLOC_FREE(parent);
6661 return NT_STATUS_OK;
6664 /****************************************************************************
6665 Deal with SMB_SET_FILE_UNIX_BASIC.
6666 ****************************************************************************/
6668 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6669 struct smb_request *req,
6670 const char *pdata,
6671 int total_data,
6672 files_struct *fsp,
6673 const struct smb_filename *smb_fname)
6675 struct smb_file_time ft;
6676 uint32 raw_unixmode;
6677 mode_t unixmode;
6678 SMB_OFF_T size = 0;
6679 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6680 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6681 NTSTATUS status = NT_STATUS_OK;
6682 bool delete_on_fail = False;
6683 enum perm_type ptype;
6684 files_struct *all_fsps = NULL;
6685 bool modify_mtime = true;
6686 struct file_id id;
6687 SMB_STRUCT_STAT sbuf;
6689 ZERO_STRUCT(ft);
6691 if (total_data < 100) {
6692 return NT_STATUS_INVALID_PARAMETER;
6695 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6696 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6697 size=IVAL(pdata,0); /* first 8 Bytes are size */
6698 #ifdef LARGE_SMB_OFF_T
6699 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6700 #else /* LARGE_SMB_OFF_T */
6701 if (IVAL(pdata,4) != 0) {
6702 /* more than 32 bits? */
6703 return NT_STATUS_INVALID_PARAMETER;
6705 #endif /* LARGE_SMB_OFF_T */
6708 ft.atime = interpret_long_date(pdata+24); /* access_time */
6709 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6710 set_owner = (uid_t)IVAL(pdata,40);
6711 set_grp = (gid_t)IVAL(pdata,48);
6712 raw_unixmode = IVAL(pdata,84);
6714 if (VALID_STAT(smb_fname->st)) {
6715 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6716 ptype = PERM_EXISTING_DIR;
6717 } else {
6718 ptype = PERM_EXISTING_FILE;
6720 } else {
6721 ptype = PERM_NEW_FILE;
6724 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6725 ptype, &unixmode);
6726 if (!NT_STATUS_IS_OK(status)) {
6727 return status;
6730 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6731 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6732 smb_fname_str_dbg(smb_fname), (double)size,
6733 (unsigned int)set_owner, (unsigned int)set_grp,
6734 (int)raw_unixmode));
6736 sbuf = smb_fname->st;
6738 if (!VALID_STAT(sbuf)) {
6739 struct smb_filename *smb_fname_tmp = NULL;
6741 * The only valid use of this is to create character and block
6742 * devices, and named pipes. This is deprecated (IMHO) and
6743 * a new info level should be used for mknod. JRA.
6746 status = smb_unix_mknod(conn,
6747 pdata,
6748 total_data,
6749 smb_fname);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 return status;
6754 status = copy_smb_filename(talloc_tos(), smb_fname,
6755 &smb_fname_tmp);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 return status;
6760 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6761 status = map_nt_error_from_unix(errno);
6762 TALLOC_FREE(smb_fname_tmp);
6763 SMB_VFS_UNLINK(conn, smb_fname);
6764 return status;
6767 sbuf = smb_fname_tmp->st;
6768 TALLOC_FREE(smb_fname_tmp);
6770 /* Ensure we don't try and change anything else. */
6771 raw_unixmode = SMB_MODE_NO_CHANGE;
6772 size = get_file_size_stat(&sbuf);
6773 ft.atime = sbuf.st_ex_atime;
6774 ft.mtime = sbuf.st_ex_mtime;
6776 * We continue here as we might want to change the
6777 * owner uid/gid.
6779 delete_on_fail = True;
6782 #if 1
6783 /* Horrible backwards compatibility hack as an old server bug
6784 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6785 * */
6787 if (!size) {
6788 size = get_file_size_stat(&sbuf);
6790 #endif
6793 * Deal with the UNIX specific mode set.
6796 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6797 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6798 "setting mode 0%o for file %s\n",
6799 (unsigned int)unixmode,
6800 smb_fname_str_dbg(smb_fname)));
6801 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6802 return map_nt_error_from_unix(errno);
6807 * Deal with the UNIX specific uid set.
6810 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6811 (sbuf.st_ex_uid != set_owner)) {
6812 int ret;
6814 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6815 "changing owner %u for path %s\n",
6816 (unsigned int)set_owner,
6817 smb_fname_str_dbg(smb_fname)));
6819 if (S_ISLNK(sbuf.st_ex_mode)) {
6820 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6821 set_owner, (gid_t)-1);
6822 } else {
6823 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6824 set_owner, (gid_t)-1);
6827 if (ret != 0) {
6828 status = map_nt_error_from_unix(errno);
6829 if (delete_on_fail) {
6830 SMB_VFS_UNLINK(conn, smb_fname);
6832 return status;
6837 * Deal with the UNIX specific gid set.
6840 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6841 (sbuf.st_ex_gid != set_grp)) {
6842 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6843 "changing group %u for file %s\n",
6844 (unsigned int)set_owner,
6845 smb_fname_str_dbg(smb_fname)));
6846 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6847 set_grp) != 0) {
6848 status = map_nt_error_from_unix(errno);
6849 if (delete_on_fail) {
6850 SMB_VFS_UNLINK(conn, smb_fname);
6852 return status;
6856 /* Deal with any size changes. */
6858 status = smb_set_file_size(conn, req,
6859 fsp,
6860 smb_fname,
6861 &sbuf,
6862 size,
6863 false);
6864 if (!NT_STATUS_IS_OK(status)) {
6865 return status;
6868 /* Deal with any time changes. */
6869 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6870 /* No change, don't cancel anything. */
6871 return status;
6874 id = vfs_file_id_from_sbuf(conn, &sbuf);
6875 for(all_fsps = file_find_di_first(id); all_fsps;
6876 all_fsps = file_find_di_next(all_fsps)) {
6878 * We're setting the time explicitly for UNIX.
6879 * Cancel any pending changes over all handles.
6881 all_fsps->update_write_time_on_close = false;
6882 TALLOC_FREE(all_fsps->update_write_time_event);
6886 * Override the "setting_write_time"
6887 * parameter here as it almost does what
6888 * we need. Just remember if we modified
6889 * mtime and send the notify ourselves.
6891 if (null_timespec(ft.mtime)) {
6892 modify_mtime = false;
6895 status = smb_set_file_time(conn,
6896 fsp,
6897 smb_fname,
6898 &ft,
6899 false);
6900 if (modify_mtime) {
6901 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6902 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6904 return status;
6907 /****************************************************************************
6908 Deal with SMB_SET_FILE_UNIX_INFO2.
6909 ****************************************************************************/
6911 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6912 struct smb_request *req,
6913 const char *pdata,
6914 int total_data,
6915 files_struct *fsp,
6916 const struct smb_filename *smb_fname)
6918 NTSTATUS status;
6919 uint32 smb_fflags;
6920 uint32 smb_fmask;
6922 if (total_data < 116) {
6923 return NT_STATUS_INVALID_PARAMETER;
6926 /* Start by setting all the fields that are common between UNIX_BASIC
6927 * and UNIX_INFO2.
6929 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6930 fsp, smb_fname);
6931 if (!NT_STATUS_IS_OK(status)) {
6932 return status;
6935 smb_fflags = IVAL(pdata, 108);
6936 smb_fmask = IVAL(pdata, 112);
6938 /* NB: We should only attempt to alter the file flags if the client
6939 * sends a non-zero mask.
6941 if (smb_fmask != 0) {
6942 int stat_fflags = 0;
6944 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6945 smb_fmask, &stat_fflags)) {
6946 /* Client asked to alter a flag we don't understand. */
6947 return NT_STATUS_INVALID_PARAMETER;
6950 if (fsp && fsp->fh->fd != -1) {
6951 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6952 return NT_STATUS_NOT_SUPPORTED;
6953 } else {
6954 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6955 stat_fflags) != 0) {
6956 return map_nt_error_from_unix(errno);
6961 /* XXX: need to add support for changing the create_time here. You
6962 * can do this for paths on Darwin with setattrlist(2). The right way
6963 * to hook this up is probably by extending the VFS utimes interface.
6966 return NT_STATUS_OK;
6969 /****************************************************************************
6970 Create a directory with POSIX semantics.
6971 ****************************************************************************/
6973 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6974 struct smb_request *req,
6975 char **ppdata,
6976 int total_data,
6977 struct smb_filename *smb_fname,
6978 int *pdata_return_size)
6980 NTSTATUS status = NT_STATUS_OK;
6981 uint32 raw_unixmode = 0;
6982 uint32 mod_unixmode = 0;
6983 mode_t unixmode = (mode_t)0;
6984 files_struct *fsp = NULL;
6985 uint16 info_level_return = 0;
6986 int info;
6987 char *pdata = *ppdata;
6989 if (total_data < 18) {
6990 return NT_STATUS_INVALID_PARAMETER;
6993 raw_unixmode = IVAL(pdata,8);
6994 /* Next 4 bytes are not yet defined. */
6996 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6997 PERM_NEW_DIR, &unixmode);
6998 if (!NT_STATUS_IS_OK(status)) {
6999 return status;
7002 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7004 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7005 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7007 status = SMB_VFS_CREATE_FILE(
7008 conn, /* conn */
7009 req, /* req */
7010 0, /* root_dir_fid */
7011 smb_fname, /* fname */
7012 FILE_READ_ATTRIBUTES, /* access_mask */
7013 FILE_SHARE_NONE, /* share_access */
7014 FILE_CREATE, /* create_disposition*/
7015 FILE_DIRECTORY_FILE, /* create_options */
7016 mod_unixmode, /* file_attributes */
7017 0, /* oplock_request */
7018 0, /* allocation_size */
7019 0, /* private_flags */
7020 NULL, /* sd */
7021 NULL, /* ea_list */
7022 &fsp, /* result */
7023 &info); /* pinfo */
7025 if (NT_STATUS_IS_OK(status)) {
7026 close_file(req, fsp, NORMAL_CLOSE);
7029 info_level_return = SVAL(pdata,16);
7031 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7032 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7033 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7034 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7035 } else {
7036 *pdata_return_size = 12;
7039 /* Realloc the data size */
7040 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7041 if (*ppdata == NULL) {
7042 *pdata_return_size = 0;
7043 return NT_STATUS_NO_MEMORY;
7045 pdata = *ppdata;
7047 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7048 SSVAL(pdata,2,0); /* No fnum. */
7049 SIVAL(pdata,4,info); /* Was directory created. */
7051 switch (info_level_return) {
7052 case SMB_QUERY_FILE_UNIX_BASIC:
7053 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7054 SSVAL(pdata,10,0); /* Padding. */
7055 store_file_unix_basic(conn, pdata + 12, fsp,
7056 &smb_fname->st);
7057 break;
7058 case SMB_QUERY_FILE_UNIX_INFO2:
7059 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7060 SSVAL(pdata,10,0); /* Padding. */
7061 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7062 &smb_fname->st);
7063 break;
7064 default:
7065 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7066 SSVAL(pdata,10,0); /* Padding. */
7067 break;
7070 return status;
7073 /****************************************************************************
7074 Open/Create a file with POSIX semantics.
7075 ****************************************************************************/
7077 static NTSTATUS smb_posix_open(connection_struct *conn,
7078 struct smb_request *req,
7079 char **ppdata,
7080 int total_data,
7081 struct smb_filename *smb_fname,
7082 int *pdata_return_size)
7084 bool extended_oplock_granted = False;
7085 char *pdata = *ppdata;
7086 uint32 flags = 0;
7087 uint32 wire_open_mode = 0;
7088 uint32 raw_unixmode = 0;
7089 uint32 mod_unixmode = 0;
7090 uint32 create_disp = 0;
7091 uint32 access_mask = 0;
7092 uint32 create_options = 0;
7093 NTSTATUS status = NT_STATUS_OK;
7094 mode_t unixmode = (mode_t)0;
7095 files_struct *fsp = NULL;
7096 int oplock_request = 0;
7097 int info = 0;
7098 uint16 info_level_return = 0;
7100 if (total_data < 18) {
7101 return NT_STATUS_INVALID_PARAMETER;
7104 flags = IVAL(pdata,0);
7105 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7106 if (oplock_request) {
7107 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7110 wire_open_mode = IVAL(pdata,4);
7112 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7113 return smb_posix_mkdir(conn, req,
7114 ppdata,
7115 total_data,
7116 smb_fname,
7117 pdata_return_size);
7120 switch (wire_open_mode & SMB_ACCMODE) {
7121 case SMB_O_RDONLY:
7122 access_mask = FILE_READ_DATA;
7123 break;
7124 case SMB_O_WRONLY:
7125 access_mask = FILE_WRITE_DATA;
7126 break;
7127 case SMB_O_RDWR:
7128 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7129 break;
7130 default:
7131 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7132 (unsigned int)wire_open_mode ));
7133 return NT_STATUS_INVALID_PARAMETER;
7136 wire_open_mode &= ~SMB_ACCMODE;
7138 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7139 create_disp = FILE_CREATE;
7140 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7141 create_disp = FILE_OVERWRITE_IF;
7142 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7143 create_disp = FILE_OPEN_IF;
7144 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7145 create_disp = FILE_OPEN;
7146 } else {
7147 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7148 (unsigned int)wire_open_mode ));
7149 return NT_STATUS_INVALID_PARAMETER;
7152 raw_unixmode = IVAL(pdata,8);
7153 /* Next 4 bytes are not yet defined. */
7155 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7156 (VALID_STAT(smb_fname->st) ?
7157 PERM_EXISTING_FILE : PERM_NEW_FILE),
7158 &unixmode);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 return status;
7164 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7166 if (wire_open_mode & SMB_O_SYNC) {
7167 create_options |= FILE_WRITE_THROUGH;
7169 if (wire_open_mode & SMB_O_APPEND) {
7170 access_mask |= FILE_APPEND_DATA;
7172 if (wire_open_mode & SMB_O_DIRECT) {
7173 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7176 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7177 smb_fname_str_dbg(smb_fname),
7178 (unsigned int)wire_open_mode,
7179 (unsigned int)unixmode ));
7181 status = SMB_VFS_CREATE_FILE(
7182 conn, /* conn */
7183 req, /* req */
7184 0, /* root_dir_fid */
7185 smb_fname, /* fname */
7186 access_mask, /* access_mask */
7187 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7188 FILE_SHARE_DELETE),
7189 create_disp, /* create_disposition*/
7190 FILE_NON_DIRECTORY_FILE, /* create_options */
7191 mod_unixmode, /* file_attributes */
7192 oplock_request, /* oplock_request */
7193 0, /* allocation_size */
7194 0, /* private_flags */
7195 NULL, /* sd */
7196 NULL, /* ea_list */
7197 &fsp, /* result */
7198 &info); /* pinfo */
7200 if (!NT_STATUS_IS_OK(status)) {
7201 return status;
7204 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7205 extended_oplock_granted = True;
7208 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7209 extended_oplock_granted = True;
7212 info_level_return = SVAL(pdata,16);
7214 /* Allocate the correct return size. */
7216 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7217 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7218 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7219 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7220 } else {
7221 *pdata_return_size = 12;
7224 /* Realloc the data size */
7225 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7226 if (*ppdata == NULL) {
7227 close_file(req, fsp, ERROR_CLOSE);
7228 *pdata_return_size = 0;
7229 return NT_STATUS_NO_MEMORY;
7231 pdata = *ppdata;
7233 if (extended_oplock_granted) {
7234 if (flags & REQUEST_BATCH_OPLOCK) {
7235 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7236 } else {
7237 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7239 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7240 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7241 } else {
7242 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7245 SSVAL(pdata,2,fsp->fnum);
7246 SIVAL(pdata,4,info); /* Was file created etc. */
7248 switch (info_level_return) {
7249 case SMB_QUERY_FILE_UNIX_BASIC:
7250 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7251 SSVAL(pdata,10,0); /* padding. */
7252 store_file_unix_basic(conn, pdata + 12, fsp,
7253 &smb_fname->st);
7254 break;
7255 case SMB_QUERY_FILE_UNIX_INFO2:
7256 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7257 SSVAL(pdata,10,0); /* padding. */
7258 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7259 &smb_fname->st);
7260 break;
7261 default:
7262 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7263 SSVAL(pdata,10,0); /* padding. */
7264 break;
7266 return NT_STATUS_OK;
7269 /****************************************************************************
7270 Delete a file with POSIX semantics.
7271 ****************************************************************************/
7273 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7274 struct smb_request *req,
7275 const char *pdata,
7276 int total_data,
7277 struct smb_filename *smb_fname)
7279 NTSTATUS status = NT_STATUS_OK;
7280 files_struct *fsp = NULL;
7281 uint16 flags = 0;
7282 char del = 1;
7283 int info = 0;
7284 int create_options = 0;
7285 int i;
7286 struct share_mode_lock *lck = NULL;
7288 if (total_data < 2) {
7289 return NT_STATUS_INVALID_PARAMETER;
7292 flags = SVAL(pdata,0);
7294 if (!VALID_STAT(smb_fname->st)) {
7295 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7298 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7299 !VALID_STAT_OF_DIR(smb_fname->st)) {
7300 return NT_STATUS_NOT_A_DIRECTORY;
7303 DEBUG(10,("smb_posix_unlink: %s %s\n",
7304 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7305 smb_fname_str_dbg(smb_fname)));
7307 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7308 create_options |= FILE_DIRECTORY_FILE;
7311 status = SMB_VFS_CREATE_FILE(
7312 conn, /* conn */
7313 req, /* req */
7314 0, /* root_dir_fid */
7315 smb_fname, /* fname */
7316 DELETE_ACCESS, /* access_mask */
7317 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7318 FILE_SHARE_DELETE),
7319 FILE_OPEN, /* create_disposition*/
7320 create_options, /* create_options */
7321 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7322 0, /* oplock_request */
7323 0, /* allocation_size */
7324 0, /* private_flags */
7325 NULL, /* sd */
7326 NULL, /* ea_list */
7327 &fsp, /* result */
7328 &info); /* pinfo */
7330 if (!NT_STATUS_IS_OK(status)) {
7331 return status;
7335 * Don't lie to client. If we can't really delete due to
7336 * non-POSIX opens return SHARING_VIOLATION.
7339 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7340 NULL);
7341 if (lck == NULL) {
7342 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7343 "lock for file %s\n", fsp_str_dbg(fsp)));
7344 close_file(req, fsp, NORMAL_CLOSE);
7345 return NT_STATUS_INVALID_PARAMETER;
7349 * See if others still have the file open. If this is the case, then
7350 * don't delete. If all opens are POSIX delete we can set the delete
7351 * on close disposition.
7353 for (i=0; i<lck->num_share_modes; i++) {
7354 struct share_mode_entry *e = &lck->share_modes[i];
7355 if (is_valid_share_mode_entry(e)) {
7356 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7357 continue;
7359 /* Fail with sharing violation. */
7360 close_file(req, fsp, NORMAL_CLOSE);
7361 TALLOC_FREE(lck);
7362 return NT_STATUS_SHARING_VIOLATION;
7367 * Set the delete on close.
7369 status = smb_set_file_disposition_info(conn,
7370 &del,
7372 fsp,
7373 smb_fname);
7375 if (!NT_STATUS_IS_OK(status)) {
7376 close_file(req, fsp, NORMAL_CLOSE);
7377 TALLOC_FREE(lck);
7378 return status;
7380 TALLOC_FREE(lck);
7381 return close_file(req, fsp, NORMAL_CLOSE);
7384 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7385 struct smb_request *req,
7386 TALLOC_CTX *mem_ctx,
7387 uint16_t info_level,
7388 files_struct *fsp,
7389 struct smb_filename *smb_fname,
7390 char **ppdata, int total_data,
7391 int *ret_data_size)
7393 char *pdata = *ppdata;
7394 NTSTATUS status = NT_STATUS_OK;
7395 int data_return_size = 0;
7397 *ret_data_size = 0;
7399 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7400 return NT_STATUS_INVALID_LEVEL;
7403 if (!CAN_WRITE(conn)) {
7404 /* Allow POSIX opens. The open path will deny
7405 * any non-readonly opens. */
7406 if (info_level != SMB_POSIX_PATH_OPEN) {
7407 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7411 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7412 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7413 fsp ? fsp->fnum : -1, info_level, total_data));
7415 switch (info_level) {
7417 case SMB_INFO_STANDARD:
7419 status = smb_set_info_standard(conn,
7420 pdata,
7421 total_data,
7422 fsp,
7423 smb_fname);
7424 break;
7427 case SMB_INFO_SET_EA:
7429 status = smb_info_set_ea(conn,
7430 pdata,
7431 total_data,
7432 fsp,
7433 smb_fname);
7434 break;
7437 case SMB_SET_FILE_BASIC_INFO:
7438 case SMB_FILE_BASIC_INFORMATION:
7440 status = smb_set_file_basic_info(conn,
7441 pdata,
7442 total_data,
7443 fsp,
7444 smb_fname);
7445 break;
7448 case SMB_FILE_ALLOCATION_INFORMATION:
7449 case SMB_SET_FILE_ALLOCATION_INFO:
7451 status = smb_set_file_allocation_info(conn, req,
7452 pdata,
7453 total_data,
7454 fsp,
7455 smb_fname);
7456 break;
7459 case SMB_FILE_END_OF_FILE_INFORMATION:
7460 case SMB_SET_FILE_END_OF_FILE_INFO:
7463 * XP/Win7 both fail after the createfile with
7464 * SMB_SET_FILE_END_OF_FILE_INFO but not
7465 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7466 * The level is known here, so pass it down
7467 * appropriately.
7469 bool should_fail =
7470 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7472 status = smb_set_file_end_of_file_info(conn, req,
7473 pdata,
7474 total_data,
7475 fsp,
7476 smb_fname,
7477 should_fail);
7478 break;
7481 case SMB_FILE_DISPOSITION_INFORMATION:
7482 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7484 #if 0
7485 /* JRA - We used to just ignore this on a path ?
7486 * Shouldn't this be invalid level on a pathname
7487 * based call ?
7489 if (tran_call != TRANSACT2_SETFILEINFO) {
7490 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7492 #endif
7493 status = smb_set_file_disposition_info(conn,
7494 pdata,
7495 total_data,
7496 fsp,
7497 smb_fname);
7498 break;
7501 case SMB_FILE_POSITION_INFORMATION:
7503 status = smb_file_position_information(conn,
7504 pdata,
7505 total_data,
7506 fsp);
7507 break;
7510 case SMB_FILE_FULL_EA_INFORMATION:
7512 status = smb_set_file_full_ea_info(conn,
7513 pdata,
7514 total_data,
7515 fsp);
7516 break;
7519 /* From tridge Samba4 :
7520 * MODE_INFORMATION in setfileinfo (I have no
7521 * idea what "mode information" on a file is - it takes a value of 0,
7522 * 2, 4 or 6. What could it be?).
7525 case SMB_FILE_MODE_INFORMATION:
7527 status = smb_file_mode_information(conn,
7528 pdata,
7529 total_data);
7530 break;
7534 * CIFS UNIX extensions.
7537 case SMB_SET_FILE_UNIX_BASIC:
7539 status = smb_set_file_unix_basic(conn, req,
7540 pdata,
7541 total_data,
7542 fsp,
7543 smb_fname);
7544 break;
7547 case SMB_SET_FILE_UNIX_INFO2:
7549 status = smb_set_file_unix_info2(conn, req,
7550 pdata,
7551 total_data,
7552 fsp,
7553 smb_fname);
7554 break;
7557 case SMB_SET_FILE_UNIX_LINK:
7559 if (fsp) {
7560 /* We must have a pathname for this. */
7561 return NT_STATUS_INVALID_LEVEL;
7563 status = smb_set_file_unix_link(conn, req, pdata,
7564 total_data, smb_fname);
7565 break;
7568 case SMB_SET_FILE_UNIX_HLINK:
7570 if (fsp) {
7571 /* We must have a pathname for this. */
7572 return NT_STATUS_INVALID_LEVEL;
7574 status = smb_set_file_unix_hlink(conn, req,
7575 pdata, total_data,
7576 smb_fname);
7577 break;
7580 case SMB_FILE_RENAME_INFORMATION:
7582 status = smb_file_rename_information(conn, req,
7583 pdata, total_data,
7584 fsp, smb_fname);
7585 break;
7588 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7590 /* SMB2 rename information. */
7591 status = smb2_file_rename_information(conn, req,
7592 pdata, total_data,
7593 fsp, smb_fname);
7594 break;
7597 #if defined(HAVE_POSIX_ACLS)
7598 case SMB_SET_POSIX_ACL:
7600 status = smb_set_posix_acl(conn,
7601 pdata,
7602 total_data,
7603 fsp,
7604 smb_fname);
7605 break;
7607 #endif
7609 case SMB_SET_POSIX_LOCK:
7611 if (!fsp) {
7612 return NT_STATUS_INVALID_LEVEL;
7614 status = smb_set_posix_lock(conn, req,
7615 pdata, total_data, fsp);
7616 break;
7619 case SMB_POSIX_PATH_OPEN:
7621 if (fsp) {
7622 /* We must have a pathname for this. */
7623 return NT_STATUS_INVALID_LEVEL;
7626 status = smb_posix_open(conn, req,
7627 ppdata,
7628 total_data,
7629 smb_fname,
7630 &data_return_size);
7631 break;
7634 case SMB_POSIX_PATH_UNLINK:
7636 if (fsp) {
7637 /* We must have a pathname for this. */
7638 return NT_STATUS_INVALID_LEVEL;
7641 status = smb_posix_unlink(conn, req,
7642 pdata,
7643 total_data,
7644 smb_fname);
7645 break;
7648 default:
7649 return NT_STATUS_INVALID_LEVEL;
7652 if (!NT_STATUS_IS_OK(status)) {
7653 return status;
7656 *ret_data_size = data_return_size;
7657 return NT_STATUS_OK;
7660 /****************************************************************************
7661 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7662 ****************************************************************************/
7664 static void call_trans2setfilepathinfo(connection_struct *conn,
7665 struct smb_request *req,
7666 unsigned int tran_call,
7667 char **pparams, int total_params,
7668 char **ppdata, int total_data,
7669 unsigned int max_data_bytes)
7671 char *params = *pparams;
7672 char *pdata = *ppdata;
7673 uint16 info_level;
7674 struct smb_filename *smb_fname = NULL;
7675 files_struct *fsp = NULL;
7676 NTSTATUS status = NT_STATUS_OK;
7677 int data_return_size = 0;
7679 if (!params) {
7680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7681 return;
7684 if (tran_call == TRANSACT2_SETFILEINFO) {
7685 if (total_params < 4) {
7686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7687 return;
7690 fsp = file_fsp(req, SVAL(params,0));
7691 /* Basic check for non-null fsp. */
7692 if (!check_fsp_open(conn, req, fsp)) {
7693 return;
7695 info_level = SVAL(params,2);
7697 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7698 &smb_fname);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 reply_nterror(req, status);
7701 return;
7704 if(fsp->is_directory || fsp->fh->fd == -1) {
7706 * This is actually a SETFILEINFO on a directory
7707 * handle (returned from an NT SMB). NT5.0 seems
7708 * to do this call. JRA.
7710 if (INFO_LEVEL_IS_UNIX(info_level)) {
7711 /* Always do lstat for UNIX calls. */
7712 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7713 DEBUG(3,("call_trans2setfilepathinfo: "
7714 "SMB_VFS_LSTAT of %s failed "
7715 "(%s)\n",
7716 smb_fname_str_dbg(smb_fname),
7717 strerror(errno)));
7718 reply_nterror(req, map_nt_error_from_unix(errno));
7719 return;
7721 } else {
7722 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7723 DEBUG(3,("call_trans2setfilepathinfo: "
7724 "fileinfo of %s failed (%s)\n",
7725 smb_fname_str_dbg(smb_fname),
7726 strerror(errno)));
7727 reply_nterror(req, map_nt_error_from_unix(errno));
7728 return;
7731 } else if (fsp->print_file) {
7733 * Doing a DELETE_ON_CLOSE should cancel a print job.
7735 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7736 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7738 DEBUG(3,("call_trans2setfilepathinfo: "
7739 "Cancelling print job (%s)\n",
7740 fsp_str_dbg(fsp)));
7742 SSVAL(params,0,0);
7743 send_trans2_replies(conn, req, params, 2,
7744 *ppdata, 0,
7745 max_data_bytes);
7746 return;
7747 } else {
7748 reply_nterror(req,
7749 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7750 return;
7752 } else {
7754 * Original code - this is an open file.
7756 if (!check_fsp(conn, req, fsp)) {
7757 return;
7760 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7761 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7762 "of fnum %d failed (%s)\n", fsp->fnum,
7763 strerror(errno)));
7764 reply_nterror(req, map_nt_error_from_unix(errno));
7765 return;
7768 } else {
7769 char *fname = NULL;
7771 /* set path info */
7772 if (total_params < 7) {
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7774 return;
7777 info_level = SVAL(params,0);
7778 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7779 total_params - 6, STR_TERMINATE,
7780 &status);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 reply_nterror(req, status);
7783 return;
7786 status = filename_convert(req, conn,
7787 req->flags2 & FLAGS2_DFS_PATHNAMES,
7788 fname,
7790 NULL,
7791 &smb_fname);
7792 if (!NT_STATUS_IS_OK(status)) {
7793 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7794 reply_botherror(req,
7795 NT_STATUS_PATH_NOT_COVERED,
7796 ERRSRV, ERRbadpath);
7797 return;
7799 reply_nterror(req, status);
7800 return;
7803 if (INFO_LEVEL_IS_UNIX(info_level)) {
7805 * For CIFS UNIX extensions the target name may not exist.
7808 /* Always do lstat for UNIX calls. */
7809 SMB_VFS_LSTAT(conn, smb_fname);
7811 } else if (!VALID_STAT(smb_fname->st) &&
7812 SMB_VFS_STAT(conn, smb_fname)) {
7813 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7814 "%s failed (%s)\n",
7815 smb_fname_str_dbg(smb_fname),
7816 strerror(errno)));
7817 reply_nterror(req, map_nt_error_from_unix(errno));
7818 return;
7822 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7823 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7824 fsp ? fsp->fnum : -1, info_level,total_data));
7826 /* Realloc the parameter size */
7827 *pparams = (char *)SMB_REALLOC(*pparams,2);
7828 if (*pparams == NULL) {
7829 reply_nterror(req, NT_STATUS_NO_MEMORY);
7830 return;
7832 params = *pparams;
7834 SSVAL(params,0,0);
7836 status = smbd_do_setfilepathinfo(conn, req, req,
7837 info_level,
7838 fsp,
7839 smb_fname,
7840 ppdata, total_data,
7841 &data_return_size);
7842 if (!NT_STATUS_IS_OK(status)) {
7843 if (open_was_deferred(req->mid)) {
7844 /* We have re-scheduled this call. */
7845 return;
7847 if (blocking_lock_was_deferred(req->mid)) {
7848 /* We have re-scheduled this call. */
7849 return;
7851 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7852 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7853 ERRSRV, ERRbadpath);
7854 return;
7856 if (info_level == SMB_POSIX_PATH_OPEN) {
7857 reply_openerror(req, status);
7858 return;
7861 reply_nterror(req, status);
7862 return;
7865 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7866 max_data_bytes);
7868 return;
7871 /****************************************************************************
7872 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7873 ****************************************************************************/
7875 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7876 char **pparams, int total_params,
7877 char **ppdata, int total_data,
7878 unsigned int max_data_bytes)
7880 struct smb_filename *smb_dname = NULL;
7881 char *params = *pparams;
7882 char *pdata = *ppdata;
7883 char *directory = NULL;
7884 NTSTATUS status = NT_STATUS_OK;
7885 struct ea_list *ea_list = NULL;
7886 TALLOC_CTX *ctx = talloc_tos();
7888 if (!CAN_WRITE(conn)) {
7889 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7890 return;
7893 if (total_params < 5) {
7894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7895 return;
7898 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7899 total_params - 4, STR_TERMINATE,
7900 &status);
7901 if (!NT_STATUS_IS_OK(status)) {
7902 reply_nterror(req, status);
7903 return;
7906 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7908 status = filename_convert(ctx,
7909 conn,
7910 req->flags2 & FLAGS2_DFS_PATHNAMES,
7911 directory,
7913 NULL,
7914 &smb_dname);
7916 if (!NT_STATUS_IS_OK(status)) {
7917 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7918 reply_botherror(req,
7919 NT_STATUS_PATH_NOT_COVERED,
7920 ERRSRV, ERRbadpath);
7921 return;
7923 reply_nterror(req, status);
7924 return;
7928 * OS/2 workplace shell seems to send SET_EA requests of "null"
7929 * length (4 bytes containing IVAL 4).
7930 * They seem to have no effect. Bug #3212. JRA.
7933 if (total_data && (total_data != 4)) {
7934 /* Any data in this call is an EA list. */
7935 if (total_data < 10) {
7936 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7937 goto out;
7940 if (IVAL(pdata,0) > total_data) {
7941 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7942 IVAL(pdata,0), (unsigned int)total_data));
7943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7944 goto out;
7947 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7948 total_data - 4);
7949 if (!ea_list) {
7950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7951 goto out;
7954 if (!lp_ea_support(SNUM(conn))) {
7955 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7956 goto out;
7959 /* If total_data == 4 Windows doesn't care what values
7960 * are placed in that field, it just ignores them.
7961 * The System i QNTC IBM SMB client puts bad values here,
7962 * so ignore them. */
7964 status = create_directory(conn, req, smb_dname);
7966 if (!NT_STATUS_IS_OK(status)) {
7967 reply_nterror(req, status);
7968 goto out;
7971 /* Try and set any given EA. */
7972 if (ea_list) {
7973 status = set_ea(conn, NULL, smb_dname, ea_list);
7974 if (!NT_STATUS_IS_OK(status)) {
7975 reply_nterror(req, status);
7976 goto out;
7980 /* Realloc the parameter and data sizes */
7981 *pparams = (char *)SMB_REALLOC(*pparams,2);
7982 if(*pparams == NULL) {
7983 reply_nterror(req, NT_STATUS_NO_MEMORY);
7984 goto out;
7986 params = *pparams;
7988 SSVAL(params,0,0);
7990 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7992 out:
7993 TALLOC_FREE(smb_dname);
7994 return;
7997 /****************************************************************************
7998 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7999 We don't actually do this - we just send a null response.
8000 ****************************************************************************/
8002 static void call_trans2findnotifyfirst(connection_struct *conn,
8003 struct smb_request *req,
8004 char **pparams, int total_params,
8005 char **ppdata, int total_data,
8006 unsigned int max_data_bytes)
8008 char *params = *pparams;
8009 uint16 info_level;
8011 if (total_params < 6) {
8012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8013 return;
8016 info_level = SVAL(params,4);
8017 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8019 switch (info_level) {
8020 case 1:
8021 case 2:
8022 break;
8023 default:
8024 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8025 return;
8028 /* Realloc the parameter and data sizes */
8029 *pparams = (char *)SMB_REALLOC(*pparams,6);
8030 if (*pparams == NULL) {
8031 reply_nterror(req, NT_STATUS_NO_MEMORY);
8032 return;
8034 params = *pparams;
8036 SSVAL(params,0,fnf_handle);
8037 SSVAL(params,2,0); /* No changes */
8038 SSVAL(params,4,0); /* No EA errors */
8040 fnf_handle++;
8042 if(fnf_handle == 0)
8043 fnf_handle = 257;
8045 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8047 return;
8050 /****************************************************************************
8051 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8052 changes). Currently this does nothing.
8053 ****************************************************************************/
8055 static void call_trans2findnotifynext(connection_struct *conn,
8056 struct smb_request *req,
8057 char **pparams, int total_params,
8058 char **ppdata, int total_data,
8059 unsigned int max_data_bytes)
8061 char *params = *pparams;
8063 DEBUG(3,("call_trans2findnotifynext\n"));
8065 /* Realloc the parameter and data sizes */
8066 *pparams = (char *)SMB_REALLOC(*pparams,4);
8067 if (*pparams == NULL) {
8068 reply_nterror(req, NT_STATUS_NO_MEMORY);
8069 return;
8071 params = *pparams;
8073 SSVAL(params,0,0); /* No changes */
8074 SSVAL(params,2,0); /* No EA errors */
8076 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8078 return;
8081 /****************************************************************************
8082 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8083 ****************************************************************************/
8085 static void call_trans2getdfsreferral(connection_struct *conn,
8086 struct smb_request *req,
8087 char **pparams, int total_params,
8088 char **ppdata, int total_data,
8089 unsigned int max_data_bytes)
8091 char *params = *pparams;
8092 char *pathname = NULL;
8093 int reply_size = 0;
8094 int max_referral_level;
8095 NTSTATUS status = NT_STATUS_OK;
8096 TALLOC_CTX *ctx = talloc_tos();
8098 DEBUG(10,("call_trans2getdfsreferral\n"));
8100 if (total_params < 3) {
8101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8102 return;
8105 max_referral_level = SVAL(params,0);
8107 if(!lp_host_msdfs()) {
8108 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8109 return;
8112 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8113 total_params - 2, STR_TERMINATE);
8114 if (!pathname) {
8115 reply_nterror(req, NT_STATUS_NOT_FOUND);
8116 return;
8118 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8119 ppdata,&status)) < 0) {
8120 reply_nterror(req, status);
8121 return;
8124 SSVAL(req->inbuf, smb_flg2,
8125 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8126 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8128 return;
8131 #define LMCAT_SPL 0x53
8132 #define LMFUNC_GETJOBID 0x60
8134 /****************************************************************************
8135 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8136 ****************************************************************************/
8138 static void call_trans2ioctl(connection_struct *conn,
8139 struct smb_request *req,
8140 char **pparams, int total_params,
8141 char **ppdata, int total_data,
8142 unsigned int max_data_bytes)
8144 char *pdata = *ppdata;
8145 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8147 /* check for an invalid fid before proceeding */
8149 if (!fsp) {
8150 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8151 return;
8154 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8155 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8156 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8157 if (*ppdata == NULL) {
8158 reply_nterror(req, NT_STATUS_NO_MEMORY);
8159 return;
8161 pdata = *ppdata;
8163 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8164 CAN ACCEPT THIS IN UNICODE. JRA. */
8166 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8167 srvstr_push(pdata, req->flags2, pdata + 2,
8168 global_myname(), 15,
8169 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8170 srvstr_push(pdata, req->flags2, pdata+18,
8171 lp_servicename(SNUM(conn)), 13,
8172 STR_ASCII|STR_TERMINATE); /* Service name */
8173 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8174 max_data_bytes);
8175 return;
8178 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8179 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8182 /****************************************************************************
8183 Reply to a SMBfindclose (stop trans2 directory search).
8184 ****************************************************************************/
8186 void reply_findclose(struct smb_request *req)
8188 int dptr_num;
8189 struct smbd_server_connection *sconn = smbd_server_conn;
8191 START_PROFILE(SMBfindclose);
8193 if (req->wct < 1) {
8194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 END_PROFILE(SMBfindclose);
8196 return;
8199 dptr_num = SVALS(req->vwv+0, 0);
8201 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8203 dptr_close(sconn, &dptr_num);
8205 reply_outbuf(req, 0, 0);
8207 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8209 END_PROFILE(SMBfindclose);
8210 return;
8213 /****************************************************************************
8214 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8215 ****************************************************************************/
8217 void reply_findnclose(struct smb_request *req)
8219 int dptr_num;
8221 START_PROFILE(SMBfindnclose);
8223 if (req->wct < 1) {
8224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8225 END_PROFILE(SMBfindnclose);
8226 return;
8229 dptr_num = SVAL(req->vwv+0, 0);
8231 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8233 /* We never give out valid handles for a
8234 findnotifyfirst - so any dptr_num is ok here.
8235 Just ignore it. */
8237 reply_outbuf(req, 0, 0);
8239 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8241 END_PROFILE(SMBfindnclose);
8242 return;
8245 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8246 struct trans_state *state)
8248 if (get_Protocol() >= PROTOCOL_NT1) {
8249 req->flags2 |= 0x40; /* IS_LONG_NAME */
8250 SSVAL(req->inbuf,smb_flg2,req->flags2);
8253 if (conn->encrypt_level == Required && !req->encrypted) {
8254 if (state->call != TRANSACT2_QFSINFO &&
8255 state->call != TRANSACT2_SETFSINFO) {
8256 DEBUG(0,("handle_trans2: encryption required "
8257 "with call 0x%x\n",
8258 (unsigned int)state->call));
8259 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8260 return;
8264 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8266 /* Now we must call the relevant TRANS2 function */
8267 switch(state->call) {
8268 case TRANSACT2_OPEN:
8270 START_PROFILE(Trans2_open);
8271 call_trans2open(conn, req,
8272 &state->param, state->total_param,
8273 &state->data, state->total_data,
8274 state->max_data_return);
8275 END_PROFILE(Trans2_open);
8276 break;
8279 case TRANSACT2_FINDFIRST:
8281 START_PROFILE(Trans2_findfirst);
8282 call_trans2findfirst(conn, req,
8283 &state->param, state->total_param,
8284 &state->data, state->total_data,
8285 state->max_data_return);
8286 END_PROFILE(Trans2_findfirst);
8287 break;
8290 case TRANSACT2_FINDNEXT:
8292 START_PROFILE(Trans2_findnext);
8293 call_trans2findnext(conn, req,
8294 &state->param, state->total_param,
8295 &state->data, state->total_data,
8296 state->max_data_return);
8297 END_PROFILE(Trans2_findnext);
8298 break;
8301 case TRANSACT2_QFSINFO:
8303 START_PROFILE(Trans2_qfsinfo);
8304 call_trans2qfsinfo(conn, req,
8305 &state->param, state->total_param,
8306 &state->data, state->total_data,
8307 state->max_data_return);
8308 END_PROFILE(Trans2_qfsinfo);
8309 break;
8312 case TRANSACT2_SETFSINFO:
8314 START_PROFILE(Trans2_setfsinfo);
8315 call_trans2setfsinfo(conn, req,
8316 &state->param, state->total_param,
8317 &state->data, state->total_data,
8318 state->max_data_return);
8319 END_PROFILE(Trans2_setfsinfo);
8320 break;
8323 case TRANSACT2_QPATHINFO:
8324 case TRANSACT2_QFILEINFO:
8326 START_PROFILE(Trans2_qpathinfo);
8327 call_trans2qfilepathinfo(conn, req, state->call,
8328 &state->param, state->total_param,
8329 &state->data, state->total_data,
8330 state->max_data_return);
8331 END_PROFILE(Trans2_qpathinfo);
8332 break;
8335 case TRANSACT2_SETPATHINFO:
8336 case TRANSACT2_SETFILEINFO:
8338 START_PROFILE(Trans2_setpathinfo);
8339 call_trans2setfilepathinfo(conn, req, state->call,
8340 &state->param, state->total_param,
8341 &state->data, state->total_data,
8342 state->max_data_return);
8343 END_PROFILE(Trans2_setpathinfo);
8344 break;
8347 case TRANSACT2_FINDNOTIFYFIRST:
8349 START_PROFILE(Trans2_findnotifyfirst);
8350 call_trans2findnotifyfirst(conn, req,
8351 &state->param, state->total_param,
8352 &state->data, state->total_data,
8353 state->max_data_return);
8354 END_PROFILE(Trans2_findnotifyfirst);
8355 break;
8358 case TRANSACT2_FINDNOTIFYNEXT:
8360 START_PROFILE(Trans2_findnotifynext);
8361 call_trans2findnotifynext(conn, req,
8362 &state->param, state->total_param,
8363 &state->data, state->total_data,
8364 state->max_data_return);
8365 END_PROFILE(Trans2_findnotifynext);
8366 break;
8369 case TRANSACT2_MKDIR:
8371 START_PROFILE(Trans2_mkdir);
8372 call_trans2mkdir(conn, req,
8373 &state->param, state->total_param,
8374 &state->data, state->total_data,
8375 state->max_data_return);
8376 END_PROFILE(Trans2_mkdir);
8377 break;
8380 case TRANSACT2_GET_DFS_REFERRAL:
8382 START_PROFILE(Trans2_get_dfs_referral);
8383 call_trans2getdfsreferral(conn, req,
8384 &state->param, state->total_param,
8385 &state->data, state->total_data,
8386 state->max_data_return);
8387 END_PROFILE(Trans2_get_dfs_referral);
8388 break;
8391 case TRANSACT2_IOCTL:
8393 START_PROFILE(Trans2_ioctl);
8394 call_trans2ioctl(conn, req,
8395 &state->param, state->total_param,
8396 &state->data, state->total_data,
8397 state->max_data_return);
8398 END_PROFILE(Trans2_ioctl);
8399 break;
8402 default:
8403 /* Error in request */
8404 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8405 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8409 /****************************************************************************
8410 Reply to a SMBtrans2.
8411 ****************************************************************************/
8413 void reply_trans2(struct smb_request *req)
8415 connection_struct *conn = req->conn;
8416 unsigned int dsoff;
8417 unsigned int dscnt;
8418 unsigned int psoff;
8419 unsigned int pscnt;
8420 unsigned int tran_call;
8421 struct trans_state *state;
8422 NTSTATUS result;
8424 START_PROFILE(SMBtrans2);
8426 if (req->wct < 14) {
8427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8428 END_PROFILE(SMBtrans2);
8429 return;
8432 dsoff = SVAL(req->vwv+12, 0);
8433 dscnt = SVAL(req->vwv+11, 0);
8434 psoff = SVAL(req->vwv+10, 0);
8435 pscnt = SVAL(req->vwv+9, 0);
8436 tran_call = SVAL(req->vwv+14, 0);
8438 result = allow_new_trans(conn->pending_trans, req->mid);
8439 if (!NT_STATUS_IS_OK(result)) {
8440 DEBUG(2, ("Got invalid trans2 request: %s\n",
8441 nt_errstr(result)));
8442 reply_nterror(req, result);
8443 END_PROFILE(SMBtrans2);
8444 return;
8447 if (IS_IPC(conn)) {
8448 switch (tran_call) {
8449 /* List the allowed trans2 calls on IPC$ */
8450 case TRANSACT2_OPEN:
8451 case TRANSACT2_GET_DFS_REFERRAL:
8452 case TRANSACT2_QFILEINFO:
8453 case TRANSACT2_QFSINFO:
8454 case TRANSACT2_SETFSINFO:
8455 break;
8456 default:
8457 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8458 END_PROFILE(SMBtrans2);
8459 return;
8463 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8464 DEBUG(0, ("talloc failed\n"));
8465 reply_nterror(req, NT_STATUS_NO_MEMORY);
8466 END_PROFILE(SMBtrans2);
8467 return;
8470 state->cmd = SMBtrans2;
8472 state->mid = req->mid;
8473 state->vuid = req->vuid;
8474 state->setup_count = SVAL(req->vwv+13, 0);
8475 state->setup = NULL;
8476 state->total_param = SVAL(req->vwv+0, 0);
8477 state->param = NULL;
8478 state->total_data = SVAL(req->vwv+1, 0);
8479 state->data = NULL;
8480 state->max_param_return = SVAL(req->vwv+2, 0);
8481 state->max_data_return = SVAL(req->vwv+3, 0);
8482 state->max_setup_return = SVAL(req->vwv+4, 0);
8483 state->close_on_completion = BITSETW(req->vwv+5, 0);
8484 state->one_way = BITSETW(req->vwv+5, 1);
8486 state->call = tran_call;
8488 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8489 is so as a sanity check */
8490 if (state->setup_count != 1) {
8492 * Need to have rc=0 for ioctl to get job id for OS/2.
8493 * Network printing will fail if function is not successful.
8494 * Similar function in reply.c will be used if protocol
8495 * is LANMAN1.0 instead of LM1.2X002.
8496 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8497 * outbuf doesn't have to be set(only job id is used).
8499 if ( (state->setup_count == 4)
8500 && (tran_call == TRANSACT2_IOCTL)
8501 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8502 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8503 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8504 } else {
8505 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8506 DEBUG(2,("Transaction is %d\n",tran_call));
8507 TALLOC_FREE(state);
8508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8509 END_PROFILE(SMBtrans2);
8510 return;
8514 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8515 goto bad_param;
8517 if (state->total_data) {
8519 if (trans_oob(state->total_data, 0, dscnt)
8520 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8521 goto bad_param;
8524 /* Can't use talloc here, the core routines do realloc on the
8525 * params and data. */
8526 state->data = (char *)SMB_MALLOC(state->total_data);
8527 if (state->data == NULL) {
8528 DEBUG(0,("reply_trans2: data malloc fail for %u "
8529 "bytes !\n", (unsigned int)state->total_data));
8530 TALLOC_FREE(state);
8531 reply_nterror(req, NT_STATUS_NO_MEMORY);
8532 END_PROFILE(SMBtrans2);
8533 return;
8536 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8539 if (state->total_param) {
8541 if (trans_oob(state->total_param, 0, pscnt)
8542 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8543 goto bad_param;
8546 /* Can't use talloc here, the core routines do realloc on the
8547 * params and data. */
8548 state->param = (char *)SMB_MALLOC(state->total_param);
8549 if (state->param == NULL) {
8550 DEBUG(0,("reply_trans: param malloc fail for %u "
8551 "bytes !\n", (unsigned int)state->total_param));
8552 SAFE_FREE(state->data);
8553 TALLOC_FREE(state);
8554 reply_nterror(req, NT_STATUS_NO_MEMORY);
8555 END_PROFILE(SMBtrans2);
8556 return;
8559 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8562 state->received_data = dscnt;
8563 state->received_param = pscnt;
8565 if ((state->received_param == state->total_param) &&
8566 (state->received_data == state->total_data)) {
8568 handle_trans2(conn, req, state);
8570 SAFE_FREE(state->data);
8571 SAFE_FREE(state->param);
8572 TALLOC_FREE(state);
8573 END_PROFILE(SMBtrans2);
8574 return;
8577 DLIST_ADD(conn->pending_trans, state);
8579 /* We need to send an interim response then receive the rest
8580 of the parameter/data bytes */
8581 reply_outbuf(req, 0, 0);
8582 show_msg((char *)req->outbuf);
8583 END_PROFILE(SMBtrans2);
8584 return;
8586 bad_param:
8588 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8589 SAFE_FREE(state->data);
8590 SAFE_FREE(state->param);
8591 TALLOC_FREE(state);
8592 END_PROFILE(SMBtrans2);
8593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8597 /****************************************************************************
8598 Reply to a SMBtranss2
8599 ****************************************************************************/
8601 void reply_transs2(struct smb_request *req)
8603 connection_struct *conn = req->conn;
8604 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8605 struct trans_state *state;
8607 START_PROFILE(SMBtranss2);
8609 show_msg((char *)req->inbuf);
8611 if (req->wct < 8) {
8612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8613 END_PROFILE(SMBtranss2);
8614 return;
8617 for (state = conn->pending_trans; state != NULL;
8618 state = state->next) {
8619 if (state->mid == req->mid) {
8620 break;
8624 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8626 END_PROFILE(SMBtranss2);
8627 return;
8630 /* Revise state->total_param and state->total_data in case they have
8631 changed downwards */
8633 if (SVAL(req->vwv+0, 0) < state->total_param)
8634 state->total_param = SVAL(req->vwv+0, 0);
8635 if (SVAL(req->vwv+1, 0) < state->total_data)
8636 state->total_data = SVAL(req->vwv+1, 0);
8638 pcnt = SVAL(req->vwv+2, 0);
8639 poff = SVAL(req->vwv+3, 0);
8640 pdisp = SVAL(req->vwv+4, 0);
8642 dcnt = SVAL(req->vwv+5, 0);
8643 doff = SVAL(req->vwv+6, 0);
8644 ddisp = SVAL(req->vwv+7, 0);
8646 state->received_param += pcnt;
8647 state->received_data += dcnt;
8649 if ((state->received_data > state->total_data) ||
8650 (state->received_param > state->total_param))
8651 goto bad_param;
8653 if (pcnt) {
8654 if (trans_oob(state->total_param, pdisp, pcnt)
8655 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8656 goto bad_param;
8658 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8661 if (dcnt) {
8662 if (trans_oob(state->total_data, ddisp, dcnt)
8663 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8664 goto bad_param;
8666 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8669 if ((state->received_param < state->total_param) ||
8670 (state->received_data < state->total_data)) {
8671 END_PROFILE(SMBtranss2);
8672 return;
8675 handle_trans2(conn, req, state);
8677 DLIST_REMOVE(conn->pending_trans, state);
8678 SAFE_FREE(state->data);
8679 SAFE_FREE(state->param);
8680 TALLOC_FREE(state);
8682 END_PROFILE(SMBtranss2);
8683 return;
8685 bad_param:
8687 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8688 DLIST_REMOVE(conn->pending_trans, state);
8689 SAFE_FREE(state->data);
8690 SAFE_FREE(state->param);
8691 TALLOC_FREE(state);
8692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8693 END_PROFILE(SMBtranss2);
8694 return;