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

Last change on this file since 1014 was 791, checked in by Silvan Scherrer, 12 years ago

Samba Server 3.5: fix for ticket #165

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