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

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

Samba Server: update trunk to 3.6.23

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