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

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

Samba Server 3.6: fix for ticket #165

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