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

Last change on this file since 717 was 599, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.9

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