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

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

Samba Server 3.5: update branche to 3.5.12

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