source: trunk/server/source3/smbd/trans2.c@ 537

Last change on this file since 537 was 480, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: trunk update to 3.5.4

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