source: vendor/3.5.8/source3/smbd/trans2.c

Last change on this file was 587, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update vendor to version 3.5.6

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