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

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

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