source: branches/samba-3.5.x/source3/smbd/trans2.c@ 736

Last change on this file since 736 was 736, checked in by Silvan Scherrer, 13 years ago

Samba Server 3.5: update branche to 3.5.16

File size: 236.3 KB
Line 
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
9
10 Extensively modified by Andrew Tridgell, 1995
11
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.
16
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.
21
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/>.
24*/
25
26#include "includes.h"
27#include "version.h"
28#include "smbd/globals.h"
29#include "../libcli/auth/libcli_auth.h"
30
31#define DIR_ENTRY_SAFETY_MARGIN 4096
32
33static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
37
38static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
42
43/********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46********************************************************************/
47
48uint64_t smb_roundup(connection_struct *conn, uint64_t val)
49{
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
51
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);
56 }
57 return val;
58}
59
60/********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64********************************************************************/
65
66uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
67{
68 uint64_t file_index;
69 if (conn->base_share_dev == psbuf->st_ex_dev) {
70 return (uint64_t)psbuf->st_ex_ino;
71 }
72 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
73 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
74 return file_index;
75}
76
77/****************************************************************************
78 Utility functions for dealing with extended attributes.
79****************************************************************************/
80
81/****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83****************************************************************************/
84
85static bool samba_private_attr_name(const char *unix_ea_name)
86{
87 static const char * const prohibited_ea_names[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME,
89 SAMBA_XATTR_DOS_ATTRIB,
90 SAMBA_XATTR_MARKER,
91 XATTR_NTACL_NAME,
92 NULL
93 };
94
95 int i;
96
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return true;
100 }
101 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
103 return true;
104 }
105 return false;
106}
107
108/****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110****************************************************************************/
111
112NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
113 files_struct *fsp, const char *fname,
114 const char *ea_name, struct ea_struct *pea)
115{
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size = 256;
118 char *val = NULL;
119 ssize_t sizeret;
120
121 again:
122
123 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
124 if (!val) {
125 return NT_STATUS_NO_MEMORY;
126 }
127
128 if (fsp && fsp->fh->fd != -1) {
129 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
130 } else {
131 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
132 }
133
134 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
135 attr_size = 65536;
136 goto again;
137 }
138
139 if (sizeret == -1) {
140 return map_nt_error_from_unix(errno);
141 }
142
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
144 dump_data(10, (uint8 *)val, sizeret);
145
146 pea->flags = 0;
147#ifndef __OS2__
148 if (strnequal(ea_name, "user.", 5)) {
149 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
150 } else {
151#else
152 {
153#endif
154 pea->name = talloc_strdup(mem_ctx, ea_name);
155 }
156 if (pea->name == NULL) {
157 TALLOC_FREE(val);
158 return NT_STATUS_NO_MEMORY;
159 }
160 pea->value.data = (unsigned char *)val;
161 pea->value.length = (size_t)sizeret;
162 return NT_STATUS_OK;
163}
164
165NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
166 files_struct *fsp, const char *fname,
167 char ***pnames, size_t *pnum_names)
168{
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
171 char *ea_namelist = NULL;
172
173 char *p;
174 char **names, **tmp;
175 size_t num_names;
176 ssize_t sizeret = -1;
177
178 if (!lp_ea_support(SNUM(conn))) {
179 if (pnames) {
180 *pnames = NULL;
181 }
182 *pnum_names = 0;
183 return NT_STATUS_OK;
184 }
185
186 /*
187 * TALLOC the result early to get the talloc hierarchy right.
188 */
189
190 names = TALLOC_ARRAY(mem_ctx, char *, 1);
191 if (names == NULL) {
192 DEBUG(0, ("talloc failed\n"));
193 return NT_STATUS_NO_MEMORY;
194 }
195
196 while (ea_namelist_size <= 65536) {
197
198 ea_namelist = TALLOC_REALLOC_ARRAY(
199 names, ea_namelist, char, ea_namelist_size);
200 if (ea_namelist == NULL) {
201 DEBUG(0, ("talloc failed\n"));
202 TALLOC_FREE(names);
203 return NT_STATUS_NO_MEMORY;
204 }
205
206 if (fsp && fsp->fh->fd != -1) {
207 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
208 ea_namelist_size);
209 } else {
210 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
211 ea_namelist_size);
212 }
213
214 if ((sizeret == -1) && (errno == ERANGE)) {
215 ea_namelist_size *= 2;
216 }
217 else {
218 break;
219 }
220 }
221
222 if (sizeret == -1) {
223 TALLOC_FREE(names);
224 return map_nt_error_from_unix(errno);
225 }
226
227 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
228 (unsigned int)sizeret));
229
230 if (sizeret == 0) {
231 TALLOC_FREE(names);
232 if (pnames) {
233 *pnames = NULL;
234 }
235 *pnum_names = 0;
236 return NT_STATUS_OK;
237 }
238
239 /*
240 * Ensure the result is 0-terminated
241 */
242
243 if (ea_namelist[sizeret-1] != '\0') {
244 TALLOC_FREE(names);
245 return NT_STATUS_INTERNAL_ERROR;
246 }
247
248 /*
249 * count the names
250 */
251 num_names = 0;
252
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
254 num_names += 1;
255 }
256
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
258 if (tmp == NULL) {
259 DEBUG(0, ("talloc failed\n"));
260 TALLOC_FREE(names);
261 return NT_STATUS_NO_MEMORY;
262 }
263
264 names = tmp;
265 num_names = 0;
266
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
269 }
270
271 if (pnames) {
272 *pnames = names;
273 } else {
274 TALLOC_FREE(names);
275 }
276 *pnum_names = num_names;
277 return NT_STATUS_OK;
278}
279
280/****************************************************************************
281 Return a linked list of the total EA's. Plus the total size
282****************************************************************************/
283
284static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
285 const char *fname, size_t *pea_total_len)
286{
287 /* Get a list of all xattrs. Max namesize is 64k. */
288 size_t i, num_names;
289 char **names;
290 struct ea_list *ea_list_head = NULL;
291 NTSTATUS status;
292
293 *pea_total_len = 0;
294
295 if (!lp_ea_support(SNUM(conn))) {
296 return NULL;
297 }
298
299 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
300 &names, &num_names);
301
302 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
303 return NULL;
304 }
305
306 for (i=0; i<num_names; i++) {
307 struct ea_list *listp;
308 fstring dos_ea_name;
309
310#ifndef __OS2__
311 if (strnequal(names[i], "system.", 7)
312 || samba_private_attr_name(names[i]))
313#else
314 if (samba_private_attr_name(names[i]))
315#endif
316 continue;
317
318 listp = TALLOC_P(mem_ctx, struct ea_list);
319 if (listp == NULL) {
320 return NULL;
321 }
322
323 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
324 fname, names[i],
325 &listp->ea))) {
326 return NULL;
327 }
328
329 push_ascii_fstring(dos_ea_name, listp->ea.name);
330
331 *pea_total_len +=
332 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
333
334 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
335 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
336 (unsigned int)listp->ea.value.length));
337
338 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
339
340 }
341
342 /* Add on 4 for total length. */
343 if (*pea_total_len) {
344 *pea_total_len += 4;
345 }
346
347 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
348 (unsigned int)*pea_total_len));
349
350 return ea_list_head;
351}
352
353/****************************************************************************
354 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
355 that was filled.
356****************************************************************************/
357
358static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
359 connection_struct *conn, struct ea_list *ea_list)
360{
361 unsigned int ret_data_size = 4;
362 char *p = pdata;
363
364 SMB_ASSERT(total_data_size >= 4);
365
366 if (!lp_ea_support(SNUM(conn))) {
367 SIVAL(pdata,4,0);
368 return 4;
369 }
370
371 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
372 size_t dos_namelen;
373 fstring dos_ea_name;
374 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
375 dos_namelen = strlen(dos_ea_name);
376 if (dos_namelen > 255 || dos_namelen == 0) {
377 break;
378 }
379 if (ea_list->ea.value.length > 65535) {
380 break;
381 }
382 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
383 break;
384 }
385
386 /* We know we have room. */
387 SCVAL(p,0,ea_list->ea.flags);
388 SCVAL(p,1,dos_namelen);
389 SSVAL(p,2,ea_list->ea.value.length);
390 fstrcpy(p+4, dos_ea_name);
391 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
392
393 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
394 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 }
396
397 ret_data_size = PTR_DIFF(p, pdata);
398 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
399 SIVAL(pdata,0,ret_data_size);
400 return ret_data_size;
401}
402
403static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
404 char *pdata,
405 unsigned int total_data_size,
406 unsigned int *ret_data_size,
407 connection_struct *conn,
408 struct ea_list *ea_list)
409{
410 uint8_t *p = (uint8_t *)pdata;
411 uint8_t *last_start = NULL;
412
413 *ret_data_size = 0;
414
415 if (!lp_ea_support(SNUM(conn))) {
416 return NT_STATUS_NO_EAS_ON_FILE;
417 }
418
419 for (; ea_list; ea_list = ea_list->next) {
420 size_t dos_namelen;
421 fstring dos_ea_name;
422 size_t this_size;
423
424 if (last_start) {
425 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
426 }
427 last_start = p;
428
429 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
430 dos_namelen = strlen(dos_ea_name);
431 if (dos_namelen > 255 || dos_namelen == 0) {
432 return NT_STATUS_INTERNAL_ERROR;
433 }
434 if (ea_list->ea.value.length > 65535) {
435 return NT_STATUS_INTERNAL_ERROR;
436 }
437
438 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
439
440 if (ea_list->next) {
441 size_t pad = 4 - (this_size % 4);
442 this_size += pad;
443 }
444
445 if (this_size > total_data_size) {
446 return NT_STATUS_INFO_LENGTH_MISMATCH;
447 }
448
449 /* We know we have room. */
450 SIVAL(p, 0x00, 0); /* next offset */
451 SCVAL(p, 0x04, ea_list->ea.flags);
452 SCVAL(p, 0x05, dos_namelen);
453 SSVAL(p, 0x06, ea_list->ea.value.length);
454 fstrcpy((char *)(p+0x08), dos_ea_name);
455 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
456
457 total_data_size -= this_size;
458 p += this_size;
459 }
460
461 *ret_data_size = PTR_DIFF(p, pdata);
462 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
463 return NT_STATUS_OK;
464}
465
466static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
467{
468 size_t total_ea_len = 0;
469 TALLOC_CTX *mem_ctx = NULL;
470
471 if (!lp_ea_support(SNUM(conn))) {
472 return 0;
473 }
474 mem_ctx = talloc_tos();
475 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
476 return total_ea_len;
477}
478
479/****************************************************************************
480 Ensure the EA name is case insensitive by matching any existing EA name.
481****************************************************************************/
482
483static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
484{
485 size_t total_ea_len;
486 TALLOC_CTX *mem_ctx = talloc_tos();
487 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
488
489 for (; ea_list; ea_list = ea_list->next) {
490 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
491 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
492 &unix_ea_name[5], ea_list->ea.name));
493 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
494 break;
495 }
496 }
497}
498
499/****************************************************************************
500 Set or delete an extended attribute.
501****************************************************************************/
502
503NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
504 const struct smb_filename *smb_fname, struct ea_list *ea_list)
505{
506 char *fname = NULL;
507
508 if (!lp_ea_support(SNUM(conn))) {
509 return NT_STATUS_EAS_NOT_SUPPORTED;
510 }
511
512 /* For now setting EAs on streams isn't supported. */
513 fname = smb_fname->base_name;
514
515 for (;ea_list; ea_list = ea_list->next) {
516 int ret;
517 fstring unix_ea_name;
518
519#ifdef __OS2__
520 /* All EA's must start with user - except on OS/2 */
521 fstrcpy(unix_ea_name, ea_list->ea.name);
522#else
523 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
524 fstrcat(unix_ea_name, ea_list->ea.name);
525#endif
526
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
528
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
530
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
534 }
535
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
543 } else {
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
547 }
548#ifdef ENOATTR
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
552 unix_ea_name));
553 ret = 0;
554 }
555#endif
556 } else {
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
563 } else {
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
568 }
569 }
570
571 if (ret == -1) {
572#ifdef ENOTSUP
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
575 }
576#endif
577 return map_nt_error_from_unix(errno);
578 }
579
580 }
581 return NT_STATUS_OK;
582}
583/****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585****************************************************************************/
586
587static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
588{
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
591
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
595
596 offset++; /* Go past the namelen byte. */
597
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
602 break;
603 }
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
606 return NULL;
607 }
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
609 &converted_size)) {
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
612 }
613 if (!eal->ea.name) {
614 return NULL;
615 }
616
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
620 }
621
622 return ea_list_head;
623}
624
625/****************************************************************************
626 Read one EA list entry from the buffer.
627****************************************************************************/
628
629struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
630{
631 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
632 uint16 val_len;
633 unsigned int namelen;
634 size_t converted_size;
635
636 if (!eal) {
637 return NULL;
638 }
639
640 if (data_size < 6) {
641 return NULL;
642 }
643
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
647
648 if (4 + namelen + 1 + val_len > data_size) {
649 return NULL;
650 }
651
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
654 return NULL;
655 }
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
658 strerror(errno)));
659 }
660 if (!eal->ea.name) {
661 return NULL;
662 }
663
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
666 return NULL;
667 }
668
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
670
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
675
676 if (pbytes_used) {
677 *pbytes_used = 4 + namelen + 1 + val_len;
678 }
679
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
682
683 return eal;
684}
685
686/****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688****************************************************************************/
689
690static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
691{
692 struct ea_list *ea_list_head = NULL;
693 size_t offset = 0;
694 size_t bytes_used = 0;
695
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
698
699 if (!eal) {
700 return NULL;
701 }
702
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
705 }
706
707 return ea_list_head;
708}
709
710/****************************************************************************
711 Count the total EA size needed.
712****************************************************************************/
713
714static size_t ea_list_size(struct ea_list *ealist)
715{
716 fstring dos_ea_name;
717 struct ea_list *listp;
718 size_t ret = 0;
719
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
723 }
724 /* Add on 4 for total length. */
725 if (ret) {
726 ret += 4;
727 }
728
729 return ret;
730}
731
732/****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736****************************************************************************/
737
738static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
739{
740 struct ea_list *nlistp, *flistp;
741
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
745 break;
746 }
747 }
748
749 if (flistp) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
753 } else {
754 /* Null entry. */
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
757 }
758 }
759
760 *total_ea_len = ea_list_size(name_list);
761 return name_list;
762}
763
764/****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769****************************************************************************/
770
771void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
773 const char *params,
774 int paramsize,
775 const char *pdata,
776 int datasize,
777 int max_data_bytes)
778{
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
784
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
787 int useable_space;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = smbd_server_conn;
795 int max_send = sconn->smb1.sessions.max_send;
796
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
800 for OS/2. */
801
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
806 overflow = True;
807 }
808
809 /* If there genuinely are no parameters or data to send just send the empty packet */
810
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(smbd_server_fd(),
815 (char *)req->outbuf,
816 true, req->seqnum+1,
817 IS_CONN_ENCRYPTED(conn),
818 &req->pcd)) {
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
820 }
821 TALLOC_FREE(req->outbuf);
822 return;
823 }
824
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
828
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
831
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
835
836 useable_space = max_send - (smb_size
837 + 2 * 10 /* wct */
838 + alignment_offset
839 + data_alignment_offset);
840
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
845 }
846
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
849
850 total_sent_thistime = params_to_send + data_to_send;
851
852 /* We can never send more than useable_space */
853 /*
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
858 */
859
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
861
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
864
865 /* Set total params and data to be sent */
866 SSVAL(req->outbuf,smb_tprcnt,paramsize);
867 SSVAL(req->outbuf,smb_tdrcnt,datasize);
868
869 /* Calculate how many parameters and data we can fit into
870 * this packet. Parameters get precedence
871 */
872
873 params_sent_thistime = MIN(params_to_send,useable_space);
874 data_sent_thistime = useable_space - params_sent_thistime;
875 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
876
877 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
878
879 /* smb_proff is the offset from the start of the SMB header to the
880 parameter bytes, however the first 4 bytes of outbuf are
881 the Netbios over TCP header. Thus use smb_base() to subtract
882 them from the calculation */
883
884 SSVAL(req->outbuf,smb_proff,
885 ((smb_buf(req->outbuf)+alignment_offset)
886 - smb_base(req->outbuf)));
887
888 if(params_sent_thistime == 0)
889 SSVAL(req->outbuf,smb_prdisp,0);
890 else
891 /* Absolute displacement of param bytes sent in this packet */
892 SSVAL(req->outbuf,smb_prdisp,pp - params);
893
894 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
895 if(data_sent_thistime == 0) {
896 SSVAL(req->outbuf,smb_droff,0);
897 SSVAL(req->outbuf,smb_drdisp, 0);
898 } else {
899 /* The offset of the data bytes is the offset of the
900 parameter bytes plus the number of parameters being sent this time */
901 SSVAL(req->outbuf, smb_droff,
902 ((smb_buf(req->outbuf)+alignment_offset)
903 - smb_base(req->outbuf))
904 + params_sent_thistime + data_alignment_offset);
905 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
906 }
907
908 /* Initialize the padding for alignment */
909
910 if (alignment_offset != 0) {
911 memset(smb_buf(req->outbuf), 0, alignment_offset);
912 }
913
914 /* Copy the param bytes into the packet */
915
916 if(params_sent_thistime) {
917 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
918 params_sent_thistime);
919 }
920
921 /* Copy in the data bytes */
922 if(data_sent_thistime) {
923 if (data_alignment_offset != 0) {
924 memset((smb_buf(req->outbuf)+alignment_offset+
925 params_sent_thistime), 0,
926 data_alignment_offset);
927 }
928 memcpy(smb_buf(req->outbuf)+alignment_offset
929 +params_sent_thistime+data_alignment_offset,
930 pd,data_sent_thistime);
931 }
932
933 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
934 params_sent_thistime, data_sent_thistime, useable_space));
935 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
936 params_to_send, data_to_send, paramsize, datasize));
937
938 if (overflow) {
939 error_packet_set((char *)req->outbuf,
940 ERRDOS,ERRbufferoverflow,
941 STATUS_BUFFER_OVERFLOW,
942 __LINE__,__FILE__);
943 }
944
945 /* Send the packet */
946 show_msg((char *)req->outbuf);
947 if (!srv_send_smb(smbd_server_fd(),
948 (char *)req->outbuf,
949 true, req->seqnum+1,
950 IS_CONN_ENCRYPTED(conn),
951 &req->pcd))
952 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
953
954 TALLOC_FREE(req->outbuf);
955
956 pp += params_sent_thistime;
957 pd += data_sent_thistime;
958
959 params_to_send -= params_sent_thistime;
960 data_to_send -= data_sent_thistime;
961
962 /* Sanity check */
963 if(params_to_send < 0 || data_to_send < 0) {
964 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
965 params_to_send, data_to_send));
966 return;
967 }
968 }
969
970 return;
971}
972
973/****************************************************************************
974 Reply to a TRANSACT2_OPEN.
975****************************************************************************/
976
977static void call_trans2open(connection_struct *conn,
978 struct smb_request *req,
979 char **pparams, int total_params,
980 char **ppdata, int total_data,
981 unsigned int max_data_bytes)
982{
983 struct smb_filename *smb_fname = NULL;
984 char *params = *pparams;
985 char *pdata = *ppdata;
986 int deny_mode;
987 int32 open_attr;
988 bool oplock_request;
989#if 0
990 bool return_additional_info;
991 int16 open_sattr;
992 time_t open_time;
993#endif
994 int open_ofun;
995 uint32 open_size;
996 char *pname;
997 char *fname = NULL;
998 SMB_OFF_T size=0;
999 int fattr=0,mtime=0;
1000 SMB_INO_T inode = 0;
1001 int smb_action = 0;
1002 files_struct *fsp;
1003 struct ea_list *ea_list = NULL;
1004 uint16 flags = 0;
1005 NTSTATUS status;
1006 uint32 access_mask;
1007 uint32 share_mode;
1008 uint32 create_disposition;
1009 uint32 create_options = 0;
1010 TALLOC_CTX *ctx = talloc_tos();
1011
1012 /*
1013 * Ensure we have enough parameters to perform the operation.
1014 */
1015
1016 if (total_params < 29) {
1017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1018 goto out;
1019 }
1020
1021 flags = SVAL(params, 0);
1022 deny_mode = SVAL(params, 2);
1023 open_attr = SVAL(params,6);
1024 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1025 if (oplock_request) {
1026 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1027 }
1028
1029#if 0
1030 return_additional_info = BITSETW(params,0);
1031 open_sattr = SVAL(params, 4);
1032 open_time = make_unix_date3(params+8);
1033#endif
1034 open_ofun = SVAL(params,12);
1035 open_size = IVAL(params,14);
1036 pname = &params[28];
1037
1038 if (IS_IPC(conn)) {
1039 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1040 goto out;
1041 }
1042
1043 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1044 total_params - 28, STR_TERMINATE,
1045 &status);
1046 if (!NT_STATUS_IS_OK(status)) {
1047 reply_nterror(req, status);
1048 goto out;
1049 }
1050
1051 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1052 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1053 (unsigned int)open_ofun, open_size));
1054
1055 status = filename_convert(ctx,
1056 conn,
1057 req->flags2 & FLAGS2_DFS_PATHNAMES,
1058 fname,
1059 0,
1060 NULL,
1061 &smb_fname);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1064 reply_botherror(req,
1065 NT_STATUS_PATH_NOT_COVERED,
1066 ERRSRV, ERRbadpath);
1067 goto out;
1068 }
1069 reply_nterror(req, status);
1070 goto out;
1071 }
1072
1073 if (open_ofun == 0) {
1074 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1075 goto out;
1076 }
1077
1078 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1079 open_ofun,
1080 &access_mask, &share_mode,
1081 &create_disposition,
1082 &create_options)) {
1083 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1084 goto out;
1085 }
1086
1087 /* Any data in this call is an EA list. */
1088 if (total_data && (total_data != 4)) {
1089 if (total_data < 10) {
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 goto out;
1092 }
1093
1094 if (IVAL(pdata,0) > total_data) {
1095 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1096 IVAL(pdata,0), (unsigned int)total_data));
1097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1098 goto out;
1099 }
1100
1101 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1102 total_data - 4);
1103 if (!ea_list) {
1104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1105 goto out;
1106 }
1107
1108 if (!lp_ea_support(SNUM(conn))) {
1109 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1110 goto out;
1111 }
1112 }
1113
1114 status = SMB_VFS_CREATE_FILE(
1115 conn, /* conn */
1116 req, /* req */
1117 0, /* root_dir_fid */
1118 smb_fname, /* fname */
1119 access_mask, /* access_mask */
1120 share_mode, /* share_access */
1121 create_disposition, /* create_disposition*/
1122 create_options, /* create_options */
1123 open_attr, /* file_attributes */
1124 oplock_request, /* oplock_request */
1125 open_size, /* allocation_size */
1126 NULL, /* sd */
1127 ea_list, /* ea_list */
1128 &fsp, /* result */
1129 &smb_action); /* psbuf */
1130
1131 if (!NT_STATUS_IS_OK(status)) {
1132 if (open_was_deferred(req->mid)) {
1133 /* We have re-scheduled this call. */
1134 goto out;
1135 }
1136 reply_openerror(req, status);
1137 goto out;
1138 }
1139
1140 size = get_file_size_stat(&smb_fname->st);
1141 fattr = dos_mode(conn, smb_fname);
1142 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1143 inode = smb_fname->st.st_ex_ino;
1144 if (fattr & aDIR) {
1145 close_file(req, fsp, ERROR_CLOSE);
1146 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1147 goto out;
1148 }
1149
1150 /* Realloc the size of parameters and data we will return */
1151 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1152 if(*pparams == NULL ) {
1153 reply_nterror(req, NT_STATUS_NO_MEMORY);
1154 goto out;
1155 }
1156 params = *pparams;
1157
1158 SSVAL(params,0,fsp->fnum);
1159 SSVAL(params,2,fattr);
1160 srv_put_dos_date2(params,4, mtime);
1161 SIVAL(params,8, (uint32)size);
1162 SSVAL(params,12,deny_mode);
1163 SSVAL(params,14,0); /* open_type - file or directory. */
1164 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1165
1166 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1167 smb_action |= EXTENDED_OPLOCK_GRANTED;
1168 }
1169
1170 SSVAL(params,18,smb_action);
1171
1172 /*
1173 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1174 */
1175 SIVAL(params,20,inode);
1176 SSVAL(params,24,0); /* Padding. */
1177 if (flags & 8) {
1178 uint32 ea_size = estimate_ea_size(conn, fsp,
1179 fsp->fsp_name->base_name);
1180 SIVAL(params, 26, ea_size);
1181 } else {
1182 SIVAL(params, 26, 0);
1183 }
1184
1185 /* Send the required number of replies */
1186 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1187 out:
1188 TALLOC_FREE(smb_fname);
1189}
1190
1191/*********************************************************
1192 Routine to check if a given string matches exactly.
1193 as a special case a mask of "." does NOT match. That
1194 is required for correct wildcard semantics
1195 Case can be significant or not.
1196**********************************************************/
1197
1198static bool exact_match(bool has_wild,
1199 bool case_sensitive,
1200 const char *str,
1201 const char *mask)
1202{
1203 if (mask[0] == '.' && mask[1] == 0) {
1204 return false;
1205 }
1206
1207 if (has_wild) {
1208 return false;
1209 }
1210
1211 if (case_sensitive) {
1212 return strcmp(str,mask)==0;
1213 } else {
1214 return StrCaseCmp(str,mask) == 0;
1215 }
1216}
1217
1218/****************************************************************************
1219 Return the filetype for UNIX extensions.
1220****************************************************************************/
1221
1222static uint32 unix_filetype(mode_t mode)
1223{
1224 if(S_ISREG(mode))
1225 return UNIX_TYPE_FILE;
1226 else if(S_ISDIR(mode))
1227 return UNIX_TYPE_DIR;
1228#ifdef S_ISLNK
1229 else if(S_ISLNK(mode))
1230 return UNIX_TYPE_SYMLINK;
1231#endif
1232#ifdef S_ISCHR
1233 else if(S_ISCHR(mode))
1234 return UNIX_TYPE_CHARDEV;
1235#endif
1236#ifdef S_ISBLK
1237 else if(S_ISBLK(mode))
1238 return UNIX_TYPE_BLKDEV;
1239#endif
1240#ifdef S_ISFIFO
1241 else if(S_ISFIFO(mode))
1242 return UNIX_TYPE_FIFO;
1243#endif
1244#ifdef S_ISSOCK
1245 else if(S_ISSOCK(mode))
1246 return UNIX_TYPE_SOCKET;
1247#endif
1248
1249 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1250 return UNIX_TYPE_UNKNOWN;
1251}
1252
1253/****************************************************************************
1254 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1255****************************************************************************/
1256
1257enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1258
1259static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1260 const SMB_STRUCT_STAT *psbuf,
1261 uint32 perms,
1262 enum perm_type ptype,
1263 mode_t *ret_perms)
1264{
1265 mode_t ret = 0;
1266
1267 if (perms == SMB_MODE_NO_CHANGE) {
1268 if (!VALID_STAT(*psbuf)) {
1269 return NT_STATUS_INVALID_PARAMETER;
1270 } else {
1271 *ret_perms = psbuf->st_ex_mode;
1272 return NT_STATUS_OK;
1273 }
1274 }
1275
1276 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1277 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1278 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1279 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1280 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1281 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1282 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1283 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1284 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1285#ifdef S_ISVTX
1286 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1287#endif
1288#ifdef S_ISGID
1289 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1290#endif
1291#ifdef S_ISUID
1292 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1293#endif
1294
1295 switch (ptype) {
1296 case PERM_NEW_FILE:
1297 /* Apply mode mask */
1298 ret &= lp_create_mask(SNUM(conn));
1299 /* Add in force bits */
1300 ret |= lp_force_create_mode(SNUM(conn));
1301 break;
1302 case PERM_NEW_DIR:
1303 ret &= lp_dir_mask(SNUM(conn));
1304 /* Add in force bits */
1305 ret |= lp_force_dir_mode(SNUM(conn));
1306 break;
1307 case PERM_EXISTING_FILE:
1308 /* Apply mode mask */
1309 ret &= lp_security_mask(SNUM(conn));
1310 /* Add in force bits */
1311 ret |= lp_force_security_mode(SNUM(conn));
1312 break;
1313 case PERM_EXISTING_DIR:
1314 /* Apply mode mask */
1315 ret &= lp_dir_security_mask(SNUM(conn));
1316 /* Add in force bits */
1317 ret |= lp_force_dir_security_mode(SNUM(conn));
1318 break;
1319 }
1320
1321 *ret_perms = ret;
1322 return NT_STATUS_OK;
1323}
1324
1325/****************************************************************************
1326 Needed to show the msdfs symlinks as directories. Modifies psbuf
1327 to be a directory if it's a msdfs link.
1328****************************************************************************/
1329
1330static bool check_msdfs_link(connection_struct *conn,
1331 const char *pathname,
1332 SMB_STRUCT_STAT *psbuf)
1333{
1334 int saved_errno = errno;
1335 if(lp_host_msdfs() &&
1336 lp_msdfs_root(SNUM(conn)) &&
1337 is_msdfs_link(conn, pathname, psbuf)) {
1338
1339 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1340 "as a directory\n",
1341 pathname));
1342 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1343 errno = saved_errno;
1344 return true;
1345 }
1346 errno = saved_errno;
1347 return false;
1348}
1349
1350
1351/****************************************************************************
1352 Get a level dependent lanman2 dir entry.
1353****************************************************************************/
1354
1355struct smbd_dirptr_lanman2_state {
1356 connection_struct *conn;
1357 uint32_t info_level;
1358 bool check_mangled_names;
1359 bool has_wild;
1360 bool got_exact_match;
1361};
1362
1363static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1364 void *private_data,
1365 const char *dname,
1366 const char *mask,
1367 char **_fname)
1368{
1369 struct smbd_dirptr_lanman2_state *state =
1370 (struct smbd_dirptr_lanman2_state *)private_data;
1371 bool ok;
1372 char mangled_name[13]; /* mangled 8.3 name. */
1373 bool got_match;
1374 const char *fname;
1375
1376 /* Mangle fname if it's an illegal name. */
1377 if (mangle_must_mangle(dname, state->conn->params)) {
1378 ok = name_to_8_3(dname, mangled_name,
1379 true, state->conn->params);
1380 if (!ok) {
1381 return false;
1382 }
1383 fname = mangled_name;
1384 } else {
1385 fname = dname;
1386 }
1387
1388 got_match = exact_match(state->has_wild,
1389 state->conn->case_sensitive,
1390 fname, mask);
1391 state->got_exact_match = got_match;
1392 if (!got_match) {
1393 got_match = mask_match(fname, mask,
1394 state->conn->case_sensitive);
1395 }
1396
1397 if(!got_match && state->check_mangled_names &&
1398 !mangle_is_8_3(fname, false, state->conn->params)) {
1399 /*
1400 * It turns out that NT matches wildcards against
1401 * both long *and* short names. This may explain some
1402 * of the wildcard wierdness from old DOS clients
1403 * that some people have been seeing.... JRA.
1404 */
1405 /* Force the mangling into 8.3. */
1406 ok = name_to_8_3(fname, mangled_name,
1407 false, state->conn->params);
1408 if (!ok) {
1409 return false;
1410 }
1411
1412 got_match = exact_match(state->has_wild,
1413 state->conn->case_sensitive,
1414 mangled_name, mask);
1415 state->got_exact_match = got_match;
1416 if (!got_match) {
1417 got_match = mask_match(mangled_name, mask,
1418 state->conn->case_sensitive);
1419 }
1420 }
1421
1422 if (!got_match) {
1423 return false;
1424 }
1425
1426 *_fname = talloc_strdup(ctx, fname);
1427 if (*_fname == NULL) {
1428 return false;
1429 }
1430
1431 return true;
1432}
1433
1434static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1435 void *private_data,
1436 struct smb_filename *smb_fname,
1437 uint32_t *_mode)
1438{
1439 struct smbd_dirptr_lanman2_state *state =
1440 (struct smbd_dirptr_lanman2_state *)private_data;
1441 bool ms_dfs_link = false;
1442 uint32_t mode = 0;
1443
1444 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1445 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1446 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1447 "Couldn't lstat [%s] (%s)\n",
1448 smb_fname_str_dbg(smb_fname),
1449 strerror(errno)));
1450 return false;
1451 }
1452 } else if (!VALID_STAT(smb_fname->st) &&
1453 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1454 /* Needed to show the msdfs symlinks as
1455 * directories */
1456
1457 ms_dfs_link = check_msdfs_link(state->conn,
1458 smb_fname->base_name,
1459 &smb_fname->st);
1460 if (!ms_dfs_link) {
1461 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1462 "Couldn't stat [%s] (%s)\n",
1463 smb_fname_str_dbg(smb_fname),
1464 strerror(errno)));
1465 return false;
1466 }
1467 }
1468
1469 if (ms_dfs_link) {
1470 mode = dos_mode_msdfs(state->conn, smb_fname);
1471 } else {
1472 mode = dos_mode(state->conn, smb_fname);
1473 }
1474
1475 *_mode = mode;
1476 return true;
1477}
1478
1479static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1480 connection_struct *conn,
1481 uint16_t flags2,
1482 uint32_t info_level,
1483 struct ea_list *name_list,
1484 bool check_mangled_names,
1485 bool requires_resume_key,
1486 uint32_t mode,
1487 const char *fname,
1488 const struct smb_filename *smb_fname,
1489 uint64_t space_remaining,
1490 uint8_t align,
1491 bool do_pad,
1492 char *base_data,
1493 char **ppdata,
1494 char *end_data,
1495 bool *out_of_space,
1496 uint64_t *last_entry_off)
1497{
1498 char *p, *q, *pdata = *ppdata;
1499 uint32_t reskey=0;
1500 uint64_t file_size = 0;
1501 uint64_t allocation_size = 0;
1502 uint64_t file_index = 0;
1503 uint32_t len;
1504 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1505 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1506 time_t c_date = (time_t)0;
1507 char *nameptr;
1508 char *last_entry_ptr;
1509 bool was_8_3;
1510 off_t off;
1511 off_t pad = 0;
1512
1513 *out_of_space = false;
1514
1515 ZERO_STRUCT(mdate_ts);
1516 ZERO_STRUCT(adate_ts);
1517 ZERO_STRUCT(create_date_ts);
1518 ZERO_STRUCT(cdate_ts);
1519
1520 if (!(mode & aDIR)) {
1521 file_size = get_file_size_stat(&smb_fname->st);
1522 }
1523 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1524
1525 file_index = get_FileIndex(conn, &smb_fname->st);
1526
1527 mdate_ts = smb_fname->st.st_ex_mtime;
1528 adate_ts = smb_fname->st.st_ex_atime;
1529 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1530 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1531
1532 if (lp_dos_filetime_resolution(SNUM(conn))) {
1533 dos_filetime_timespec(&create_date_ts);
1534 dos_filetime_timespec(&mdate_ts);
1535 dos_filetime_timespec(&adate_ts);
1536 dos_filetime_timespec(&cdate_ts);
1537 }
1538
1539 create_date = convert_timespec_to_time_t(create_date_ts);
1540 mdate = convert_timespec_to_time_t(mdate_ts);
1541 adate = convert_timespec_to_time_t(adate_ts);
1542 c_date = convert_timespec_to_time_t(cdate_ts);
1543
1544 /* align the record */
1545 off = PTR_DIFF(pdata, base_data);
1546 pad = (off + (align-1)) & ~(align-1);
1547 pad -= off;
1548 off += pad;
1549 /* initialize padding to 0 */
1550 if (pad) {
1551 memset(pdata, 0, pad);
1552 }
1553 space_remaining -= pad;
1554
1555 pdata += pad;
1556 p = pdata;
1557 last_entry_ptr = p;
1558
1559 pad = 0;
1560 off = 0;
1561
1562 switch (info_level) {
1563 case SMB_FIND_INFO_STANDARD:
1564 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1565 if(requires_resume_key) {
1566 SIVAL(p,0,reskey);
1567 p += 4;
1568 }
1569 srv_put_dos_date2(p,0,create_date);
1570 srv_put_dos_date2(p,4,adate);
1571 srv_put_dos_date2(p,8,mdate);
1572 SIVAL(p,12,(uint32)file_size);
1573 SIVAL(p,16,(uint32)allocation_size);
1574 SSVAL(p,20,mode);
1575 p += 23;
1576 nameptr = p;
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 p += ucs2_align(base_data, p, 0);
1579 }
1580 len = srvstr_push(base_data, flags2, p,
1581 fname, PTR_DIFF(end_data, p),
1582 STR_TERMINATE);
1583 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1584 if (len > 2) {
1585 SCVAL(nameptr, -1, len - 2);
1586 } else {
1587 SCVAL(nameptr, -1, 0);
1588 }
1589 } else {
1590 if (len > 1) {
1591 SCVAL(nameptr, -1, len - 1);
1592 } else {
1593 SCVAL(nameptr, -1, 0);
1594 }
1595 }
1596 p += len;
1597 break;
1598
1599 case SMB_FIND_EA_SIZE:
1600 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1601 if (requires_resume_key) {
1602 SIVAL(p,0,reskey);
1603 p += 4;
1604 }
1605 srv_put_dos_date2(p,0,create_date);
1606 srv_put_dos_date2(p,4,adate);
1607 srv_put_dos_date2(p,8,mdate);
1608 SIVAL(p,12,(uint32)file_size);
1609 SIVAL(p,16,(uint32)allocation_size);
1610 SSVAL(p,20,mode);
1611 {
1612 unsigned int ea_size = estimate_ea_size(conn, NULL,
1613 smb_fname->base_name);
1614 SIVAL(p,22,ea_size); /* Extended attributes */
1615 }
1616 p += 27;
1617 nameptr = p - 1;
1618 len = srvstr_push(base_data, flags2,
1619 p, fname, PTR_DIFF(end_data, p),
1620 STR_TERMINATE | STR_NOALIGN);
1621 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1622 if (len > 2) {
1623 len -= 2;
1624 } else {
1625 len = 0;
1626 }
1627 } else {
1628 if (len > 1) {
1629 len -= 1;
1630 } else {
1631 len = 0;
1632 }
1633 }
1634 SCVAL(nameptr,0,len);
1635 p += len;
1636 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1637 break;
1638
1639 case SMB_FIND_EA_LIST:
1640 {
1641 struct ea_list *file_list = NULL;
1642 size_t ea_len = 0;
1643
1644 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1645 if (!name_list) {
1646 return false;
1647 }
1648 if (requires_resume_key) {
1649 SIVAL(p,0,reskey);
1650 p += 4;
1651 }
1652 srv_put_dos_date2(p,0,create_date);
1653 srv_put_dos_date2(p,4,adate);
1654 srv_put_dos_date2(p,8,mdate);
1655 SIVAL(p,12,(uint32)file_size);
1656 SIVAL(p,16,(uint32)allocation_size);
1657 SSVAL(p,20,mode);
1658 p += 22; /* p now points to the EA area. */
1659
1660 file_list = get_ea_list_from_file(ctx, conn, NULL,
1661 smb_fname->base_name,
1662 &ea_len);
1663 name_list = ea_list_union(name_list, file_list, &ea_len);
1664
1665 /* We need to determine if this entry will fit in the space available. */
1666 /* Max string size is 255 bytes. */
1667 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1668 *out_of_space = true;
1669 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1670 return False; /* Not finished - just out of space */
1671 }
1672
1673 /* Push the ea_data followed by the name. */
1674 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1675 nameptr = p;
1676 len = srvstr_push(base_data, flags2,
1677 p + 1, fname, PTR_DIFF(end_data, p+1),
1678 STR_TERMINATE | STR_NOALIGN);
1679 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1680 if (len > 2) {
1681 len -= 2;
1682 } else {
1683 len = 0;
1684 }
1685 } else {
1686 if (len > 1) {
1687 len -= 1;
1688 } else {
1689 len = 0;
1690 }
1691 }
1692 SCVAL(nameptr,0,len);
1693 p += len + 1;
1694 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1695 break;
1696 }
1697
1698 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1699 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1700 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1701 p += 4;
1702 SIVAL(p,0,reskey); p += 4;
1703 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1704 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1705 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1706 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1707 SOFF_T(p,0,file_size); p += 8;
1708 SOFF_T(p,0,allocation_size); p += 8;
1709 SIVAL(p,0,mode); p += 4;
1710 q = p; p += 4; /* q is placeholder for name length. */
1711 {
1712 unsigned int ea_size = estimate_ea_size(conn, NULL,
1713 smb_fname->base_name);
1714 SIVAL(p,0,ea_size); /* Extended attributes */
1715 p += 4;
1716 }
1717 /* Clear the short name buffer. This is
1718 * IMPORTANT as not doing so will trigger
1719 * a Win2k client bug. JRA.
1720 */
1721 if (!was_8_3 && check_mangled_names) {
1722 char mangled_name[13]; /* mangled 8.3 name. */
1723 if (!name_to_8_3(fname,mangled_name,True,
1724 conn->params)) {
1725 /* Error - mangle failed ! */
1726 memset(mangled_name,'\0',12);
1727 }
1728 mangled_name[12] = 0;
1729 len = srvstr_push(base_data, flags2,
1730 p+2, mangled_name, 24,
1731 STR_UPPER|STR_UNICODE);
1732 if (len < 24) {
1733 memset(p + 2 + len,'\0',24 - len);
1734 }
1735 SSVAL(p, 0, len);
1736 } else {
1737 memset(p,'\0',26);
1738 }
1739 p += 2 + 24;
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q,0,len);
1744 p += len;
1745
1746 len = PTR_DIFF(p, pdata);
1747 pad = (len + (align-1)) & ~(align-1);
1748 /*
1749 * offset to the next entry, the caller
1750 * will overwrite it for the last entry
1751 * that's why we always include the padding
1752 */
1753 SIVAL(pdata,0,pad);
1754 /*
1755 * set padding to zero
1756 */
1757 if (do_pad) {
1758 memset(p, 0, pad - len);
1759 p = pdata + pad;
1760 } else {
1761 p = pdata + len;
1762 }
1763 break;
1764
1765 case SMB_FIND_FILE_DIRECTORY_INFO:
1766 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1767 p += 4;
1768 SIVAL(p,0,reskey); p += 4;
1769 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1770 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1771 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1772 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1773 SOFF_T(p,0,file_size); p += 8;
1774 SOFF_T(p,0,allocation_size); p += 8;
1775 SIVAL(p,0,mode); p += 4;
1776 len = srvstr_push(base_data, flags2,
1777 p + 4, fname, PTR_DIFF(end_data, p+4),
1778 STR_TERMINATE_ASCII);
1779 SIVAL(p,0,len);
1780 p += 4 + len;
1781
1782 len = PTR_DIFF(p, pdata);
1783 pad = (len + (align-1)) & ~(align-1);
1784 /*
1785 * offset to the next entry, the caller
1786 * will overwrite it for the last entry
1787 * that's why we always include the padding
1788 */
1789 SIVAL(pdata,0,pad);
1790 /*
1791 * set padding to zero
1792 */
1793 if (do_pad) {
1794 memset(p, 0, pad - len);
1795 p = pdata + pad;
1796 } else {
1797 p = pdata + len;
1798 }
1799 break;
1800
1801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1803 p += 4;
1804 SIVAL(p,0,reskey); p += 4;
1805 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1806 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1807 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1808 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1809 SOFF_T(p,0,file_size); p += 8;
1810 SOFF_T(p,0,allocation_size); p += 8;
1811 SIVAL(p,0,mode); p += 4;
1812 q = p; p += 4; /* q is placeholder for name length. */
1813 {
1814 unsigned int ea_size = estimate_ea_size(conn, NULL,
1815 smb_fname->base_name);
1816 SIVAL(p,0,ea_size); /* Extended attributes */
1817 p +=4;
1818 }
1819 len = srvstr_push(base_data, flags2, p,
1820 fname, PTR_DIFF(end_data, p),
1821 STR_TERMINATE_ASCII);
1822 SIVAL(q, 0, len);
1823 p += len;
1824
1825 len = PTR_DIFF(p, pdata);
1826 pad = (len + (align-1)) & ~(align-1);
1827 /*
1828 * offset to the next entry, the caller
1829 * will overwrite it for the last entry
1830 * that's why we always include the padding
1831 */
1832 SIVAL(pdata,0,pad);
1833 /*
1834 * set padding to zero
1835 */
1836 if (do_pad) {
1837 memset(p, 0, pad - len);
1838 p = pdata + pad;
1839 } else {
1840 p = pdata + len;
1841 }
1842 break;
1843
1844 case SMB_FIND_FILE_NAMES_INFO:
1845 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1846 p += 4;
1847 SIVAL(p,0,reskey); p += 4;
1848 p += 4;
1849 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1850 acl on a dir (tridge) */
1851 len = srvstr_push(base_data, flags2, p,
1852 fname, PTR_DIFF(end_data, p),
1853 STR_TERMINATE_ASCII);
1854 SIVAL(p, -4, len);
1855 p += len;
1856
1857 len = PTR_DIFF(p, pdata);
1858 pad = (len + (align-1)) & ~(align-1);
1859 /*
1860 * offset to the next entry, the caller
1861 * will overwrite it for the last entry
1862 * that's why we always include the padding
1863 */
1864 SIVAL(pdata,0,pad);
1865 /*
1866 * set padding to zero
1867 */
1868 if (do_pad) {
1869 memset(p, 0, pad - len);
1870 p = pdata + pad;
1871 } else {
1872 p = pdata + len;
1873 }
1874 break;
1875
1876 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1877 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1878 p += 4;
1879 SIVAL(p,0,reskey); p += 4;
1880 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1881 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1882 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1883 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1884 SOFF_T(p,0,file_size); p += 8;
1885 SOFF_T(p,0,allocation_size); p += 8;
1886 SIVAL(p,0,mode); p += 4;
1887 q = p; p += 4; /* q is placeholder for name length. */
1888 {
1889 unsigned int ea_size = estimate_ea_size(conn, NULL,
1890 smb_fname->base_name);
1891 SIVAL(p,0,ea_size); /* Extended attributes */
1892 p +=4;
1893 }
1894 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1895 SBVAL(p,0,file_index); p += 8;
1896 len = srvstr_push(base_data, flags2, p,
1897 fname, PTR_DIFF(end_data, p),
1898 STR_TERMINATE_ASCII);
1899 SIVAL(q, 0, len);
1900 p += len;
1901
1902 len = PTR_DIFF(p, pdata);
1903 pad = (len + (align-1)) & ~(align-1);
1904 /*
1905 * offset to the next entry, the caller
1906 * will overwrite it for the last entry
1907 * that's why we always include the padding
1908 */
1909 SIVAL(pdata,0,pad);
1910 /*
1911 * set padding to zero
1912 */
1913 if (do_pad) {
1914 memset(p, 0, pad - len);
1915 p = pdata + pad;
1916 } else {
1917 p = pdata + len;
1918 }
1919 break;
1920
1921 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1922 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1923 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1924 p += 4;
1925 SIVAL(p,0,reskey); p += 4;
1926 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1927 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1930 SOFF_T(p,0,file_size); p += 8;
1931 SOFF_T(p,0,allocation_size); p += 8;
1932 SIVAL(p,0,mode); p += 4;
1933 q = p; p += 4; /* q is placeholder for name length */
1934 {
1935 unsigned int ea_size = estimate_ea_size(conn, NULL,
1936 smb_fname->base_name);
1937 SIVAL(p,0,ea_size); /* Extended attributes */
1938 p +=4;
1939 }
1940 /* Clear the short name buffer. This is
1941 * IMPORTANT as not doing so will trigger
1942 * a Win2k client bug. JRA.
1943 */
1944 if (!was_8_3 && check_mangled_names) {
1945 char mangled_name[13]; /* mangled 8.3 name. */
1946 if (!name_to_8_3(fname,mangled_name,True,
1947 conn->params)) {
1948 /* Error - mangle failed ! */
1949 memset(mangled_name,'\0',12);
1950 }
1951 mangled_name[12] = 0;
1952 len = srvstr_push(base_data, flags2,
1953 p+2, mangled_name, 24,
1954 STR_UPPER|STR_UNICODE);
1955 SSVAL(p, 0, len);
1956 if (len < 24) {
1957 memset(p + 2 + len,'\0',24 - len);
1958 }
1959 SSVAL(p, 0, len);
1960 } else {
1961 memset(p,'\0',26);
1962 }
1963 p += 26;
1964 SSVAL(p,0,0); p += 2; /* Reserved ? */
1965 SBVAL(p,0,file_index); p += 8;
1966 len = srvstr_push(base_data, flags2, p,
1967 fname, PTR_DIFF(end_data, p),
1968 STR_TERMINATE_ASCII);
1969 SIVAL(q,0,len);
1970 p += len;
1971
1972 len = PTR_DIFF(p, pdata);
1973 pad = (len + (align-1)) & ~(align-1);
1974 /*
1975 * offset to the next entry, the caller
1976 * will overwrite it for the last entry
1977 * that's why we always include the padding
1978 */
1979 SIVAL(pdata,0,pad);
1980 /*
1981 * set padding to zero
1982 */
1983 if (do_pad) {
1984 memset(p, 0, pad - len);
1985 p = pdata + pad;
1986 } else {
1987 p = pdata + len;
1988 }
1989 break;
1990
1991 /* CIFS UNIX Extension. */
1992
1993 case SMB_FIND_FILE_UNIX:
1994 case SMB_FIND_FILE_UNIX_INFO2:
1995 p+= 4;
1996 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1997
1998 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1999
2000 if (info_level == SMB_FIND_FILE_UNIX) {
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2002 p = store_file_unix_basic(conn, p,
2003 NULL, &smb_fname->st);
2004 len = srvstr_push(base_data, flags2, p,
2005 fname, PTR_DIFF(end_data, p),
2006 STR_TERMINATE);
2007 } else {
2008 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2009 p = store_file_unix_basic_info2(conn, p,
2010 NULL, &smb_fname->st);
2011 nameptr = p;
2012 p += 4;
2013 len = srvstr_push(base_data, flags2, p, fname,
2014 PTR_DIFF(end_data, p), 0);
2015 SIVAL(nameptr, 0, len);
2016 }
2017
2018 p += len;
2019
2020 len = PTR_DIFF(p, pdata);
2021 pad = (len + (align-1)) & ~(align-1);
2022 /*
2023 * offset to the next entry, the caller
2024 * will overwrite it for the last entry
2025 * that's why we always include the padding
2026 */
2027 SIVAL(pdata,0,pad);
2028 /*
2029 * set padding to zero
2030 */
2031 if (do_pad) {
2032 memset(p, 0, pad - len);
2033 p = pdata + pad;
2034 } else {
2035 p = pdata + len;
2036 }
2037 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2038
2039 break;
2040
2041 default:
2042 return false;
2043 }
2044
2045 if (PTR_DIFF(p,pdata) > space_remaining) {
2046 *out_of_space = true;
2047 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2048 return false; /* Not finished - just out of space */
2049 }
2050
2051 /* Setup the last entry pointer, as an offset from base_data */
2052 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2053 /* Advance the data pointer to the next slot */
2054 *ppdata = p;
2055
2056 return true;
2057}
2058
2059bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2060 connection_struct *conn,
2061 struct dptr_struct *dirptr,
2062 uint16 flags2,
2063 const char *path_mask,
2064 uint32 dirtype,
2065 int info_level,
2066 int requires_resume_key,
2067 bool dont_descend,
2068 bool ask_sharemode,
2069 uint8_t align,
2070 bool do_pad,
2071 char **ppdata,
2072 char *base_data,
2073 char *end_data,
2074 int space_remaining,
2075 bool *out_of_space,
2076 bool *got_exact_match,
2077 int *_last_entry_off,
2078 struct ea_list *name_list)
2079{
2080 const char *p;
2081 const char *mask = NULL;
2082 long prev_dirpos = 0;
2083 uint32_t mode = 0;
2084 char *fname = NULL;
2085 struct smb_filename *smb_fname = NULL;
2086 struct smbd_dirptr_lanman2_state state;
2087 bool ok;
2088 uint64_t last_entry_off = 0;
2089
2090 ZERO_STRUCT(state);
2091 state.conn = conn;
2092 state.info_level = info_level;
2093 state.check_mangled_names = lp_manglednames(conn->params);
2094 state.has_wild = dptr_has_wild(dirptr);
2095 state.got_exact_match = false;
2096
2097 *out_of_space = false;
2098 *got_exact_match = false;
2099
2100 p = strrchr_m(path_mask,'/');
2101 if(p != NULL) {
2102 if(p[1] == '\0') {
2103 mask = "*.*";
2104 } else {
2105 mask = p+1;
2106 }
2107 } else {
2108 mask = path_mask;
2109 }
2110
2111 ok = smbd_dirptr_get_entry(ctx,
2112 dirptr,
2113 mask,
2114 dirtype,
2115 dont_descend,
2116 ask_sharemode,
2117 smbd_dirptr_lanman2_match_fn,
2118 smbd_dirptr_lanman2_mode_fn,
2119 &state,
2120 &fname,
2121 &smb_fname,
2122 &mode,
2123 &prev_dirpos);
2124 if (!ok) {
2125 return false;
2126 }
2127
2128 *got_exact_match = state.got_exact_match;
2129
2130 ok = smbd_marshall_dir_entry(ctx,
2131 conn,
2132 flags2,
2133 info_level,
2134 name_list,
2135 state.check_mangled_names,
2136 requires_resume_key,
2137 mode,
2138 fname,
2139 smb_fname,
2140 space_remaining,
2141 align,
2142 do_pad,
2143 base_data,
2144 ppdata,
2145 end_data,
2146 out_of_space,
2147 &last_entry_off);
2148 TALLOC_FREE(fname);
2149 TALLOC_FREE(smb_fname);
2150 if (*out_of_space) {
2151 dptr_SeekDir(dirptr, prev_dirpos);
2152 return false;
2153 }
2154 if (!ok) {
2155 return false;
2156 }
2157
2158 *_last_entry_off = last_entry_off;
2159 return true;
2160}
2161
2162static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2163 connection_struct *conn,
2164 struct dptr_struct *dirptr,
2165 uint16 flags2,
2166 const char *path_mask,
2167 uint32 dirtype,
2168 int info_level,
2169 bool requires_resume_key,
2170 bool dont_descend,
2171 bool ask_sharemode,
2172 char **ppdata,
2173 char *base_data,
2174 char *end_data,
2175 int space_remaining,
2176 bool *out_of_space,
2177 bool *got_exact_match,
2178 int *last_entry_off,
2179 struct ea_list *name_list)
2180{
2181 uint8_t align = 4;
2182 const bool do_pad = true;
2183
2184 if (info_level >= 1 && info_level <= 3) {
2185 /* No alignment on earlier info levels. */
2186 align = 1;
2187 }
2188
2189 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2190 path_mask, dirtype, info_level,
2191 requires_resume_key, dont_descend, ask_sharemode,
2192 align, do_pad,
2193 ppdata, base_data, end_data,
2194 space_remaining,
2195 out_of_space, got_exact_match,
2196 last_entry_off, name_list);
2197}
2198
2199/****************************************************************************
2200 Reply to a TRANS2_FINDFIRST.
2201****************************************************************************/
2202
2203static void call_trans2findfirst(connection_struct *conn,
2204 struct smb_request *req,
2205 char **pparams, int total_params,
2206 char **ppdata, int total_data,
2207 unsigned int max_data_bytes)
2208{
2209 /* We must be careful here that we don't return more than the
2210 allowed number of data bytes. If this means returning fewer than
2211 maxentries then so be it. We assume that the redirector has
2212 enough room for the fixed number of parameter bytes it has
2213 requested. */
2214 struct smb_filename *smb_dname = NULL;
2215 char *params = *pparams;
2216 char *pdata = *ppdata;
2217 char *data_end;
2218 uint32 dirtype;
2219 int maxentries;
2220 uint16 findfirst_flags;
2221 bool close_after_first;
2222 bool close_if_end;
2223 bool requires_resume_key;
2224 int info_level;
2225 char *directory = NULL;
2226 char *mask = NULL;
2227 char *p;
2228 int last_entry_off=0;
2229 int dptr_num = -1;
2230 int numentries = 0;
2231 int i;
2232 bool finished = False;
2233 bool dont_descend = False;
2234 bool out_of_space = False;
2235 int space_remaining;
2236 bool mask_contains_wcard = False;
2237 struct ea_list *ea_list = NULL;
2238 NTSTATUS ntstatus = NT_STATUS_OK;
2239 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2240 TALLOC_CTX *ctx = talloc_tos();
2241 struct dptr_struct *dirptr = NULL;
2242 struct smbd_server_connection *sconn = smbd_server_conn;
2243 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2244
2245 if (total_params < 13) {
2246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2247 goto out;
2248 }
2249
2250 dirtype = SVAL(params,0);
2251 maxentries = SVAL(params,2);
2252 findfirst_flags = SVAL(params,4);
2253 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2254 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2255 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2256 info_level = SVAL(params,6);
2257
2258 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2259close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2260 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2261 info_level, max_data_bytes));
2262
2263 if (!maxentries) {
2264 /* W2K3 seems to treat zero as 1. */
2265 maxentries = 1;
2266 }
2267
2268 switch (info_level) {
2269 case SMB_FIND_INFO_STANDARD:
2270 case SMB_FIND_EA_SIZE:
2271 case SMB_FIND_EA_LIST:
2272 case SMB_FIND_FILE_DIRECTORY_INFO:
2273 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2274 case SMB_FIND_FILE_NAMES_INFO:
2275 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2276 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2277 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2278 break;
2279 case SMB_FIND_FILE_UNIX:
2280 case SMB_FIND_FILE_UNIX_INFO2:
2281 /* Always use filesystem for UNIX mtime query. */
2282 ask_sharemode = false;
2283 if (!lp_unix_extensions()) {
2284 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2285 goto out;
2286 }
2287 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2288 break;
2289 default:
2290 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2291 goto out;
2292 }
2293
2294 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2295 params+12, total_params - 12,
2296 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2297 if (!NT_STATUS_IS_OK(ntstatus)) {
2298 reply_nterror(req, ntstatus);
2299 goto out;
2300 }
2301
2302 ntstatus = filename_convert(ctx, conn,
2303 req->flags2 & FLAGS2_DFS_PATHNAMES,
2304 directory,
2305 ucf_flags,
2306 &mask_contains_wcard,
2307 &smb_dname);
2308 if (!NT_STATUS_IS_OK(ntstatus)) {
2309 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2310 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2311 ERRSRV, ERRbadpath);
2312 goto out;
2313 }
2314 reply_nterror(req, ntstatus);
2315 goto out;
2316 }
2317
2318 mask = smb_dname->original_lcomp;
2319
2320 directory = smb_dname->base_name;
2321
2322 p = strrchr_m(directory,'/');
2323 if(p == NULL) {
2324 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2325 if((directory[0] == '.') && (directory[1] == '\0')) {
2326 mask = talloc_strdup(ctx,"*");
2327 if (!mask) {
2328 reply_nterror(req, NT_STATUS_NO_MEMORY);
2329 goto out;
2330 }
2331 mask_contains_wcard = True;
2332 }
2333 directory = talloc_strdup(talloc_tos(), "./");
2334 if (!directory) {
2335 reply_nterror(req, NT_STATUS_NO_MEMORY);
2336 goto out;
2337 }
2338 } else {
2339 *p = 0;
2340 }
2341
2342 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2343
2344 if (info_level == SMB_FIND_EA_LIST) {
2345 uint32 ea_size;
2346
2347 if (total_data < 4) {
2348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2349 goto out;
2350 }
2351
2352 ea_size = IVAL(pdata,0);
2353 if (ea_size != total_data) {
2354 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2355total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2357 goto out;
2358 }
2359
2360 if (!lp_ea_support(SNUM(conn))) {
2361 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2362 goto out;
2363 }
2364
2365 /* Pull out the list of names. */
2366 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2367 if (!ea_list) {
2368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 goto out;
2370 }
2371 }
2372
2373 *ppdata = (char *)SMB_REALLOC(
2374 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2375 if(*ppdata == NULL ) {
2376 reply_nterror(req, NT_STATUS_NO_MEMORY);
2377 goto out;
2378 }
2379 pdata = *ppdata;
2380 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2381
2382 /* Realloc the params space */
2383 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2384 if (*pparams == NULL) {
2385 reply_nterror(req, NT_STATUS_NO_MEMORY);
2386 goto out;
2387 }
2388 params = *pparams;
2389
2390 /* Save the wildcard match and attribs we are using on this directory -
2391 needed as lanman2 assumes these are being saved between calls */
2392
2393 ntstatus = dptr_create(conn,
2394 directory,
2395 False,
2396 True,
2397 req->smbpid,
2398 mask,
2399 mask_contains_wcard,
2400 dirtype,
2401 &dirptr);
2402
2403 if (!NT_STATUS_IS_OK(ntstatus)) {
2404 reply_nterror(req, ntstatus);
2405 goto out;
2406 }
2407
2408 dptr_num = dptr_dnum(dirptr);
2409 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2410
2411 /* Initialize per TRANS2_FIND_FIRST operation data */
2412 dptr_init_search_op(dirptr);
2413
2414 /* We don't need to check for VOL here as this is returned by
2415 a different TRANS2 call. */
2416
2417 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2418 directory,lp_dontdescend(SNUM(conn))));
2419 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2420 dont_descend = True;
2421
2422 p = pdata;
2423 space_remaining = max_data_bytes;
2424 out_of_space = False;
2425
2426 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2427 bool got_exact_match = False;
2428
2429 /* this is a heuristic to avoid seeking the dirptr except when
2430 absolutely necessary. It allows for a filename of about 40 chars */
2431 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2432 out_of_space = True;
2433 finished = False;
2434 } else {
2435 finished = !get_lanman2_dir_entry(ctx,
2436 conn,
2437 dirptr,
2438 req->flags2,
2439 mask,dirtype,info_level,
2440 requires_resume_key,dont_descend,
2441 ask_sharemode,
2442 &p,pdata,data_end,
2443 space_remaining, &out_of_space,
2444 &got_exact_match,
2445 &last_entry_off, ea_list);
2446 }
2447
2448 if (finished && out_of_space)
2449 finished = False;
2450
2451 if (!finished && !out_of_space)
2452 numentries++;
2453
2454 /*
2455 * As an optimisation if we know we aren't looking
2456 * for a wildcard name (ie. the name matches the wildcard exactly)
2457 * then we can finish on any (first) match.
2458 * This speeds up large directory searches. JRA.
2459 */
2460
2461 if(got_exact_match)
2462 finished = True;
2463
2464 /* Ensure space_remaining never goes -ve. */
2465 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2466 space_remaining = 0;
2467 out_of_space = true;
2468 } else {
2469 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2470 }
2471 }
2472
2473 /* Check if we can close the dirptr */
2474 if(close_after_first || (finished && close_if_end)) {
2475 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2476 dptr_close(sconn, &dptr_num);
2477 }
2478
2479 /*
2480 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2481 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2482 * the protocol level is less than NT1. Tested with smbclient. JRA.
2483 * This should fix the OS/2 client bug #2335.
2484 */
2485
2486 if(numentries == 0) {
2487 dptr_close(sconn, &dptr_num);
2488 if (get_Protocol() < PROTOCOL_NT1) {
2489 reply_force_doserror(req, ERRDOS, ERRnofiles);
2490 goto out;
2491 } else {
2492 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2493 ERRDOS, ERRbadfile);
2494 goto out;
2495 }
2496 }
2497
2498 /* At this point pdata points to numentries directory entries. */
2499
2500 /* Set up the return parameter block */
2501 SSVAL(params,0,dptr_num);
2502 SSVAL(params,2,numentries);
2503 SSVAL(params,4,finished);
2504 SSVAL(params,6,0); /* Never an EA error */
2505 SSVAL(params,8,last_entry_off);
2506
2507 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2508 max_data_bytes);
2509
2510 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2511 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2512 if (!directory) {
2513 reply_nterror(req, NT_STATUS_NO_MEMORY);
2514 }
2515 }
2516
2517 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2518 smb_fn_name(req->cmd),
2519 mask, directory, dirtype, numentries ) );
2520
2521 /*
2522 * Force a name mangle here to ensure that the
2523 * mask as an 8.3 name is top of the mangled cache.
2524 * The reasons for this are subtle. Don't remove
2525 * this code unless you know what you are doing
2526 * (see PR#13758). JRA.
2527 */
2528
2529 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2530 char mangled_name[13];
2531 name_to_8_3(mask, mangled_name, True, conn->params);
2532 }
2533 out:
2534 TALLOC_FREE(smb_dname);
2535 return;
2536}
2537
2538/****************************************************************************
2539 Reply to a TRANS2_FINDNEXT.
2540****************************************************************************/
2541
2542static void call_trans2findnext(connection_struct *conn,
2543 struct smb_request *req,
2544 char **pparams, int total_params,
2545 char **ppdata, int total_data,
2546 unsigned int max_data_bytes)
2547{
2548 /* We must be careful here that we don't return more than the
2549 allowed number of data bytes. If this means returning fewer than
2550 maxentries then so be it. We assume that the redirector has
2551 enough room for the fixed number of parameter bytes it has
2552 requested. */
2553 char *params = *pparams;
2554 char *pdata = *ppdata;
2555 char *data_end;
2556 int dptr_num;
2557 int maxentries;
2558 uint16 info_level;
2559 uint32 resume_key;
2560 uint16 findnext_flags;
2561 bool close_after_request;
2562 bool close_if_end;
2563 bool requires_resume_key;
2564 bool continue_bit;
2565 bool mask_contains_wcard = False;
2566 char *resume_name = NULL;
2567 const char *mask = NULL;
2568 const char *directory = NULL;
2569 char *p = NULL;
2570 uint16 dirtype;
2571 int numentries = 0;
2572 int i, last_entry_off=0;
2573 bool finished = False;
2574 bool dont_descend = False;
2575 bool out_of_space = False;
2576 int space_remaining;
2577 struct ea_list *ea_list = NULL;
2578 NTSTATUS ntstatus = NT_STATUS_OK;
2579 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2580 TALLOC_CTX *ctx = talloc_tos();
2581 struct dptr_struct *dirptr;
2582 struct smbd_server_connection *sconn = smbd_server_conn;
2583
2584 if (total_params < 13) {
2585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2586 return;
2587 }
2588
2589 dptr_num = SVAL(params,0);
2590 maxentries = SVAL(params,2);
2591 info_level = SVAL(params,4);
2592 resume_key = IVAL(params,6);
2593 findnext_flags = SVAL(params,10);
2594 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2595 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2596 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2597 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2598
2599 if (!continue_bit) {
2600 /* We only need resume_name if continue_bit is zero. */
2601 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2602 params+12,
2603 total_params - 12, STR_TERMINATE, &ntstatus,
2604 &mask_contains_wcard);
2605 if (!NT_STATUS_IS_OK(ntstatus)) {
2606 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2607 complain (it thinks we're asking for the directory above the shared
2608 path or an invalid name). Catch this as the resume name is only compared, never used in
2609 a file access. JRA. */
2610 srvstr_pull_talloc(ctx, params, req->flags2,
2611 &resume_name, params+12,
2612 total_params - 12,
2613 STR_TERMINATE);
2614
2615 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2616 reply_nterror(req, ntstatus);
2617 return;
2618 }
2619 }
2620 }
2621
2622 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2623close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2624resume_key = %d resume name = %s continue=%d level = %d\n",
2625 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2626 requires_resume_key, resume_key,
2627 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2628
2629 if (!maxentries) {
2630 /* W2K3 seems to treat zero as 1. */
2631 maxentries = 1;
2632 }
2633
2634 switch (info_level) {
2635 case SMB_FIND_INFO_STANDARD:
2636 case SMB_FIND_EA_SIZE:
2637 case SMB_FIND_EA_LIST:
2638 case SMB_FIND_FILE_DIRECTORY_INFO:
2639 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2640 case SMB_FIND_FILE_NAMES_INFO:
2641 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2642 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2643 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2644 break;
2645 case SMB_FIND_FILE_UNIX:
2646 case SMB_FIND_FILE_UNIX_INFO2:
2647 /* Always use filesystem for UNIX mtime query. */
2648 ask_sharemode = false;
2649 if (!lp_unix_extensions()) {
2650 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2651 return;
2652 }
2653 break;
2654 default:
2655 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2656 return;
2657 }
2658
2659 if (info_level == SMB_FIND_EA_LIST) {
2660 uint32 ea_size;
2661
2662 if (total_data < 4) {
2663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2664 return;
2665 }
2666
2667 ea_size = IVAL(pdata,0);
2668 if (ea_size != total_data) {
2669 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2670total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2672 return;
2673 }
2674
2675 if (!lp_ea_support(SNUM(conn))) {
2676 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2677 return;
2678 }
2679
2680 /* Pull out the list of names. */
2681 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2682 if (!ea_list) {
2683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2684 return;
2685 }
2686 }
2687
2688 *ppdata = (char *)SMB_REALLOC(
2689 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2690 if(*ppdata == NULL) {
2691 reply_nterror(req, NT_STATUS_NO_MEMORY);
2692 return;
2693 }
2694
2695 pdata = *ppdata;
2696 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2697
2698 /* Realloc the params space */
2699 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2700 if(*pparams == NULL ) {
2701 reply_nterror(req, NT_STATUS_NO_MEMORY);
2702 return;
2703 }
2704
2705 params = *pparams;
2706
2707 /* Check that the dptr is valid */
2708 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2709 reply_nterror(req, STATUS_NO_MORE_FILES);
2710 return;
2711 }
2712
2713 directory = dptr_path(sconn, dptr_num);
2714
2715 /* Get the wildcard mask from the dptr */
2716 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2717 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2718 reply_nterror(req, STATUS_NO_MORE_FILES);
2719 return;
2720 }
2721
2722 mask = p;
2723
2724 /* Get the attr mask from the dptr */
2725 dirtype = dptr_attr(sconn, dptr_num);
2726
2727 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2728 dptr_num, mask, dirtype,
2729 (long)dirptr,
2730 dptr_TellDir(dirptr)));
2731
2732 /* Initialize per TRANS2_FIND_NEXT operation data */
2733 dptr_init_search_op(dirptr);
2734
2735 /* We don't need to check for VOL here as this is returned by
2736 a different TRANS2 call. */
2737
2738 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2739 directory,lp_dontdescend(SNUM(conn))));
2740 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2741 dont_descend = True;
2742
2743 p = pdata;
2744 space_remaining = max_data_bytes;
2745 out_of_space = False;
2746
2747 /*
2748 * Seek to the correct position. We no longer use the resume key but
2749 * depend on the last file name instead.
2750 */
2751
2752 if(!continue_bit && resume_name && *resume_name) {
2753 SMB_STRUCT_STAT st;
2754
2755 long current_pos = 0;
2756 /*
2757 * Remember, name_to_8_3 is called by
2758 * get_lanman2_dir_entry(), so the resume name
2759 * could be mangled. Ensure we check the unmangled name.
2760 */
2761
2762 if (mangle_is_mangled(resume_name, conn->params)) {
2763 char *new_resume_name = NULL;
2764 mangle_lookup_name_from_8_3(ctx,
2765 resume_name,
2766 &new_resume_name,
2767 conn->params);
2768 if (new_resume_name) {
2769 resume_name = new_resume_name;
2770 }
2771 }
2772
2773 /*
2774 * Fix for NT redirector problem triggered by resume key indexes
2775 * changing between directory scans. We now return a resume key of 0
2776 * and instead look for the filename to continue from (also given
2777 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2778 * findfirst/findnext (as is usual) then the directory pointer
2779 * should already be at the correct place.
2780 */
2781
2782 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2783 } /* end if resume_name && !continue_bit */
2784
2785 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2786 bool got_exact_match = False;
2787
2788 /* this is a heuristic to avoid seeking the dirptr except when
2789 absolutely necessary. It allows for a filename of about 40 chars */
2790 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2791 out_of_space = True;
2792 finished = False;
2793 } else {
2794 finished = !get_lanman2_dir_entry(ctx,
2795 conn,
2796 dirptr,
2797 req->flags2,
2798 mask,dirtype,info_level,
2799 requires_resume_key,dont_descend,
2800 ask_sharemode,
2801 &p,pdata,data_end,
2802 space_remaining, &out_of_space,
2803 &got_exact_match,
2804 &last_entry_off, ea_list);
2805 }
2806
2807 if (finished && out_of_space)
2808 finished = False;
2809
2810 if (!finished && !out_of_space)
2811 numentries++;
2812
2813 /*
2814 * As an optimisation if we know we aren't looking
2815 * for a wildcard name (ie. the name matches the wildcard exactly)
2816 * then we can finish on any (first) match.
2817 * This speeds up large directory searches. JRA.
2818 */
2819
2820 if(got_exact_match)
2821 finished = True;
2822
2823 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2824 }
2825
2826 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2827 smb_fn_name(req->cmd),
2828 mask, directory, dirtype, numentries ) );
2829
2830 /* Check if we can close the dirptr */
2831 if(close_after_request || (finished && close_if_end)) {
2832 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2833 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2834 }
2835
2836 /* Set up the return parameter block */
2837 SSVAL(params,0,numentries);
2838 SSVAL(params,2,finished);
2839 SSVAL(params,4,0); /* Never an EA error */
2840 SSVAL(params,6,last_entry_off);
2841
2842 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2843 max_data_bytes);
2844
2845 return;
2846}
2847
2848unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2849{
2850 E_md4hash(lp_servicename(SNUM(conn)),objid);
2851 return objid;
2852}
2853
2854static void samba_extended_info_version(struct smb_extended_info *extended_info)
2855{
2856 SMB_ASSERT(extended_info != NULL);
2857
2858 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2859 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2860 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2861 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2862#ifdef SAMBA_VERSION_REVISION
2863 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2864#endif
2865 extended_info->samba_subversion = 0;
2866#ifdef SAMBA_VERSION_RC_RELEASE
2867 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2868#else
2869#ifdef SAMBA_VERSION_PRE_RELEASE
2870 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2871#endif
2872#endif
2873#ifdef SAMBA_VERSION_VENDOR_PATCH
2874 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2875#endif
2876 extended_info->samba_gitcommitdate = 0;
2877#ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2878 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2879#endif
2880
2881 memset(extended_info->samba_version_string, 0,
2882 sizeof(extended_info->samba_version_string));
2883
2884 snprintf (extended_info->samba_version_string,
2885 sizeof(extended_info->samba_version_string),
2886 "%s", samba_version_string());
2887}
2888
2889NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2890 TALLOC_CTX *mem_ctx,
2891 uint16_t info_level,
2892 uint16_t flags2,
2893 unsigned int max_data_bytes,
2894 char **ppdata,
2895 int *ret_data_len)
2896{
2897 char *pdata, *end_data;
2898 int data_len = 0, len;
2899 const char *vname = volume_label(SNUM(conn));
2900 int snum = SNUM(conn);
2901 char *fstype = lp_fstype(SNUM(conn));
2902 uint32 additional_flags = 0;
2903 struct smb_filename smb_fname_dot;
2904 SMB_STRUCT_STAT st;
2905
2906 if (IS_IPC(conn)) {
2907 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2908 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2909 "info level (0x%x) on IPC$.\n",
2910 (unsigned int)info_level));
2911 return NT_STATUS_ACCESS_DENIED;
2912 }
2913 }
2914
2915 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2916
2917 ZERO_STRUCT(smb_fname_dot);
2918 smb_fname_dot.base_name = discard_const_p(char, ".");
2919
2920 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2921 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2922 return map_nt_error_from_unix(errno);
2923 }
2924
2925 st = smb_fname_dot.st;
2926
2927 *ppdata = (char *)SMB_REALLOC(
2928 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2929 if (*ppdata == NULL) {
2930 return NT_STATUS_NO_MEMORY;
2931 }
2932
2933 pdata = *ppdata;
2934 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2935 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2936
2937 switch (info_level) {
2938 case SMB_INFO_ALLOCATION:
2939 {
2940 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2941 data_len = 18;
2942 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2943 return map_nt_error_from_unix(errno);
2944 }
2945
2946 block_size = lp_block_size(snum);
2947 if (bsize < block_size) {
2948 uint64_t factor = block_size/bsize;
2949 bsize = block_size;
2950 dsize /= factor;
2951 dfree /= factor;
2952 }
2953 if (bsize > block_size) {
2954 uint64_t factor = bsize/block_size;
2955 bsize = block_size;
2956 dsize *= factor;
2957 dfree *= factor;
2958 }
2959 bytes_per_sector = 512;
2960 sectors_per_unit = bsize/bytes_per_sector;
2961
2962 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2963cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2964 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2965
2966 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2967 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2968 SIVAL(pdata,l1_cUnit,dsize);
2969 SIVAL(pdata,l1_cUnitAvail,dfree);
2970 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2971 break;
2972 }
2973
2974 case SMB_INFO_VOLUME:
2975 /* Return volume name */
2976 /*
2977 * Add volume serial number - hash of a combination of
2978 * the called hostname and the service name.
2979 */
2980 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2981 /*
2982 * Win2k3 and previous mess this up by sending a name length
2983 * one byte short. I believe only older clients (OS/2 Win9x) use
2984 * this call so try fixing this by adding a terminating null to
2985 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2986 */
2987 len = srvstr_push(
2988 pdata, flags2,
2989 pdata+l2_vol_szVolLabel, vname,
2990 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2991 STR_NOALIGN|STR_TERMINATE);
2992 SCVAL(pdata,l2_vol_cch,len);
2993 data_len = l2_vol_szVolLabel + len;
2994 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2995 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2996 len, vname));
2997 break;
2998
2999 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3000 case SMB_FS_ATTRIBUTE_INFORMATION:
3001
3002 additional_flags = 0;
3003#if defined(HAVE_SYS_QUOTAS)
3004 additional_flags |= FILE_VOLUME_QUOTAS;
3005#endif
3006
3007 if(lp_nt_acl_support(SNUM(conn))) {
3008 additional_flags |= FILE_PERSISTENT_ACLS;
3009 }
3010
3011 /* Capabilities are filled in at connection time through STATVFS call */
3012 additional_flags |= conn->fs_capabilities;
3013 additional_flags |= lp_parm_int(conn->params->service,
3014 "share", "fake_fscaps",
3015 0);
3016
3017 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3018 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3019 additional_flags); /* FS ATTRIBUTES */
3020
3021 SIVAL(pdata,4,255); /* Max filename component length */
3022 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3023 and will think we can't do long filenames */
3024 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3025 PTR_DIFF(end_data, pdata+12),
3026 STR_UNICODE);
3027 SIVAL(pdata,8,len);
3028 data_len = 12 + len;
3029 break;
3030
3031 case SMB_QUERY_FS_LABEL_INFO:
3032 case SMB_FS_LABEL_INFORMATION:
3033 len = srvstr_push(pdata, flags2, pdata+4, vname,
3034 PTR_DIFF(end_data, pdata+4), 0);
3035 data_len = 4 + len;
3036 SIVAL(pdata,0,len);
3037 break;
3038
3039 case SMB_QUERY_FS_VOLUME_INFO:
3040 case SMB_FS_VOLUME_INFORMATION:
3041
3042 /*
3043 * Add volume serial number - hash of a combination of
3044 * the called hostname and the service name.
3045 */
3046 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3047 (str_checksum(get_local_machine_name())<<16));
3048
3049 /* Max label len is 32 characters. */
3050 len = srvstr_push(pdata, flags2, pdata+18, vname,
3051 PTR_DIFF(end_data, pdata+18),
3052 STR_UNICODE);
3053 SIVAL(pdata,12,len);
3054 data_len = 18+len;
3055
3056 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3057 (int)strlen(vname),vname, lp_servicename(snum)));
3058 break;
3059
3060 case SMB_QUERY_FS_SIZE_INFO:
3061 case SMB_FS_SIZE_INFORMATION:
3062 {
3063 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3064 data_len = 24;
3065 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3066 return map_nt_error_from_unix(errno);
3067 }
3068 block_size = lp_block_size(snum);
3069 if (bsize < block_size) {
3070 uint64_t factor = block_size/bsize;
3071 bsize = block_size;
3072 dsize /= factor;
3073 dfree /= factor;
3074 }
3075 if (bsize > block_size) {
3076 uint64_t factor = bsize/block_size;
3077 bsize = block_size;
3078 dsize *= factor;
3079 dfree *= factor;
3080 }
3081 bytes_per_sector = 512;
3082 sectors_per_unit = bsize/bytes_per_sector;
3083 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3084cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3085 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3086 SBIG_UINT(pdata,0,dsize);
3087 SBIG_UINT(pdata,8,dfree);
3088 SIVAL(pdata,16,sectors_per_unit);
3089 SIVAL(pdata,20,bytes_per_sector);
3090 break;
3091 }
3092
3093 case SMB_FS_FULL_SIZE_INFORMATION:
3094 {
3095 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3096 data_len = 32;
3097 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3098 return map_nt_error_from_unix(errno);
3099 }
3100 block_size = lp_block_size(snum);
3101 if (bsize < block_size) {
3102 uint64_t factor = block_size/bsize;
3103 bsize = block_size;
3104 dsize /= factor;
3105 dfree /= factor;
3106 }
3107 if (bsize > block_size) {
3108 uint64_t factor = bsize/block_size;
3109 bsize = block_size;
3110 dsize *= factor;
3111 dfree *= factor;
3112 }
3113 bytes_per_sector = 512;
3114 sectors_per_unit = bsize/bytes_per_sector;
3115 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3116cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3117 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3118 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3119 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3120 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3121 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3122 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3123 break;
3124 }
3125
3126 case SMB_QUERY_FS_DEVICE_INFO:
3127 case SMB_FS_DEVICE_INFORMATION:
3128 data_len = 8;
3129 SIVAL(pdata,0,0); /* dev type */
3130 SIVAL(pdata,4,0); /* characteristics */
3131 break;
3132
3133#ifdef HAVE_SYS_QUOTAS
3134 case SMB_FS_QUOTA_INFORMATION:
3135 /*
3136 * what we have to send --metze:
3137 *
3138 * Unknown1: 24 NULL bytes
3139 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3140 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3141 * Quota Flags: 2 byte :
3142 * Unknown3: 6 NULL bytes
3143 *
3144 * 48 bytes total
3145 *
3146 * details for Quota Flags:
3147 *
3148 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3149 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3150 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3151 * 0x0001 Enable Quotas: enable quota for this fs
3152 *
3153 */
3154 {
3155 /* we need to fake up a fsp here,
3156 * because its not send in this call
3157 */
3158 files_struct fsp;
3159 SMB_NTQUOTA_STRUCT quotas;
3160
3161 ZERO_STRUCT(fsp);
3162 ZERO_STRUCT(quotas);
3163
3164 fsp.conn = conn;
3165 fsp.fnum = -1;
3166
3167 /* access check */
3168 if (conn->server_info->utok.uid != sec_initial_uid() &&
3169 !conn->admin_user) {
3170 DEBUG(0,("set_user_quota: access_denied "
3171 "service [%s] user [%s]\n",
3172 lp_servicename(SNUM(conn)),
3173 conn->server_info->unix_name));
3174 return NT_STATUS_ACCESS_DENIED;
3175 }
3176
3177 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3178 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3179 return map_nt_error_from_unix(errno);
3180 }
3181
3182 data_len = 48;
3183
3184 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3185 lp_servicename(SNUM(conn))));
3186
3187 /* Unknown1 24 NULL bytes*/
3188 SBIG_UINT(pdata,0,(uint64_t)0);
3189 SBIG_UINT(pdata,8,(uint64_t)0);
3190 SBIG_UINT(pdata,16,(uint64_t)0);
3191
3192 /* Default Soft Quota 8 bytes */
3193 SBIG_UINT(pdata,24,quotas.softlim);
3194
3195 /* Default Hard Quota 8 bytes */
3196 SBIG_UINT(pdata,32,quotas.hardlim);
3197
3198 /* Quota flag 2 bytes */
3199 SSVAL(pdata,40,quotas.qflags);
3200
3201 /* Unknown3 6 NULL bytes */
3202 SSVAL(pdata,42,0);
3203 SIVAL(pdata,44,0);
3204
3205 break;
3206 }
3207#endif /* HAVE_SYS_QUOTAS */
3208 case SMB_FS_OBJECTID_INFORMATION:
3209 {
3210 unsigned char objid[16];
3211 struct smb_extended_info extended_info;
3212 memcpy(pdata,create_volume_objectid(conn, objid),16);
3213 samba_extended_info_version (&extended_info);
3214 SIVAL(pdata,16,extended_info.samba_magic);
3215 SIVAL(pdata,20,extended_info.samba_version);
3216 SIVAL(pdata,24,extended_info.samba_subversion);
3217 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3218 memcpy(pdata+36,extended_info.samba_version_string,28);
3219 data_len = 64;
3220 break;
3221 }
3222
3223 /*
3224 * Query the version and capabilities of the CIFS UNIX extensions
3225 * in use.
3226 */
3227
3228 case SMB_QUERY_CIFS_UNIX_INFO:
3229 {
3230 bool large_write = lp_min_receive_file_size() &&
3231 !srv_is_signing_active(smbd_server_conn);
3232 bool large_read = !srv_is_signing_active(smbd_server_conn);
3233 int encrypt_caps = 0;
3234
3235 if (!lp_unix_extensions()) {
3236 return NT_STATUS_INVALID_LEVEL;
3237 }
3238
3239 switch (conn->encrypt_level) {
3240 case 0:
3241 encrypt_caps = 0;
3242 break;
3243 case 1:
3244 case Auto:
3245 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3246 break;
3247 case Required:
3248 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3249 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3250 large_write = false;
3251 large_read = false;
3252 break;
3253 }
3254
3255 data_len = 12;
3256 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3257 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3258
3259 /* We have POSIX ACLs, pathname, encryption,
3260 * large read/write, and locking capability. */
3261
3262 SBIG_UINT(pdata,4,((uint64_t)(
3263 CIFS_UNIX_POSIX_ACLS_CAP|
3264 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3265 CIFS_UNIX_FCNTL_LOCKS_CAP|
3266 CIFS_UNIX_EXTATTR_CAP|
3267 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3268 encrypt_caps|
3269 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3270 (large_write ?
3271 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3272 break;
3273 }
3274
3275 case SMB_QUERY_POSIX_FS_INFO:
3276 {
3277 int rc;
3278 vfs_statvfs_struct svfs;
3279
3280 if (!lp_unix_extensions()) {
3281 return NT_STATUS_INVALID_LEVEL;
3282 }
3283
3284 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3285
3286 if (!rc) {
3287 data_len = 56;
3288 SIVAL(pdata,0,svfs.OptimalTransferSize);
3289 SIVAL(pdata,4,svfs.BlockSize);
3290 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3291 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3292 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3293 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3294 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3295 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3296 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3297#ifdef EOPNOTSUPP
3298 } else if (rc == EOPNOTSUPP) {
3299 return NT_STATUS_INVALID_LEVEL;
3300#endif /* EOPNOTSUPP */
3301 } else {
3302 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3303 return NT_STATUS_DOS(ERRSRV, ERRerror);
3304 }
3305 break;
3306 }
3307
3308 case SMB_QUERY_POSIX_WHOAMI:
3309 {
3310 uint32_t flags = 0;
3311 uint32_t sid_bytes;
3312 int i;
3313
3314 if (!lp_unix_extensions()) {
3315 return NT_STATUS_INVALID_LEVEL;
3316 }
3317
3318 if (max_data_bytes < 40) {
3319 return NT_STATUS_BUFFER_TOO_SMALL;
3320 }
3321
3322 /* We ARE guest if global_sid_Builtin_Guests is
3323 * in our list of SIDs.
3324 */
3325 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3326 conn->server_info->ptok)) {
3327 flags |= SMB_WHOAMI_GUEST;
3328 }
3329
3330 /* We are NOT guest if global_sid_Authenticated_Users
3331 * is in our list of SIDs.
3332 */
3333 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3334 conn->server_info->ptok)) {
3335 flags &= ~SMB_WHOAMI_GUEST;
3336 }
3337
3338 /* NOTE: 8 bytes for UID/GID, irrespective of native
3339 * platform size. This matches
3340 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3341 */
3342 data_len = 4 /* flags */
3343 + 4 /* flag mask */
3344 + 8 /* uid */
3345 + 8 /* gid */
3346 + 4 /* ngroups */
3347 + 4 /* num_sids */
3348 + 4 /* SID bytes */
3349 + 4 /* pad/reserved */
3350 + (conn->server_info->utok.ngroups * 8)
3351 /* groups list */
3352 + (conn->server_info->ptok->num_sids *
3353 SID_MAX_SIZE)
3354 /* SID list */;
3355
3356 SIVAL(pdata, 0, flags);
3357 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3358 SBIG_UINT(pdata, 8,
3359 (uint64_t)conn->server_info->utok.uid);
3360 SBIG_UINT(pdata, 16,
3361 (uint64_t)conn->server_info->utok.gid);
3362
3363
3364 if (data_len >= max_data_bytes) {
3365 /* Potential overflow, skip the GIDs and SIDs. */
3366
3367 SIVAL(pdata, 24, 0); /* num_groups */
3368 SIVAL(pdata, 28, 0); /* num_sids */
3369 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3370 SIVAL(pdata, 36, 0); /* reserved */
3371
3372 data_len = 40;
3373 break;
3374 }
3375
3376 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3377 SIVAL(pdata, 28, conn->server_info->num_sids);
3378
3379 /* We walk the SID list twice, but this call is fairly
3380 * infrequent, and I don't expect that it's performance
3381 * sensitive -- jpeach
3382 */
3383 for (i = 0, sid_bytes = 0;
3384 i < conn->server_info->ptok->num_sids; ++i) {
3385 sid_bytes += ndr_size_dom_sid(
3386 &conn->server_info->ptok->user_sids[i],
3387 NULL,
3388 0);
3389 }
3390
3391 /* SID list byte count */
3392 SIVAL(pdata, 32, sid_bytes);
3393
3394 /* 4 bytes pad/reserved - must be zero */
3395 SIVAL(pdata, 36, 0);
3396 data_len = 40;
3397
3398 /* GID list */
3399 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3400 SBIG_UINT(pdata, data_len,
3401 (uint64_t)conn->server_info->utok.groups[i]);
3402 data_len += 8;
3403 }
3404
3405 /* SID list */
3406 for (i = 0;
3407 i < conn->server_info->ptok->num_sids; ++i) {
3408 int sid_len = ndr_size_dom_sid(
3409 &conn->server_info->ptok->user_sids[i],
3410 NULL,
3411 0);
3412
3413 sid_linearize(pdata + data_len, sid_len,
3414 &conn->server_info->ptok->user_sids[i]);
3415 data_len += sid_len;
3416 }
3417
3418 break;
3419 }
3420
3421 case SMB_MAC_QUERY_FS_INFO:
3422 /*
3423 * Thursby MAC extension... ONLY on NTFS filesystems
3424 * once we do streams then we don't need this
3425 */
3426 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3427 data_len = 88;
3428 SIVAL(pdata,84,0x100); /* Don't support mac... */
3429 break;
3430 }
3431 /* drop through */
3432 default:
3433 return NT_STATUS_INVALID_LEVEL;
3434 }
3435
3436 *ret_data_len = data_len;
3437 return NT_STATUS_OK;
3438}
3439
3440/****************************************************************************
3441 Reply to a TRANS2_QFSINFO (query filesystem info).
3442****************************************************************************/
3443
3444static void call_trans2qfsinfo(connection_struct *conn,
3445 struct smb_request *req,
3446 char **pparams, int total_params,
3447 char **ppdata, int total_data,
3448 unsigned int max_data_bytes)
3449{
3450 char *params = *pparams;
3451 uint16_t info_level;
3452 int data_len = 0;
3453 NTSTATUS status;
3454
3455 if (total_params < 2) {
3456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3457 return;
3458 }
3459
3460 info_level = SVAL(params,0);
3461
3462 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3463 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3464 DEBUG(0,("call_trans2qfsinfo: encryption required "
3465 "and info level 0x%x sent.\n",
3466 (unsigned int)info_level));
3467 exit_server_cleanly("encryption required "
3468 "on connection");
3469 return;
3470 }
3471 }
3472
3473 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3474
3475 status = smbd_do_qfsinfo(conn, req,
3476 info_level,
3477 req->flags2,
3478 max_data_bytes,
3479 ppdata, &data_len);
3480 if (!NT_STATUS_IS_OK(status)) {
3481 reply_nterror(req, status);
3482 return;
3483 }
3484
3485 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3486 max_data_bytes);
3487
3488 DEBUG( 4, ( "%s info_level = %d\n",
3489 smb_fn_name(req->cmd), info_level) );
3490
3491 return;
3492}
3493
3494/****************************************************************************
3495 Reply to a TRANS2_SETFSINFO (set filesystem info).
3496****************************************************************************/
3497
3498static void call_trans2setfsinfo(connection_struct *conn,
3499 struct smb_request *req,
3500 char **pparams, int total_params,
3501 char **ppdata, int total_data,
3502 unsigned int max_data_bytes)
3503{
3504 char *pdata = *ppdata;
3505 char *params = *pparams;
3506 uint16 info_level;
3507
3508 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3509
3510 /* */
3511 if (total_params < 4) {
3512 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3513 total_params));
3514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3515 return;
3516 }
3517
3518 info_level = SVAL(params,2);
3519
3520 if (IS_IPC(conn)) {
3521 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3522 info_level != SMB_SET_CIFS_UNIX_INFO) {
3523 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3524 "info level (0x%x) on IPC$.\n",
3525 (unsigned int)info_level));
3526 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3527 return;
3528 }
3529 }
3530
3531 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3532 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3533 DEBUG(0,("call_trans2setfsinfo: encryption required "
3534 "and info level 0x%x sent.\n",
3535 (unsigned int)info_level));
3536 exit_server_cleanly("encryption required "
3537 "on connection");
3538 return;
3539 }
3540 }
3541
3542 switch(info_level) {
3543 case SMB_SET_CIFS_UNIX_INFO:
3544 {
3545 uint16 client_unix_major;
3546 uint16 client_unix_minor;
3547 uint32 client_unix_cap_low;
3548 uint32 client_unix_cap_high;
3549
3550 if (!lp_unix_extensions()) {
3551 reply_nterror(req,
3552 NT_STATUS_INVALID_LEVEL);
3553 return;
3554 }
3555
3556 /* There should be 12 bytes of capabilities set. */
3557 if (total_data < 8) {
3558 reply_nterror(
3559 req,
3560 NT_STATUS_INVALID_PARAMETER);
3561 return;
3562 }
3563 client_unix_major = SVAL(pdata,0);
3564 client_unix_minor = SVAL(pdata,2);
3565 client_unix_cap_low = IVAL(pdata,4);
3566 client_unix_cap_high = IVAL(pdata,8);
3567 /* Just print these values for now. */
3568 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3569cap_low = 0x%x, cap_high = 0x%x\n",
3570 (unsigned int)client_unix_major,
3571 (unsigned int)client_unix_minor,
3572 (unsigned int)client_unix_cap_low,
3573 (unsigned int)client_unix_cap_high ));
3574
3575 /* Here is where we must switch to posix pathname processing... */
3576 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3577 lp_set_posix_pathnames();
3578 mangle_change_to_posix();
3579 }
3580
3581 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3582 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3583 /* Client that knows how to do posix locks,
3584 * but not posix open/mkdir operations. Set a
3585 * default type for read/write checks. */
3586
3587 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3588
3589 }
3590 break;
3591 }
3592
3593 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3594 {
3595 NTSTATUS status;
3596 size_t param_len = 0;
3597 size_t data_len = total_data;
3598
3599 if (!lp_unix_extensions()) {
3600 reply_nterror(
3601 req,
3602 NT_STATUS_INVALID_LEVEL);
3603 return;
3604 }
3605
3606 if (lp_smb_encrypt(SNUM(conn)) == false) {
3607 reply_nterror(
3608 req,
3609 NT_STATUS_NOT_SUPPORTED);
3610 return;
3611 }
3612
3613 DEBUG( 4,("call_trans2setfsinfo: "
3614 "request transport encryption.\n"));
3615
3616 status = srv_request_encryption_setup(conn,
3617 (unsigned char **)ppdata,
3618 &data_len,
3619 (unsigned char **)pparams,
3620 &param_len);
3621
3622 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3623 !NT_STATUS_IS_OK(status)) {
3624 reply_nterror(req, status);
3625 return;
3626 }
3627
3628 send_trans2_replies(conn, req,
3629 *pparams,
3630 param_len,
3631 *ppdata,
3632 data_len,
3633 max_data_bytes);
3634
3635 if (NT_STATUS_IS_OK(status)) {
3636 /* Server-side transport
3637 * encryption is now *on*. */
3638 status = srv_encryption_start(conn);
3639 if (!NT_STATUS_IS_OK(status)) {
3640 exit_server_cleanly(
3641 "Failure in setting "
3642 "up encrypted transport");
3643 }
3644 }
3645 return;
3646 }
3647
3648 case SMB_FS_QUOTA_INFORMATION:
3649 {
3650 files_struct *fsp = NULL;
3651 SMB_NTQUOTA_STRUCT quotas;
3652
3653 ZERO_STRUCT(quotas);
3654
3655 /* access check */
3656 if (((conn->server_info->utok.uid != sec_initial_uid()) && !conn->admin_user)
3657 ||!CAN_WRITE(conn)) {
3658 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3659 lp_servicename(SNUM(conn)),
3660 conn->server_info->unix_name));
3661 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3662 return;
3663 }
3664
3665 /* note: normaly there're 48 bytes,
3666 * but we didn't use the last 6 bytes for now
3667 * --metze
3668 */
3669 fsp = file_fsp(req, SVAL(params,0));
3670
3671 if (!check_fsp_ntquota_handle(conn, req,
3672 fsp)) {
3673 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3674 reply_nterror(
3675 req, NT_STATUS_INVALID_HANDLE);
3676 return;
3677 }
3678
3679 if (total_data < 42) {
3680 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3681 total_data));
3682 reply_nterror(
3683 req,
3684 NT_STATUS_INVALID_PARAMETER);
3685 return;
3686 }
3687
3688 /* unknown_1 24 NULL bytes in pdata*/
3689
3690 /* the soft quotas 8 bytes (uint64_t)*/
3691 quotas.softlim = (uint64_t)IVAL(pdata,24);
3692#ifdef LARGE_SMB_OFF_T
3693 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3694#else /* LARGE_SMB_OFF_T */
3695 if ((IVAL(pdata,28) != 0)&&
3696 ((quotas.softlim != 0xFFFFFFFF)||
3697 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3698 /* more than 32 bits? */
3699 reply_nterror(
3700 req,
3701 NT_STATUS_INVALID_PARAMETER);
3702 return;
3703 }
3704#endif /* LARGE_SMB_OFF_T */
3705
3706 /* the hard quotas 8 bytes (uint64_t)*/
3707 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3708#ifdef LARGE_SMB_OFF_T
3709 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3710#else /* LARGE_SMB_OFF_T */
3711 if ((IVAL(pdata,36) != 0)&&
3712 ((quotas.hardlim != 0xFFFFFFFF)||
3713 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3714 /* more than 32 bits? */
3715 reply_nterror(
3716 req,
3717 NT_STATUS_INVALID_PARAMETER);
3718 return;
3719 }
3720#endif /* LARGE_SMB_OFF_T */
3721
3722 /* quota_flags 2 bytes **/
3723 quotas.qflags = SVAL(pdata,40);
3724
3725 /* unknown_2 6 NULL bytes follow*/
3726
3727 /* now set the quotas */
3728 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3729 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3730 reply_nterror(req, map_nt_error_from_unix(errno));
3731 return;
3732 }
3733
3734 break;
3735 }
3736 default:
3737 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3738 info_level));
3739 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3740 return;
3741 break;
3742 }
3743
3744 /*
3745 * sending this reply works fine,
3746 * but I'm not sure it's the same
3747 * like windows do...
3748 * --metze
3749 */
3750 reply_outbuf(req, 10, 0);
3751}
3752
3753#if defined(HAVE_POSIX_ACLS)
3754/****************************************************************************
3755 Utility function to count the number of entries in a POSIX acl.
3756****************************************************************************/
3757
3758static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3759{
3760 unsigned int ace_count = 0;
3761 int entry_id = SMB_ACL_FIRST_ENTRY;
3762 SMB_ACL_ENTRY_T entry;
3763
3764 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3765 /* get_next... */
3766 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3767 entry_id = SMB_ACL_NEXT_ENTRY;
3768 }
3769 ace_count++;
3770 }
3771 return ace_count;
3772}
3773
3774/****************************************************************************
3775 Utility function to marshall a POSIX acl into wire format.
3776****************************************************************************/
3777
3778static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3779{
3780 int entry_id = SMB_ACL_FIRST_ENTRY;
3781 SMB_ACL_ENTRY_T entry;
3782
3783 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3784 SMB_ACL_TAG_T tagtype;
3785 SMB_ACL_PERMSET_T permset;
3786 unsigned char perms = 0;
3787 unsigned int own_grp;
3788
3789 /* get_next... */
3790 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3791 entry_id = SMB_ACL_NEXT_ENTRY;
3792 }
3793
3794 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3795 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3796 return False;
3797 }
3798
3799 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3800 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3801 return False;
3802 }
3803
3804 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3805 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3806 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3807
3808 SCVAL(pdata,1,perms);
3809
3810 switch (tagtype) {
3811 case SMB_ACL_USER_OBJ:
3812 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3813 own_grp = (unsigned int)pst->st_ex_uid;
3814 SIVAL(pdata,2,own_grp);
3815 SIVAL(pdata,6,0);
3816 break;
3817 case SMB_ACL_USER:
3818 {
3819 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3820 if (!puid) {
3821 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3822 return False;
3823 }
3824 own_grp = (unsigned int)*puid;
3825 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3826 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3827 SIVAL(pdata,2,own_grp);
3828 SIVAL(pdata,6,0);
3829 break;
3830 }
3831 case SMB_ACL_GROUP_OBJ:
3832 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3833 own_grp = (unsigned int)pst->st_ex_gid;
3834 SIVAL(pdata,2,own_grp);
3835 SIVAL(pdata,6,0);
3836 break;
3837 case SMB_ACL_GROUP:
3838 {
3839 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3840 if (!pgid) {
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3842 return False;
3843 }
3844 own_grp = (unsigned int)*pgid;
3845 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3846 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3847 SIVAL(pdata,2,own_grp);
3848 SIVAL(pdata,6,0);
3849 break;
3850 }
3851 case SMB_ACL_MASK:
3852 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3853 SIVAL(pdata,2,0xFFFFFFFF);
3854 SIVAL(pdata,6,0xFFFFFFFF);
3855 break;
3856 case SMB_ACL_OTHER:
3857 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3858 SIVAL(pdata,2,0xFFFFFFFF);
3859 SIVAL(pdata,6,0xFFFFFFFF);
3860 break;
3861 default:
3862 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3863 return False;
3864 }
3865 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3866 }
3867
3868 return True;
3869}
3870#endif
3871
3872/****************************************************************************
3873 Store the FILE_UNIX_BASIC info.
3874****************************************************************************/
3875
3876static char *store_file_unix_basic(connection_struct *conn,
3877 char *pdata,
3878 files_struct *fsp,
3879 const SMB_STRUCT_STAT *psbuf)
3880{
3881 uint64_t file_index = get_FileIndex(conn, psbuf);
3882
3883 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3884 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3885
3886 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3887 pdata += 8;
3888
3889 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3890 pdata += 8;
3891
3892 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3893 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3894 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3895 pdata += 24;
3896
3897 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3898 SIVAL(pdata,4,0);
3899 pdata += 8;
3900
3901 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3902 SIVAL(pdata,4,0);
3903 pdata += 8;
3904
3905 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3906 pdata += 4;
3907
3908 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3909 SIVAL(pdata,4,0);
3910 pdata += 8;
3911
3912 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3913 SIVAL(pdata,4,0);
3914 pdata += 8;
3915
3916 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3917 pdata += 8;
3918
3919 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3920 SIVAL(pdata,4,0);
3921 pdata += 8;
3922
3923 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3924 SIVAL(pdata,4,0);
3925 pdata += 8;
3926
3927 return pdata;
3928}
3929
3930/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3931 * the chflags(2) (or equivalent) flags.
3932 *
3933 * XXX: this really should be behind the VFS interface. To do this, we would
3934 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3935 * Each VFS module could then implement its own mapping as appropriate for the
3936 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3937 */
3938static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3939 info2_flags_map[] =
3940{
3941#ifdef UF_NODUMP
3942 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3943#endif
3944
3945#ifdef UF_IMMUTABLE
3946 { UF_IMMUTABLE, EXT_IMMUTABLE },
3947#endif
3948
3949#ifdef UF_APPEND
3950 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3951#endif
3952
3953#ifdef UF_HIDDEN
3954 { UF_HIDDEN, EXT_HIDDEN },
3955#endif
3956
3957 /* Do not remove. We need to guarantee that this array has at least one
3958 * entry to build on HP-UX.
3959 */
3960 { 0, 0 }
3961
3962};
3963
3964static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3965 uint32 *smb_fflags, uint32 *smb_fmask)
3966{
3967 int i;
3968
3969 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3970 *smb_fmask |= info2_flags_map[i].smb_fflag;
3971 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3972 *smb_fflags |= info2_flags_map[i].smb_fflag;
3973 }
3974 }
3975}
3976
3977static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3978 const uint32 smb_fflags,
3979 const uint32 smb_fmask,
3980 int *stat_fflags)
3981{
3982 uint32 max_fmask = 0;
3983 int i;
3984
3985 *stat_fflags = psbuf->st_ex_flags;
3986
3987 /* For each flags requested in smb_fmask, check the state of the
3988 * corresponding flag in smb_fflags and set or clear the matching
3989 * stat flag.
3990 */
3991
3992 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3993 max_fmask |= info2_flags_map[i].smb_fflag;
3994 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3995 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3996 *stat_fflags |= info2_flags_map[i].stat_fflag;
3997 } else {
3998 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3999 }
4000 }
4001 }
4002
4003 /* If smb_fmask is asking to set any bits that are not supported by
4004 * our flag mappings, we should fail.
4005 */
4006 if ((smb_fmask & max_fmask) != smb_fmask) {
4007 return False;
4008 }
4009
4010 return True;
4011}
4012
4013
4014/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4015 * of file flags and birth (create) time.
4016 */
4017static char *store_file_unix_basic_info2(connection_struct *conn,
4018 char *pdata,
4019 files_struct *fsp,
4020 const SMB_STRUCT_STAT *psbuf)
4021{
4022 uint32 file_flags = 0;
4023 uint32 flags_mask = 0;
4024
4025 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4026
4027 /* Create (birth) time 64 bit */
4028 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4029 pdata += 8;
4030
4031 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4032 SIVAL(pdata, 0, file_flags); /* flags */
4033 SIVAL(pdata, 4, flags_mask); /* mask */
4034 pdata += 8;
4035
4036 return pdata;
4037}
4038
4039static NTSTATUS marshall_stream_info(unsigned int num_streams,
4040 const struct stream_struct *streams,
4041 char *data,
4042 unsigned int max_data_bytes,
4043 unsigned int *data_size)
4044{
4045 unsigned int i;
4046 unsigned int ofs = 0;
4047
4048 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4049 unsigned int next_offset;
4050 size_t namelen;
4051 smb_ucs2_t *namebuf;
4052
4053 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4054 streams[i].name, &namelen) ||
4055 namelen <= 2)
4056 {
4057 return NT_STATUS_INVALID_PARAMETER;
4058 }
4059
4060 /*
4061 * name_buf is now null-terminated, we need to marshall as not
4062 * terminated
4063 */
4064
4065 namelen -= 2;
4066
4067 SIVAL(data, ofs+4, namelen);
4068 SOFF_T(data, ofs+8, streams[i].size);
4069 SOFF_T(data, ofs+16, streams[i].alloc_size);
4070 memcpy(data+ofs+24, namebuf, namelen);
4071 TALLOC_FREE(namebuf);
4072
4073 next_offset = ofs + 24 + namelen;
4074
4075 if (i == num_streams-1) {
4076 SIVAL(data, ofs, 0);
4077 }
4078 else {
4079 unsigned int align = ndr_align_size(next_offset, 8);
4080
4081 memset(data+next_offset, 0, align);
4082 next_offset += align;
4083
4084 SIVAL(data, ofs, next_offset - ofs);
4085 ofs = next_offset;
4086 }
4087
4088 ofs = next_offset;
4089 }
4090
4091 *data_size = ofs;
4092
4093 return NT_STATUS_OK;
4094}
4095
4096/****************************************************************************
4097 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4098****************************************************************************/
4099
4100static void call_trans2qpipeinfo(connection_struct *conn,
4101 struct smb_request *req,
4102 unsigned int tran_call,
4103 char **pparams, int total_params,
4104 char **ppdata, int total_data,
4105 unsigned int max_data_bytes)
4106{
4107 char *params = *pparams;
4108 char *pdata = *ppdata;
4109 unsigned int data_size = 0;
4110 unsigned int param_size = 2;
4111 uint16 info_level;
4112 files_struct *fsp;
4113
4114 if (!params) {
4115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4116 return;
4117 }
4118
4119 if (total_params < 4) {
4120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4121 return;
4122 }
4123
4124 fsp = file_fsp(req, SVAL(params,0));
4125 if (!fsp_is_np(fsp)) {
4126 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4127 return;
4128 }
4129
4130 info_level = SVAL(params,2);
4131
4132 *pparams = (char *)SMB_REALLOC(*pparams,2);
4133 if (*pparams == NULL) {
4134 reply_nterror(req, NT_STATUS_NO_MEMORY);
4135 return;
4136 }
4137 params = *pparams;
4138 SSVAL(params,0,0);
4139 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4140 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4141 if (*ppdata == NULL ) {
4142 reply_nterror(req, NT_STATUS_NO_MEMORY);
4143 return;
4144 }
4145 pdata = *ppdata;
4146
4147 switch (info_level) {
4148 case SMB_FILE_STANDARD_INFORMATION:
4149 memset(pdata,0,24);
4150 SOFF_T(pdata,0,4096LL);
4151 SIVAL(pdata,16,1);
4152 SIVAL(pdata,20,1);
4153 data_size = 24;
4154 break;
4155
4156 default:
4157 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4158 return;
4159 }
4160
4161 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4162 max_data_bytes);
4163
4164 return;
4165}
4166
4167NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4168 TALLOC_CTX *mem_ctx,
4169 uint16_t info_level,
4170 files_struct *fsp,
4171 struct smb_filename *smb_fname,
4172 bool delete_pending,
4173 struct timespec write_time_ts,
4174 bool ms_dfs_link,
4175 struct ea_list *ea_list,
4176 int lock_data_count,
4177 char *lock_data,
4178 uint16_t flags2,
4179 unsigned int max_data_bytes,
4180 char **ppdata,
4181 unsigned int *pdata_size)
4182{
4183 char *pdata = *ppdata;
4184 char *dstart, *dend;
4185 unsigned int data_size;
4186 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4187 time_t create_time, mtime, atime, c_time;
4188 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4189 char *p;
4190 char *base_name;
4191 char *dos_fname;
4192 int mode;
4193 int nlink;
4194 NTSTATUS status;
4195 uint64_t file_size = 0;
4196 uint64_t pos = 0;
4197 uint64_t allocation_size = 0;
4198 uint64_t file_index = 0;
4199 uint32_t access_mask = 0;
4200
4201 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4202 return NT_STATUS_INVALID_LEVEL;
4203 }
4204
4205 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4206 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4207 info_level, max_data_bytes));
4208
4209 if (ms_dfs_link) {
4210 mode = dos_mode_msdfs(conn, smb_fname);
4211 } else {
4212 mode = dos_mode(conn, smb_fname);
4213 }
4214
4215 nlink = psbuf->st_ex_nlink;
4216
4217 if (nlink && (mode&aDIR)) {
4218 nlink = 1;
4219 }
4220
4221 if ((nlink > 0) && delete_pending) {
4222 nlink -= 1;
4223 }
4224
4225 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4226 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4227 if (*ppdata == NULL) {
4228 return NT_STATUS_NO_MEMORY;
4229 }
4230 pdata = *ppdata;
4231 dstart = pdata;
4232 dend = dstart + data_size - 1;
4233
4234 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4235 update_stat_ex_mtime(psbuf, write_time_ts);
4236 }
4237
4238 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4239 mtime_ts = psbuf->st_ex_mtime;
4240 atime_ts = psbuf->st_ex_atime;
4241 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4242
4243 if (lp_dos_filetime_resolution(SNUM(conn))) {
4244 dos_filetime_timespec(&create_time_ts);
4245 dos_filetime_timespec(&mtime_ts);
4246 dos_filetime_timespec(&atime_ts);
4247 dos_filetime_timespec(&ctime_ts);
4248 }
4249
4250 create_time = convert_timespec_to_time_t(create_time_ts);
4251 mtime = convert_timespec_to_time_t(mtime_ts);
4252 atime = convert_timespec_to_time_t(atime_ts);
4253 c_time = convert_timespec_to_time_t(ctime_ts);
4254
4255 p = strrchr_m(smb_fname->base_name,'/');
4256 if (!p)
4257 base_name = smb_fname->base_name;
4258 else
4259 base_name = p+1;
4260
4261 /* NT expects the name to be in an exact form of the *full*
4262 filename. See the trans2 torture test */
4263 if (ISDOT(base_name)) {
4264 dos_fname = talloc_strdup(mem_ctx, "\\");
4265 if (!dos_fname) {
4266 return NT_STATUS_NO_MEMORY;
4267 }
4268 } else {
4269 dos_fname = talloc_asprintf(mem_ctx,
4270 "\\%s",
4271 smb_fname->base_name);
4272 if (!dos_fname) {
4273 return NT_STATUS_NO_MEMORY;
4274 }
4275 if (is_ntfs_stream_smb_fname(smb_fname)) {
4276 dos_fname = talloc_asprintf(dos_fname, "%s",
4277 smb_fname->stream_name);
4278 if (!dos_fname) {
4279 return NT_STATUS_NO_MEMORY;
4280 }
4281 }
4282
4283 string_replace(dos_fname, '/', '\\');
4284 }
4285
4286 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4287
4288 if (!fsp) {
4289 /* Do we have this path open ? */
4290 files_struct *fsp1;
4291 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4292 fsp1 = file_find_di_first(fileid);
4293 if (fsp1 && fsp1->initial_allocation_size) {
4294 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4295 }
4296 }
4297
4298 if (!(mode & aDIR)) {
4299 file_size = get_file_size_stat(psbuf);
4300 }
4301
4302 if (fsp) {
4303 pos = fsp->fh->position_information;
4304 }
4305
4306 if (fsp) {
4307 access_mask = fsp->access_mask;
4308 } else {
4309 /* GENERIC_EXECUTE mapping from Windows */
4310 access_mask = 0x12019F;
4311 }
4312
4313 /* This should be an index number - looks like
4314 dev/ino to me :-)
4315
4316 I think this causes us to fail the IFSKIT
4317 BasicFileInformationTest. -tpot */
4318 file_index = get_FileIndex(conn, psbuf);
4319
4320 switch (info_level) {
4321 case SMB_INFO_STANDARD:
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4323 data_size = 22;
4324 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4325 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4326 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4327 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4328 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4329 SSVAL(pdata,l1_attrFile,mode);
4330 break;
4331
4332 case SMB_INFO_QUERY_EA_SIZE:
4333 {
4334 unsigned int ea_size =
4335 estimate_ea_size(conn, fsp,
4336 smb_fname->base_name);
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4338 data_size = 26;
4339 srv_put_dos_date2(pdata,0,create_time);
4340 srv_put_dos_date2(pdata,4,atime);
4341 srv_put_dos_date2(pdata,8,mtime); /* write time */
4342 SIVAL(pdata,12,(uint32)file_size);
4343 SIVAL(pdata,16,(uint32)allocation_size);
4344 SSVAL(pdata,20,mode);
4345 SIVAL(pdata,22,ea_size);
4346 break;
4347 }
4348
4349 case SMB_INFO_IS_NAME_VALID:
4350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4351 if (fsp) {
4352 /* os/2 needs this ? really ?*/
4353 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4354 }
4355 /* This is only reached for qpathinfo */
4356 data_size = 0;
4357 break;
4358
4359 case SMB_INFO_QUERY_EAS_FROM_LIST:
4360 {
4361 size_t total_ea_len = 0;
4362 struct ea_list *ea_file_list = NULL;
4363
4364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4365
4366 ea_file_list =
4367 get_ea_list_from_file(mem_ctx, conn, fsp,
4368 smb_fname->base_name,
4369 &total_ea_len);
4370 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4371
4372 if (!ea_list || (total_ea_len > data_size)) {
4373 data_size = 4;
4374 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4375 break;
4376 }
4377
4378 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4379 break;
4380 }
4381
4382 case SMB_INFO_QUERY_ALL_EAS:
4383 {
4384 /* We have data_size bytes to put EA's into. */
4385 size_t total_ea_len = 0;
4386
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4388
4389 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4390 smb_fname->base_name,
4391 &total_ea_len);
4392 if (!ea_list || (total_ea_len > data_size)) {
4393 data_size = 4;
4394 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4395 break;
4396 }
4397
4398 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4399 break;
4400 }
4401
4402 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4403 {
4404 /* This is FileFullEaInformation - 0xF which maps to
4405 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4406
4407 /* We have data_size bytes to put EA's into. */
4408 size_t total_ea_len = 0;
4409 struct ea_list *ea_file_list = NULL;
4410
4411 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4412
4413 /*TODO: add filtering and index handling */
4414
4415 ea_file_list =
4416 get_ea_list_from_file(mem_ctx, conn, fsp,
4417 smb_fname->base_name,
4418 &total_ea_len);
4419 if (!ea_file_list) {
4420 return NT_STATUS_NO_EAS_ON_FILE;
4421 }
4422
4423 status = fill_ea_chained_buffer(mem_ctx,
4424 pdata,
4425 data_size,
4426 &data_size,
4427 conn, ea_file_list);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 return status;
4430 }
4431 break;
4432 }
4433
4434 case SMB_FILE_BASIC_INFORMATION:
4435 case SMB_QUERY_FILE_BASIC_INFO:
4436
4437 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4438 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4439 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4440 } else {
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4442 data_size = 40;
4443 SIVAL(pdata,36,0);
4444 }
4445 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4446 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4447 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4448 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4449 SIVAL(pdata,32,mode);
4450
4451 DEBUG(5,("SMB_QFBI - "));
4452 DEBUG(5,("create: %s ", ctime(&create_time)));
4453 DEBUG(5,("access: %s ", ctime(&atime)));
4454 DEBUG(5,("write: %s ", ctime(&mtime)));
4455 DEBUG(5,("change: %s ", ctime(&c_time)));
4456 DEBUG(5,("mode: %x\n", mode));
4457 break;
4458
4459 case SMB_FILE_STANDARD_INFORMATION:
4460 case SMB_QUERY_FILE_STANDARD_INFO:
4461
4462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4463 data_size = 24;
4464 SOFF_T(pdata,0,allocation_size);
4465 SOFF_T(pdata,8,file_size);
4466 SIVAL(pdata,16,nlink);
4467 SCVAL(pdata,20,delete_pending?1:0);
4468 SCVAL(pdata,21,(mode&aDIR)?1:0);
4469 SSVAL(pdata,22,0); /* Padding. */
4470 break;
4471
4472 case SMB_FILE_EA_INFORMATION:
4473 case SMB_QUERY_FILE_EA_INFO:
4474 {
4475 unsigned int ea_size =
4476 estimate_ea_size(conn, fsp, smb_fname->base_name);
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4478 data_size = 4;
4479 SIVAL(pdata,0,ea_size);
4480 break;
4481 }
4482
4483 /* Get the 8.3 name - used if NT SMB was negotiated. */
4484 case SMB_QUERY_FILE_ALT_NAME_INFO:
4485 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4486 {
4487 int len;
4488 char mangled_name[13];
4489 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4490 if (!name_to_8_3(base_name,mangled_name,
4491 True,conn->params)) {
4492 return NT_STATUS_NO_MEMORY;
4493 }
4494 len = srvstr_push(dstart, flags2,
4495 pdata+4, mangled_name,
4496 PTR_DIFF(dend, pdata+4),
4497 STR_UNICODE);
4498 data_size = 4 + len;
4499 SIVAL(pdata,0,len);
4500 break;
4501 }
4502
4503 case SMB_QUERY_FILE_NAME_INFO:
4504 {
4505 int len;
4506 /*
4507 this must be *exactly* right for ACLs on mapped drives to work
4508 */
4509 len = srvstr_push(dstart, flags2,
4510 pdata+4, dos_fname,
4511 PTR_DIFF(dend, pdata+4),
4512 STR_UNICODE);
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4514 data_size = 4 + len;
4515 SIVAL(pdata,0,len);
4516 break;
4517 }
4518
4519 case SMB_FILE_ALLOCATION_INFORMATION:
4520 case SMB_QUERY_FILE_ALLOCATION_INFO:
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4522 data_size = 8;
4523 SOFF_T(pdata,0,allocation_size);
4524 break;
4525
4526 case SMB_FILE_END_OF_FILE_INFORMATION:
4527 case SMB_QUERY_FILE_END_OF_FILEINFO:
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4529 data_size = 8;
4530 SOFF_T(pdata,0,file_size);
4531 break;
4532
4533 case SMB_QUERY_FILE_ALL_INFO:
4534 case SMB_FILE_ALL_INFORMATION:
4535 {
4536 int len;
4537 unsigned int ea_size =
4538 estimate_ea_size(conn, fsp, smb_fname->base_name);
4539 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4540 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4541 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4542 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4543 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4544 SIVAL(pdata,32,mode);
4545 SIVAL(pdata,36,0); /* padding. */
4546 pdata += 40;
4547 SOFF_T(pdata,0,allocation_size);
4548 SOFF_T(pdata,8,file_size);
4549 SIVAL(pdata,16,nlink);
4550 SCVAL(pdata,20,delete_pending);
4551 SCVAL(pdata,21,(mode&aDIR)?1:0);
4552 SSVAL(pdata,22,0);
4553 pdata += 24;
4554 SIVAL(pdata,0,ea_size);
4555 pdata += 4; /* EA info */
4556 len = srvstr_push(dstart, flags2,
4557 pdata+4, dos_fname,
4558 PTR_DIFF(dend, pdata+4),
4559 STR_UNICODE);
4560 SIVAL(pdata,0,len);
4561 pdata += 4 + len;
4562 data_size = PTR_DIFF(pdata,(*ppdata));
4563 break;
4564 }
4565
4566 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4567 {
4568 int len;
4569 unsigned int ea_size =
4570 estimate_ea_size(conn, fsp, smb_fname->base_name);
4571 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4572 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4573 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4574 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4575 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4576 SIVAL(pdata, 0x20, mode);
4577 SIVAL(pdata, 0x24, 0); /* padding. */
4578 SBVAL(pdata, 0x28, allocation_size);
4579 SBVAL(pdata, 0x30, file_size);
4580 SIVAL(pdata, 0x38, nlink);
4581 SCVAL(pdata, 0x3C, delete_pending);
4582 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4583 SSVAL(pdata, 0x3E, 0); /* padding */
4584 SBVAL(pdata, 0x40, file_index);
4585 SIVAL(pdata, 0x48, ea_size);
4586 SIVAL(pdata, 0x4C, access_mask);
4587 SBVAL(pdata, 0x50, pos);
4588 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4589 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4590
4591 pdata += 0x60;
4592
4593 len = srvstr_push(dstart, flags2,
4594 pdata+4, dos_fname,
4595 PTR_DIFF(dend, pdata+4),
4596 STR_UNICODE);
4597 SIVAL(pdata,0,len);
4598 pdata += 4 + len;
4599 data_size = PTR_DIFF(pdata,(*ppdata));
4600 break;
4601 }
4602 case SMB_FILE_INTERNAL_INFORMATION:
4603
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4605 SBVAL(pdata, 0, file_index);
4606 data_size = 8;
4607 break;
4608
4609 case SMB_FILE_ACCESS_INFORMATION:
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4611 SIVAL(pdata, 0, access_mask);
4612 data_size = 4;
4613 break;
4614
4615 case SMB_FILE_NAME_INFORMATION:
4616 /* Pathname with leading '\'. */
4617 {
4618 size_t byte_len;
4619 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4621 SIVAL(pdata,0,byte_len);
4622 data_size = 4 + byte_len;
4623 break;
4624 }
4625
4626 case SMB_FILE_DISPOSITION_INFORMATION:
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4628 data_size = 1;
4629 SCVAL(pdata,0,delete_pending);
4630 break;
4631
4632 case SMB_FILE_POSITION_INFORMATION:
4633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4634 data_size = 8;
4635 SOFF_T(pdata,0,pos);
4636 break;
4637
4638 case SMB_FILE_MODE_INFORMATION:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4640 SIVAL(pdata,0,mode);
4641 data_size = 4;
4642 break;
4643
4644 case SMB_FILE_ALIGNMENT_INFORMATION:
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4646 SIVAL(pdata,0,0); /* No alignment needed. */
4647 data_size = 4;
4648 break;
4649
4650 /*
4651 * NT4 server just returns "invalid query" to this - if we try
4652 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4653 * want this. JRA.
4654 */
4655 /* The first statement above is false - verified using Thursby
4656 * client against NT4 -- gcolley.
4657 */
4658 case SMB_QUERY_FILE_STREAM_INFO:
4659 case SMB_FILE_STREAM_INFORMATION: {
4660 unsigned int num_streams;
4661 struct stream_struct *streams;
4662
4663 DEBUG(10,("smbd_do_qfilepathinfo: "
4664 "SMB_FILE_STREAM_INFORMATION\n"));
4665
4666 if (is_ntfs_stream_smb_fname(smb_fname)) {
4667 return NT_STATUS_INVALID_PARAMETER;
4668 }
4669
4670 status = SMB_VFS_STREAMINFO(
4671 conn, fsp, smb_fname->base_name, talloc_tos(),
4672 &num_streams, &streams);
4673
4674 if (!NT_STATUS_IS_OK(status)) {
4675 DEBUG(10, ("could not get stream info: %s\n",
4676 nt_errstr(status)));
4677 return status;
4678 }
4679
4680 status = marshall_stream_info(num_streams, streams,
4681 pdata, max_data_bytes,
4682 &data_size);
4683
4684 if (!NT_STATUS_IS_OK(status)) {
4685 DEBUG(10, ("marshall_stream_info failed: %s\n",
4686 nt_errstr(status)));
4687 return status;
4688 }
4689
4690 TALLOC_FREE(streams);
4691
4692 break;
4693 }
4694 case SMB_QUERY_COMPRESSION_INFO:
4695 case SMB_FILE_COMPRESSION_INFORMATION:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4697 SOFF_T(pdata,0,file_size);
4698 SIVAL(pdata,8,0); /* ??? */
4699 SIVAL(pdata,12,0); /* ??? */
4700 data_size = 16;
4701 break;
4702
4703 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4705 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4706 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4707 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4708 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4709 SOFF_T(pdata,32,allocation_size);
4710 SOFF_T(pdata,40,file_size);
4711 SIVAL(pdata,48,mode);
4712 SIVAL(pdata,52,0); /* ??? */
4713 data_size = 56;
4714 break;
4715
4716 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4718 SIVAL(pdata,0,mode);
4719 SIVAL(pdata,4,0);
4720 data_size = 8;
4721 break;
4722
4723 /*
4724 * CIFS UNIX Extensions.
4725 */
4726
4727 case SMB_QUERY_FILE_UNIX_BASIC:
4728
4729 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4730 data_size = PTR_DIFF(pdata,(*ppdata));
4731
4732 {
4733 int i;
4734 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4735
4736 for (i=0; i<100; i++)
4737 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4738 DEBUG(4,("\n"));
4739 }
4740
4741 break;
4742
4743 case SMB_QUERY_FILE_UNIX_INFO2:
4744
4745 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4746 data_size = PTR_DIFF(pdata,(*ppdata));
4747
4748 {
4749 int i;
4750 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4751
4752 for (i=0; i<100; i++)
4753 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4754 DEBUG(4,("\n"));
4755 }
4756
4757 break;
4758
4759 case SMB_QUERY_FILE_UNIX_LINK:
4760 {
4761 int len;
4762 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4763
4764 if (!buffer) {
4765 return NT_STATUS_NO_MEMORY;
4766 }
4767
4768 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4769#ifdef S_ISLNK
4770 if(!S_ISLNK(psbuf->st_ex_mode)) {
4771 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4772 }
4773#else
4774 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4775#endif
4776 len = SMB_VFS_READLINK(conn,
4777 smb_fname->base_name,
4778 buffer, PATH_MAX);
4779 if (len == -1) {
4780 return map_nt_error_from_unix(errno);
4781 }
4782 buffer[len] = 0;
4783 len = srvstr_push(dstart, flags2,
4784 pdata, buffer,
4785 PTR_DIFF(dend, pdata),
4786 STR_TERMINATE);
4787 pdata += len;
4788 data_size = PTR_DIFF(pdata,(*ppdata));
4789
4790 break;
4791 }
4792
4793#if defined(HAVE_POSIX_ACLS)
4794 case SMB_QUERY_POSIX_ACL:
4795 {
4796 SMB_ACL_T file_acl = NULL;
4797 SMB_ACL_T def_acl = NULL;
4798 uint16 num_file_acls = 0;
4799 uint16 num_def_acls = 0;
4800
4801 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4802 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4803 } else {
4804 file_acl =
4805 SMB_VFS_SYS_ACL_GET_FILE(conn,
4806 smb_fname->base_name,
4807 SMB_ACL_TYPE_ACCESS);
4808 }
4809
4810 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4811 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4812 "not implemented on "
4813 "filesystem containing %s\n",
4814 smb_fname->base_name));
4815 return NT_STATUS_NOT_IMPLEMENTED;
4816 }
4817
4818 if (S_ISDIR(psbuf->st_ex_mode)) {
4819 if (fsp && fsp->is_directory) {
4820 def_acl =
4821 SMB_VFS_SYS_ACL_GET_FILE(
4822 conn,
4823 fsp->fsp_name->base_name,
4824 SMB_ACL_TYPE_DEFAULT);
4825 } else {
4826 def_acl =
4827 SMB_VFS_SYS_ACL_GET_FILE(
4828 conn,
4829 smb_fname->base_name,
4830 SMB_ACL_TYPE_DEFAULT);
4831 }
4832 def_acl = free_empty_sys_acl(conn, def_acl);
4833 }
4834
4835 num_file_acls = count_acl_entries(conn, file_acl);
4836 num_def_acls = count_acl_entries(conn, def_acl);
4837
4838 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4839 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4840 data_size,
4841 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4842 SMB_POSIX_ACL_HEADER_SIZE) ));
4843 if (file_acl) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4845 }
4846 if (def_acl) {
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4848 }
4849 return NT_STATUS_BUFFER_TOO_SMALL;
4850 }
4851
4852 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4853 SSVAL(pdata,2,num_file_acls);
4854 SSVAL(pdata,4,num_def_acls);
4855 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4856 if (file_acl) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4858 }
4859 if (def_acl) {
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4861 }
4862 return NT_STATUS_INTERNAL_ERROR;
4863 }
4864 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4865 if (file_acl) {
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4867 }
4868 if (def_acl) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4870 }
4871 return NT_STATUS_INTERNAL_ERROR;
4872 }
4873
4874 if (file_acl) {
4875 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4876 }
4877 if (def_acl) {
4878 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4879 }
4880 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4881 break;
4882 }
4883#endif
4884
4885
4886 case SMB_QUERY_POSIX_LOCK:
4887 {
4888 uint64_t count;
4889 uint64_t offset;
4890 uint32 lock_pid;
4891 enum brl_type lock_type;
4892
4893 /* We need an open file with a real fd for this. */
4894 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4895 return NT_STATUS_INVALID_LEVEL;
4896 }
4897
4898 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4899 return NT_STATUS_INVALID_PARAMETER;
4900 }
4901
4902 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4903 case POSIX_LOCK_TYPE_READ:
4904 lock_type = READ_LOCK;
4905 break;
4906 case POSIX_LOCK_TYPE_WRITE:
4907 lock_type = WRITE_LOCK;
4908 break;
4909 case POSIX_LOCK_TYPE_UNLOCK:
4910 default:
4911 /* There's no point in asking for an unlock... */
4912 return NT_STATUS_INVALID_PARAMETER;
4913 }
4914
4915 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4916#if defined(HAVE_LONGLONG)
4917 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4918 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4919 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4920 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4921#else /* HAVE_LONGLONG */
4922 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4923 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4924#endif /* HAVE_LONGLONG */
4925
4926 status = query_lock(fsp,
4927 &lock_pid,
4928 &count,
4929 &offset,
4930 &lock_type,
4931 POSIX_LOCK);
4932
4933 if (ERROR_WAS_LOCK_DENIED(status)) {
4934 /* Here we need to report who has it locked... */
4935 data_size = POSIX_LOCK_DATA_SIZE;
4936
4937 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4938 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4939 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4940#if defined(HAVE_LONGLONG)
4941 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4942 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4943 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4944 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4945#else /* HAVE_LONGLONG */
4946 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4947 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4948#endif /* HAVE_LONGLONG */
4949
4950 } else if (NT_STATUS_IS_OK(status)) {
4951 /* For success we just return a copy of what we sent
4952 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4953 data_size = POSIX_LOCK_DATA_SIZE;
4954 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4955 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4956 } else {
4957 return status;
4958 }
4959 break;
4960 }
4961
4962 default:
4963 return NT_STATUS_INVALID_LEVEL;
4964 }
4965
4966 *pdata_size = data_size;
4967 return NT_STATUS_OK;
4968}
4969
4970/****************************************************************************
4971 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4972 file name or file id).
4973****************************************************************************/
4974
4975static void call_trans2qfilepathinfo(connection_struct *conn,
4976 struct smb_request *req,
4977 unsigned int tran_call,
4978 char **pparams, int total_params,
4979 char **ppdata, int total_data,
4980 unsigned int max_data_bytes)
4981{
4982 char *params = *pparams;
4983 char *pdata = *ppdata;
4984 uint16 info_level;
4985 unsigned int data_size = 0;
4986 unsigned int param_size = 2;
4987 struct smb_filename *smb_fname = NULL;
4988 bool delete_pending = False;
4989 struct timespec write_time_ts;
4990 files_struct *fsp = NULL;
4991 struct file_id fileid;
4992 struct ea_list *ea_list = NULL;
4993 int lock_data_count = 0;
4994 char *lock_data = NULL;
4995 bool ms_dfs_link = false;
4996 NTSTATUS status = NT_STATUS_OK;
4997
4998 if (!params) {
4999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5000 return;
5001 }
5002
5003 ZERO_STRUCT(write_time_ts);
5004
5005 if (tran_call == TRANSACT2_QFILEINFO) {
5006 if (total_params < 4) {
5007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5008 return;
5009 }
5010
5011 if (IS_IPC(conn)) {
5012 call_trans2qpipeinfo(conn, req, tran_call,
5013 pparams, total_params,
5014 ppdata, total_data,
5015 max_data_bytes);
5016 return;
5017 }
5018
5019 fsp = file_fsp(req, SVAL(params,0));
5020 info_level = SVAL(params,2);
5021
5022 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5023
5024 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5025 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5026 return;
5027 }
5028
5029 /* Initial check for valid fsp ptr. */
5030 if (!check_fsp_open(conn, req, fsp)) {
5031 return;
5032 }
5033
5034 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5035 &smb_fname);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 reply_nterror(req, status);
5038 return;
5039 }
5040
5041 if(fsp->fake_file_handle) {
5042 /*
5043 * This is actually for the QUOTA_FAKE_FILE --metze
5044 */
5045
5046 /* We know this name is ok, it's already passed the checks. */
5047
5048 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5049 /*
5050 * This is actually a QFILEINFO on a directory
5051 * handle (returned from an NT SMB). NT5.0 seems
5052 * to do this call. JRA.
5053 */
5054
5055 if (INFO_LEVEL_IS_UNIX(info_level)) {
5056 /* Always do lstat for UNIX calls. */
5057 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5058 DEBUG(3,("call_trans2qfilepathinfo: "
5059 "SMB_VFS_LSTAT of %s failed "
5060 "(%s)\n",
5061 smb_fname_str_dbg(smb_fname),
5062 strerror(errno)));
5063 reply_nterror(req,
5064 map_nt_error_from_unix(errno));
5065 return;
5066 }
5067 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5068 DEBUG(3,("call_trans2qfilepathinfo: "
5069 "SMB_VFS_STAT of %s failed (%s)\n",
5070 smb_fname_str_dbg(smb_fname),
5071 strerror(errno)));
5072 reply_nterror(req,
5073 map_nt_error_from_unix(errno));
5074 return;
5075 }
5076
5077 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5078 get_file_infos(fileid, &delete_pending, &write_time_ts);
5079 } else {
5080 /*
5081 * Original code - this is an open file.
5082 */
5083 if (!check_fsp(conn, req, fsp)) {
5084 return;
5085 }
5086
5087 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5088 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5089 fsp->fnum, strerror(errno)));
5090 reply_nterror(req,
5091 map_nt_error_from_unix(errno));
5092 return;
5093 }
5094 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5095 get_file_infos(fileid, &delete_pending, &write_time_ts);
5096 }
5097
5098 } else {
5099 char *fname = NULL;
5100 uint32_t ucf_flags = 0;
5101
5102 /* qpathinfo */
5103 if (total_params < 7) {
5104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5105 return;
5106 }
5107
5108 info_level = SVAL(params,0);
5109
5110 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5111
5112 if (INFO_LEVEL_IS_UNIX(info_level)) {
5113 if (!lp_unix_extensions()) {
5114 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5115 return;
5116 }
5117 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5118 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5119 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5120 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5121 }
5122 }
5123
5124 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5125 total_params - 6,
5126 STR_TERMINATE, &status);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 reply_nterror(req, status);
5129 return;
5130 }
5131
5132 status = filename_convert(req,
5133 conn,
5134 req->flags2 & FLAGS2_DFS_PATHNAMES,
5135 fname,
5136 ucf_flags,
5137 NULL,
5138 &smb_fname);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5141 reply_botherror(req,
5142 NT_STATUS_PATH_NOT_COVERED,
5143 ERRSRV, ERRbadpath);
5144 return;
5145 }
5146 reply_nterror(req, status);
5147 return;
5148 }
5149
5150 /* If this is a stream, check if there is a delete_pending. */
5151 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5152 && is_ntfs_stream_smb_fname(smb_fname)) {
5153 struct smb_filename *smb_fname_base = NULL;
5154
5155 /* Create an smb_filename with stream_name == NULL. */
5156 status =
5157 create_synthetic_smb_fname(talloc_tos(),
5158 smb_fname->base_name,
5159 NULL, NULL,
5160 &smb_fname_base);
5161 if (!NT_STATUS_IS_OK(status)) {
5162 reply_nterror(req, status);
5163 return;
5164 }
5165
5166 if (INFO_LEVEL_IS_UNIX(info_level)) {
5167 /* Always do lstat for UNIX calls. */
5168 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5169 DEBUG(3,("call_trans2qfilepathinfo: "
5170 "SMB_VFS_LSTAT of %s failed "
5171 "(%s)\n",
5172 smb_fname_str_dbg(smb_fname_base),
5173 strerror(errno)));
5174 TALLOC_FREE(smb_fname_base);
5175 reply_nterror(req,
5176 map_nt_error_from_unix(errno));
5177 return;
5178 }
5179 } else {
5180 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5181 DEBUG(3,("call_trans2qfilepathinfo: "
5182 "fileinfo of %s failed "
5183 "(%s)\n",
5184 smb_fname_str_dbg(smb_fname_base),
5185 strerror(errno)));
5186 TALLOC_FREE(smb_fname_base);
5187 reply_nterror(req,
5188 map_nt_error_from_unix(errno));
5189 return;
5190 }
5191 }
5192
5193 fileid = vfs_file_id_from_sbuf(conn,
5194 &smb_fname_base->st);
5195 TALLOC_FREE(smb_fname_base);
5196 get_file_infos(fileid, &delete_pending, NULL);
5197 if (delete_pending) {
5198 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5199 return;
5200 }
5201 }
5202
5203 if (INFO_LEVEL_IS_UNIX(info_level)) {
5204 /* Always do lstat for UNIX calls. */
5205 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5206 DEBUG(3,("call_trans2qfilepathinfo: "
5207 "SMB_VFS_LSTAT of %s failed (%s)\n",
5208 smb_fname_str_dbg(smb_fname),
5209 strerror(errno)));
5210 reply_nterror(req,
5211 map_nt_error_from_unix(errno));
5212 return;
5213 }
5214
5215 } else if (!VALID_STAT(smb_fname->st) &&
5216 SMB_VFS_STAT(conn, smb_fname) &&
5217 (info_level != SMB_INFO_IS_NAME_VALID)) {
5218 ms_dfs_link = check_msdfs_link(conn,
5219 smb_fname->base_name,
5220 &smb_fname->st);
5221
5222 if (!ms_dfs_link) {
5223 DEBUG(3,("call_trans2qfilepathinfo: "
5224 "SMB_VFS_STAT of %s failed (%s)\n",
5225 smb_fname_str_dbg(smb_fname),
5226 strerror(errno)));
5227 reply_nterror(req,
5228 map_nt_error_from_unix(errno));
5229 return;
5230 }
5231 }
5232
5233 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5234 get_file_infos(fileid, &delete_pending, &write_time_ts);
5235 if (delete_pending) {
5236 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5237 return;
5238 }
5239 }
5240
5241 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5242 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5243 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5244
5245 /* Pull out any data sent here before we realloc. */
5246 switch (info_level) {
5247 case SMB_INFO_QUERY_EAS_FROM_LIST:
5248 {
5249 /* Pull any EA list from the data portion. */
5250 uint32 ea_size;
5251
5252 if (total_data < 4) {
5253 reply_nterror(
5254 req, NT_STATUS_INVALID_PARAMETER);
5255 return;
5256 }
5257 ea_size = IVAL(pdata,0);
5258
5259 if (total_data > 0 && ea_size != total_data) {
5260 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5261total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5262 reply_nterror(
5263 req, NT_STATUS_INVALID_PARAMETER);
5264 return;
5265 }
5266
5267 if (!lp_ea_support(SNUM(conn))) {
5268 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5269 return;
5270 }
5271
5272 /* Pull out the list of names. */
5273 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5274 if (!ea_list) {
5275 reply_nterror(
5276 req, NT_STATUS_INVALID_PARAMETER);
5277 return;
5278 }
5279 break;
5280 }
5281
5282 case SMB_QUERY_POSIX_LOCK:
5283 {
5284 if (fsp == NULL || fsp->fh->fd == -1) {
5285 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5286 return;
5287 }
5288
5289 if (total_data != POSIX_LOCK_DATA_SIZE) {
5290 reply_nterror(
5291 req, NT_STATUS_INVALID_PARAMETER);
5292 return;
5293 }
5294
5295 /* Copy the lock range data. */
5296 lock_data = (char *)TALLOC_MEMDUP(
5297 req, pdata, total_data);
5298 if (!lock_data) {
5299 reply_nterror(req, NT_STATUS_NO_MEMORY);
5300 return;
5301 }
5302 lock_data_count = total_data;
5303 }
5304 default:
5305 break;
5306 }
5307
5308 *pparams = (char *)SMB_REALLOC(*pparams,2);
5309 if (*pparams == NULL) {
5310 reply_nterror(req, NT_STATUS_NO_MEMORY);
5311 return;
5312 }
5313 params = *pparams;
5314 SSVAL(params,0,0);
5315
5316 /*
5317 * draft-leach-cifs-v1-spec-02.txt
5318 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5319 * says:
5320 *
5321 * The requested information is placed in the Data portion of the
5322 * transaction response. For the information levels greater than 0x100,
5323 * the transaction response has 1 parameter word which should be
5324 * ignored by the client.
5325 *
5326 * However Windows only follows this rule for the IS_NAME_VALID call.
5327 */
5328 switch (info_level) {
5329 case SMB_INFO_IS_NAME_VALID:
5330 param_size = 0;
5331 break;
5332 }
5333
5334 if ((info_level & 0xFF00) == 0xFF00) {
5335 /*
5336 * We use levels that start with 0xFF00
5337 * internally to represent SMB2 specific levels
5338 */
5339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5340 return;
5341 }
5342
5343 status = smbd_do_qfilepathinfo(conn, req, info_level,
5344 fsp, smb_fname,
5345 delete_pending, write_time_ts,
5346 ms_dfs_link, ea_list,
5347 lock_data_count, lock_data,
5348 req->flags2, max_data_bytes,
5349 ppdata, &data_size);
5350 if (!NT_STATUS_IS_OK(status)) {
5351 reply_nterror(req, status);
5352 return;
5353 }
5354
5355 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5356 max_data_bytes);
5357
5358 return;
5359}
5360
5361/****************************************************************************
5362 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5363 code.
5364****************************************************************************/
5365
5366NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5367 connection_struct *conn,
5368 const struct smb_filename *smb_fname_old,
5369 const struct smb_filename *smb_fname_new)
5370{
5371 NTSTATUS status = NT_STATUS_OK;
5372
5373 /* source must already exist. */
5374 if (!VALID_STAT(smb_fname_old->st)) {
5375 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5376 }
5377
5378 /* Disallow if newname already exists. */
5379 if (VALID_STAT(smb_fname_new->st)) {
5380 return NT_STATUS_OBJECT_NAME_COLLISION;
5381 }
5382
5383 /* No links from a directory. */
5384 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5385 return NT_STATUS_FILE_IS_A_DIRECTORY;
5386 }
5387
5388 /* Setting a hardlink to/from a stream isn't currently supported. */
5389 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5390 is_ntfs_stream_smb_fname(smb_fname_new)) {
5391 return NT_STATUS_INVALID_PARAMETER;
5392 }
5393
5394 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5395 smb_fname_old->base_name, smb_fname_new->base_name));
5396
5397 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5398 smb_fname_new->base_name) != 0) {
5399 status = map_nt_error_from_unix(errno);
5400 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5401 nt_errstr(status), smb_fname_old->base_name,
5402 smb_fname_new->base_name));
5403 }
5404 return status;
5405}
5406
5407/****************************************************************************
5408 Deal with setting the time from any of the setfilepathinfo functions.
5409****************************************************************************/
5410
5411NTSTATUS smb_set_file_time(connection_struct *conn,
5412 files_struct *fsp,
5413 const struct smb_filename *smb_fname,
5414 struct smb_file_time *ft,
5415 bool setting_write_time)
5416{
5417 struct smb_filename smb_fname_base;
5418 uint32 action =
5419 FILE_NOTIFY_CHANGE_LAST_ACCESS
5420 |FILE_NOTIFY_CHANGE_LAST_WRITE
5421 |FILE_NOTIFY_CHANGE_CREATION;
5422
5423 if (!VALID_STAT(smb_fname->st)) {
5424 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5425 }
5426
5427 /* get some defaults (no modifications) if any info is zero or -1. */
5428 if (null_timespec(ft->create_time)) {
5429 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5430 }
5431
5432 if (null_timespec(ft->atime)) {
5433 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5434 }
5435
5436 if (null_timespec(ft->mtime)) {
5437 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5438 }
5439
5440 if (!setting_write_time) {
5441 /* ft->mtime comes from change time, not write time. */
5442 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5443 }
5444
5445 /* Ensure the resolution is the correct for
5446 * what we can store on this filesystem. */
5447
5448 round_timespec(conn->ts_res, &ft->create_time);
5449 round_timespec(conn->ts_res, &ft->ctime);
5450 round_timespec(conn->ts_res, &ft->atime);
5451 round_timespec(conn->ts_res, &ft->mtime);
5452
5453 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5454 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5455 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5456 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5457 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5458 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5459 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5460 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5461
5462 if (setting_write_time) {
5463 /*
5464 * This was a Windows setfileinfo on an open file.
5465 * NT does this a lot. We also need to
5466 * set the time here, as it can be read by
5467 * FindFirst/FindNext and with the patch for bug #2045
5468 * in smbd/fileio.c it ensures that this timestamp is
5469 * kept sticky even after a write. We save the request
5470 * away and will set it on file close and after a write. JRA.
5471 */
5472
5473 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5474 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5475
5476 if (fsp != NULL) {
5477 if (fsp->base_fsp) {
5478 set_sticky_write_time_fsp(fsp->base_fsp,
5479 ft->mtime);
5480 } else {
5481 set_sticky_write_time_fsp(fsp, ft->mtime);
5482 }
5483 } else {
5484 set_sticky_write_time_path(
5485 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5486 ft->mtime);
5487 }
5488 }
5489
5490#ifdef __OS2__
5491 /* YD ticket#60, the file is opened, we cannot write to it,
5492 * so we can return immediately (see above for more comments).
5493 */
5494 else {
5495#endif
5496 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5497
5498 /* Always call ntimes on the base, even if a stream was passed in. */
5499 smb_fname_base = *smb_fname;
5500 smb_fname_base.stream_name = NULL;
5501
5502 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5503 return map_nt_error_from_unix(errno);
5504 }
5505#ifdef __OS2__
5506 }
5507#endif
5508
5509 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5510 smb_fname->base_name);
5511 return NT_STATUS_OK;
5512}
5513
5514/****************************************************************************
5515 Deal with setting the dosmode from any of the setfilepathinfo functions.
5516****************************************************************************/
5517
5518static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5519 const struct smb_filename *smb_fname,
5520 uint32 dosmode)
5521{
5522 struct smb_filename *smb_fname_base = NULL;
5523 NTSTATUS status;
5524
5525 if (!VALID_STAT(smb_fname->st)) {
5526 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5527 }
5528
5529 /* Always operate on the base_name, even if a stream was passed in. */
5530 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5531 NULL, &smb_fname->st,
5532 &smb_fname_base);
5533 if (!NT_STATUS_IS_OK(status)) {
5534 return status;
5535 }
5536
5537 if (dosmode) {
5538 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5539 dosmode |= aDIR;
5540 } else {
5541 dosmode &= ~aDIR;
5542 }
5543 }
5544
5545 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5546
5547 /* check the mode isn't different, before changing it */
5548 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5549 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5550 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5551 (unsigned int)dosmode));
5552
5553 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5554 false)) {
5555 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5556 "%s failed (%s)\n",
5557 smb_fname_str_dbg(smb_fname_base),
5558 strerror(errno)));
5559 status = map_nt_error_from_unix(errno);
5560 goto out;
5561 }
5562 }
5563 status = NT_STATUS_OK;
5564 out:
5565 TALLOC_FREE(smb_fname_base);
5566 return status;
5567}
5568
5569/****************************************************************************
5570 Deal with setting the size from any of the setfilepathinfo functions.
5571****************************************************************************/
5572
5573static NTSTATUS smb_set_file_size(connection_struct *conn,
5574 struct smb_request *req,
5575 files_struct *fsp,
5576 const struct smb_filename *smb_fname,
5577 const SMB_STRUCT_STAT *psbuf,
5578 SMB_OFF_T size,
5579 bool fail_after_createfile)
5580{
5581 NTSTATUS status = NT_STATUS_OK;
5582 struct smb_filename *smb_fname_tmp = NULL;
5583 files_struct *new_fsp = NULL;
5584
5585 if (!VALID_STAT(*psbuf)) {
5586 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5587 }
5588
5589 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5590
5591 if (size == get_file_size_stat(psbuf)) {
5592 return NT_STATUS_OK;
5593 }
5594
5595 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5596 smb_fname_str_dbg(smb_fname), (double)size));
5597
5598 if (fsp && fsp->fh->fd != -1) {
5599 /* Handle based call. */
5600 if (vfs_set_filelen(fsp, size) == -1) {
5601 return map_nt_error_from_unix(errno);
5602 }
5603 trigger_write_time_update_immediate(fsp);
5604 return NT_STATUS_OK;
5605 }
5606
5607 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5608 if (!NT_STATUS_IS_OK(status)) {
5609 return status;
5610 }
5611
5612 smb_fname_tmp->st = *psbuf;
5613
5614 status = SMB_VFS_CREATE_FILE(
5615 conn, /* conn */
5616 req, /* req */
5617 0, /* root_dir_fid */
5618 smb_fname_tmp, /* fname */
5619 FILE_WRITE_ATTRIBUTES, /* access_mask */
5620 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5621 FILE_SHARE_DELETE),
5622 FILE_OPEN, /* create_disposition*/
5623 0, /* create_options */
5624 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5625 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5626 0, /* allocation_size */
5627 NULL, /* sd */
5628 NULL, /* ea_list */
5629 &new_fsp, /* result */
5630 NULL); /* pinfo */
5631
5632 TALLOC_FREE(smb_fname_tmp);
5633
5634 if (!NT_STATUS_IS_OK(status)) {
5635 /* NB. We check for open_was_deferred in the caller. */
5636 return status;
5637 }
5638
5639 /* See RAW-SFILEINFO-END-OF-FILE */
5640 if (fail_after_createfile) {
5641 close_file(req, new_fsp,NORMAL_CLOSE);
5642 return NT_STATUS_INVALID_LEVEL;
5643 }
5644
5645 if (vfs_set_filelen(new_fsp, size) == -1) {
5646 status = map_nt_error_from_unix(errno);
5647 close_file(req, new_fsp,NORMAL_CLOSE);
5648 return status;
5649 }
5650
5651 trigger_write_time_update_immediate(new_fsp);
5652 close_file(req, new_fsp,NORMAL_CLOSE);
5653 return NT_STATUS_OK;
5654}
5655
5656/****************************************************************************
5657 Deal with SMB_INFO_SET_EA.
5658****************************************************************************/
5659
5660static NTSTATUS smb_info_set_ea(connection_struct *conn,
5661 const char *pdata,
5662 int total_data,
5663 files_struct *fsp,
5664 const struct smb_filename *smb_fname)
5665{
5666 struct ea_list *ea_list = NULL;
5667 TALLOC_CTX *ctx = NULL;
5668 NTSTATUS status = NT_STATUS_OK;
5669
5670 if (total_data < 10) {
5671
5672 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5673 length. They seem to have no effect. Bug #3212. JRA */
5674
5675 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5676 /* We're done. We only get EA info in this call. */
5677 return NT_STATUS_OK;
5678 }
5679
5680 return NT_STATUS_INVALID_PARAMETER;
5681 }
5682
5683 if (IVAL(pdata,0) > total_data) {
5684 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5685 IVAL(pdata,0), (unsigned int)total_data));
5686 return NT_STATUS_INVALID_PARAMETER;
5687 }
5688
5689 ctx = talloc_tos();
5690 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5691 if (!ea_list) {
5692 return NT_STATUS_INVALID_PARAMETER;
5693 }
5694 status = set_ea(conn, fsp, smb_fname, ea_list);
5695
5696 return status;
5697}
5698
5699/****************************************************************************
5700 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5701****************************************************************************/
5702
5703static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5704 const char *pdata,
5705 int total_data,
5706 files_struct *fsp)
5707{
5708 struct ea_list *ea_list = NULL;
5709 NTSTATUS status;
5710
5711 if (!fsp) {
5712 return NT_STATUS_INVALID_HANDLE;
5713 }
5714
5715 if (!lp_ea_support(SNUM(conn))) {
5716 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5717 "EA's not supported.\n",
5718 (unsigned int)total_data));
5719 return NT_STATUS_EAS_NOT_SUPPORTED;
5720 }
5721
5722 if (total_data < 10) {
5723 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5724 "too small.\n",
5725 (unsigned int)total_data));
5726 return NT_STATUS_INVALID_PARAMETER;
5727 }
5728
5729 ea_list = read_nttrans_ea_list(talloc_tos(),
5730 pdata,
5731 total_data);
5732
5733 if (!ea_list) {
5734 return NT_STATUS_INVALID_PARAMETER;
5735 }
5736 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5737
5738 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5739 smb_fname_str_dbg(fsp->fsp_name),
5740 nt_errstr(status) ));
5741
5742 return status;
5743}
5744
5745
5746/****************************************************************************
5747 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5748****************************************************************************/
5749
5750static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5751 const char *pdata,
5752 int total_data,
5753 files_struct *fsp,
5754 struct smb_filename *smb_fname)
5755{
5756 NTSTATUS status = NT_STATUS_OK;
5757 bool delete_on_close;
5758 uint32 dosmode = 0;
5759
5760 if (total_data < 1) {
5761 return NT_STATUS_INVALID_PARAMETER;
5762 }
5763
5764 if (fsp == NULL) {
5765 return NT_STATUS_INVALID_HANDLE;
5766 }
5767
5768 delete_on_close = (CVAL(pdata,0) ? True : False);
5769 dosmode = dos_mode(conn, smb_fname);
5770
5771 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5772 "delete_on_close = %u\n",
5773 smb_fname_str_dbg(smb_fname),
5774 (unsigned int)dosmode,
5775 (unsigned int)delete_on_close ));
5776
5777 if (delete_on_close) {
5778 status = can_set_delete_on_close(fsp, dosmode);
5779 if (!NT_STATUS_IS_OK(status)) {
5780 return status;
5781 }
5782 }
5783
5784 /* The set is across all open files on this dev/inode pair. */
5785 if (!set_delete_on_close(fsp, delete_on_close,
5786 &conn->server_info->utok)) {
5787 return NT_STATUS_ACCESS_DENIED;
5788 }
5789 return NT_STATUS_OK;
5790}
5791
5792/****************************************************************************
5793 Deal with SMB_FILE_POSITION_INFORMATION.
5794****************************************************************************/
5795
5796static NTSTATUS smb_file_position_information(connection_struct *conn,
5797 const char *pdata,
5798 int total_data,
5799 files_struct *fsp)
5800{
5801 uint64_t position_information;
5802
5803 if (total_data < 8) {
5804 return NT_STATUS_INVALID_PARAMETER;
5805 }
5806
5807 if (fsp == NULL) {
5808 /* Ignore on pathname based set. */
5809 return NT_STATUS_OK;
5810 }
5811
5812 position_information = (uint64_t)IVAL(pdata,0);
5813#ifdef LARGE_SMB_OFF_T
5814 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5815#else /* LARGE_SMB_OFF_T */
5816 if (IVAL(pdata,4) != 0) {
5817 /* more than 32 bits? */
5818 return NT_STATUS_INVALID_PARAMETER;
5819 }
5820#endif /* LARGE_SMB_OFF_T */
5821
5822 DEBUG(10,("smb_file_position_information: Set file position "
5823 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5824 (double)position_information));
5825 fsp->fh->position_information = position_information;
5826 return NT_STATUS_OK;
5827}
5828
5829/****************************************************************************
5830 Deal with SMB_FILE_MODE_INFORMATION.
5831****************************************************************************/
5832
5833static NTSTATUS smb_file_mode_information(connection_struct *conn,
5834 const char *pdata,
5835 int total_data)
5836{
5837 uint32 mode;
5838
5839 if (total_data < 4) {
5840 return NT_STATUS_INVALID_PARAMETER;
5841 }
5842 mode = IVAL(pdata,0);
5843 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5844 return NT_STATUS_INVALID_PARAMETER;
5845 }
5846 return NT_STATUS_OK;
5847}
5848
5849/****************************************************************************
5850 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5851****************************************************************************/
5852
5853static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5854 struct smb_request *req,
5855 const char *pdata,
5856 int total_data,
5857 const struct smb_filename *smb_fname)
5858{
5859 char *link_target = NULL;
5860 const char *newname = smb_fname->base_name;
5861 TALLOC_CTX *ctx = talloc_tos();
5862
5863 /* Set a symbolic link. */
5864 /* Don't allow this if follow links is false. */
5865
5866 if (total_data == 0) {
5867 return NT_STATUS_INVALID_PARAMETER;
5868 }
5869
5870 if (!lp_symlinks(SNUM(conn))) {
5871 return NT_STATUS_ACCESS_DENIED;
5872 }
5873
5874 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5875 total_data, STR_TERMINATE);
5876
5877 if (!link_target) {
5878 return NT_STATUS_INVALID_PARAMETER;
5879 }
5880
5881 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5882 newname, link_target ));
5883
5884 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5885 return map_nt_error_from_unix(errno);
5886 }
5887
5888 return NT_STATUS_OK;
5889}
5890
5891/****************************************************************************
5892 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5893****************************************************************************/
5894
5895static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5896 struct smb_request *req,
5897 const char *pdata, int total_data,
5898 const struct smb_filename *smb_fname_new)
5899{
5900 char *oldname = NULL;
5901 struct smb_filename *smb_fname_old = NULL;
5902 TALLOC_CTX *ctx = talloc_tos();
5903 NTSTATUS status = NT_STATUS_OK;
5904
5905 /* Set a hard link. */
5906 if (total_data == 0) {
5907 return NT_STATUS_INVALID_PARAMETER;
5908 }
5909
5910 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5911 total_data, STR_TERMINATE, &status);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 return status;
5914 }
5915
5916 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5917 smb_fname_str_dbg(smb_fname_new), oldname));
5918
5919 status = filename_convert(ctx,
5920 conn,
5921 req->flags2 & FLAGS2_DFS_PATHNAMES,
5922 oldname,
5923 0,
5924 NULL,
5925 &smb_fname_old);
5926 if (!NT_STATUS_IS_OK(status)) {
5927 return status;
5928 }
5929
5930 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5931}
5932
5933/****************************************************************************
5934 Deal with SMB_FILE_RENAME_INFORMATION.
5935****************************************************************************/
5936
5937static NTSTATUS smb_file_rename_information(connection_struct *conn,
5938 struct smb_request *req,
5939 const char *pdata,
5940 int total_data,
5941 files_struct *fsp,
5942 struct smb_filename *smb_fname_src)
5943{
5944 bool overwrite;
5945 uint32 root_fid;
5946 uint32 len;
5947 char *newname = NULL;
5948 struct smb_filename *smb_fname_dst = NULL;
5949 bool dest_has_wcard = False;
5950 NTSTATUS status = NT_STATUS_OK;
5951 char *p;
5952 TALLOC_CTX *ctx = talloc_tos();
5953
5954 if (total_data < 13) {
5955 return NT_STATUS_INVALID_PARAMETER;
5956 }
5957
5958 overwrite = (CVAL(pdata,0) ? True : False);
5959 root_fid = IVAL(pdata,4);
5960 len = IVAL(pdata,8);
5961
5962 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5963 return NT_STATUS_INVALID_PARAMETER;
5964 }
5965
5966 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5967 len, 0, &status,
5968 &dest_has_wcard);
5969 if (!NT_STATUS_IS_OK(status)) {
5970 return status;
5971 }
5972
5973 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5974 newname));
5975
5976 status = resolve_dfspath_wcard(ctx, conn,
5977 req->flags2 & FLAGS2_DFS_PATHNAMES,
5978 newname,
5979 true,
5980 &newname,
5981 &dest_has_wcard);
5982 if (!NT_STATUS_IS_OK(status)) {
5983 return status;
5984 }
5985
5986 /* Check the new name has no '/' characters. */
5987 if (strchr_m(newname, '/')) {
5988 return NT_STATUS_NOT_SUPPORTED;
5989 }
5990
5991 if (fsp && fsp->base_fsp) {
5992 /* newname must be a stream name. */
5993 if (newname[0] != ':') {
5994 return NT_STATUS_NOT_SUPPORTED;
5995 }
5996
5997 /* Create an smb_fname to call rename_internals_fsp() with. */
5998 status = create_synthetic_smb_fname(talloc_tos(),
5999 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6000 &smb_fname_dst);
6001 if (!NT_STATUS_IS_OK(status)) {
6002 goto out;
6003 }
6004
6005 /*
6006 * Set the original last component, since
6007 * rename_internals_fsp() requires it.
6008 */
6009 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6010 newname);
6011 if (smb_fname_dst->original_lcomp == NULL) {
6012 status = NT_STATUS_NO_MEMORY;
6013 goto out;
6014 }
6015
6016 } else {
6017 /*
6018 * Build up an smb_fname_dst based on the filename passed in.
6019 * We basically just strip off the last component, and put on
6020 * the newname instead.
6021 */
6022 char *base_name = NULL;
6023
6024 /* newname must *not* be a stream name. */
6025 if (newname[0] == ':') {
6026 return NT_STATUS_NOT_SUPPORTED;
6027 }
6028
6029 /*
6030 * Strip off the last component (filename) of the path passed
6031 * in.
6032 */
6033 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6034 if (!base_name) {
6035 return NT_STATUS_NO_MEMORY;
6036 }
6037 p = strrchr_m(base_name, '/');
6038 if (p) {
6039 p[1] = '\0';
6040 } else {
6041 base_name = talloc_strdup(ctx, "./");
6042 if (!base_name) {
6043 return NT_STATUS_NO_MEMORY;
6044 }
6045 }
6046 /* Append the new name. */
6047 base_name = talloc_asprintf_append(base_name,
6048 "%s",
6049 newname);
6050 if (!base_name) {
6051 return NT_STATUS_NO_MEMORY;
6052 }
6053
6054 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6055 (UCF_SAVE_LCOMP |
6056 (dest_has_wcard ?
6057 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6058 0)));
6059
6060 /* If an error we expect this to be
6061 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6062
6063 if (!NT_STATUS_IS_OK(status)) {
6064 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6065 status)) {
6066 goto out;
6067 }
6068 /* Create an smb_fname to call rename_internals_fsp() */
6069 status = create_synthetic_smb_fname(ctx,
6070 base_name, NULL,
6071 NULL,
6072 &smb_fname_dst);
6073 if (!NT_STATUS_IS_OK(status)) {
6074 goto out;
6075 }
6076 }
6077 }
6078
6079 if (fsp) {
6080 DEBUG(10,("smb_file_rename_information: "
6081 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6082 fsp->fnum, fsp_str_dbg(fsp),
6083 smb_fname_str_dbg(smb_fname_dst)));
6084 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6085 overwrite);
6086 } else {
6087 DEBUG(10,("smb_file_rename_information: "
6088 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6089 smb_fname_str_dbg(smb_fname_src),
6090 smb_fname_str_dbg(smb_fname_dst)));
6091 status = rename_internals(ctx, conn, req, smb_fname_src,
6092 smb_fname_dst, 0, overwrite, false,
6093 dest_has_wcard,
6094 FILE_WRITE_ATTRIBUTES);
6095 }
6096 out:
6097 TALLOC_FREE(smb_fname_dst);
6098 return status;
6099}
6100
6101/****************************************************************************
6102 Deal with SMB_SET_POSIX_ACL.
6103****************************************************************************/
6104
6105#if defined(HAVE_POSIX_ACLS)
6106static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6107 const char *pdata,
6108 int total_data,
6109 files_struct *fsp,
6110 const struct smb_filename *smb_fname)
6111{
6112 uint16 posix_acl_version;
6113 uint16 num_file_acls;
6114 uint16 num_def_acls;
6115 bool valid_file_acls = True;
6116 bool valid_def_acls = True;
6117
6118 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6119 return NT_STATUS_INVALID_PARAMETER;
6120 }
6121 posix_acl_version = SVAL(pdata,0);
6122 num_file_acls = SVAL(pdata,2);
6123 num_def_acls = SVAL(pdata,4);
6124
6125 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6126 valid_file_acls = False;
6127 num_file_acls = 0;
6128 }
6129
6130 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6131 valid_def_acls = False;
6132 num_def_acls = 0;
6133 }
6134
6135 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6136 return NT_STATUS_INVALID_PARAMETER;
6137 }
6138
6139 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6140 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6141 return NT_STATUS_INVALID_PARAMETER;
6142 }
6143
6144 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6145 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6146 (unsigned int)num_file_acls,
6147 (unsigned int)num_def_acls));
6148
6149 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6150 smb_fname->base_name, num_file_acls,
6151 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6152 return map_nt_error_from_unix(errno);
6153 }
6154
6155 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6156 smb_fname->base_name, &smb_fname->st, num_def_acls,
6157 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6158 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6159 return map_nt_error_from_unix(errno);
6160 }
6161 return NT_STATUS_OK;
6162}
6163#endif
6164
6165/****************************************************************************
6166 Deal with SMB_SET_POSIX_LOCK.
6167****************************************************************************/
6168
6169static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6170 struct smb_request *req,
6171 const char *pdata,
6172 int total_data,
6173 files_struct *fsp)
6174{
6175 uint64_t count;
6176 uint64_t offset;
6177 uint32 lock_pid;
6178 bool blocking_lock = False;
6179 enum brl_type lock_type;
6180
6181 NTSTATUS status = NT_STATUS_OK;
6182
6183 if (fsp == NULL || fsp->fh->fd == -1) {
6184 return NT_STATUS_INVALID_HANDLE;
6185 }
6186
6187 if (total_data != POSIX_LOCK_DATA_SIZE) {
6188 return NT_STATUS_INVALID_PARAMETER;
6189 }
6190
6191 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6192 case POSIX_LOCK_TYPE_READ:
6193 lock_type = READ_LOCK;
6194 break;
6195 case POSIX_LOCK_TYPE_WRITE:
6196 /* Return the right POSIX-mappable error code for files opened read-only. */
6197 if (!fsp->can_write) {
6198 return NT_STATUS_INVALID_HANDLE;
6199 }
6200 lock_type = WRITE_LOCK;
6201 break;
6202 case POSIX_LOCK_TYPE_UNLOCK:
6203 lock_type = UNLOCK_LOCK;
6204 break;
6205 default:
6206 return NT_STATUS_INVALID_PARAMETER;
6207 }
6208
6209 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6210 blocking_lock = False;
6211 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6212 blocking_lock = True;
6213 } else {
6214 return NT_STATUS_INVALID_PARAMETER;
6215 }
6216
6217 if (!lp_blocking_locks(SNUM(conn))) {
6218 blocking_lock = False;
6219 }
6220
6221 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6222#if defined(HAVE_LONGLONG)
6223 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6224 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6225 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6226 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6227#else /* HAVE_LONGLONG */
6228 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6229 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6230#endif /* HAVE_LONGLONG */
6231
6232 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6233 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6234 fsp_str_dbg(fsp),
6235 (unsigned int)lock_type,
6236 (unsigned int)lock_pid,
6237 (double)count,
6238 (double)offset ));
6239
6240 if (lock_type == UNLOCK_LOCK) {
6241 status = do_unlock(smbd_messaging_context(),
6242 fsp,
6243 lock_pid,
6244 count,
6245 offset,
6246 POSIX_LOCK);
6247 } else {
6248 uint32 block_smbpid;
6249
6250 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6251 fsp,
6252 lock_pid,
6253 count,
6254 offset,
6255 lock_type,
6256 POSIX_LOCK,
6257 blocking_lock,
6258 &status,
6259 &block_smbpid,
6260 NULL);
6261
6262 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6263 /*
6264 * A blocking lock was requested. Package up
6265 * this smb into a queued request and push it
6266 * onto the blocking lock queue.
6267 */
6268 if(push_blocking_lock_request(br_lck,
6269 req,
6270 fsp,
6271 -1, /* infinite timeout. */
6272 0,
6273 lock_pid,
6274 lock_type,
6275 POSIX_LOCK,
6276 offset,
6277 count,
6278 block_smbpid)) {
6279 TALLOC_FREE(br_lck);
6280 return status;
6281 }
6282 }
6283 TALLOC_FREE(br_lck);
6284 }
6285
6286 return status;
6287}
6288
6289/****************************************************************************
6290 Deal with SMB_SET_FILE_BASIC_INFO.
6291****************************************************************************/
6292
6293static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6294 const char *pdata,
6295 int total_data,
6296 files_struct *fsp,
6297 const struct smb_filename *smb_fname)
6298{
6299 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6300 struct smb_file_time ft;
6301 uint32 dosmode = 0;
6302 NTSTATUS status = NT_STATUS_OK;
6303
6304 ZERO_STRUCT(ft);
6305
6306 if (total_data < 36) {
6307 return NT_STATUS_INVALID_PARAMETER;
6308 }
6309
6310 /* Set the attributes */
6311 dosmode = IVAL(pdata,32);
6312 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6313 if (!NT_STATUS_IS_OK(status)) {
6314 return status;
6315 }
6316
6317 /* create time */
6318 ft.create_time = interpret_long_date(pdata);
6319
6320 /* access time */
6321 ft.atime = interpret_long_date(pdata+8);
6322
6323 /* write time. */
6324 ft.mtime = interpret_long_date(pdata+16);
6325
6326 /* change time. */
6327 ft.ctime = interpret_long_date(pdata+24);
6328
6329 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6330 smb_fname_str_dbg(smb_fname)));
6331
6332 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6333 true);
6334}
6335
6336/****************************************************************************
6337 Deal with SMB_INFO_STANDARD.
6338****************************************************************************/
6339
6340static NTSTATUS smb_set_info_standard(connection_struct *conn,
6341 const char *pdata,
6342 int total_data,
6343 files_struct *fsp,
6344 const struct smb_filename *smb_fname)
6345{
6346 struct smb_file_time ft;
6347
6348 ZERO_STRUCT(ft);
6349
6350 if (total_data < 12) {
6351 return NT_STATUS_INVALID_PARAMETER;
6352 }
6353
6354 /* create time */
6355 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6356 /* access time */
6357 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6358 /* write time */
6359 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6360
6361 DEBUG(10,("smb_set_info_standard: file %s\n",
6362 smb_fname_str_dbg(smb_fname)));
6363
6364 return smb_set_file_time(conn,
6365 fsp,
6366 smb_fname,
6367 &ft,
6368 true);
6369}
6370
6371/****************************************************************************
6372 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6373****************************************************************************/
6374
6375static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6376 struct smb_request *req,
6377 const char *pdata,
6378 int total_data,
6379 files_struct *fsp,
6380 struct smb_filename *smb_fname)
6381{
6382 uint64_t allocation_size = 0;
6383 NTSTATUS status = NT_STATUS_OK;
6384 files_struct *new_fsp = NULL;
6385
6386 if (!VALID_STAT(smb_fname->st)) {
6387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6388 }
6389
6390 if (total_data < 8) {
6391 return NT_STATUS_INVALID_PARAMETER;
6392 }
6393
6394 allocation_size = (uint64_t)IVAL(pdata,0);
6395#ifdef LARGE_SMB_OFF_T
6396 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6397#else /* LARGE_SMB_OFF_T */
6398 if (IVAL(pdata,4) != 0) {
6399 /* more than 32 bits? */
6400 return NT_STATUS_INVALID_PARAMETER;
6401 }
6402#endif /* LARGE_SMB_OFF_T */
6403
6404 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6405 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6406 (double)allocation_size));
6407
6408 if (allocation_size) {
6409 allocation_size = smb_roundup(conn, allocation_size);
6410 }
6411
6412 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6413 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6414 (double)allocation_size));
6415
6416 if (fsp && fsp->fh->fd != -1) {
6417 /* Open file handle. */
6418 /* Only change if needed. */
6419 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6420 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6421 return map_nt_error_from_unix(errno);
6422 }
6423 }
6424 /* But always update the time. */
6425 /*
6426 * This is equivalent to a write. Ensure it's seen immediately
6427 * if there are no pending writes.
6428 */
6429 trigger_write_time_update_immediate(fsp);
6430 return NT_STATUS_OK;
6431 }
6432
6433 /* Pathname or stat or directory file. */
6434 status = SMB_VFS_CREATE_FILE(
6435 conn, /* conn */
6436 req, /* req */
6437 0, /* root_dir_fid */
6438 smb_fname, /* fname */
6439 FILE_WRITE_DATA, /* access_mask */
6440 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6441 FILE_SHARE_DELETE),
6442 FILE_OPEN, /* create_disposition*/
6443 0, /* create_options */
6444 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6445 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6446 0, /* allocation_size */
6447 NULL, /* sd */
6448 NULL, /* ea_list */
6449 &new_fsp, /* result */
6450 NULL); /* pinfo */
6451
6452 if (!NT_STATUS_IS_OK(status)) {
6453 /* NB. We check for open_was_deferred in the caller. */
6454 return status;
6455 }
6456
6457 /* Only change if needed. */
6458 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6459 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6460 status = map_nt_error_from_unix(errno);
6461 close_file(req, new_fsp, NORMAL_CLOSE);
6462 return status;
6463 }
6464 }
6465
6466 /* Changing the allocation size should set the last mod time. */
6467 /*
6468 * This is equivalent to a write. Ensure it's seen immediately
6469 * if there are no pending writes.
6470 */
6471 trigger_write_time_update_immediate(new_fsp);
6472
6473 close_file(req, new_fsp, NORMAL_CLOSE);
6474 return NT_STATUS_OK;
6475}
6476
6477/****************************************************************************
6478 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6479****************************************************************************/
6480
6481static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6482 struct smb_request *req,
6483 const char *pdata,
6484 int total_data,
6485 files_struct *fsp,
6486 const struct smb_filename *smb_fname,
6487 bool fail_after_createfile)
6488{
6489 SMB_OFF_T size;
6490
6491 if (total_data < 8) {
6492 return NT_STATUS_INVALID_PARAMETER;
6493 }
6494
6495 size = IVAL(pdata,0);
6496#ifdef LARGE_SMB_OFF_T
6497 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6498#else /* LARGE_SMB_OFF_T */
6499 if (IVAL(pdata,4) != 0) {
6500 /* more than 32 bits? */
6501 return NT_STATUS_INVALID_PARAMETER;
6502 }
6503#endif /* LARGE_SMB_OFF_T */
6504 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6505 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6506 (double)size));
6507
6508 return smb_set_file_size(conn, req,
6509 fsp,
6510 smb_fname,
6511 &smb_fname->st,
6512 size,
6513 fail_after_createfile);
6514}
6515
6516/****************************************************************************
6517 Allow a UNIX info mknod.
6518****************************************************************************/
6519
6520static NTSTATUS smb_unix_mknod(connection_struct *conn,
6521 const char *pdata,
6522 int total_data,
6523 const struct smb_filename *smb_fname)
6524{
6525 uint32 file_type = IVAL(pdata,56);
6526#if defined(HAVE_MAKEDEV)
6527 uint32 dev_major = IVAL(pdata,60);
6528 uint32 dev_minor = IVAL(pdata,68);
6529#endif
6530 SMB_DEV_T dev = (SMB_DEV_T)0;
6531 uint32 raw_unixmode = IVAL(pdata,84);
6532 NTSTATUS status;
6533 mode_t unixmode;
6534
6535 if (total_data < 100) {
6536 return NT_STATUS_INVALID_PARAMETER;
6537 }
6538
6539 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6540 PERM_NEW_FILE, &unixmode);
6541 if (!NT_STATUS_IS_OK(status)) {
6542 return status;
6543 }
6544
6545#if defined(HAVE_MAKEDEV)
6546 dev = makedev(dev_major, dev_minor);
6547#endif
6548
6549 switch (file_type) {
6550#if defined(S_IFIFO)
6551 case UNIX_TYPE_FIFO:
6552 unixmode |= S_IFIFO;
6553 break;
6554#endif
6555#if defined(S_IFSOCK)
6556 case UNIX_TYPE_SOCKET:
6557 unixmode |= S_IFSOCK;
6558 break;
6559#endif
6560#if defined(S_IFCHR)
6561 case UNIX_TYPE_CHARDEV:
6562 unixmode |= S_IFCHR;
6563 break;
6564#endif
6565#if defined(S_IFBLK)
6566 case UNIX_TYPE_BLKDEV:
6567 unixmode |= S_IFBLK;
6568 break;
6569#endif
6570 default:
6571 return NT_STATUS_INVALID_PARAMETER;
6572 }
6573
6574 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6575 "%.0f mode 0%o for file %s\n", (double)dev,
6576 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6577
6578 /* Ok - do the mknod. */
6579 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6580 return map_nt_error_from_unix(errno);
6581 }
6582
6583 /* If any of the other "set" calls fail we
6584 * don't want to end up with a half-constructed mknod.
6585 */
6586
6587 if (lp_inherit_perms(SNUM(conn))) {
6588 char *parent;
6589 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6590 &parent, NULL)) {
6591 return NT_STATUS_NO_MEMORY;
6592 }
6593 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6594 unixmode);
6595 TALLOC_FREE(parent);
6596 }
6597
6598 return NT_STATUS_OK;
6599}
6600
6601/****************************************************************************
6602 Deal with SMB_SET_FILE_UNIX_BASIC.
6603****************************************************************************/
6604
6605static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6606 struct smb_request *req,
6607 const char *pdata,
6608 int total_data,
6609 files_struct *fsp,
6610 const struct smb_filename *smb_fname)
6611{
6612 struct smb_file_time ft;
6613 uint32 raw_unixmode;
6614 mode_t unixmode;
6615 SMB_OFF_T size = 0;
6616 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6617 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6618 NTSTATUS status = NT_STATUS_OK;
6619 bool delete_on_fail = False;
6620 enum perm_type ptype;
6621 files_struct *all_fsps = NULL;
6622 bool modify_mtime = true;
6623 struct file_id id;
6624 struct smb_filename *smb_fname_tmp = NULL;
6625 SMB_STRUCT_STAT sbuf;
6626
6627 ZERO_STRUCT(ft);
6628
6629 if (total_data < 100) {
6630 return NT_STATUS_INVALID_PARAMETER;
6631 }
6632
6633 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6634 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6635 size=IVAL(pdata,0); /* first 8 Bytes are size */
6636#ifdef LARGE_SMB_OFF_T
6637 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6638#else /* LARGE_SMB_OFF_T */
6639 if (IVAL(pdata,4) != 0) {
6640 /* more than 32 bits? */
6641 return NT_STATUS_INVALID_PARAMETER;
6642 }
6643#endif /* LARGE_SMB_OFF_T */
6644 }
6645
6646 ft.atime = interpret_long_date(pdata+24); /* access_time */
6647 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6648 set_owner = (uid_t)IVAL(pdata,40);
6649 set_grp = (gid_t)IVAL(pdata,48);
6650 raw_unixmode = IVAL(pdata,84);
6651
6652 if (VALID_STAT(smb_fname->st)) {
6653 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6654 ptype = PERM_EXISTING_DIR;
6655 } else {
6656 ptype = PERM_EXISTING_FILE;
6657 }
6658 } else {
6659 ptype = PERM_NEW_FILE;
6660 }
6661
6662 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6663 ptype, &unixmode);
6664 if (!NT_STATUS_IS_OK(status)) {
6665 return status;
6666 }
6667
6668 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6669 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6670 smb_fname_str_dbg(smb_fname), (double)size,
6671 (unsigned int)set_owner, (unsigned int)set_grp,
6672 (int)raw_unixmode));
6673
6674 sbuf = smb_fname->st;
6675
6676 if (!VALID_STAT(sbuf)) {
6677 /*
6678 * The only valid use of this is to create character and block
6679 * devices, and named pipes. This is deprecated (IMHO) and
6680 * a new info level should be used for mknod. JRA.
6681 */
6682
6683 status = smb_unix_mknod(conn,
6684 pdata,
6685 total_data,
6686 smb_fname);
6687 if (!NT_STATUS_IS_OK(status)) {
6688 return status;
6689 }
6690
6691 status = copy_smb_filename(talloc_tos(), smb_fname,
6692 &smb_fname_tmp);
6693 if (!NT_STATUS_IS_OK(status)) {
6694 return status;
6695 }
6696
6697 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6698 status = map_nt_error_from_unix(errno);
6699 TALLOC_FREE(smb_fname_tmp);
6700 SMB_VFS_UNLINK(conn, smb_fname);
6701 return status;
6702 }
6703
6704 sbuf = smb_fname_tmp->st;
6705 smb_fname = smb_fname_tmp;
6706
6707 /* Ensure we don't try and change anything else. */
6708 raw_unixmode = SMB_MODE_NO_CHANGE;
6709 size = get_file_size_stat(&sbuf);
6710 ft.atime = sbuf.st_ex_atime;
6711 ft.mtime = sbuf.st_ex_mtime;
6712 /*
6713 * We continue here as we might want to change the
6714 * owner uid/gid.
6715 */
6716 delete_on_fail = True;
6717 }
6718
6719#if 1
6720 /* Horrible backwards compatibility hack as an old server bug
6721 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6722 * */
6723
6724 if (!size) {
6725 size = get_file_size_stat(&sbuf);
6726 }
6727#endif
6728
6729 /*
6730 * Deal with the UNIX specific mode set.
6731 */
6732
6733 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6734 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6735 "setting mode 0%o for file %s\n",
6736 (unsigned int)unixmode,
6737 smb_fname_str_dbg(smb_fname)));
6738 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6739 return map_nt_error_from_unix(errno);
6740 }
6741 }
6742
6743 /*
6744 * Deal with the UNIX specific uid set.
6745 */
6746
6747 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6748 (sbuf.st_ex_uid != set_owner)) {
6749 int ret;
6750
6751 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6752 "changing owner %u for path %s\n",
6753 (unsigned int)set_owner,
6754 smb_fname_str_dbg(smb_fname)));
6755
6756 if (S_ISLNK(sbuf.st_ex_mode)) {
6757 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6758 set_owner, (gid_t)-1);
6759 } else {
6760 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6761 set_owner, (gid_t)-1);
6762 }
6763
6764 if (ret != 0) {
6765 status = map_nt_error_from_unix(errno);
6766 if (delete_on_fail) {
6767 SMB_VFS_UNLINK(conn, smb_fname);
6768 }
6769 return status;
6770 }
6771 }
6772
6773 /*
6774 * Deal with the UNIX specific gid set.
6775 */
6776
6777 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6778 (sbuf.st_ex_gid != set_grp)) {
6779 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6780 "changing group %u for file %s\n",
6781 (unsigned int)set_owner,
6782 smb_fname_str_dbg(smb_fname)));
6783 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6784 set_grp) != 0) {
6785 status = map_nt_error_from_unix(errno);
6786 if (delete_on_fail) {
6787 SMB_VFS_UNLINK(conn, smb_fname);
6788 }
6789 return status;
6790 }
6791 }
6792
6793 /* Deal with any size changes. */
6794
6795 status = smb_set_file_size(conn, req,
6796 fsp,
6797 smb_fname,
6798 &sbuf,
6799 size,
6800 false);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 return status;
6803 }
6804
6805 /* Deal with any time changes. */
6806 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6807 /* No change, don't cancel anything. */
6808 return status;
6809 }
6810
6811 id = vfs_file_id_from_sbuf(conn, &sbuf);
6812 for(all_fsps = file_find_di_first(id); all_fsps;
6813 all_fsps = file_find_di_next(all_fsps)) {
6814 /*
6815 * We're setting the time explicitly for UNIX.
6816 * Cancel any pending changes over all handles.
6817 */
6818 all_fsps->update_write_time_on_close = false;
6819 TALLOC_FREE(all_fsps->update_write_time_event);
6820 }
6821
6822 /*
6823 * Override the "setting_write_time"
6824 * parameter here as it almost does what
6825 * we need. Just remember if we modified
6826 * mtime and send the notify ourselves.
6827 */
6828 if (null_timespec(ft.mtime)) {
6829 modify_mtime = false;
6830 }
6831
6832 status = smb_set_file_time(conn,
6833 fsp,
6834 smb_fname,
6835 &ft,
6836 false);
6837 if (modify_mtime) {
6838 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6839 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6840 }
6841 return status;
6842}
6843
6844/****************************************************************************
6845 Deal with SMB_SET_FILE_UNIX_INFO2.
6846****************************************************************************/
6847
6848static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6849 struct smb_request *req,
6850 const char *pdata,
6851 int total_data,
6852 files_struct *fsp,
6853 const struct smb_filename *smb_fname)
6854{
6855 NTSTATUS status;
6856 uint32 smb_fflags;
6857 uint32 smb_fmask;
6858
6859 if (total_data < 116) {
6860 return NT_STATUS_INVALID_PARAMETER;
6861 }
6862
6863 /* Start by setting all the fields that are common between UNIX_BASIC
6864 * and UNIX_INFO2.
6865 */
6866 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6867 fsp, smb_fname);
6868 if (!NT_STATUS_IS_OK(status)) {
6869 return status;
6870 }
6871
6872 smb_fflags = IVAL(pdata, 108);
6873 smb_fmask = IVAL(pdata, 112);
6874
6875 /* NB: We should only attempt to alter the file flags if the client
6876 * sends a non-zero mask.
6877 */
6878 if (smb_fmask != 0) {
6879 int stat_fflags = 0;
6880
6881 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6882 smb_fmask, &stat_fflags)) {
6883 /* Client asked to alter a flag we don't understand. */
6884 return NT_STATUS_INVALID_PARAMETER;
6885 }
6886
6887 if (fsp && fsp->fh->fd != -1) {
6888 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6889 return NT_STATUS_NOT_SUPPORTED;
6890 } else {
6891 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6892 stat_fflags) != 0) {
6893 return map_nt_error_from_unix(errno);
6894 }
6895 }
6896 }
6897
6898 /* XXX: need to add support for changing the create_time here. You
6899 * can do this for paths on Darwin with setattrlist(2). The right way
6900 * to hook this up is probably by extending the VFS utimes interface.
6901 */
6902
6903 return NT_STATUS_OK;
6904}
6905
6906/****************************************************************************
6907 Create a directory with POSIX semantics.
6908****************************************************************************/
6909
6910static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6911 struct smb_request *req,
6912 char **ppdata,
6913 int total_data,
6914 struct smb_filename *smb_fname,
6915 int *pdata_return_size)
6916{
6917 NTSTATUS status = NT_STATUS_OK;
6918 uint32 raw_unixmode = 0;
6919 uint32 mod_unixmode = 0;
6920 mode_t unixmode = (mode_t)0;
6921 files_struct *fsp = NULL;
6922 uint16 info_level_return = 0;
6923 int info;
6924 char *pdata = *ppdata;
6925
6926 if (total_data < 18) {
6927 return NT_STATUS_INVALID_PARAMETER;
6928 }
6929
6930 raw_unixmode = IVAL(pdata,8);
6931 /* Next 4 bytes are not yet defined. */
6932
6933 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6934 PERM_NEW_DIR, &unixmode);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 return status;
6937 }
6938
6939 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6940
6941 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6942 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6943
6944 status = SMB_VFS_CREATE_FILE(
6945 conn, /* conn */
6946 req, /* req */
6947 0, /* root_dir_fid */
6948 smb_fname, /* fname */
6949 FILE_READ_ATTRIBUTES, /* access_mask */
6950 FILE_SHARE_NONE, /* share_access */
6951 FILE_CREATE, /* create_disposition*/
6952 FILE_DIRECTORY_FILE, /* create_options */
6953 mod_unixmode, /* file_attributes */
6954 0, /* oplock_request */
6955 0, /* allocation_size */
6956 NULL, /* sd */
6957 NULL, /* ea_list */
6958 &fsp, /* result */
6959 &info); /* pinfo */
6960
6961 if (NT_STATUS_IS_OK(status)) {
6962 close_file(req, fsp, NORMAL_CLOSE);
6963 }
6964
6965 info_level_return = SVAL(pdata,16);
6966
6967 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6968 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6969 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6970 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6971 } else {
6972 *pdata_return_size = 12;
6973 }
6974
6975 /* Realloc the data size */
6976 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6977 if (*ppdata == NULL) {
6978 *pdata_return_size = 0;
6979 return NT_STATUS_NO_MEMORY;
6980 }
6981 pdata = *ppdata;
6982
6983 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6984 SSVAL(pdata,2,0); /* No fnum. */
6985 SIVAL(pdata,4,info); /* Was directory created. */
6986
6987 switch (info_level_return) {
6988 case SMB_QUERY_FILE_UNIX_BASIC:
6989 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6990 SSVAL(pdata,10,0); /* Padding. */
6991 store_file_unix_basic(conn, pdata + 12, fsp,
6992 &smb_fname->st);
6993 break;
6994 case SMB_QUERY_FILE_UNIX_INFO2:
6995 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6996 SSVAL(pdata,10,0); /* Padding. */
6997 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6998 &smb_fname->st);
6999 break;
7000 default:
7001 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7002 SSVAL(pdata,10,0); /* Padding. */
7003 break;
7004 }
7005
7006 return status;
7007}
7008
7009/****************************************************************************
7010 Open/Create a file with POSIX semantics.
7011****************************************************************************/
7012
7013static NTSTATUS smb_posix_open(connection_struct *conn,
7014 struct smb_request *req,
7015 char **ppdata,
7016 int total_data,
7017 struct smb_filename *smb_fname,
7018 int *pdata_return_size)
7019{
7020 bool extended_oplock_granted = False;
7021 char *pdata = *ppdata;
7022 uint32 flags = 0;
7023 uint32 wire_open_mode = 0;
7024 uint32 raw_unixmode = 0;
7025 uint32 mod_unixmode = 0;
7026 uint32 create_disp = 0;
7027 uint32 access_mask = 0;
7028 uint32 create_options = 0;
7029 NTSTATUS status = NT_STATUS_OK;
7030 mode_t unixmode = (mode_t)0;
7031 files_struct *fsp = NULL;
7032 int oplock_request = 0;
7033 int info = 0;
7034 uint16 info_level_return = 0;
7035
7036 if (total_data < 18) {
7037 return NT_STATUS_INVALID_PARAMETER;
7038 }
7039
7040 flags = IVAL(pdata,0);
7041 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7042 if (oplock_request) {
7043 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7044 }
7045
7046 wire_open_mode = IVAL(pdata,4);
7047
7048 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7049 return smb_posix_mkdir(conn, req,
7050 ppdata,
7051 total_data,
7052 smb_fname,
7053 pdata_return_size);
7054 }
7055
7056 switch (wire_open_mode & SMB_ACCMODE) {
7057 case SMB_O_RDONLY:
7058 access_mask = FILE_READ_DATA;
7059 break;
7060 case SMB_O_WRONLY:
7061 access_mask = FILE_WRITE_DATA;
7062 break;
7063 case SMB_O_RDWR:
7064 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7065 break;
7066 default:
7067 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7068 (unsigned int)wire_open_mode ));
7069 return NT_STATUS_INVALID_PARAMETER;
7070 }
7071
7072 wire_open_mode &= ~SMB_ACCMODE;
7073
7074 /* First take care of O_CREAT|O_EXCL interactions. */
7075 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7076 case (SMB_O_CREAT | SMB_O_EXCL):
7077 /* File exists fail. File not exist create. */
7078 create_disp = FILE_CREATE;
7079 break;
7080 case SMB_O_CREAT:
7081 /* File exists open. File not exist create. */
7082 create_disp = FILE_OPEN_IF;
7083 break;
7084 case 0:
7085 /* File exists open. File not exist fail. */
7086 create_disp = FILE_OPEN;
7087 break;
7088 case SMB_O_EXCL:
7089 /* O_EXCL on its own without O_CREAT is undefined. */
7090 default:
7091 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7092 (unsigned int)wire_open_mode ));
7093 return NT_STATUS_INVALID_PARAMETER;
7094 }
7095
7096 /* Next factor in the effects of O_TRUNC. */
7097 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7098
7099 if (wire_open_mode & SMB_O_TRUNC) {
7100 switch (create_disp) {
7101 case FILE_CREATE:
7102 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7103 /* Leave create_disp alone as
7104 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7105 */
7106 /* File exists fail. File not exist create. */
7107 break;
7108 case FILE_OPEN_IF:
7109 /* SMB_O_CREAT | SMB_O_TRUNC */
7110 /* File exists overwrite. File not exist create. */
7111 create_disp = FILE_OVERWRITE_IF;
7112 break;
7113 case FILE_OPEN:
7114 /* SMB_O_TRUNC */
7115 /* File exists overwrite. File not exist fail. */
7116 create_disp = FILE_OVERWRITE;
7117 break;
7118 default:
7119 /* Cannot get here. */
7120 smb_panic("smb_posix_open: logic error");
7121 return NT_STATUS_INVALID_PARAMETER;
7122 }
7123 }
7124
7125 raw_unixmode = IVAL(pdata,8);
7126 /* Next 4 bytes are not yet defined. */
7127
7128 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7129 (VALID_STAT(smb_fname->st) ?
7130 PERM_EXISTING_FILE : PERM_NEW_FILE),
7131 &unixmode);
7132
7133 if (!NT_STATUS_IS_OK(status)) {
7134 return status;
7135 }
7136
7137 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7138
7139 if (wire_open_mode & SMB_O_SYNC) {
7140 create_options |= FILE_WRITE_THROUGH;
7141 }
7142 if (wire_open_mode & SMB_O_APPEND) {
7143 access_mask |= FILE_APPEND_DATA;
7144 }
7145 if (wire_open_mode & SMB_O_DIRECT) {
7146 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7147 }
7148
7149 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7150 smb_fname_str_dbg(smb_fname),
7151 (unsigned int)wire_open_mode,
7152 (unsigned int)unixmode ));
7153
7154 status = SMB_VFS_CREATE_FILE(
7155 conn, /* conn */
7156 req, /* req */
7157 0, /* root_dir_fid */
7158 smb_fname, /* fname */
7159 access_mask, /* access_mask */
7160 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7161 FILE_SHARE_DELETE),
7162 create_disp, /* create_disposition*/
7163 FILE_NON_DIRECTORY_FILE, /* create_options */
7164 mod_unixmode, /* file_attributes */
7165 oplock_request, /* oplock_request */
7166 0, /* allocation_size */
7167 NULL, /* sd */
7168 NULL, /* ea_list */
7169 &fsp, /* result */
7170 &info); /* pinfo */
7171
7172 if (!NT_STATUS_IS_OK(status)) {
7173 return status;
7174 }
7175
7176 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7177 extended_oplock_granted = True;
7178 }
7179
7180 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7181 extended_oplock_granted = True;
7182 }
7183
7184 info_level_return = SVAL(pdata,16);
7185
7186 /* Allocate the correct return size. */
7187
7188 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7189 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7190 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7191 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7192 } else {
7193 *pdata_return_size = 12;
7194 }
7195
7196 /* Realloc the data size */
7197 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7198 if (*ppdata == NULL) {
7199 close_file(req, fsp, ERROR_CLOSE);
7200 *pdata_return_size = 0;
7201 return NT_STATUS_NO_MEMORY;
7202 }
7203 pdata = *ppdata;
7204
7205 if (extended_oplock_granted) {
7206 if (flags & REQUEST_BATCH_OPLOCK) {
7207 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7208 } else {
7209 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7210 }
7211 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7212 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7213 } else {
7214 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7215 }
7216
7217 SSVAL(pdata,2,fsp->fnum);
7218 SIVAL(pdata,4,info); /* Was file created etc. */
7219
7220 switch (info_level_return) {
7221 case SMB_QUERY_FILE_UNIX_BASIC:
7222 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7223 SSVAL(pdata,10,0); /* padding. */
7224 store_file_unix_basic(conn, pdata + 12, fsp,
7225 &smb_fname->st);
7226 break;
7227 case SMB_QUERY_FILE_UNIX_INFO2:
7228 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7229 SSVAL(pdata,10,0); /* padding. */
7230 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7231 &smb_fname->st);
7232 break;
7233 default:
7234 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7235 SSVAL(pdata,10,0); /* padding. */
7236 break;
7237 }
7238 return NT_STATUS_OK;
7239}
7240
7241/****************************************************************************
7242 Delete a file with POSIX semantics.
7243****************************************************************************/
7244
7245static NTSTATUS smb_posix_unlink(connection_struct *conn,
7246 struct smb_request *req,
7247 const char *pdata,
7248 int total_data,
7249 struct smb_filename *smb_fname)
7250{
7251 NTSTATUS status = NT_STATUS_OK;
7252 files_struct *fsp = NULL;
7253 uint16 flags = 0;
7254 char del = 1;
7255 int info = 0;
7256 int create_options = 0;
7257 int i;
7258 struct share_mode_lock *lck = NULL;
7259
7260 if (total_data < 2) {
7261 return NT_STATUS_INVALID_PARAMETER;
7262 }
7263
7264 flags = SVAL(pdata,0);
7265
7266 if (!VALID_STAT(smb_fname->st)) {
7267 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7268 }
7269
7270 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7271 !VALID_STAT_OF_DIR(smb_fname->st)) {
7272 return NT_STATUS_NOT_A_DIRECTORY;
7273 }
7274
7275 DEBUG(10,("smb_posix_unlink: %s %s\n",
7276 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7277 smb_fname_str_dbg(smb_fname)));
7278
7279 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7280 create_options |= FILE_DIRECTORY_FILE;
7281 }
7282
7283 status = SMB_VFS_CREATE_FILE(
7284 conn, /* conn */
7285 req, /* req */
7286 0, /* root_dir_fid */
7287 smb_fname, /* fname */
7288 DELETE_ACCESS, /* access_mask */
7289 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7290 FILE_SHARE_DELETE),
7291 FILE_OPEN, /* create_disposition*/
7292 create_options, /* create_options */
7293 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7294 0, /* oplock_request */
7295 0, /* allocation_size */
7296 NULL, /* sd */
7297 NULL, /* ea_list */
7298 &fsp, /* result */
7299 &info); /* pinfo */
7300
7301 if (!NT_STATUS_IS_OK(status)) {
7302 return status;
7303 }
7304
7305 /*
7306 * Don't lie to client. If we can't really delete due to
7307 * non-POSIX opens return SHARING_VIOLATION.
7308 */
7309
7310 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7311 NULL);
7312 if (lck == NULL) {
7313 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7314 "lock for file %s\n", fsp_str_dbg(fsp)));
7315 close_file(req, fsp, NORMAL_CLOSE);
7316 return NT_STATUS_INVALID_PARAMETER;
7317 }
7318
7319 /*
7320 * See if others still have the file open. If this is the case, then
7321 * don't delete. If all opens are POSIX delete we can set the delete
7322 * on close disposition.
7323 */
7324 for (i=0; i<lck->num_share_modes; i++) {
7325 struct share_mode_entry *e = &lck->share_modes[i];
7326 if (is_valid_share_mode_entry(e)) {
7327 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7328 continue;
7329 }
7330 /* Fail with sharing violation. */
7331 close_file(req, fsp, NORMAL_CLOSE);
7332 TALLOC_FREE(lck);
7333 return NT_STATUS_SHARING_VIOLATION;
7334 }
7335 }
7336
7337 /*
7338 * Set the delete on close.
7339 */
7340 status = smb_set_file_disposition_info(conn,
7341 &del,
7342 1,
7343 fsp,
7344 smb_fname);
7345
7346 if (!NT_STATUS_IS_OK(status)) {
7347 close_file(req, fsp, NORMAL_CLOSE);
7348 TALLOC_FREE(lck);
7349 return status;
7350 }
7351 TALLOC_FREE(lck);
7352 return close_file(req, fsp, NORMAL_CLOSE);
7353}
7354
7355NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7356 struct smb_request *req,
7357 TALLOC_CTX *mem_ctx,
7358 uint16_t info_level,
7359 files_struct *fsp,
7360 struct smb_filename *smb_fname,
7361 char **ppdata, int total_data,
7362 int *ret_data_size)
7363{
7364 char *pdata = *ppdata;
7365 NTSTATUS status = NT_STATUS_OK;
7366 int data_return_size = 0;
7367
7368 *ret_data_size = 0;
7369
7370 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7371 return NT_STATUS_INVALID_LEVEL;
7372 }
7373
7374 if (!CAN_WRITE(conn)) {
7375 /* Allow POSIX opens. The open path will deny
7376 * any non-readonly opens. */
7377 if (info_level != SMB_POSIX_PATH_OPEN) {
7378 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7379 }
7380 }
7381
7382 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7383 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7384 fsp ? fsp->fnum : -1, info_level, total_data));
7385
7386 switch (info_level) {
7387
7388 case SMB_INFO_STANDARD:
7389 {
7390 status = smb_set_info_standard(conn,
7391 pdata,
7392 total_data,
7393 fsp,
7394 smb_fname);
7395 break;
7396 }
7397
7398 case SMB_INFO_SET_EA:
7399 {
7400 status = smb_info_set_ea(conn,
7401 pdata,
7402 total_data,
7403 fsp,
7404 smb_fname);
7405 break;
7406 }
7407
7408 case SMB_SET_FILE_BASIC_INFO:
7409 case SMB_FILE_BASIC_INFORMATION:
7410 {
7411 status = smb_set_file_basic_info(conn,
7412 pdata,
7413 total_data,
7414 fsp,
7415 smb_fname);
7416 break;
7417 }
7418
7419 case SMB_FILE_ALLOCATION_INFORMATION:
7420 case SMB_SET_FILE_ALLOCATION_INFO:
7421 {
7422 status = smb_set_file_allocation_info(conn, req,
7423 pdata,
7424 total_data,
7425 fsp,
7426 smb_fname);
7427 break;
7428 }
7429
7430 case SMB_FILE_END_OF_FILE_INFORMATION:
7431 case SMB_SET_FILE_END_OF_FILE_INFO:
7432 {
7433 /*
7434 * XP/Win7 both fail after the createfile with
7435 * SMB_SET_FILE_END_OF_FILE_INFO but not
7436 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7437 * The level is known here, so pass it down
7438 * appropriately.
7439 */
7440 bool should_fail =
7441 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7442
7443 status = smb_set_file_end_of_file_info(conn, req,
7444 pdata,
7445 total_data,
7446 fsp,
7447 smb_fname,
7448 should_fail);
7449 break;
7450 }
7451
7452 case SMB_FILE_DISPOSITION_INFORMATION:
7453 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7454 {
7455#if 0
7456 /* JRA - We used to just ignore this on a path ?
7457 * Shouldn't this be invalid level on a pathname
7458 * based call ?
7459 */
7460 if (tran_call != TRANSACT2_SETFILEINFO) {
7461 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7462 }
7463#endif
7464 status = smb_set_file_disposition_info(conn,
7465 pdata,
7466 total_data,
7467 fsp,
7468 smb_fname);
7469 break;
7470 }
7471
7472 case SMB_FILE_POSITION_INFORMATION:
7473 {
7474 status = smb_file_position_information(conn,
7475 pdata,
7476 total_data,
7477 fsp);
7478 break;
7479 }
7480
7481 case SMB_FILE_FULL_EA_INFORMATION:
7482 {
7483 status = smb_set_file_full_ea_info(conn,
7484 pdata,
7485 total_data,
7486 fsp);
7487 break;
7488 }
7489
7490 /* From tridge Samba4 :
7491 * MODE_INFORMATION in setfileinfo (I have no
7492 * idea what "mode information" on a file is - it takes a value of 0,
7493 * 2, 4 or 6. What could it be?).
7494 */
7495
7496 case SMB_FILE_MODE_INFORMATION:
7497 {
7498 status = smb_file_mode_information(conn,
7499 pdata,
7500 total_data);
7501 break;
7502 }
7503
7504 /*
7505 * CIFS UNIX extensions.
7506 */
7507
7508 case SMB_SET_FILE_UNIX_BASIC:
7509 {
7510 status = smb_set_file_unix_basic(conn, req,
7511 pdata,
7512 total_data,
7513 fsp,
7514 smb_fname);
7515 break;
7516 }
7517
7518 case SMB_SET_FILE_UNIX_INFO2:
7519 {
7520 status = smb_set_file_unix_info2(conn, req,
7521 pdata,
7522 total_data,
7523 fsp,
7524 smb_fname);
7525 break;
7526 }
7527
7528 case SMB_SET_FILE_UNIX_LINK:
7529 {
7530 if (fsp) {
7531 /* We must have a pathname for this. */
7532 return NT_STATUS_INVALID_LEVEL;
7533 }
7534 status = smb_set_file_unix_link(conn, req, pdata,
7535 total_data, smb_fname);
7536 break;
7537 }
7538
7539 case SMB_SET_FILE_UNIX_HLINK:
7540 {
7541 if (fsp) {
7542 /* We must have a pathname for this. */
7543 return NT_STATUS_INVALID_LEVEL;
7544 }
7545 status = smb_set_file_unix_hlink(conn, req,
7546 pdata, total_data,
7547 smb_fname);
7548 break;
7549 }
7550
7551 case SMB_FILE_RENAME_INFORMATION:
7552 {
7553 status = smb_file_rename_information(conn, req,
7554 pdata, total_data,
7555 fsp, smb_fname);
7556 break;
7557 }
7558
7559#if defined(HAVE_POSIX_ACLS)
7560 case SMB_SET_POSIX_ACL:
7561 {
7562 status = smb_set_posix_acl(conn,
7563 pdata,
7564 total_data,
7565 fsp,
7566 smb_fname);
7567 break;
7568 }
7569#endif
7570
7571 case SMB_SET_POSIX_LOCK:
7572 {
7573 if (!fsp) {
7574 return NT_STATUS_INVALID_LEVEL;
7575 }
7576 status = smb_set_posix_lock(conn, req,
7577 pdata, total_data, fsp);
7578 break;
7579 }
7580
7581 case SMB_POSIX_PATH_OPEN:
7582 {
7583 if (fsp) {
7584 /* We must have a pathname for this. */
7585 return NT_STATUS_INVALID_LEVEL;
7586 }
7587
7588 status = smb_posix_open(conn, req,
7589 ppdata,
7590 total_data,
7591 smb_fname,
7592 &data_return_size);
7593 break;
7594 }
7595
7596 case SMB_POSIX_PATH_UNLINK:
7597 {
7598 if (fsp) {
7599 /* We must have a pathname for this. */
7600 return NT_STATUS_INVALID_LEVEL;
7601 }
7602
7603 status = smb_posix_unlink(conn, req,
7604 pdata,
7605 total_data,
7606 smb_fname);
7607 break;
7608 }
7609
7610 default:
7611 return NT_STATUS_INVALID_LEVEL;
7612 }
7613
7614 if (!NT_STATUS_IS_OK(status)) {
7615 return status;
7616 }
7617
7618 *ret_data_size = data_return_size;
7619 return NT_STATUS_OK;
7620}
7621
7622/****************************************************************************
7623 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7624****************************************************************************/
7625
7626static void call_trans2setfilepathinfo(connection_struct *conn,
7627 struct smb_request *req,
7628 unsigned int tran_call,
7629 char **pparams, int total_params,
7630 char **ppdata, int total_data,
7631 unsigned int max_data_bytes)
7632{
7633 char *params = *pparams;
7634 char *pdata = *ppdata;
7635 uint16 info_level;
7636 struct smb_filename *smb_fname = NULL;
7637 files_struct *fsp = NULL;
7638 NTSTATUS status = NT_STATUS_OK;
7639 int data_return_size = 0;
7640
7641 if (!params) {
7642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7643 return;
7644 }
7645
7646 if (tran_call == TRANSACT2_SETFILEINFO) {
7647 if (total_params < 4) {
7648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7649 return;
7650 }
7651
7652 fsp = file_fsp(req, SVAL(params,0));
7653 /* Basic check for non-null fsp. */
7654 if (!check_fsp_open(conn, req, fsp)) {
7655 return;
7656 }
7657 info_level = SVAL(params,2);
7658
7659 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7660 &smb_fname);
7661 if (!NT_STATUS_IS_OK(status)) {
7662 reply_nterror(req, status);
7663 return;
7664 }
7665
7666 if(fsp->is_directory || fsp->fh->fd == -1) {
7667 /*
7668 * This is actually a SETFILEINFO on a directory
7669 * handle (returned from an NT SMB). NT5.0 seems
7670 * to do this call. JRA.
7671 */
7672 if (INFO_LEVEL_IS_UNIX(info_level)) {
7673 /* Always do lstat for UNIX calls. */
7674 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7675 DEBUG(3,("call_trans2setfilepathinfo: "
7676 "SMB_VFS_LSTAT of %s failed "
7677 "(%s)\n",
7678 smb_fname_str_dbg(smb_fname),
7679 strerror(errno)));
7680 reply_nterror(req, map_nt_error_from_unix(errno));
7681 return;
7682 }
7683 } else {
7684 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7685 DEBUG(3,("call_trans2setfilepathinfo: "
7686 "fileinfo of %s failed (%s)\n",
7687 smb_fname_str_dbg(smb_fname),
7688 strerror(errno)));
7689 reply_nterror(req, map_nt_error_from_unix(errno));
7690 return;
7691 }
7692 }
7693 } else if (fsp->print_file) {
7694 /*
7695 * Doing a DELETE_ON_CLOSE should cancel a print job.
7696 */
7697 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7698 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7699
7700 DEBUG(3,("call_trans2setfilepathinfo: "
7701 "Cancelling print job (%s)\n",
7702 fsp_str_dbg(fsp)));
7703
7704 SSVAL(params,0,0);
7705 send_trans2_replies(conn, req, params, 2,
7706 *ppdata, 0,
7707 max_data_bytes);
7708 return;
7709 } else {
7710 reply_nterror(req,
7711 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7712 return;
7713 }
7714 } else {
7715 /*
7716 * Original code - this is an open file.
7717 */
7718 if (!check_fsp(conn, req, fsp)) {
7719 return;
7720 }
7721
7722 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7723 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7724 "of fnum %d failed (%s)\n", fsp->fnum,
7725 strerror(errno)));
7726 reply_nterror(req, map_nt_error_from_unix(errno));
7727 return;
7728 }
7729 }
7730 } else {
7731 char *fname = NULL;
7732 uint32_t ucf_flags = 0;
7733
7734 /* set path info */
7735 if (total_params < 7) {
7736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7737 return;
7738 }
7739
7740 info_level = SVAL(params,0);
7741 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7742 total_params - 6, STR_TERMINATE,
7743 &status);
7744 if (!NT_STATUS_IS_OK(status)) {
7745 reply_nterror(req, status);
7746 return;
7747 }
7748
7749 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
7750 info_level == SMB_SET_FILE_UNIX_INFO2 ||
7751 info_level == SMB_FILE_RENAME_INFORMATION ||
7752 info_level == SMB_POSIX_PATH_UNLINK) {
7753 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
7754 }
7755
7756 status = filename_convert(req, conn,
7757 req->flags2 & FLAGS2_DFS_PATHNAMES,
7758 fname,
7759 ucf_flags,
7760 NULL,
7761 &smb_fname);
7762 if (!NT_STATUS_IS_OK(status)) {
7763 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7764 reply_botherror(req,
7765 NT_STATUS_PATH_NOT_COVERED,
7766 ERRSRV, ERRbadpath);
7767 return;
7768 }
7769 reply_nterror(req, status);
7770 return;
7771 }
7772
7773 if (INFO_LEVEL_IS_UNIX(info_level)) {
7774 /*
7775 * For CIFS UNIX extensions the target name may not exist.
7776 */
7777
7778 /* Always do lstat for UNIX calls. */
7779 SMB_VFS_LSTAT(conn, smb_fname);
7780
7781 } else if (!VALID_STAT(smb_fname->st) &&
7782 SMB_VFS_STAT(conn, smb_fname)) {
7783 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7784 "%s failed (%s)\n",
7785 smb_fname_str_dbg(smb_fname),
7786 strerror(errno)));
7787 reply_nterror(req, map_nt_error_from_unix(errno));
7788 return;
7789 }
7790 }
7791
7792 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7793 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7794 fsp ? fsp->fnum : -1, info_level,total_data));
7795
7796 /* Realloc the parameter size */
7797 *pparams = (char *)SMB_REALLOC(*pparams,2);
7798 if (*pparams == NULL) {
7799 reply_nterror(req, NT_STATUS_NO_MEMORY);
7800 return;
7801 }
7802 params = *pparams;
7803
7804 SSVAL(params,0,0);
7805
7806 status = smbd_do_setfilepathinfo(conn, req, req,
7807 info_level,
7808 fsp,
7809 smb_fname,
7810 ppdata, total_data,
7811 &data_return_size);
7812 if (!NT_STATUS_IS_OK(status)) {
7813 if (open_was_deferred(req->mid)) {
7814 /* We have re-scheduled this call. */
7815 return;
7816 }
7817 if (blocking_lock_was_deferred(req->mid)) {
7818 /* We have re-scheduled this call. */
7819 return;
7820 }
7821 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7822 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7823 ERRSRV, ERRbadpath);
7824 return;
7825 }
7826 if (info_level == SMB_POSIX_PATH_OPEN) {
7827 reply_openerror(req, status);
7828 return;
7829 }
7830
7831 reply_nterror(req, status);
7832 return;
7833 }
7834
7835 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7836 max_data_bytes);
7837
7838 return;
7839}
7840
7841/****************************************************************************
7842 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7843****************************************************************************/
7844
7845static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7846 char **pparams, int total_params,
7847 char **ppdata, int total_data,
7848 unsigned int max_data_bytes)
7849{
7850 struct smb_filename *smb_dname = NULL;
7851 char *params = *pparams;
7852 char *pdata = *ppdata;
7853 char *directory = NULL;
7854 NTSTATUS status = NT_STATUS_OK;
7855 struct ea_list *ea_list = NULL;
7856 TALLOC_CTX *ctx = talloc_tos();
7857
7858 if (!CAN_WRITE(conn)) {
7859 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7860 return;
7861 }
7862
7863 if (total_params < 5) {
7864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7865 return;
7866 }
7867
7868 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7869 total_params - 4, STR_TERMINATE,
7870 &status);
7871 if (!NT_STATUS_IS_OK(status)) {
7872 reply_nterror(req, status);
7873 return;
7874 }
7875
7876 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7877
7878 status = filename_convert(ctx,
7879 conn,
7880 req->flags2 & FLAGS2_DFS_PATHNAMES,
7881 directory,
7882 0,
7883 NULL,
7884 &smb_dname);
7885
7886 if (!NT_STATUS_IS_OK(status)) {
7887 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7888 reply_botherror(req,
7889 NT_STATUS_PATH_NOT_COVERED,
7890 ERRSRV, ERRbadpath);
7891 return;
7892 }
7893 reply_nterror(req, status);
7894 return;
7895 }
7896
7897 /*
7898 * OS/2 workplace shell seems to send SET_EA requests of "null"
7899 * length (4 bytes containing IVAL 4).
7900 * They seem to have no effect. Bug #3212. JRA.
7901 */
7902
7903 if (total_data && (total_data != 4)) {
7904 /* Any data in this call is an EA list. */
7905 if (total_data < 10) {
7906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7907 goto out;
7908 }
7909
7910 if (IVAL(pdata,0) > total_data) {
7911 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7912 IVAL(pdata,0), (unsigned int)total_data));
7913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7914 goto out;
7915 }
7916
7917 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7918 total_data - 4);
7919 if (!ea_list) {
7920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7921 goto out;
7922 }
7923
7924 if (!lp_ea_support(SNUM(conn))) {
7925 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7926 goto out;
7927 }
7928 }
7929 /* If total_data == 4 Windows doesn't care what values
7930 * are placed in that field, it just ignores them.
7931 * The System i QNTC IBM SMB client puts bad values here,
7932 * so ignore them. */
7933
7934 status = create_directory(conn, req, smb_dname);
7935
7936 if (!NT_STATUS_IS_OK(status)) {
7937 reply_nterror(req, status);
7938 goto out;
7939 }
7940
7941 /* Try and set any given EA. */
7942 if (ea_list) {
7943 status = set_ea(conn, NULL, smb_dname, ea_list);
7944 if (!NT_STATUS_IS_OK(status)) {
7945 reply_nterror(req, status);
7946 goto out;
7947 }
7948 }
7949
7950 /* Realloc the parameter and data sizes */
7951 *pparams = (char *)SMB_REALLOC(*pparams,2);
7952 if(*pparams == NULL) {
7953 reply_nterror(req, NT_STATUS_NO_MEMORY);
7954 goto out;
7955 }
7956 params = *pparams;
7957
7958 SSVAL(params,0,0);
7959
7960 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7961
7962 out:
7963 TALLOC_FREE(smb_dname);
7964 return;
7965}
7966
7967/****************************************************************************
7968 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7969 We don't actually do this - we just send a null response.
7970****************************************************************************/
7971
7972static void call_trans2findnotifyfirst(connection_struct *conn,
7973 struct smb_request *req,
7974 char **pparams, int total_params,
7975 char **ppdata, int total_data,
7976 unsigned int max_data_bytes)
7977{
7978 char *params = *pparams;
7979 uint16 info_level;
7980
7981 if (total_params < 6) {
7982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7983 return;
7984 }
7985
7986 info_level = SVAL(params,4);
7987 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7988
7989 switch (info_level) {
7990 case 1:
7991 case 2:
7992 break;
7993 default:
7994 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7995 return;
7996 }
7997
7998 /* Realloc the parameter and data sizes */
7999 *pparams = (char *)SMB_REALLOC(*pparams,6);
8000 if (*pparams == NULL) {
8001 reply_nterror(req, NT_STATUS_NO_MEMORY);
8002 return;
8003 }
8004 params = *pparams;
8005
8006 SSVAL(params,0,fnf_handle);
8007 SSVAL(params,2,0); /* No changes */
8008 SSVAL(params,4,0); /* No EA errors */
8009
8010 fnf_handle++;
8011
8012 if(fnf_handle == 0)
8013 fnf_handle = 257;
8014
8015 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8016
8017 return;
8018}
8019
8020/****************************************************************************
8021 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8022 changes). Currently this does nothing.
8023****************************************************************************/
8024
8025static void call_trans2findnotifynext(connection_struct *conn,
8026 struct smb_request *req,
8027 char **pparams, int total_params,
8028 char **ppdata, int total_data,
8029 unsigned int max_data_bytes)
8030{
8031 char *params = *pparams;
8032
8033 DEBUG(3,("call_trans2findnotifynext\n"));
8034
8035 /* Realloc the parameter and data sizes */
8036 *pparams = (char *)SMB_REALLOC(*pparams,4);
8037 if (*pparams == NULL) {
8038 reply_nterror(req, NT_STATUS_NO_MEMORY);
8039 return;
8040 }
8041 params = *pparams;
8042
8043 SSVAL(params,0,0); /* No changes */
8044 SSVAL(params,2,0); /* No EA errors */
8045
8046 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8047
8048 return;
8049}
8050
8051/****************************************************************************
8052 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8053****************************************************************************/
8054
8055static void call_trans2getdfsreferral(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)
8060{
8061 char *params = *pparams;
8062 char *pathname = NULL;
8063 int reply_size = 0;
8064 int max_referral_level;
8065 NTSTATUS status = NT_STATUS_OK;
8066 TALLOC_CTX *ctx = talloc_tos();
8067
8068 DEBUG(10,("call_trans2getdfsreferral\n"));
8069
8070 if (total_params < 3) {
8071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8072 return;
8073 }
8074
8075 max_referral_level = SVAL(params,0);
8076
8077 if(!lp_host_msdfs()) {
8078 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8079 return;
8080 }
8081
8082 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8083 total_params - 2, STR_TERMINATE);
8084 if (!pathname) {
8085 reply_nterror(req, NT_STATUS_NOT_FOUND);
8086 return;
8087 }
8088 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8089 ppdata,&status)) < 0) {
8090 reply_nterror(req, status);
8091 return;
8092 }
8093
8094 SSVAL(req->inbuf, smb_flg2,
8095 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8096 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8097
8098 return;
8099}
8100
8101#define LMCAT_SPL 0x53
8102#define LMFUNC_GETJOBID 0x60
8103
8104/****************************************************************************
8105 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8106****************************************************************************/
8107
8108static void call_trans2ioctl(connection_struct *conn,
8109 struct smb_request *req,
8110 char **pparams, int total_params,
8111 char **ppdata, int total_data,
8112 unsigned int max_data_bytes)
8113{
8114 char *pdata = *ppdata;
8115 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8116
8117 /* check for an invalid fid before proceeding */
8118
8119 if (!fsp) {
8120 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8121 return;
8122 }
8123
8124 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8125 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8126 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8127 if (*ppdata == NULL) {
8128 reply_nterror(req, NT_STATUS_NO_MEMORY);
8129 return;
8130 }
8131 pdata = *ppdata;
8132
8133 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8134 CAN ACCEPT THIS IN UNICODE. JRA. */
8135
8136 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8137 srvstr_push(pdata, req->flags2, pdata + 2,
8138 global_myname(), 15,
8139 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8140 srvstr_push(pdata, req->flags2, pdata+18,
8141 lp_servicename(SNUM(conn)), 13,
8142 STR_ASCII|STR_TERMINATE); /* Service name */
8143 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8144 max_data_bytes);
8145 return;
8146 }
8147
8148 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8149 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8150}
8151
8152/****************************************************************************
8153 Reply to a SMBfindclose (stop trans2 directory search).
8154****************************************************************************/
8155
8156void reply_findclose(struct smb_request *req)
8157{
8158 int dptr_num;
8159 struct smbd_server_connection *sconn = smbd_server_conn;
8160
8161 START_PROFILE(SMBfindclose);
8162
8163 if (req->wct < 1) {
8164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8165 END_PROFILE(SMBfindclose);
8166 return;
8167 }
8168
8169 dptr_num = SVALS(req->vwv+0, 0);
8170
8171 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8172
8173 dptr_close(sconn, &dptr_num);
8174
8175 reply_outbuf(req, 0, 0);
8176
8177 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8178
8179 END_PROFILE(SMBfindclose);
8180 return;
8181}
8182
8183/****************************************************************************
8184 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8185****************************************************************************/
8186
8187void reply_findnclose(struct smb_request *req)
8188{
8189 int dptr_num;
8190
8191 START_PROFILE(SMBfindnclose);
8192
8193 if (req->wct < 1) {
8194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195 END_PROFILE(SMBfindnclose);
8196 return;
8197 }
8198
8199 dptr_num = SVAL(req->vwv+0, 0);
8200
8201 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8202
8203 /* We never give out valid handles for a
8204 findnotifyfirst - so any dptr_num is ok here.
8205 Just ignore it. */
8206
8207 reply_outbuf(req, 0, 0);
8208
8209 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8210
8211 END_PROFILE(SMBfindnclose);
8212 return;
8213}
8214
8215static void handle_trans2(connection_struct *conn, struct smb_request *req,
8216 struct trans_state *state)
8217{
8218 if (get_Protocol() >= PROTOCOL_NT1) {
8219 req->flags2 |= 0x40; /* IS_LONG_NAME */
8220 SSVAL(req->inbuf,smb_flg2,req->flags2);
8221 }
8222
8223 if (conn->encrypt_level == Required && !req->encrypted) {
8224 if (state->call != TRANSACT2_QFSINFO &&
8225 state->call != TRANSACT2_SETFSINFO) {
8226 DEBUG(0,("handle_trans2: encryption required "
8227 "with call 0x%x\n",
8228 (unsigned int)state->call));
8229 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8230 return;
8231 }
8232 }
8233
8234 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8235
8236 /* Now we must call the relevant TRANS2 function */
8237 switch(state->call) {
8238 case TRANSACT2_OPEN:
8239 {
8240 START_PROFILE(Trans2_open);
8241 call_trans2open(conn, req,
8242 &state->param, state->total_param,
8243 &state->data, state->total_data,
8244 state->max_data_return);
8245 END_PROFILE(Trans2_open);
8246 break;
8247 }
8248
8249 case TRANSACT2_FINDFIRST:
8250 {
8251 START_PROFILE(Trans2_findfirst);
8252 call_trans2findfirst(conn, req,
8253 &state->param, state->total_param,
8254 &state->data, state->total_data,
8255 state->max_data_return);
8256 END_PROFILE(Trans2_findfirst);
8257 break;
8258 }
8259
8260 case TRANSACT2_FINDNEXT:
8261 {
8262 START_PROFILE(Trans2_findnext);
8263 call_trans2findnext(conn, req,
8264 &state->param, state->total_param,
8265 &state->data, state->total_data,
8266 state->max_data_return);
8267 END_PROFILE(Trans2_findnext);
8268 break;
8269 }
8270
8271 case TRANSACT2_QFSINFO:
8272 {
8273 START_PROFILE(Trans2_qfsinfo);
8274 call_trans2qfsinfo(conn, req,
8275 &state->param, state->total_param,
8276 &state->data, state->total_data,
8277 state->max_data_return);
8278 END_PROFILE(Trans2_qfsinfo);
8279 break;
8280 }
8281
8282 case TRANSACT2_SETFSINFO:
8283 {
8284 START_PROFILE(Trans2_setfsinfo);
8285 call_trans2setfsinfo(conn, req,
8286 &state->param, state->total_param,
8287 &state->data, state->total_data,
8288 state->max_data_return);
8289 END_PROFILE(Trans2_setfsinfo);
8290 break;
8291 }
8292
8293 case TRANSACT2_QPATHINFO:
8294 case TRANSACT2_QFILEINFO:
8295 {
8296 START_PROFILE(Trans2_qpathinfo);
8297 call_trans2qfilepathinfo(conn, req, state->call,
8298 &state->param, state->total_param,
8299 &state->data, state->total_data,
8300 state->max_data_return);
8301 END_PROFILE(Trans2_qpathinfo);
8302 break;
8303 }
8304
8305 case TRANSACT2_SETPATHINFO:
8306 case TRANSACT2_SETFILEINFO:
8307 {
8308 START_PROFILE(Trans2_setpathinfo);
8309 call_trans2setfilepathinfo(conn, req, state->call,
8310 &state->param, state->total_param,
8311 &state->data, state->total_data,
8312 state->max_data_return);
8313 END_PROFILE(Trans2_setpathinfo);
8314 break;
8315 }
8316
8317 case TRANSACT2_FINDNOTIFYFIRST:
8318 {
8319 START_PROFILE(Trans2_findnotifyfirst);
8320 call_trans2findnotifyfirst(conn, req,
8321 &state->param, state->total_param,
8322 &state->data, state->total_data,
8323 state->max_data_return);
8324 END_PROFILE(Trans2_findnotifyfirst);
8325 break;
8326 }
8327
8328 case TRANSACT2_FINDNOTIFYNEXT:
8329 {
8330 START_PROFILE(Trans2_findnotifynext);
8331 call_trans2findnotifynext(conn, req,
8332 &state->param, state->total_param,
8333 &state->data, state->total_data,
8334 state->max_data_return);
8335 END_PROFILE(Trans2_findnotifynext);
8336 break;
8337 }
8338
8339 case TRANSACT2_MKDIR:
8340 {
8341 START_PROFILE(Trans2_mkdir);
8342 call_trans2mkdir(conn, req,
8343 &state->param, state->total_param,
8344 &state->data, state->total_data,
8345 state->max_data_return);
8346 END_PROFILE(Trans2_mkdir);
8347 break;
8348 }
8349
8350 case TRANSACT2_GET_DFS_REFERRAL:
8351 {
8352 START_PROFILE(Trans2_get_dfs_referral);
8353 call_trans2getdfsreferral(conn, req,
8354 &state->param, state->total_param,
8355 &state->data, state->total_data,
8356 state->max_data_return);
8357 END_PROFILE(Trans2_get_dfs_referral);
8358 break;
8359 }
8360
8361 case TRANSACT2_IOCTL:
8362 {
8363 START_PROFILE(Trans2_ioctl);
8364 call_trans2ioctl(conn, req,
8365 &state->param, state->total_param,
8366 &state->data, state->total_data,
8367 state->max_data_return);
8368 END_PROFILE(Trans2_ioctl);
8369 break;
8370 }
8371
8372 default:
8373 /* Error in request */
8374 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8375 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8376 }
8377}
8378
8379/****************************************************************************
8380 Reply to a SMBtrans2.
8381 ****************************************************************************/
8382
8383void reply_trans2(struct smb_request *req)
8384{
8385 connection_struct *conn = req->conn;
8386 unsigned int dsoff;
8387 unsigned int dscnt;
8388 unsigned int psoff;
8389 unsigned int pscnt;
8390 unsigned int tran_call;
8391 struct trans_state *state;
8392 NTSTATUS result;
8393
8394 START_PROFILE(SMBtrans2);
8395
8396 if (req->wct < 14) {
8397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8398 END_PROFILE(SMBtrans2);
8399 return;
8400 }
8401
8402 dsoff = SVAL(req->vwv+12, 0);
8403 dscnt = SVAL(req->vwv+11, 0);
8404 psoff = SVAL(req->vwv+10, 0);
8405 pscnt = SVAL(req->vwv+9, 0);
8406 tran_call = SVAL(req->vwv+14, 0);
8407
8408 result = allow_new_trans(conn->pending_trans, req->mid);
8409 if (!NT_STATUS_IS_OK(result)) {
8410 DEBUG(2, ("Got invalid trans2 request: %s\n",
8411 nt_errstr(result)));
8412 reply_nterror(req, result);
8413 END_PROFILE(SMBtrans2);
8414 return;
8415 }
8416
8417 if (IS_IPC(conn)) {
8418 switch (tran_call) {
8419 /* List the allowed trans2 calls on IPC$ */
8420 case TRANSACT2_OPEN:
8421 case TRANSACT2_GET_DFS_REFERRAL:
8422 case TRANSACT2_QFILEINFO:
8423 case TRANSACT2_QFSINFO:
8424 case TRANSACT2_SETFSINFO:
8425 break;
8426 default:
8427 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8428 END_PROFILE(SMBtrans2);
8429 return;
8430 }
8431 }
8432
8433 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8434 DEBUG(0, ("talloc failed\n"));
8435 reply_nterror(req, NT_STATUS_NO_MEMORY);
8436 END_PROFILE(SMBtrans2);
8437 return;
8438 }
8439
8440 state->cmd = SMBtrans2;
8441
8442 state->mid = req->mid;
8443 state->vuid = req->vuid;
8444 state->setup_count = SVAL(req->vwv+13, 0);
8445 state->setup = NULL;
8446 state->total_param = SVAL(req->vwv+0, 0);
8447 state->param = NULL;
8448 state->total_data = SVAL(req->vwv+1, 0);
8449 state->data = NULL;
8450 state->max_param_return = SVAL(req->vwv+2, 0);
8451 state->max_data_return = SVAL(req->vwv+3, 0);
8452 state->max_setup_return = SVAL(req->vwv+4, 0);
8453 state->close_on_completion = BITSETW(req->vwv+5, 0);
8454 state->one_way = BITSETW(req->vwv+5, 1);
8455
8456 state->call = tran_call;
8457
8458 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8459 is so as a sanity check */
8460 if (state->setup_count != 1) {
8461 /*
8462 * Need to have rc=0 for ioctl to get job id for OS/2.
8463 * Network printing will fail if function is not successful.
8464 * Similar function in reply.c will be used if protocol
8465 * is LANMAN1.0 instead of LM1.2X002.
8466 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8467 * outbuf doesn't have to be set(only job id is used).
8468 */
8469 if ( (state->setup_count == 4)
8470 && (tran_call == TRANSACT2_IOCTL)
8471 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8472 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8473 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8474 } else {
8475 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8476 DEBUG(2,("Transaction is %d\n",tran_call));
8477 TALLOC_FREE(state);
8478 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8479 END_PROFILE(SMBtrans2);
8480 return;
8481 }
8482 }
8483
8484 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8485 goto bad_param;
8486
8487 if (state->total_data) {
8488
8489 if (trans_oob(state->total_data, 0, dscnt)
8490 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8491 goto bad_param;
8492 }
8493
8494 /* Can't use talloc here, the core routines do realloc on the
8495 * params and data. */
8496 state->data = (char *)SMB_MALLOC(state->total_data);
8497 if (state->data == NULL) {
8498 DEBUG(0,("reply_trans2: data malloc fail for %u "
8499 "bytes !\n", (unsigned int)state->total_data));
8500 TALLOC_FREE(state);
8501 reply_nterror(req, NT_STATUS_NO_MEMORY);
8502 END_PROFILE(SMBtrans2);
8503 return;
8504 }
8505
8506 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8507 }
8508
8509 if (state->total_param) {
8510
8511 if (trans_oob(state->total_param, 0, pscnt)
8512 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8513 goto bad_param;
8514 }
8515
8516 /* Can't use talloc here, the core routines do realloc on the
8517 * params and data. */
8518 state->param = (char *)SMB_MALLOC(state->total_param);
8519 if (state->param == NULL) {
8520 DEBUG(0,("reply_trans: param malloc fail for %u "
8521 "bytes !\n", (unsigned int)state->total_param));
8522 SAFE_FREE(state->data);
8523 TALLOC_FREE(state);
8524 reply_nterror(req, NT_STATUS_NO_MEMORY);
8525 END_PROFILE(SMBtrans2);
8526 return;
8527 }
8528
8529 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8530 }
8531
8532 state->received_data = dscnt;
8533 state->received_param = pscnt;
8534
8535 if ((state->received_param == state->total_param) &&
8536 (state->received_data == state->total_data)) {
8537
8538 handle_trans2(conn, req, state);
8539
8540 SAFE_FREE(state->data);
8541 SAFE_FREE(state->param);
8542 TALLOC_FREE(state);
8543 END_PROFILE(SMBtrans2);
8544 return;
8545 }
8546
8547 DLIST_ADD(conn->pending_trans, state);
8548
8549 /* We need to send an interim response then receive the rest
8550 of the parameter/data bytes */
8551 reply_outbuf(req, 0, 0);
8552 show_msg((char *)req->outbuf);
8553 END_PROFILE(SMBtrans2);
8554 return;
8555
8556 bad_param:
8557
8558 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8559 SAFE_FREE(state->data);
8560 SAFE_FREE(state->param);
8561 TALLOC_FREE(state);
8562 END_PROFILE(SMBtrans2);
8563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8564}
8565
8566
8567/****************************************************************************
8568 Reply to a SMBtranss2
8569 ****************************************************************************/
8570
8571void reply_transs2(struct smb_request *req)
8572{
8573 connection_struct *conn = req->conn;
8574 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8575 struct trans_state *state;
8576
8577 START_PROFILE(SMBtranss2);
8578
8579 show_msg((char *)req->inbuf);
8580
8581 /* Windows clients expect all replies to
8582 a transact secondary (SMBtranss2 0x33)
8583 to have a command code of transact
8584 (SMBtrans2 0x32). See bug #8989
8585 and also [MS-CIFS] section 2.2.4.47.2
8586 for details.
8587 */
8588 req->cmd = SMBtrans2;
8589
8590 if (req->wct < 8) {
8591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8592 END_PROFILE(SMBtranss2);
8593 return;
8594 }
8595
8596 for (state = conn->pending_trans; state != NULL;
8597 state = state->next) {
8598 if (state->mid == req->mid) {
8599 break;
8600 }
8601 }
8602
8603 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8605 END_PROFILE(SMBtranss2);
8606 return;
8607 }
8608
8609 /* Revise state->total_param and state->total_data in case they have
8610 changed downwards */
8611
8612 if (SVAL(req->vwv+0, 0) < state->total_param)
8613 state->total_param = SVAL(req->vwv+0, 0);
8614 if (SVAL(req->vwv+1, 0) < state->total_data)
8615 state->total_data = SVAL(req->vwv+1, 0);
8616
8617 pcnt = SVAL(req->vwv+2, 0);
8618 poff = SVAL(req->vwv+3, 0);
8619 pdisp = SVAL(req->vwv+4, 0);
8620
8621 dcnt = SVAL(req->vwv+5, 0);
8622 doff = SVAL(req->vwv+6, 0);
8623 ddisp = SVAL(req->vwv+7, 0);
8624
8625 state->received_param += pcnt;
8626 state->received_data += dcnt;
8627
8628 if ((state->received_data > state->total_data) ||
8629 (state->received_param > state->total_param))
8630 goto bad_param;
8631
8632 if (pcnt) {
8633 if (trans_oob(state->total_param, pdisp, pcnt)
8634 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8635 goto bad_param;
8636 }
8637 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8638 }
8639
8640 if (dcnt) {
8641 if (trans_oob(state->total_data, ddisp, dcnt)
8642 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8643 goto bad_param;
8644 }
8645 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8646 }
8647
8648 if ((state->received_param < state->total_param) ||
8649 (state->received_data < state->total_data)) {
8650 END_PROFILE(SMBtranss2);
8651 return;
8652 }
8653
8654 handle_trans2(conn, req, state);
8655
8656 DLIST_REMOVE(conn->pending_trans, state);
8657 SAFE_FREE(state->data);
8658 SAFE_FREE(state->param);
8659 TALLOC_FREE(state);
8660
8661 END_PROFILE(SMBtranss2);
8662 return;
8663
8664 bad_param:
8665
8666 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8667 DLIST_REMOVE(conn->pending_trans, state);
8668 SAFE_FREE(state->data);
8669 SAFE_FREE(state->param);
8670 TALLOC_FREE(state);
8671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8672 END_PROFILE(SMBtranss2);
8673 return;
8674}
Note: See TracBrowser for help on using the repository browser.