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

Last change on this file since 752 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

File size: 243.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
9
10 Extensively modified by Andrew Tridgell, 1995
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
24*/
25
26#include "includes.h"
27#include "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#ifdef __OS2__
5536 /* YD ticket#60, the file is opened, we cannot write to it,
5537 * so we can return immediately (see above for more comments).
5538 */
5539 else {
5540#endif
5541 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5542
5543 /* Always call ntimes on the base, even if a stream was passed in. */
5544 smb_fname_base = *smb_fname;
5545 smb_fname_base.stream_name = NULL;
5546
5547 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5548 return map_nt_error_from_unix(errno);
5549 }
5550#ifdef __OS2__
5551 }
5552#endif
5553
5554 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5555 smb_fname->base_name);
5556 return NT_STATUS_OK;
5557}
5558
5559/****************************************************************************
5560 Deal with setting the dosmode from any of the setfilepathinfo functions.
5561****************************************************************************/
5562
5563static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5564 const struct smb_filename *smb_fname,
5565 uint32 dosmode)
5566{
5567 struct smb_filename *smb_fname_base = NULL;
5568 NTSTATUS status;
5569
5570 if (!VALID_STAT(smb_fname->st)) {
5571 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5572 }
5573
5574 /* Always operate on the base_name, even if a stream was passed in. */
5575 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5576 NULL, &smb_fname->st,
5577 &smb_fname_base);
5578 if (!NT_STATUS_IS_OK(status)) {
5579 return status;
5580 }
5581
5582 if (dosmode) {
5583 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5584 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5585 } else {
5586 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5587 }
5588 }
5589
5590 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5591
5592 /* check the mode isn't different, before changing it */
5593 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5594 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5595 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5596 (unsigned int)dosmode));
5597
5598 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5599 false)) {
5600 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5601 "%s failed (%s)\n",
5602 smb_fname_str_dbg(smb_fname_base),
5603 strerror(errno)));
5604 status = map_nt_error_from_unix(errno);
5605 goto out;
5606 }
5607 }
5608 status = NT_STATUS_OK;
5609 out:
5610 TALLOC_FREE(smb_fname_base);
5611 return status;
5612}
5613
5614/****************************************************************************
5615 Deal with setting the size from any of the setfilepathinfo functions.
5616****************************************************************************/
5617
5618static NTSTATUS smb_set_file_size(connection_struct *conn,
5619 struct smb_request *req,
5620 files_struct *fsp,
5621 const struct smb_filename *smb_fname,
5622 const SMB_STRUCT_STAT *psbuf,
5623 SMB_OFF_T size,
5624 bool fail_after_createfile)
5625{
5626 NTSTATUS status = NT_STATUS_OK;
5627 struct smb_filename *smb_fname_tmp = NULL;
5628 files_struct *new_fsp = NULL;
5629
5630 if (!VALID_STAT(*psbuf)) {
5631 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5632 }
5633
5634 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5635 return NT_STATUS_ACCESS_DENIED;
5636 }
5637
5638 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5639
5640 if (size == get_file_size_stat(psbuf)) {
5641 return NT_STATUS_OK;
5642 }
5643
5644 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5645 smb_fname_str_dbg(smb_fname), (double)size));
5646
5647 if (fsp && fsp->fh->fd != -1) {
5648 /* Handle based call. */
5649 if (vfs_set_filelen(fsp, size) == -1) {
5650 return map_nt_error_from_unix(errno);
5651 }
5652 trigger_write_time_update_immediate(fsp);
5653 return NT_STATUS_OK;
5654 }
5655
5656 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 return status;
5659 }
5660
5661 smb_fname_tmp->st = *psbuf;
5662
5663 status = SMB_VFS_CREATE_FILE(
5664 conn, /* conn */
5665 req, /* req */
5666 0, /* root_dir_fid */
5667 smb_fname_tmp, /* fname */
5668 FILE_WRITE_DATA, /* access_mask */
5669 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5670 FILE_SHARE_DELETE),
5671 FILE_OPEN, /* create_disposition*/
5672 0, /* create_options */
5673 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5674 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5675 0, /* allocation_size */
5676 0, /* private_flags */
5677 NULL, /* sd */
5678 NULL, /* ea_list */
5679 &new_fsp, /* result */
5680 NULL); /* pinfo */
5681
5682 TALLOC_FREE(smb_fname_tmp);
5683
5684 if (!NT_STATUS_IS_OK(status)) {
5685 /* NB. We check for open_was_deferred in the caller. */
5686 return status;
5687 }
5688
5689 /* See RAW-SFILEINFO-END-OF-FILE */
5690 if (fail_after_createfile) {
5691 close_file(req, new_fsp,NORMAL_CLOSE);
5692 return NT_STATUS_INVALID_LEVEL;
5693 }
5694
5695 if (vfs_set_filelen(new_fsp, size) == -1) {
5696 status = map_nt_error_from_unix(errno);
5697 close_file(req, new_fsp,NORMAL_CLOSE);
5698 return status;
5699 }
5700
5701 trigger_write_time_update_immediate(new_fsp);
5702 close_file(req, new_fsp,NORMAL_CLOSE);
5703 return NT_STATUS_OK;
5704}
5705
5706/****************************************************************************
5707 Deal with SMB_INFO_SET_EA.
5708****************************************************************************/
5709
5710static NTSTATUS smb_info_set_ea(connection_struct *conn,
5711 const char *pdata,
5712 int total_data,
5713 files_struct *fsp,
5714 const struct smb_filename *smb_fname)
5715{
5716 struct ea_list *ea_list = NULL;
5717 TALLOC_CTX *ctx = NULL;
5718 NTSTATUS status = NT_STATUS_OK;
5719
5720 if (total_data < 10) {
5721
5722 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5723 length. They seem to have no effect. Bug #3212. JRA */
5724
5725 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5726 /* We're done. We only get EA info in this call. */
5727 return NT_STATUS_OK;
5728 }
5729
5730 return NT_STATUS_INVALID_PARAMETER;
5731 }
5732
5733 if (IVAL(pdata,0) > total_data) {
5734 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5735 IVAL(pdata,0), (unsigned int)total_data));
5736 return NT_STATUS_INVALID_PARAMETER;
5737 }
5738
5739 ctx = talloc_tos();
5740 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5741 if (!ea_list) {
5742 return NT_STATUS_INVALID_PARAMETER;
5743 }
5744
5745 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5746 return NT_STATUS_ACCESS_DENIED;
5747 }
5748
5749 status = set_ea(conn, fsp, smb_fname, ea_list);
5750
5751 return status;
5752}
5753
5754/****************************************************************************
5755 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5756****************************************************************************/
5757
5758static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5759 const char *pdata,
5760 int total_data,
5761 files_struct *fsp)
5762{
5763 struct ea_list *ea_list = NULL;
5764 NTSTATUS status;
5765
5766 if (!fsp) {
5767 return NT_STATUS_INVALID_HANDLE;
5768 }
5769
5770 if (!lp_ea_support(SNUM(conn))) {
5771 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5772 "EA's not supported.\n",
5773 (unsigned int)total_data));
5774 return NT_STATUS_EAS_NOT_SUPPORTED;
5775 }
5776
5777 if (total_data < 10) {
5778 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5779 "too small.\n",
5780 (unsigned int)total_data));
5781 return NT_STATUS_INVALID_PARAMETER;
5782 }
5783
5784 ea_list = read_nttrans_ea_list(talloc_tos(),
5785 pdata,
5786 total_data);
5787
5788 if (!ea_list) {
5789 return NT_STATUS_INVALID_PARAMETER;
5790 }
5791
5792 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5793 return NT_STATUS_ACCESS_DENIED;
5794 }
5795
5796 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5797
5798 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5799 smb_fname_str_dbg(fsp->fsp_name),
5800 nt_errstr(status) ));
5801
5802 return status;
5803}
5804
5805
5806/****************************************************************************
5807 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5808****************************************************************************/
5809
5810static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5811 const char *pdata,
5812 int total_data,
5813 files_struct *fsp,
5814 struct smb_filename *smb_fname)
5815{
5816 NTSTATUS status = NT_STATUS_OK;
5817 bool delete_on_close;
5818 uint32 dosmode = 0;
5819
5820 if (total_data < 1) {
5821 return NT_STATUS_INVALID_PARAMETER;
5822 }
5823
5824 if (fsp == NULL) {
5825 return NT_STATUS_INVALID_HANDLE;
5826 }
5827
5828 delete_on_close = (CVAL(pdata,0) ? True : False);
5829 dosmode = dos_mode(conn, smb_fname);
5830
5831 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5832 "delete_on_close = %u\n",
5833 smb_fname_str_dbg(smb_fname),
5834 (unsigned int)dosmode,
5835 (unsigned int)delete_on_close ));
5836
5837 if (delete_on_close) {
5838 status = can_set_delete_on_close(fsp, dosmode);
5839 if (!NT_STATUS_IS_OK(status)) {
5840 return status;
5841 }
5842 }
5843
5844 /* The set is across all open files on this dev/inode pair. */
5845 if (!set_delete_on_close(fsp, delete_on_close,
5846 conn->session_info->security_token,
5847 &conn->session_info->utok)) {
5848 return NT_STATUS_ACCESS_DENIED;
5849 }
5850 return NT_STATUS_OK;
5851}
5852
5853/****************************************************************************
5854 Deal with SMB_FILE_POSITION_INFORMATION.
5855****************************************************************************/
5856
5857static NTSTATUS smb_file_position_information(connection_struct *conn,
5858 const char *pdata,
5859 int total_data,
5860 files_struct *fsp)
5861{
5862 uint64_t position_information;
5863
5864 if (total_data < 8) {
5865 return NT_STATUS_INVALID_PARAMETER;
5866 }
5867
5868 if (fsp == NULL) {
5869 /* Ignore on pathname based set. */
5870 return NT_STATUS_OK;
5871 }
5872
5873 position_information = (uint64_t)IVAL(pdata,0);
5874#ifdef LARGE_SMB_OFF_T
5875 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5876#else /* LARGE_SMB_OFF_T */
5877 if (IVAL(pdata,4) != 0) {
5878 /* more than 32 bits? */
5879 return NT_STATUS_INVALID_PARAMETER;
5880 }
5881#endif /* LARGE_SMB_OFF_T */
5882
5883 DEBUG(10,("smb_file_position_information: Set file position "
5884 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5885 (double)position_information));
5886 fsp->fh->position_information = position_information;
5887 return NT_STATUS_OK;
5888}
5889
5890/****************************************************************************
5891 Deal with SMB_FILE_MODE_INFORMATION.
5892****************************************************************************/
5893
5894static NTSTATUS smb_file_mode_information(connection_struct *conn,
5895 const char *pdata,
5896 int total_data)
5897{
5898 uint32 mode;
5899
5900 if (total_data < 4) {
5901 return NT_STATUS_INVALID_PARAMETER;
5902 }
5903 mode = IVAL(pdata,0);
5904 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5905 return NT_STATUS_INVALID_PARAMETER;
5906 }
5907 return NT_STATUS_OK;
5908}
5909
5910/****************************************************************************
5911 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5912****************************************************************************/
5913
5914static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5915 struct smb_request *req,
5916 const char *pdata,
5917 int total_data,
5918 const struct smb_filename *smb_fname)
5919{
5920 char *link_target = NULL;
5921 const char *newname = smb_fname->base_name;
5922 TALLOC_CTX *ctx = talloc_tos();
5923
5924 /* Set a symbolic link. */
5925 /* Don't allow this if follow links is false. */
5926
5927 if (total_data == 0) {
5928 return NT_STATUS_INVALID_PARAMETER;
5929 }
5930
5931 if (!lp_symlinks(SNUM(conn))) {
5932 return NT_STATUS_ACCESS_DENIED;
5933 }
5934
5935 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5936 total_data, STR_TERMINATE);
5937
5938 if (!link_target) {
5939 return NT_STATUS_INVALID_PARAMETER;
5940 }
5941
5942 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5943 newname, link_target ));
5944
5945 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5946 return map_nt_error_from_unix(errno);
5947 }
5948
5949 return NT_STATUS_OK;
5950}
5951
5952/****************************************************************************
5953 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5954****************************************************************************/
5955
5956static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5957 struct smb_request *req,
5958 const char *pdata, int total_data,
5959 struct smb_filename *smb_fname_new)
5960{
5961 char *oldname = NULL;
5962 struct smb_filename *smb_fname_old = NULL;
5963 TALLOC_CTX *ctx = talloc_tos();
5964 NTSTATUS status = NT_STATUS_OK;
5965
5966 /* Set a hard link. */
5967 if (total_data == 0) {
5968 return NT_STATUS_INVALID_PARAMETER;
5969 }
5970
5971 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5972 total_data, STR_TERMINATE, &status);
5973 if (!NT_STATUS_IS_OK(status)) {
5974 return status;
5975 }
5976
5977 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5978 smb_fname_str_dbg(smb_fname_new), oldname));
5979
5980 status = filename_convert(ctx,
5981 conn,
5982 req->flags2 & FLAGS2_DFS_PATHNAMES,
5983 oldname,
5984 0,
5985 NULL,
5986 &smb_fname_old);
5987 if (!NT_STATUS_IS_OK(status)) {
5988 return status;
5989 }
5990
5991 return hardlink_internals(ctx, conn, req, false,
5992 smb_fname_old, smb_fname_new);
5993}
5994
5995/****************************************************************************
5996 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5997****************************************************************************/
5998
5999static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6000 struct smb_request *req,
6001 const char *pdata,
6002 int total_data,
6003 files_struct *fsp,
6004 struct smb_filename *smb_fname_src)
6005{
6006 bool overwrite;
6007 uint32_t len;
6008 char *newname = NULL;
6009 struct smb_filename *smb_fname_dst = NULL;
6010 NTSTATUS status = NT_STATUS_OK;
6011 TALLOC_CTX *ctx = talloc_tos();
6012
6013 if (!fsp) {
6014 return NT_STATUS_INVALID_HANDLE;
6015 }
6016
6017 if (total_data < 20) {
6018 return NT_STATUS_INVALID_PARAMETER;
6019 }
6020
6021 overwrite = (CVAL(pdata,0) ? True : False);
6022 len = IVAL(pdata,16);
6023
6024 if (len > (total_data - 20) || (len == 0)) {
6025 return NT_STATUS_INVALID_PARAMETER;
6026 }
6027
6028 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6029 &pdata[20], len, STR_TERMINATE,
6030 &status);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 return status;
6033 }
6034
6035 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6036 newname));
6037
6038 status = filename_convert(ctx,
6039 conn,
6040 req->flags2 & FLAGS2_DFS_PATHNAMES,
6041 newname,
6042 UCF_SAVE_LCOMP,
6043 NULL,
6044 &smb_fname_dst);
6045 if (!NT_STATUS_IS_OK(status)) {
6046 return status;
6047 }
6048
6049 if (fsp->base_fsp) {
6050 /* newname must be a stream name. */
6051 if (newname[0] != ':') {
6052 return NT_STATUS_NOT_SUPPORTED;
6053 }
6054
6055 /* Create an smb_fname to call rename_internals_fsp() with. */
6056 status = create_synthetic_smb_fname(talloc_tos(),
6057 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6058 &smb_fname_dst);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 goto out;
6061 }
6062
6063 /*
6064 * Set the original last component, since
6065 * rename_internals_fsp() requires it.
6066 */
6067 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6068 newname);
6069 if (smb_fname_dst->original_lcomp == NULL) {
6070 status = NT_STATUS_NO_MEMORY;
6071 goto out;
6072 }
6073
6074 }
6075
6076 DEBUG(10,("smb2_file_rename_information: "
6077 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6078 fsp->fnum, fsp_str_dbg(fsp),
6079 smb_fname_str_dbg(smb_fname_dst)));
6080 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6081 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6082 overwrite);
6083
6084 out:
6085 TALLOC_FREE(smb_fname_dst);
6086 return status;
6087}
6088
6089static NTSTATUS smb_file_link_information(connection_struct *conn,
6090 struct smb_request *req,
6091 const char *pdata,
6092 int total_data,
6093 files_struct *fsp,
6094 struct smb_filename *smb_fname_src)
6095{
6096 bool overwrite;
6097 uint32_t len;
6098 char *newname = NULL;
6099 struct smb_filename *smb_fname_dst = NULL;
6100 NTSTATUS status = NT_STATUS_OK;
6101 TALLOC_CTX *ctx = talloc_tos();
6102
6103 if (!fsp) {
6104 return NT_STATUS_INVALID_HANDLE;
6105 }
6106
6107 if (total_data < 20) {
6108 return NT_STATUS_INVALID_PARAMETER;
6109 }
6110
6111 overwrite = (CVAL(pdata,0) ? true : false);
6112 len = IVAL(pdata,16);
6113
6114 if (len > (total_data - 20) || (len == 0)) {
6115 return NT_STATUS_INVALID_PARAMETER;
6116 }
6117
6118 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6119 &pdata[20], len, STR_TERMINATE,
6120 &status);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 return status;
6123 }
6124
6125 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6126 newname));
6127
6128 status = filename_convert(ctx,
6129 conn,
6130 req->flags2 & FLAGS2_DFS_PATHNAMES,
6131 newname,
6132 UCF_SAVE_LCOMP,
6133 NULL,
6134 &smb_fname_dst);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 return status;
6137 }
6138
6139 if (fsp->base_fsp) {
6140 /* No stream names. */
6141 return NT_STATUS_NOT_SUPPORTED;
6142 }
6143
6144 DEBUG(10,("smb_file_link_information: "
6145 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6146 fsp->fnum, fsp_str_dbg(fsp),
6147 smb_fname_str_dbg(smb_fname_dst)));
6148 status = hardlink_internals(ctx,
6149 conn,
6150 req,
6151 overwrite,
6152 fsp->fsp_name,
6153 smb_fname_dst);
6154
6155 TALLOC_FREE(smb_fname_dst);
6156 return status;
6157}
6158
6159/****************************************************************************
6160 Deal with SMB_FILE_RENAME_INFORMATION.
6161****************************************************************************/
6162
6163static NTSTATUS smb_file_rename_information(connection_struct *conn,
6164 struct smb_request *req,
6165 const char *pdata,
6166 int total_data,
6167 files_struct *fsp,
6168 struct smb_filename *smb_fname_src)
6169{
6170 bool overwrite;
6171 uint32 root_fid;
6172 uint32 len;
6173 char *newname = NULL;
6174 struct smb_filename *smb_fname_dst = NULL;
6175 bool dest_has_wcard = False;
6176 NTSTATUS status = NT_STATUS_OK;
6177 char *p;
6178 TALLOC_CTX *ctx = talloc_tos();
6179
6180 if (total_data < 13) {
6181 return NT_STATUS_INVALID_PARAMETER;
6182 }
6183
6184 overwrite = (CVAL(pdata,0) ? True : False);
6185 root_fid = IVAL(pdata,4);
6186 len = IVAL(pdata,8);
6187
6188 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6189 return NT_STATUS_INVALID_PARAMETER;
6190 }
6191
6192 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6193 len, 0, &status,
6194 &dest_has_wcard);
6195 if (!NT_STATUS_IS_OK(status)) {
6196 return status;
6197 }
6198
6199 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6200 newname));
6201
6202 status = resolve_dfspath_wcard(ctx, conn,
6203 req->flags2 & FLAGS2_DFS_PATHNAMES,
6204 newname,
6205 true,
6206 &newname,
6207 &dest_has_wcard);
6208 if (!NT_STATUS_IS_OK(status)) {
6209 return status;
6210 }
6211
6212 /* Check the new name has no '/' characters. */
6213 if (strchr_m(newname, '/')) {
6214 return NT_STATUS_NOT_SUPPORTED;
6215 }
6216
6217 if (fsp && fsp->base_fsp) {
6218 /* newname must be a stream name. */
6219 if (newname[0] != ':') {
6220 return NT_STATUS_NOT_SUPPORTED;
6221 }
6222
6223 /* Create an smb_fname to call rename_internals_fsp() with. */
6224 status = create_synthetic_smb_fname(talloc_tos(),
6225 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6226 &smb_fname_dst);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 goto out;
6229 }
6230
6231 /*
6232 * Set the original last component, since
6233 * rename_internals_fsp() requires it.
6234 */
6235 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6236 newname);
6237 if (smb_fname_dst->original_lcomp == NULL) {
6238 status = NT_STATUS_NO_MEMORY;
6239 goto out;
6240 }
6241
6242 } else {
6243 /*
6244 * Build up an smb_fname_dst based on the filename passed in.
6245 * We basically just strip off the last component, and put on
6246 * the newname instead.
6247 */
6248 char *base_name = NULL;
6249
6250 /* newname must *not* be a stream name. */
6251 if (newname[0] == ':') {
6252 return NT_STATUS_NOT_SUPPORTED;
6253 }
6254
6255 /*
6256 * Strip off the last component (filename) of the path passed
6257 * in.
6258 */
6259 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6260 if (!base_name) {
6261 return NT_STATUS_NO_MEMORY;
6262 }
6263 p = strrchr_m(base_name, '/');
6264 if (p) {
6265 p[1] = '\0';
6266 } else {
6267 base_name = talloc_strdup(ctx, "");
6268 if (!base_name) {
6269 return NT_STATUS_NO_MEMORY;
6270 }
6271 }
6272 /* Append the new name. */
6273 base_name = talloc_asprintf_append(base_name,
6274 "%s",
6275 newname);
6276 if (!base_name) {
6277 return NT_STATUS_NO_MEMORY;
6278 }
6279
6280 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6281 (UCF_SAVE_LCOMP |
6282 (dest_has_wcard ?
6283 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6284 0)));
6285
6286 /* If an error we expect this to be
6287 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6288
6289 if (!NT_STATUS_IS_OK(status)) {
6290 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6291 status)) {
6292 goto out;
6293 }
6294 /* Create an smb_fname to call rename_internals_fsp() */
6295 status = create_synthetic_smb_fname(ctx,
6296 base_name, NULL,
6297 NULL,
6298 &smb_fname_dst);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 goto out;
6301 }
6302 }
6303 }
6304
6305 if (fsp) {
6306 DEBUG(10,("smb_file_rename_information: "
6307 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6308 fsp->fnum, fsp_str_dbg(fsp),
6309 smb_fname_str_dbg(smb_fname_dst)));
6310 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6311 overwrite);
6312 } else {
6313 DEBUG(10,("smb_file_rename_information: "
6314 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6315 smb_fname_str_dbg(smb_fname_src),
6316 smb_fname_str_dbg(smb_fname_dst)));
6317 status = rename_internals(ctx, conn, req, smb_fname_src,
6318 smb_fname_dst, 0, overwrite, false,
6319 dest_has_wcard,
6320 FILE_WRITE_ATTRIBUTES);
6321 }
6322 out:
6323 TALLOC_FREE(smb_fname_dst);
6324 return status;
6325}
6326
6327/****************************************************************************
6328 Deal with SMB_SET_POSIX_ACL.
6329****************************************************************************/
6330
6331#if defined(HAVE_POSIX_ACLS)
6332static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6333 const char *pdata,
6334 int total_data,
6335 files_struct *fsp,
6336 const struct smb_filename *smb_fname)
6337{
6338 uint16 posix_acl_version;
6339 uint16 num_file_acls;
6340 uint16 num_def_acls;
6341 bool valid_file_acls = True;
6342 bool valid_def_acls = True;
6343
6344 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6345 return NT_STATUS_INVALID_PARAMETER;
6346 }
6347 posix_acl_version = SVAL(pdata,0);
6348 num_file_acls = SVAL(pdata,2);
6349 num_def_acls = SVAL(pdata,4);
6350
6351 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6352 valid_file_acls = False;
6353 num_file_acls = 0;
6354 }
6355
6356 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6357 valid_def_acls = False;
6358 num_def_acls = 0;
6359 }
6360
6361 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6362 return NT_STATUS_INVALID_PARAMETER;
6363 }
6364
6365 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6366 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6367 return NT_STATUS_INVALID_PARAMETER;
6368 }
6369
6370 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6371 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6372 (unsigned int)num_file_acls,
6373 (unsigned int)num_def_acls));
6374
6375 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6376 smb_fname->base_name, num_file_acls,
6377 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6378 return map_nt_error_from_unix(errno);
6379 }
6380
6381 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6382 smb_fname->base_name, &smb_fname->st, num_def_acls,
6383 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6384 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6385 return map_nt_error_from_unix(errno);
6386 }
6387 return NT_STATUS_OK;
6388}
6389#endif
6390
6391/****************************************************************************
6392 Deal with SMB_SET_POSIX_LOCK.
6393****************************************************************************/
6394
6395static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6396 struct smb_request *req,
6397 const char *pdata,
6398 int total_data,
6399 files_struct *fsp)
6400{
6401 uint64_t count;
6402 uint64_t offset;
6403 uint64_t smblctx;
6404 bool blocking_lock = False;
6405 enum brl_type lock_type;
6406
6407 NTSTATUS status = NT_STATUS_OK;
6408
6409 if (fsp == NULL || fsp->fh->fd == -1) {
6410 return NT_STATUS_INVALID_HANDLE;
6411 }
6412
6413 if (total_data != POSIX_LOCK_DATA_SIZE) {
6414 return NT_STATUS_INVALID_PARAMETER;
6415 }
6416
6417 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6418 case POSIX_LOCK_TYPE_READ:
6419 lock_type = READ_LOCK;
6420 break;
6421 case POSIX_LOCK_TYPE_WRITE:
6422 /* Return the right POSIX-mappable error code for files opened read-only. */
6423 if (!fsp->can_write) {
6424 return NT_STATUS_INVALID_HANDLE;
6425 }
6426 lock_type = WRITE_LOCK;
6427 break;
6428 case POSIX_LOCK_TYPE_UNLOCK:
6429 lock_type = UNLOCK_LOCK;
6430 break;
6431 default:
6432 return NT_STATUS_INVALID_PARAMETER;
6433 }
6434
6435 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6436 blocking_lock = False;
6437 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6438 blocking_lock = True;
6439 } else {
6440 return NT_STATUS_INVALID_PARAMETER;
6441 }
6442
6443 if (!lp_blocking_locks(SNUM(conn))) {
6444 blocking_lock = False;
6445 }
6446
6447 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6448#if defined(HAVE_LONGLONG)
6449 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6450 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6451 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6452 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6453#else /* HAVE_LONGLONG */
6454 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6455 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6456#endif /* HAVE_LONGLONG */
6457
6458 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6459 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6460 fsp_str_dbg(fsp),
6461 (unsigned int)lock_type,
6462 (unsigned long long)smblctx,
6463 (double)count,
6464 (double)offset ));
6465
6466 if (lock_type == UNLOCK_LOCK) {
6467 status = do_unlock(req->sconn->msg_ctx,
6468 fsp,
6469 smblctx,
6470 count,
6471 offset,
6472 POSIX_LOCK);
6473 } else {
6474 uint64_t block_smblctx;
6475
6476 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6477 fsp,
6478 smblctx,
6479 count,
6480 offset,
6481 lock_type,
6482 POSIX_LOCK,
6483 blocking_lock,
6484 &status,
6485 &block_smblctx,
6486 NULL);
6487
6488 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6489 /*
6490 * A blocking lock was requested. Package up
6491 * this smb into a queued request and push it
6492 * onto the blocking lock queue.
6493 */
6494 if(push_blocking_lock_request(br_lck,
6495 req,
6496 fsp,
6497 -1, /* infinite timeout. */
6498 0,
6499 smblctx,
6500 lock_type,
6501 POSIX_LOCK,
6502 offset,
6503 count,
6504 block_smblctx)) {
6505 TALLOC_FREE(br_lck);
6506 return status;
6507 }
6508 }
6509 TALLOC_FREE(br_lck);
6510 }
6511
6512 return status;
6513}
6514
6515/****************************************************************************
6516 Deal with SMB_SET_FILE_BASIC_INFO.
6517****************************************************************************/
6518
6519static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6520 const char *pdata,
6521 int total_data,
6522 files_struct *fsp,
6523 const struct smb_filename *smb_fname)
6524{
6525 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6526 struct smb_file_time ft;
6527 uint32 dosmode = 0;
6528 NTSTATUS status = NT_STATUS_OK;
6529
6530 ZERO_STRUCT(ft);
6531
6532 if (total_data < 36) {
6533 return NT_STATUS_INVALID_PARAMETER;
6534 }
6535
6536 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6537 return NT_STATUS_ACCESS_DENIED;
6538 }
6539
6540 /* Set the attributes */
6541 dosmode = IVAL(pdata,32);
6542 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 return status;
6545 }
6546
6547 /* create time */
6548 ft.create_time = interpret_long_date(pdata);
6549
6550 /* access time */
6551 ft.atime = interpret_long_date(pdata+8);
6552
6553 /* write time. */
6554 ft.mtime = interpret_long_date(pdata+16);
6555
6556 /* change time. */
6557 ft.ctime = interpret_long_date(pdata+24);
6558
6559 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6560 smb_fname_str_dbg(smb_fname)));
6561
6562 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6563 true);
6564}
6565
6566/****************************************************************************
6567 Deal with SMB_INFO_STANDARD.
6568****************************************************************************/
6569
6570static NTSTATUS smb_set_info_standard(connection_struct *conn,
6571 const char *pdata,
6572 int total_data,
6573 files_struct *fsp,
6574 const struct smb_filename *smb_fname)
6575{
6576 struct smb_file_time ft;
6577
6578 ZERO_STRUCT(ft);
6579
6580 if (total_data < 12) {
6581 return NT_STATUS_INVALID_PARAMETER;
6582 }
6583
6584 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6585 return NT_STATUS_ACCESS_DENIED;
6586 }
6587
6588 /* create time */
6589 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6590 /* access time */
6591 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6592 /* write time */
6593 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6594
6595 DEBUG(10,("smb_set_info_standard: file %s\n",
6596 smb_fname_str_dbg(smb_fname)));
6597
6598 return smb_set_file_time(conn,
6599 fsp,
6600 smb_fname,
6601 &ft,
6602 true);
6603}
6604
6605/****************************************************************************
6606 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6607****************************************************************************/
6608
6609static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6610 struct smb_request *req,
6611 const char *pdata,
6612 int total_data,
6613 files_struct *fsp,
6614 struct smb_filename *smb_fname)
6615{
6616 uint64_t allocation_size = 0;
6617 NTSTATUS status = NT_STATUS_OK;
6618 files_struct *new_fsp = NULL;
6619
6620 if (!VALID_STAT(smb_fname->st)) {
6621 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6622 }
6623
6624 if (total_data < 8) {
6625 return NT_STATUS_INVALID_PARAMETER;
6626 }
6627
6628 allocation_size = (uint64_t)IVAL(pdata,0);
6629#ifdef LARGE_SMB_OFF_T
6630 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6631#else /* LARGE_SMB_OFF_T */
6632 if (IVAL(pdata,4) != 0) {
6633 /* more than 32 bits? */
6634 return NT_STATUS_INVALID_PARAMETER;
6635 }
6636#endif /* LARGE_SMB_OFF_T */
6637
6638 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6639 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6640 (double)allocation_size));
6641
6642 if (allocation_size) {
6643 allocation_size = smb_roundup(conn, allocation_size);
6644 }
6645
6646 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6647 return NT_STATUS_ACCESS_DENIED;
6648 }
6649
6650 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6651 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6652 (double)allocation_size));
6653
6654 if (fsp && fsp->fh->fd != -1) {
6655 /* Open file handle. */
6656 /* Only change if needed. */
6657 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6658 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6659 return map_nt_error_from_unix(errno);
6660 }
6661 }
6662 /* But always update the time. */
6663 /*
6664 * This is equivalent to a write. Ensure it's seen immediately
6665 * if there are no pending writes.
6666 */
6667 trigger_write_time_update_immediate(fsp);
6668 return NT_STATUS_OK;
6669 }
6670
6671 /* Pathname or stat or directory file. */
6672 status = SMB_VFS_CREATE_FILE(
6673 conn, /* conn */
6674 req, /* req */
6675 0, /* root_dir_fid */
6676 smb_fname, /* fname */
6677 FILE_WRITE_DATA, /* access_mask */
6678 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6679 FILE_SHARE_DELETE),
6680 FILE_OPEN, /* create_disposition*/
6681 0, /* create_options */
6682 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6683 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6684 0, /* allocation_size */
6685 0, /* private_flags */
6686 NULL, /* sd */
6687 NULL, /* ea_list */
6688 &new_fsp, /* result */
6689 NULL); /* pinfo */
6690
6691 if (!NT_STATUS_IS_OK(status)) {
6692 /* NB. We check for open_was_deferred in the caller. */
6693 return status;
6694 }
6695
6696 /* Only change if needed. */
6697 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6698 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6699 status = map_nt_error_from_unix(errno);
6700 close_file(req, new_fsp, NORMAL_CLOSE);
6701 return status;
6702 }
6703 }
6704
6705 /* Changing the allocation size should set the last mod time. */
6706 /*
6707 * This is equivalent to a write. Ensure it's seen immediately
6708 * if there are no pending writes.
6709 */
6710 trigger_write_time_update_immediate(new_fsp);
6711
6712 close_file(req, new_fsp, NORMAL_CLOSE);
6713 return NT_STATUS_OK;
6714}
6715
6716/****************************************************************************
6717 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6718****************************************************************************/
6719
6720static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6721 struct smb_request *req,
6722 const char *pdata,
6723 int total_data,
6724 files_struct *fsp,
6725 const struct smb_filename *smb_fname,
6726 bool fail_after_createfile)
6727{
6728 SMB_OFF_T size;
6729
6730 if (total_data < 8) {
6731 return NT_STATUS_INVALID_PARAMETER;
6732 }
6733
6734 size = IVAL(pdata,0);
6735#ifdef LARGE_SMB_OFF_T
6736 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6737#else /* LARGE_SMB_OFF_T */
6738 if (IVAL(pdata,4) != 0) {
6739 /* more than 32 bits? */
6740 return NT_STATUS_INVALID_PARAMETER;
6741 }
6742#endif /* LARGE_SMB_OFF_T */
6743 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6744 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6745 (double)size));
6746
6747 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6748 return NT_STATUS_ACCESS_DENIED;
6749 }
6750
6751 return smb_set_file_size(conn, req,
6752 fsp,
6753 smb_fname,
6754 &smb_fname->st,
6755 size,
6756 fail_after_createfile);
6757}
6758
6759/****************************************************************************
6760 Allow a UNIX info mknod.
6761****************************************************************************/
6762
6763static NTSTATUS smb_unix_mknod(connection_struct *conn,
6764 const char *pdata,
6765 int total_data,
6766 const struct smb_filename *smb_fname)
6767{
6768 uint32 file_type = IVAL(pdata,56);
6769#if defined(HAVE_MAKEDEV)
6770 uint32 dev_major = IVAL(pdata,60);
6771 uint32 dev_minor = IVAL(pdata,68);
6772#endif
6773 SMB_DEV_T dev = (SMB_DEV_T)0;
6774 uint32 raw_unixmode = IVAL(pdata,84);
6775 NTSTATUS status;
6776 mode_t unixmode;
6777
6778 if (total_data < 100) {
6779 return NT_STATUS_INVALID_PARAMETER;
6780 }
6781
6782 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6783 PERM_NEW_FILE, &unixmode);
6784 if (!NT_STATUS_IS_OK(status)) {
6785 return status;
6786 }
6787
6788#if defined(HAVE_MAKEDEV)
6789 dev = makedev(dev_major, dev_minor);
6790#endif
6791
6792 switch (file_type) {
6793#if defined(S_IFIFO)
6794 case UNIX_TYPE_FIFO:
6795 unixmode |= S_IFIFO;
6796 break;
6797#endif
6798#if defined(S_IFSOCK)
6799 case UNIX_TYPE_SOCKET:
6800 unixmode |= S_IFSOCK;
6801 break;
6802#endif
6803#if defined(S_IFCHR)
6804 case UNIX_TYPE_CHARDEV:
6805 unixmode |= S_IFCHR;
6806 break;
6807#endif
6808#if defined(S_IFBLK)
6809 case UNIX_TYPE_BLKDEV:
6810 unixmode |= S_IFBLK;
6811 break;
6812#endif
6813 default:
6814 return NT_STATUS_INVALID_PARAMETER;
6815 }
6816
6817 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6818 "%.0f mode 0%o for file %s\n", (double)dev,
6819 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6820
6821 /* Ok - do the mknod. */
6822 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6823 return map_nt_error_from_unix(errno);
6824 }
6825
6826 /* If any of the other "set" calls fail we
6827 * don't want to end up with a half-constructed mknod.
6828 */
6829
6830 if (lp_inherit_perms(SNUM(conn))) {
6831 char *parent;
6832 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6833 &parent, NULL)) {
6834 return NT_STATUS_NO_MEMORY;
6835 }
6836 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6837 unixmode);
6838 TALLOC_FREE(parent);
6839 }
6840
6841 return NT_STATUS_OK;
6842}
6843
6844/****************************************************************************
6845 Deal with SMB_SET_FILE_UNIX_BASIC.
6846****************************************************************************/
6847
6848static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6849 struct smb_request *req,
6850 const char *pdata,
6851 int total_data,
6852 files_struct *fsp,
6853 const struct smb_filename *smb_fname)
6854{
6855 struct smb_file_time ft;
6856 uint32 raw_unixmode;
6857 mode_t unixmode;
6858 SMB_OFF_T size = 0;
6859 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6860 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6861 NTSTATUS status = NT_STATUS_OK;
6862 bool delete_on_fail = False;
6863 enum perm_type ptype;
6864 files_struct *all_fsps = NULL;
6865 bool modify_mtime = true;
6866 struct file_id id;
6867 struct smb_filename *smb_fname_tmp = NULL;
6868 SMB_STRUCT_STAT sbuf;
6869
6870 ZERO_STRUCT(ft);
6871
6872 if (total_data < 100) {
6873 return NT_STATUS_INVALID_PARAMETER;
6874 }
6875
6876 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6877 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6878 size=IVAL(pdata,0); /* first 8 Bytes are size */
6879#ifdef LARGE_SMB_OFF_T
6880 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6881#else /* LARGE_SMB_OFF_T */
6882 if (IVAL(pdata,4) != 0) {
6883 /* more than 32 bits? */
6884 return NT_STATUS_INVALID_PARAMETER;
6885 }
6886#endif /* LARGE_SMB_OFF_T */
6887 }
6888
6889 ft.atime = interpret_long_date(pdata+24); /* access_time */
6890 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6891 set_owner = (uid_t)IVAL(pdata,40);
6892 set_grp = (gid_t)IVAL(pdata,48);
6893 raw_unixmode = IVAL(pdata,84);
6894
6895 if (VALID_STAT(smb_fname->st)) {
6896 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6897 ptype = PERM_EXISTING_DIR;
6898 } else {
6899 ptype = PERM_EXISTING_FILE;
6900 }
6901 } else {
6902 ptype = PERM_NEW_FILE;
6903 }
6904
6905 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6906 ptype, &unixmode);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 return status;
6909 }
6910
6911 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6912 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6913 smb_fname_str_dbg(smb_fname), (double)size,
6914 (unsigned int)set_owner, (unsigned int)set_grp,
6915 (int)raw_unixmode));
6916
6917 sbuf = smb_fname->st;
6918
6919 if (!VALID_STAT(sbuf)) {
6920 /*
6921 * The only valid use of this is to create character and block
6922 * devices, and named pipes. This is deprecated (IMHO) and
6923 * a new info level should be used for mknod. JRA.
6924 */
6925
6926 status = smb_unix_mknod(conn,
6927 pdata,
6928 total_data,
6929 smb_fname);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 return status;
6932 }
6933
6934 status = copy_smb_filename(talloc_tos(), smb_fname,
6935 &smb_fname_tmp);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 return status;
6938 }
6939
6940 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6941 status = map_nt_error_from_unix(errno);
6942 TALLOC_FREE(smb_fname_tmp);
6943 SMB_VFS_UNLINK(conn, smb_fname);
6944 return status;
6945 }
6946
6947 sbuf = smb_fname_tmp->st;
6948 smb_fname = smb_fname_tmp;
6949
6950 /* Ensure we don't try and change anything else. */
6951 raw_unixmode = SMB_MODE_NO_CHANGE;
6952 size = get_file_size_stat(&sbuf);
6953 ft.atime = sbuf.st_ex_atime;
6954 ft.mtime = sbuf.st_ex_mtime;
6955 /*
6956 * We continue here as we might want to change the
6957 * owner uid/gid.
6958 */
6959 delete_on_fail = True;
6960 }
6961
6962#if 1
6963 /* Horrible backwards compatibility hack as an old server bug
6964 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6965 * */
6966
6967 if (!size) {
6968 size = get_file_size_stat(&sbuf);
6969 }
6970#endif
6971
6972 /*
6973 * Deal with the UNIX specific mode set.
6974 */
6975
6976 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6977 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6978 "setting mode 0%o for file %s\n",
6979 (unsigned int)unixmode,
6980 smb_fname_str_dbg(smb_fname)));
6981 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6982 return map_nt_error_from_unix(errno);
6983 }
6984 }
6985
6986 /*
6987 * Deal with the UNIX specific uid set.
6988 */
6989
6990 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6991 (sbuf.st_ex_uid != set_owner)) {
6992 int ret;
6993
6994 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6995 "changing owner %u for path %s\n",
6996 (unsigned int)set_owner,
6997 smb_fname_str_dbg(smb_fname)));
6998
6999 if (S_ISLNK(sbuf.st_ex_mode)) {
7000 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7001 set_owner, (gid_t)-1);
7002 } else {
7003 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7004 set_owner, (gid_t)-1);
7005 }
7006
7007 if (ret != 0) {
7008 status = map_nt_error_from_unix(errno);
7009 if (delete_on_fail) {
7010 SMB_VFS_UNLINK(conn, smb_fname);
7011 }
7012 return status;
7013 }
7014 }
7015
7016 /*
7017 * Deal with the UNIX specific gid set.
7018 */
7019
7020 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7021 (sbuf.st_ex_gid != set_grp)) {
7022 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7023 "changing group %u for file %s\n",
7024 (unsigned int)set_owner,
7025 smb_fname_str_dbg(smb_fname)));
7026 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7027 set_grp) != 0) {
7028 status = map_nt_error_from_unix(errno);
7029 if (delete_on_fail) {
7030 SMB_VFS_UNLINK(conn, smb_fname);
7031 }
7032 return status;
7033 }
7034 }
7035
7036 /* Deal with any size changes. */
7037
7038 status = smb_set_file_size(conn, req,
7039 fsp,
7040 smb_fname,
7041 &sbuf,
7042 size,
7043 false);
7044 if (!NT_STATUS_IS_OK(status)) {
7045 return status;
7046 }
7047
7048 /* Deal with any time changes. */
7049 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7050 /* No change, don't cancel anything. */
7051 return status;
7052 }
7053
7054 id = vfs_file_id_from_sbuf(conn, &sbuf);
7055 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7056 all_fsps = file_find_di_next(all_fsps)) {
7057 /*
7058 * We're setting the time explicitly for UNIX.
7059 * Cancel any pending changes over all handles.
7060 */
7061 all_fsps->update_write_time_on_close = false;
7062 TALLOC_FREE(all_fsps->update_write_time_event);
7063 }
7064
7065 /*
7066 * Override the "setting_write_time"
7067 * parameter here as it almost does what
7068 * we need. Just remember if we modified
7069 * mtime and send the notify ourselves.
7070 */
7071 if (null_timespec(ft.mtime)) {
7072 modify_mtime = false;
7073 }
7074
7075 status = smb_set_file_time(conn,
7076 fsp,
7077 smb_fname,
7078 &ft,
7079 false);
7080 if (modify_mtime) {
7081 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7082 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7083 }
7084 return status;
7085}
7086
7087/****************************************************************************
7088 Deal with SMB_SET_FILE_UNIX_INFO2.
7089****************************************************************************/
7090
7091static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7092 struct smb_request *req,
7093 const char *pdata,
7094 int total_data,
7095 files_struct *fsp,
7096 const struct smb_filename *smb_fname)
7097{
7098 NTSTATUS status;
7099 uint32 smb_fflags;
7100 uint32 smb_fmask;
7101
7102 if (total_data < 116) {
7103 return NT_STATUS_INVALID_PARAMETER;
7104 }
7105
7106 /* Start by setting all the fields that are common between UNIX_BASIC
7107 * and UNIX_INFO2.
7108 */
7109 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7110 fsp, smb_fname);
7111 if (!NT_STATUS_IS_OK(status)) {
7112 return status;
7113 }
7114
7115 smb_fflags = IVAL(pdata, 108);
7116 smb_fmask = IVAL(pdata, 112);
7117
7118 /* NB: We should only attempt to alter the file flags if the client
7119 * sends a non-zero mask.
7120 */
7121 if (smb_fmask != 0) {
7122 int stat_fflags = 0;
7123
7124 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7125 smb_fmask, &stat_fflags)) {
7126 /* Client asked to alter a flag we don't understand. */
7127 return NT_STATUS_INVALID_PARAMETER;
7128 }
7129
7130 if (fsp && fsp->fh->fd != -1) {
7131 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7132 return NT_STATUS_NOT_SUPPORTED;
7133 } else {
7134 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7135 stat_fflags) != 0) {
7136 return map_nt_error_from_unix(errno);
7137 }
7138 }
7139 }
7140
7141 /* XXX: need to add support for changing the create_time here. You
7142 * can do this for paths on Darwin with setattrlist(2). The right way
7143 * to hook this up is probably by extending the VFS utimes interface.
7144 */
7145
7146 return NT_STATUS_OK;
7147}
7148
7149/****************************************************************************
7150 Create a directory with POSIX semantics.
7151****************************************************************************/
7152
7153static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7154 struct smb_request *req,
7155 char **ppdata,
7156 int total_data,
7157 struct smb_filename *smb_fname,
7158 int *pdata_return_size)
7159{
7160 NTSTATUS status = NT_STATUS_OK;
7161 uint32 raw_unixmode = 0;
7162 uint32 mod_unixmode = 0;
7163 mode_t unixmode = (mode_t)0;
7164 files_struct *fsp = NULL;
7165 uint16 info_level_return = 0;
7166 int info;
7167 char *pdata = *ppdata;
7168
7169 if (total_data < 18) {
7170 return NT_STATUS_INVALID_PARAMETER;
7171 }
7172
7173 raw_unixmode = IVAL(pdata,8);
7174 /* Next 4 bytes are not yet defined. */
7175
7176 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7177 PERM_NEW_DIR, &unixmode);
7178 if (!NT_STATUS_IS_OK(status)) {
7179 return status;
7180 }
7181
7182 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7183
7184 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7185 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7186
7187 status = SMB_VFS_CREATE_FILE(
7188 conn, /* conn */
7189 req, /* req */
7190 0, /* root_dir_fid */
7191 smb_fname, /* fname */
7192 FILE_READ_ATTRIBUTES, /* access_mask */
7193 FILE_SHARE_NONE, /* share_access */
7194 FILE_CREATE, /* create_disposition*/
7195 FILE_DIRECTORY_FILE, /* create_options */
7196 mod_unixmode, /* file_attributes */
7197 0, /* oplock_request */
7198 0, /* allocation_size */
7199 0, /* private_flags */
7200 NULL, /* sd */
7201 NULL, /* ea_list */
7202 &fsp, /* result */
7203 &info); /* pinfo */
7204
7205 if (NT_STATUS_IS_OK(status)) {
7206 close_file(req, fsp, NORMAL_CLOSE);
7207 }
7208
7209 info_level_return = SVAL(pdata,16);
7210
7211 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7212 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7213 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7214 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7215 } else {
7216 *pdata_return_size = 12;
7217 }
7218
7219 /* Realloc the data size */
7220 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7221 if (*ppdata == NULL) {
7222 *pdata_return_size = 0;
7223 return NT_STATUS_NO_MEMORY;
7224 }
7225 pdata = *ppdata;
7226
7227 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7228 SSVAL(pdata,2,0); /* No fnum. */
7229 SIVAL(pdata,4,info); /* Was directory created. */
7230
7231 switch (info_level_return) {
7232 case SMB_QUERY_FILE_UNIX_BASIC:
7233 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7234 SSVAL(pdata,10,0); /* Padding. */
7235 store_file_unix_basic(conn, pdata + 12, fsp,
7236 &smb_fname->st);
7237 break;
7238 case SMB_QUERY_FILE_UNIX_INFO2:
7239 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7240 SSVAL(pdata,10,0); /* Padding. */
7241 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7242 &smb_fname->st);
7243 break;
7244 default:
7245 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7246 SSVAL(pdata,10,0); /* Padding. */
7247 break;
7248 }
7249
7250 return status;
7251}
7252
7253/****************************************************************************
7254 Open/Create a file with POSIX semantics.
7255****************************************************************************/
7256
7257#define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7258#define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7259
7260static NTSTATUS smb_posix_open(connection_struct *conn,
7261 struct smb_request *req,
7262 char **ppdata,
7263 int total_data,
7264 struct smb_filename *smb_fname,
7265 int *pdata_return_size)
7266{
7267 bool extended_oplock_granted = False;
7268 char *pdata = *ppdata;
7269 uint32 flags = 0;
7270 uint32 wire_open_mode = 0;
7271 uint32 raw_unixmode = 0;
7272 uint32 mod_unixmode = 0;
7273 uint32 create_disp = 0;
7274 uint32 access_mask = 0;
7275 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7276 NTSTATUS status = NT_STATUS_OK;
7277 mode_t unixmode = (mode_t)0;
7278 files_struct *fsp = NULL;
7279 int oplock_request = 0;
7280 int info = 0;
7281 uint16 info_level_return = 0;
7282
7283 if (total_data < 18) {
7284 return NT_STATUS_INVALID_PARAMETER;
7285 }
7286
7287 flags = IVAL(pdata,0);
7288 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7289 if (oplock_request) {
7290 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7291 }
7292
7293 wire_open_mode = IVAL(pdata,4);
7294
7295 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7296 return smb_posix_mkdir(conn, req,
7297 ppdata,
7298 total_data,
7299 smb_fname,
7300 pdata_return_size);
7301 }
7302
7303 switch (wire_open_mode & SMB_ACCMODE) {
7304 case SMB_O_RDONLY:
7305 access_mask = SMB_O_RDONLY_MAPPING;
7306 break;
7307 case SMB_O_WRONLY:
7308 access_mask = SMB_O_WRONLY_MAPPING;
7309 break;
7310 case SMB_O_RDWR:
7311 access_mask = (SMB_O_RDONLY_MAPPING|
7312 SMB_O_WRONLY_MAPPING);
7313 break;
7314 default:
7315 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7316 (unsigned int)wire_open_mode ));
7317 return NT_STATUS_INVALID_PARAMETER;
7318 }
7319
7320 wire_open_mode &= ~SMB_ACCMODE;
7321
7322 /* First take care of O_CREAT|O_EXCL interactions. */
7323 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7324 case (SMB_O_CREAT | SMB_O_EXCL):
7325 /* File exists fail. File not exist create. */
7326 create_disp = FILE_CREATE;
7327 break;
7328 case SMB_O_CREAT:
7329 /* File exists open. File not exist create. */
7330 create_disp = FILE_OPEN_IF;
7331 break;
7332 case 0:
7333 /* File exists open. File not exist fail. */
7334 create_disp = FILE_OPEN;
7335 break;
7336 case SMB_O_EXCL:
7337 /* O_EXCL on its own without O_CREAT is undefined. */
7338 default:
7339 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7340 (unsigned int)wire_open_mode ));
7341 return NT_STATUS_INVALID_PARAMETER;
7342 }
7343
7344 /* Next factor in the effects of O_TRUNC. */
7345 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7346
7347 if (wire_open_mode & SMB_O_TRUNC) {
7348 switch (create_disp) {
7349 case FILE_CREATE:
7350 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7351 /* Leave create_disp alone as
7352 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7353 */
7354 /* File exists fail. File not exist create. */
7355 break;
7356 case FILE_OPEN_IF:
7357 /* SMB_O_CREAT | SMB_O_TRUNC */
7358 /* File exists overwrite. File not exist create. */
7359 create_disp = FILE_OVERWRITE_IF;
7360 break;
7361 case FILE_OPEN:
7362 /* SMB_O_TRUNC */
7363 /* File exists overwrite. File not exist fail. */
7364 create_disp = FILE_OVERWRITE;
7365 break;
7366 default:
7367 /* Cannot get here. */
7368 smb_panic("smb_posix_open: logic error");
7369 return NT_STATUS_INVALID_PARAMETER;
7370 }
7371 }
7372
7373 raw_unixmode = IVAL(pdata,8);
7374 /* Next 4 bytes are not yet defined. */
7375
7376 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7377 (VALID_STAT(smb_fname->st) ?
7378 PERM_EXISTING_FILE : PERM_NEW_FILE),
7379 &unixmode);
7380
7381 if (!NT_STATUS_IS_OK(status)) {
7382 return status;
7383 }
7384
7385 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7386
7387 if (wire_open_mode & SMB_O_SYNC) {
7388 create_options |= FILE_WRITE_THROUGH;
7389 }
7390 if (wire_open_mode & SMB_O_APPEND) {
7391 access_mask |= FILE_APPEND_DATA;
7392 }
7393 if (wire_open_mode & SMB_O_DIRECT) {
7394 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7395 }
7396
7397 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7398 VALID_STAT_OF_DIR(smb_fname->st)) {
7399 if (access_mask != SMB_O_RDONLY_MAPPING) {
7400 return NT_STATUS_FILE_IS_A_DIRECTORY;
7401 }
7402 create_options &= ~FILE_NON_DIRECTORY_FILE;
7403 create_options |= FILE_DIRECTORY_FILE;
7404 }
7405
7406 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7407 smb_fname_str_dbg(smb_fname),
7408 (unsigned int)wire_open_mode,
7409 (unsigned int)unixmode ));
7410
7411 status = SMB_VFS_CREATE_FILE(
7412 conn, /* conn */
7413 req, /* req */
7414 0, /* root_dir_fid */
7415 smb_fname, /* fname */
7416 access_mask, /* access_mask */
7417 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7418 FILE_SHARE_DELETE),
7419 create_disp, /* create_disposition*/
7420 create_options, /* create_options */
7421 mod_unixmode, /* file_attributes */
7422 oplock_request, /* oplock_request */
7423 0, /* allocation_size */
7424 0, /* private_flags */
7425 NULL, /* sd */
7426 NULL, /* ea_list */
7427 &fsp, /* result */
7428 &info); /* pinfo */
7429
7430 if (!NT_STATUS_IS_OK(status)) {
7431 return status;
7432 }
7433
7434 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7435 extended_oplock_granted = True;
7436 }
7437
7438 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7439 extended_oplock_granted = True;
7440 }
7441
7442 info_level_return = SVAL(pdata,16);
7443
7444 /* Allocate the correct return size. */
7445
7446 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7447 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7448 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7449 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7450 } else {
7451 *pdata_return_size = 12;
7452 }
7453
7454 /* Realloc the data size */
7455 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7456 if (*ppdata == NULL) {
7457 close_file(req, fsp, ERROR_CLOSE);
7458 *pdata_return_size = 0;
7459 return NT_STATUS_NO_MEMORY;
7460 }
7461 pdata = *ppdata;
7462
7463 if (extended_oplock_granted) {
7464 if (flags & REQUEST_BATCH_OPLOCK) {
7465 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7466 } else {
7467 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7468 }
7469 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7470 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7471 } else {
7472 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7473 }
7474
7475 SSVAL(pdata,2,fsp->fnum);
7476 SIVAL(pdata,4,info); /* Was file created etc. */
7477
7478 switch (info_level_return) {
7479 case SMB_QUERY_FILE_UNIX_BASIC:
7480 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7481 SSVAL(pdata,10,0); /* padding. */
7482 store_file_unix_basic(conn, pdata + 12, fsp,
7483 &smb_fname->st);
7484 break;
7485 case SMB_QUERY_FILE_UNIX_INFO2:
7486 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7487 SSVAL(pdata,10,0); /* padding. */
7488 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7489 &smb_fname->st);
7490 break;
7491 default:
7492 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7493 SSVAL(pdata,10,0); /* padding. */
7494 break;
7495 }
7496 return NT_STATUS_OK;
7497}
7498
7499/****************************************************************************
7500 Delete a file with POSIX semantics.
7501****************************************************************************/
7502
7503static NTSTATUS smb_posix_unlink(connection_struct *conn,
7504 struct smb_request *req,
7505 const char *pdata,
7506 int total_data,
7507 struct smb_filename *smb_fname)
7508{
7509 NTSTATUS status = NT_STATUS_OK;
7510 files_struct *fsp = NULL;
7511 uint16 flags = 0;
7512 char del = 1;
7513 int info = 0;
7514 int create_options = 0;
7515 int i;
7516 struct share_mode_lock *lck = NULL;
7517
7518 if (total_data < 2) {
7519 return NT_STATUS_INVALID_PARAMETER;
7520 }
7521
7522 flags = SVAL(pdata,0);
7523
7524 if (!VALID_STAT(smb_fname->st)) {
7525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7526 }
7527
7528 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7529 !VALID_STAT_OF_DIR(smb_fname->st)) {
7530 return NT_STATUS_NOT_A_DIRECTORY;
7531 }
7532
7533 DEBUG(10,("smb_posix_unlink: %s %s\n",
7534 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7535 smb_fname_str_dbg(smb_fname)));
7536
7537 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7538 create_options |= FILE_DIRECTORY_FILE;
7539 }
7540
7541 status = SMB_VFS_CREATE_FILE(
7542 conn, /* conn */
7543 req, /* req */
7544 0, /* root_dir_fid */
7545 smb_fname, /* fname */
7546 DELETE_ACCESS, /* access_mask */
7547 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7548 FILE_SHARE_DELETE),
7549 FILE_OPEN, /* create_disposition*/
7550 create_options, /* create_options */
7551 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7552 0, /* oplock_request */
7553 0, /* allocation_size */
7554 0, /* private_flags */
7555 NULL, /* sd */
7556 NULL, /* ea_list */
7557 &fsp, /* result */
7558 &info); /* pinfo */
7559
7560 if (!NT_STATUS_IS_OK(status)) {
7561 return status;
7562 }
7563
7564 /*
7565 * Don't lie to client. If we can't really delete due to
7566 * non-POSIX opens return SHARING_VIOLATION.
7567 */
7568
7569 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7570 NULL);
7571 if (lck == NULL) {
7572 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7573 "lock for file %s\n", fsp_str_dbg(fsp)));
7574 close_file(req, fsp, NORMAL_CLOSE);
7575 return NT_STATUS_INVALID_PARAMETER;
7576 }
7577
7578 /*
7579 * See if others still have the file open. If this is the case, then
7580 * don't delete. If all opens are POSIX delete we can set the delete
7581 * on close disposition.
7582 */
7583 for (i=0; i<lck->num_share_modes; i++) {
7584 struct share_mode_entry *e = &lck->share_modes[i];
7585 if (is_valid_share_mode_entry(e)) {
7586 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7587 continue;
7588 }
7589 /* Fail with sharing violation. */
7590 close_file(req, fsp, NORMAL_CLOSE);
7591 TALLOC_FREE(lck);
7592 return NT_STATUS_SHARING_VIOLATION;
7593 }
7594 }
7595
7596 /*
7597 * Set the delete on close.
7598 */
7599 status = smb_set_file_disposition_info(conn,
7600 &del,
7601 1,
7602 fsp,
7603 smb_fname);
7604
7605 if (!NT_STATUS_IS_OK(status)) {
7606 close_file(req, fsp, NORMAL_CLOSE);
7607 TALLOC_FREE(lck);
7608 return status;
7609 }
7610 TALLOC_FREE(lck);
7611 return close_file(req, fsp, NORMAL_CLOSE);
7612}
7613
7614NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7615 struct smb_request *req,
7616 TALLOC_CTX *mem_ctx,
7617 uint16_t info_level,
7618 files_struct *fsp,
7619 struct smb_filename *smb_fname,
7620 char **ppdata, int total_data,
7621 int *ret_data_size)
7622{
7623 char *pdata = *ppdata;
7624 NTSTATUS status = NT_STATUS_OK;
7625 int data_return_size = 0;
7626
7627 *ret_data_size = 0;
7628
7629 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7630 return NT_STATUS_INVALID_LEVEL;
7631 }
7632
7633 if (!CAN_WRITE(conn)) {
7634 /* Allow POSIX opens. The open path will deny
7635 * any non-readonly opens. */
7636 if (info_level != SMB_POSIX_PATH_OPEN) {
7637 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7638 }
7639 }
7640
7641 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7642 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7643 fsp ? fsp->fnum : -1, info_level, total_data));
7644
7645 switch (info_level) {
7646
7647 case SMB_INFO_STANDARD:
7648 {
7649 status = smb_set_info_standard(conn,
7650 pdata,
7651 total_data,
7652 fsp,
7653 smb_fname);
7654 break;
7655 }
7656
7657 case SMB_INFO_SET_EA:
7658 {
7659 status = smb_info_set_ea(conn,
7660 pdata,
7661 total_data,
7662 fsp,
7663 smb_fname);
7664 break;
7665 }
7666
7667 case SMB_SET_FILE_BASIC_INFO:
7668 case SMB_FILE_BASIC_INFORMATION:
7669 {
7670 status = smb_set_file_basic_info(conn,
7671 pdata,
7672 total_data,
7673 fsp,
7674 smb_fname);
7675 break;
7676 }
7677
7678 case SMB_FILE_ALLOCATION_INFORMATION:
7679 case SMB_SET_FILE_ALLOCATION_INFO:
7680 {
7681 status = smb_set_file_allocation_info(conn, req,
7682 pdata,
7683 total_data,
7684 fsp,
7685 smb_fname);
7686 break;
7687 }
7688
7689 case SMB_FILE_END_OF_FILE_INFORMATION:
7690 case SMB_SET_FILE_END_OF_FILE_INFO:
7691 {
7692 /*
7693 * XP/Win7 both fail after the createfile with
7694 * SMB_SET_FILE_END_OF_FILE_INFO but not
7695 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7696 * The level is known here, so pass it down
7697 * appropriately.
7698 */
7699 bool should_fail =
7700 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7701
7702 status = smb_set_file_end_of_file_info(conn, req,
7703 pdata,
7704 total_data,
7705 fsp,
7706 smb_fname,
7707 should_fail);
7708 break;
7709 }
7710
7711 case SMB_FILE_DISPOSITION_INFORMATION:
7712 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7713 {
7714#if 0
7715 /* JRA - We used to just ignore this on a path ?
7716 * Shouldn't this be invalid level on a pathname
7717 * based call ?
7718 */
7719 if (tran_call != TRANSACT2_SETFILEINFO) {
7720 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7721 }
7722#endif
7723 status = smb_set_file_disposition_info(conn,
7724 pdata,
7725 total_data,
7726 fsp,
7727 smb_fname);
7728 break;
7729 }
7730
7731 case SMB_FILE_POSITION_INFORMATION:
7732 {
7733 status = smb_file_position_information(conn,
7734 pdata,
7735 total_data,
7736 fsp);
7737 break;
7738 }
7739
7740 case SMB_FILE_FULL_EA_INFORMATION:
7741 {
7742 status = smb_set_file_full_ea_info(conn,
7743 pdata,
7744 total_data,
7745 fsp);
7746 break;
7747 }
7748
7749 /* From tridge Samba4 :
7750 * MODE_INFORMATION in setfileinfo (I have no
7751 * idea what "mode information" on a file is - it takes a value of 0,
7752 * 2, 4 or 6. What could it be?).
7753 */
7754
7755 case SMB_FILE_MODE_INFORMATION:
7756 {
7757 status = smb_file_mode_information(conn,
7758 pdata,
7759 total_data);
7760 break;
7761 }
7762
7763 /*
7764 * CIFS UNIX extensions.
7765 */
7766
7767 case SMB_SET_FILE_UNIX_BASIC:
7768 {
7769 status = smb_set_file_unix_basic(conn, req,
7770 pdata,
7771 total_data,
7772 fsp,
7773 smb_fname);
7774 break;
7775 }
7776
7777 case SMB_SET_FILE_UNIX_INFO2:
7778 {
7779 status = smb_set_file_unix_info2(conn, req,
7780 pdata,
7781 total_data,
7782 fsp,
7783 smb_fname);
7784 break;
7785 }
7786
7787 case SMB_SET_FILE_UNIX_LINK:
7788 {
7789 if (fsp) {
7790 /* We must have a pathname for this. */
7791 return NT_STATUS_INVALID_LEVEL;
7792 }
7793 status = smb_set_file_unix_link(conn, req, pdata,
7794 total_data, smb_fname);
7795 break;
7796 }
7797
7798 case SMB_SET_FILE_UNIX_HLINK:
7799 {
7800 if (fsp) {
7801 /* We must have a pathname for this. */
7802 return NT_STATUS_INVALID_LEVEL;
7803 }
7804 status = smb_set_file_unix_hlink(conn, req,
7805 pdata, total_data,
7806 smb_fname);
7807 break;
7808 }
7809
7810 case SMB_FILE_RENAME_INFORMATION:
7811 {
7812 status = smb_file_rename_information(conn, req,
7813 pdata, total_data,
7814 fsp, smb_fname);
7815 break;
7816 }
7817
7818 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7819 {
7820 /* SMB2 rename information. */
7821 status = smb2_file_rename_information(conn, req,
7822 pdata, total_data,
7823 fsp, smb_fname);
7824 break;
7825 }
7826
7827 case SMB_FILE_LINK_INFORMATION:
7828 {
7829 status = smb_file_link_information(conn, req,
7830 pdata, total_data,
7831 fsp, smb_fname);
7832 break;
7833 }
7834
7835#if defined(HAVE_POSIX_ACLS)
7836 case SMB_SET_POSIX_ACL:
7837 {
7838 status = smb_set_posix_acl(conn,
7839 pdata,
7840 total_data,
7841 fsp,
7842 smb_fname);
7843 break;
7844 }
7845#endif
7846
7847 case SMB_SET_POSIX_LOCK:
7848 {
7849 if (!fsp) {
7850 return NT_STATUS_INVALID_LEVEL;
7851 }
7852 status = smb_set_posix_lock(conn, req,
7853 pdata, total_data, fsp);
7854 break;
7855 }
7856
7857 case SMB_POSIX_PATH_OPEN:
7858 {
7859 if (fsp) {
7860 /* We must have a pathname for this. */
7861 return NT_STATUS_INVALID_LEVEL;
7862 }
7863
7864 status = smb_posix_open(conn, req,
7865 ppdata,
7866 total_data,
7867 smb_fname,
7868 &data_return_size);
7869 break;
7870 }
7871
7872 case SMB_POSIX_PATH_UNLINK:
7873 {
7874 if (fsp) {
7875 /* We must have a pathname for this. */
7876 return NT_STATUS_INVALID_LEVEL;
7877 }
7878
7879 status = smb_posix_unlink(conn, req,
7880 pdata,
7881 total_data,
7882 smb_fname);
7883 break;
7884 }
7885
7886 default:
7887 return NT_STATUS_INVALID_LEVEL;
7888 }
7889
7890 if (!NT_STATUS_IS_OK(status)) {
7891 return status;
7892 }
7893
7894 *ret_data_size = data_return_size;
7895 return NT_STATUS_OK;
7896}
7897
7898/****************************************************************************
7899 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7900****************************************************************************/
7901
7902static void call_trans2setfilepathinfo(connection_struct *conn,
7903 struct smb_request *req,
7904 unsigned int tran_call,
7905 char **pparams, int total_params,
7906 char **ppdata, int total_data,
7907 unsigned int max_data_bytes)
7908{
7909 char *params = *pparams;
7910 char *pdata = *ppdata;
7911 uint16 info_level;
7912 struct smb_filename *smb_fname = NULL;
7913 files_struct *fsp = NULL;
7914 NTSTATUS status = NT_STATUS_OK;
7915 int data_return_size = 0;
7916
7917 if (!params) {
7918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7919 return;
7920 }
7921
7922 if (tran_call == TRANSACT2_SETFILEINFO) {
7923 if (total_params < 4) {
7924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7925 return;
7926 }
7927
7928 fsp = file_fsp(req, SVAL(params,0));
7929 /* Basic check for non-null fsp. */
7930 if (!check_fsp_open(conn, req, fsp)) {
7931 return;
7932 }
7933 info_level = SVAL(params,2);
7934
7935 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7936 &smb_fname);
7937 if (!NT_STATUS_IS_OK(status)) {
7938 reply_nterror(req, status);
7939 return;
7940 }
7941
7942 if(fsp->fh->fd == -1) {
7943 /*
7944 * This is actually a SETFILEINFO on a directory
7945 * handle (returned from an NT SMB). NT5.0 seems
7946 * to do this call. JRA.
7947 */
7948 if (INFO_LEVEL_IS_UNIX(info_level)) {
7949 /* Always do lstat for UNIX calls. */
7950 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7951 DEBUG(3,("call_trans2setfilepathinfo: "
7952 "SMB_VFS_LSTAT of %s failed "
7953 "(%s)\n",
7954 smb_fname_str_dbg(smb_fname),
7955 strerror(errno)));
7956 reply_nterror(req, map_nt_error_from_unix(errno));
7957 return;
7958 }
7959 } else {
7960 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7961 DEBUG(3,("call_trans2setfilepathinfo: "
7962 "fileinfo of %s failed (%s)\n",
7963 smb_fname_str_dbg(smb_fname),
7964 strerror(errno)));
7965 reply_nterror(req, map_nt_error_from_unix(errno));
7966 return;
7967 }
7968 }
7969 } else if (fsp->print_file) {
7970 /*
7971 * Doing a DELETE_ON_CLOSE should cancel a print job.
7972 */
7973 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7974 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7975
7976 DEBUG(3,("call_trans2setfilepathinfo: "
7977 "Cancelling print job (%s)\n",
7978 fsp_str_dbg(fsp)));
7979
7980 SSVAL(params,0,0);
7981 send_trans2_replies(conn, req, params, 2,
7982 *ppdata, 0,
7983 max_data_bytes);
7984 return;
7985 } else {
7986 reply_nterror(req,
7987 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7988 return;
7989 }
7990 } else {
7991 /*
7992 * Original code - this is an open file.
7993 */
7994 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7995 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7996 "of fnum %d failed (%s)\n", fsp->fnum,
7997 strerror(errno)));
7998 reply_nterror(req, map_nt_error_from_unix(errno));
7999 return;
8000 }
8001 }
8002 } else {
8003 char *fname = NULL;
8004 uint32_t ucf_flags = 0;
8005
8006 /* set path info */
8007 if (total_params < 7) {
8008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8009 return;
8010 }
8011
8012 info_level = SVAL(params,0);
8013 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8014 total_params - 6, STR_TERMINATE,
8015 &status);
8016 if (!NT_STATUS_IS_OK(status)) {
8017 reply_nterror(req, status);
8018 return;
8019 }
8020
8021 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8022 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8023 info_level == SMB_FILE_RENAME_INFORMATION ||
8024 info_level == SMB_POSIX_PATH_UNLINK) {
8025 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8026 }
8027
8028 status = filename_convert(req, conn,
8029 req->flags2 & FLAGS2_DFS_PATHNAMES,
8030 fname,
8031 ucf_flags,
8032 NULL,
8033 &smb_fname);
8034 if (!NT_STATUS_IS_OK(status)) {
8035 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8036 reply_botherror(req,
8037 NT_STATUS_PATH_NOT_COVERED,
8038 ERRSRV, ERRbadpath);
8039 return;
8040 }
8041 reply_nterror(req, status);
8042 return;
8043 }
8044
8045 if (INFO_LEVEL_IS_UNIX(info_level)) {
8046 /*
8047 * For CIFS UNIX extensions the target name may not exist.
8048 */
8049
8050 /* Always do lstat for UNIX calls. */
8051 SMB_VFS_LSTAT(conn, smb_fname);
8052
8053 } else if (!VALID_STAT(smb_fname->st) &&
8054 SMB_VFS_STAT(conn, smb_fname)) {
8055 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8056 "%s failed (%s)\n",
8057 smb_fname_str_dbg(smb_fname),
8058 strerror(errno)));
8059 reply_nterror(req, map_nt_error_from_unix(errno));
8060 return;
8061 }
8062 }
8063
8064 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8065 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8066 fsp ? fsp->fnum : -1, info_level,total_data));
8067
8068 /* Realloc the parameter size */
8069 *pparams = (char *)SMB_REALLOC(*pparams,2);
8070 if (*pparams == NULL) {
8071 reply_nterror(req, NT_STATUS_NO_MEMORY);
8072 return;
8073 }
8074 params = *pparams;
8075
8076 SSVAL(params,0,0);
8077
8078 status = smbd_do_setfilepathinfo(conn, req, req,
8079 info_level,
8080 fsp,
8081 smb_fname,
8082 ppdata, total_data,
8083 &data_return_size);
8084 if (!NT_STATUS_IS_OK(status)) {
8085 if (open_was_deferred(req->mid)) {
8086 /* We have re-scheduled this call. */
8087 return;
8088 }
8089 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8090 /* We have re-scheduled this call. */
8091 return;
8092 }
8093 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8094 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8095 ERRSRV, ERRbadpath);
8096 return;
8097 }
8098 if (info_level == SMB_POSIX_PATH_OPEN) {
8099 reply_openerror(req, status);
8100 return;
8101 }
8102
8103 reply_nterror(req, status);
8104 return;
8105 }
8106
8107 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8108 max_data_bytes);
8109
8110 return;
8111}
8112
8113/****************************************************************************
8114 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8115****************************************************************************/
8116
8117static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8118 char **pparams, int total_params,
8119 char **ppdata, int total_data,
8120 unsigned int max_data_bytes)
8121{
8122 struct smb_filename *smb_dname = NULL;
8123 char *params = *pparams;
8124 char *pdata = *ppdata;
8125 char *directory = NULL;
8126 NTSTATUS status = NT_STATUS_OK;
8127 struct ea_list *ea_list = NULL;
8128 TALLOC_CTX *ctx = talloc_tos();
8129
8130 if (!CAN_WRITE(conn)) {
8131 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8132 return;
8133 }
8134
8135 if (total_params < 5) {
8136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8137 return;
8138 }
8139
8140 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8141 total_params - 4, STR_TERMINATE,
8142 &status);
8143 if (!NT_STATUS_IS_OK(status)) {
8144 reply_nterror(req, status);
8145 return;
8146 }
8147
8148 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8149
8150 status = filename_convert(ctx,
8151 conn,
8152 req->flags2 & FLAGS2_DFS_PATHNAMES,
8153 directory,
8154 0,
8155 NULL,
8156 &smb_dname);
8157
8158 if (!NT_STATUS_IS_OK(status)) {
8159 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8160 reply_botherror(req,
8161 NT_STATUS_PATH_NOT_COVERED,
8162 ERRSRV, ERRbadpath);
8163 return;
8164 }
8165 reply_nterror(req, status);
8166 return;
8167 }
8168
8169 /*
8170 * OS/2 workplace shell seems to send SET_EA requests of "null"
8171 * length (4 bytes containing IVAL 4).
8172 * They seem to have no effect. Bug #3212. JRA.
8173 */
8174
8175 if (total_data && (total_data != 4)) {
8176 /* Any data in this call is an EA list. */
8177 if (total_data < 10) {
8178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8179 goto out;
8180 }
8181
8182 if (IVAL(pdata,0) > total_data) {
8183 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8184 IVAL(pdata,0), (unsigned int)total_data));
8185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8186 goto out;
8187 }
8188
8189 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8190 total_data - 4);
8191 if (!ea_list) {
8192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8193 goto out;
8194 }
8195
8196 if (!lp_ea_support(SNUM(conn))) {
8197 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8198 goto out;
8199 }
8200 }
8201 /* If total_data == 4 Windows doesn't care what values
8202 * are placed in that field, it just ignores them.
8203 * The System i QNTC IBM SMB client puts bad values here,
8204 * so ignore them. */
8205
8206 status = create_directory(conn, req, smb_dname);
8207
8208 if (!NT_STATUS_IS_OK(status)) {
8209 reply_nterror(req, status);
8210 goto out;
8211 }
8212
8213 /* Try and set any given EA. */
8214 if (ea_list) {
8215 status = set_ea(conn, NULL, smb_dname, ea_list);
8216 if (!NT_STATUS_IS_OK(status)) {
8217 reply_nterror(req, status);
8218 goto out;
8219 }
8220 }
8221
8222 /* Realloc the parameter and data sizes */
8223 *pparams = (char *)SMB_REALLOC(*pparams,2);
8224 if(*pparams == NULL) {
8225 reply_nterror(req, NT_STATUS_NO_MEMORY);
8226 goto out;
8227 }
8228 params = *pparams;
8229
8230 SSVAL(params,0,0);
8231
8232 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8233
8234 out:
8235 TALLOC_FREE(smb_dname);
8236 return;
8237}
8238
8239/****************************************************************************
8240 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8241 We don't actually do this - we just send a null response.
8242****************************************************************************/
8243
8244static void call_trans2findnotifyfirst(connection_struct *conn,
8245 struct smb_request *req,
8246 char **pparams, int total_params,
8247 char **ppdata, int total_data,
8248 unsigned int max_data_bytes)
8249{
8250 char *params = *pparams;
8251 uint16 info_level;
8252
8253 if (total_params < 6) {
8254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8255 return;
8256 }
8257
8258 info_level = SVAL(params,4);
8259 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8260
8261 switch (info_level) {
8262 case 1:
8263 case 2:
8264 break;
8265 default:
8266 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8267 return;
8268 }
8269
8270 /* Realloc the parameter and data sizes */
8271 *pparams = (char *)SMB_REALLOC(*pparams,6);
8272 if (*pparams == NULL) {
8273 reply_nterror(req, NT_STATUS_NO_MEMORY);
8274 return;
8275 }
8276 params = *pparams;
8277
8278 SSVAL(params,0,fnf_handle);
8279 SSVAL(params,2,0); /* No changes */
8280 SSVAL(params,4,0); /* No EA errors */
8281
8282 fnf_handle++;
8283
8284 if(fnf_handle == 0)
8285 fnf_handle = 257;
8286
8287 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8288
8289 return;
8290}
8291
8292/****************************************************************************
8293 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8294 changes). Currently this does nothing.
8295****************************************************************************/
8296
8297static void call_trans2findnotifynext(connection_struct *conn,
8298 struct smb_request *req,
8299 char **pparams, int total_params,
8300 char **ppdata, int total_data,
8301 unsigned int max_data_bytes)
8302{
8303 char *params = *pparams;
8304
8305 DEBUG(3,("call_trans2findnotifynext\n"));
8306
8307 /* Realloc the parameter and data sizes */
8308 *pparams = (char *)SMB_REALLOC(*pparams,4);
8309 if (*pparams == NULL) {
8310 reply_nterror(req, NT_STATUS_NO_MEMORY);
8311 return;
8312 }
8313 params = *pparams;
8314
8315 SSVAL(params,0,0); /* No changes */
8316 SSVAL(params,2,0); /* No EA errors */
8317
8318 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8319
8320 return;
8321}
8322
8323/****************************************************************************
8324 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8325****************************************************************************/
8326
8327static void call_trans2getdfsreferral(connection_struct *conn,
8328 struct smb_request *req,
8329 char **pparams, int total_params,
8330 char **ppdata, int total_data,
8331 unsigned int max_data_bytes)
8332{
8333 char *params = *pparams;
8334 char *pathname = NULL;
8335 int reply_size = 0;
8336 int max_referral_level;
8337 NTSTATUS status = NT_STATUS_OK;
8338 TALLOC_CTX *ctx = talloc_tos();
8339
8340 DEBUG(10,("call_trans2getdfsreferral\n"));
8341
8342 if (total_params < 3) {
8343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8344 return;
8345 }
8346
8347 max_referral_level = SVAL(params,0);
8348
8349 if(!lp_host_msdfs()) {
8350 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8351 return;
8352 }
8353
8354 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8355 total_params - 2, STR_TERMINATE);
8356 if (!pathname) {
8357 reply_nterror(req, NT_STATUS_NOT_FOUND);
8358 return;
8359 }
8360 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8361 ppdata,&status)) < 0) {
8362 reply_nterror(req, status);
8363 return;
8364 }
8365
8366 SSVAL(req->inbuf, smb_flg2,
8367 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8368 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8369
8370 return;
8371}
8372
8373#define LMCAT_SPL 0x53
8374#define LMFUNC_GETJOBID 0x60
8375
8376/****************************************************************************
8377 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8378****************************************************************************/
8379
8380static void call_trans2ioctl(connection_struct *conn,
8381 struct smb_request *req,
8382 char **pparams, int total_params,
8383 char **ppdata, int total_data,
8384 unsigned int max_data_bytes)
8385{
8386 char *pdata = *ppdata;
8387 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8388
8389 /* check for an invalid fid before proceeding */
8390
8391 if (!fsp) {
8392 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8393 return;
8394 }
8395
8396 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8397 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8398 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8399 if (*ppdata == NULL) {
8400 reply_nterror(req, NT_STATUS_NO_MEMORY);
8401 return;
8402 }
8403 pdata = *ppdata;
8404
8405 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8406 CAN ACCEPT THIS IN UNICODE. JRA. */
8407
8408 /* Job number */
8409 if (fsp->print_file) {
8410 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8411 } else {
8412 SSVAL(pdata, 0, 0);
8413 }
8414 srvstr_push(pdata, req->flags2, pdata + 2,
8415 global_myname(), 15,
8416 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8417 srvstr_push(pdata, req->flags2, pdata+18,
8418 lp_servicename(SNUM(conn)), 13,
8419 STR_ASCII|STR_TERMINATE); /* Service name */
8420 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8421 max_data_bytes);
8422 return;
8423 }
8424
8425 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8426 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8427}
8428
8429/****************************************************************************
8430 Reply to a SMBfindclose (stop trans2 directory search).
8431****************************************************************************/
8432
8433void reply_findclose(struct smb_request *req)
8434{
8435 int dptr_num;
8436 struct smbd_server_connection *sconn = req->sconn;
8437
8438 START_PROFILE(SMBfindclose);
8439
8440 if (req->wct < 1) {
8441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8442 END_PROFILE(SMBfindclose);
8443 return;
8444 }
8445
8446 dptr_num = SVALS(req->vwv+0, 0);
8447
8448 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8449
8450 dptr_close(sconn, &dptr_num);
8451
8452 reply_outbuf(req, 0, 0);
8453
8454 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8455
8456 END_PROFILE(SMBfindclose);
8457 return;
8458}
8459
8460/****************************************************************************
8461 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8462****************************************************************************/
8463
8464void reply_findnclose(struct smb_request *req)
8465{
8466 int dptr_num;
8467
8468 START_PROFILE(SMBfindnclose);
8469
8470 if (req->wct < 1) {
8471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8472 END_PROFILE(SMBfindnclose);
8473 return;
8474 }
8475
8476 dptr_num = SVAL(req->vwv+0, 0);
8477
8478 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8479
8480 /* We never give out valid handles for a
8481 findnotifyfirst - so any dptr_num is ok here.
8482 Just ignore it. */
8483
8484 reply_outbuf(req, 0, 0);
8485
8486 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8487
8488 END_PROFILE(SMBfindnclose);
8489 return;
8490}
8491
8492static void handle_trans2(connection_struct *conn, struct smb_request *req,
8493 struct trans_state *state)
8494{
8495 if (get_Protocol() >= PROTOCOL_NT1) {
8496 req->flags2 |= 0x40; /* IS_LONG_NAME */
8497 SSVAL(req->inbuf,smb_flg2,req->flags2);
8498 }
8499
8500 if (conn->encrypt_level == Required && !req->encrypted) {
8501 if (state->call != TRANSACT2_QFSINFO &&
8502 state->call != TRANSACT2_SETFSINFO) {
8503 DEBUG(0,("handle_trans2: encryption required "
8504 "with call 0x%x\n",
8505 (unsigned int)state->call));
8506 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8507 return;
8508 }
8509 }
8510
8511 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8512
8513 /* Now we must call the relevant TRANS2 function */
8514 switch(state->call) {
8515 case TRANSACT2_OPEN:
8516 {
8517 START_PROFILE(Trans2_open);
8518 call_trans2open(conn, req,
8519 &state->param, state->total_param,
8520 &state->data, state->total_data,
8521 state->max_data_return);
8522 END_PROFILE(Trans2_open);
8523 break;
8524 }
8525
8526 case TRANSACT2_FINDFIRST:
8527 {
8528 START_PROFILE(Trans2_findfirst);
8529 call_trans2findfirst(conn, req,
8530 &state->param, state->total_param,
8531 &state->data, state->total_data,
8532 state->max_data_return);
8533 END_PROFILE(Trans2_findfirst);
8534 break;
8535 }
8536
8537 case TRANSACT2_FINDNEXT:
8538 {
8539 START_PROFILE(Trans2_findnext);
8540 call_trans2findnext(conn, req,
8541 &state->param, state->total_param,
8542 &state->data, state->total_data,
8543 state->max_data_return);
8544 END_PROFILE(Trans2_findnext);
8545 break;
8546 }
8547
8548 case TRANSACT2_QFSINFO:
8549 {
8550 START_PROFILE(Trans2_qfsinfo);
8551 call_trans2qfsinfo(conn, req,
8552 &state->param, state->total_param,
8553 &state->data, state->total_data,
8554 state->max_data_return);
8555 END_PROFILE(Trans2_qfsinfo);
8556 break;
8557 }
8558
8559 case TRANSACT2_SETFSINFO:
8560 {
8561 START_PROFILE(Trans2_setfsinfo);
8562 call_trans2setfsinfo(conn, req,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_setfsinfo);
8567 break;
8568 }
8569
8570 case TRANSACT2_QPATHINFO:
8571 case TRANSACT2_QFILEINFO:
8572 {
8573 START_PROFILE(Trans2_qpathinfo);
8574 call_trans2qfilepathinfo(conn, req, state->call,
8575 &state->param, state->total_param,
8576 &state->data, state->total_data,
8577 state->max_data_return);
8578 END_PROFILE(Trans2_qpathinfo);
8579 break;
8580 }
8581
8582 case TRANSACT2_SETPATHINFO:
8583 case TRANSACT2_SETFILEINFO:
8584 {
8585 START_PROFILE(Trans2_setpathinfo);
8586 call_trans2setfilepathinfo(conn, req, state->call,
8587 &state->param, state->total_param,
8588 &state->data, state->total_data,
8589 state->max_data_return);
8590 END_PROFILE(Trans2_setpathinfo);
8591 break;
8592 }
8593
8594 case TRANSACT2_FINDNOTIFYFIRST:
8595 {
8596 START_PROFILE(Trans2_findnotifyfirst);
8597 call_trans2findnotifyfirst(conn, req,
8598 &state->param, state->total_param,
8599 &state->data, state->total_data,
8600 state->max_data_return);
8601 END_PROFILE(Trans2_findnotifyfirst);
8602 break;
8603 }
8604
8605 case TRANSACT2_FINDNOTIFYNEXT:
8606 {
8607 START_PROFILE(Trans2_findnotifynext);
8608 call_trans2findnotifynext(conn, req,
8609 &state->param, state->total_param,
8610 &state->data, state->total_data,
8611 state->max_data_return);
8612 END_PROFILE(Trans2_findnotifynext);
8613 break;
8614 }
8615
8616 case TRANSACT2_MKDIR:
8617 {
8618 START_PROFILE(Trans2_mkdir);
8619 call_trans2mkdir(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_mkdir);
8624 break;
8625 }
8626
8627 case TRANSACT2_GET_DFS_REFERRAL:
8628 {
8629 START_PROFILE(Trans2_get_dfs_referral);
8630 call_trans2getdfsreferral(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_get_dfs_referral);
8635 break;
8636 }
8637
8638 case TRANSACT2_IOCTL:
8639 {
8640 START_PROFILE(Trans2_ioctl);
8641 call_trans2ioctl(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_ioctl);
8646 break;
8647 }
8648
8649 default:
8650 /* Error in request */
8651 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8652 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8653 }
8654}
8655
8656/****************************************************************************
8657 Reply to a SMBtrans2.
8658 ****************************************************************************/
8659
8660void reply_trans2(struct smb_request *req)
8661{
8662 connection_struct *conn = req->conn;
8663 unsigned int dsoff;
8664 unsigned int dscnt;
8665 unsigned int psoff;
8666 unsigned int pscnt;
8667 unsigned int tran_call;
8668 struct trans_state *state;
8669 NTSTATUS result;
8670
8671 START_PROFILE(SMBtrans2);
8672
8673 if (req->wct < 14) {
8674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8675 END_PROFILE(SMBtrans2);
8676 return;
8677 }
8678
8679 dsoff = SVAL(req->vwv+12, 0);
8680 dscnt = SVAL(req->vwv+11, 0);
8681 psoff = SVAL(req->vwv+10, 0);
8682 pscnt = SVAL(req->vwv+9, 0);
8683 tran_call = SVAL(req->vwv+14, 0);
8684
8685 result = allow_new_trans(conn->pending_trans, req->mid);
8686 if (!NT_STATUS_IS_OK(result)) {
8687 DEBUG(2, ("Got invalid trans2 request: %s\n",
8688 nt_errstr(result)));
8689 reply_nterror(req, result);
8690 END_PROFILE(SMBtrans2);
8691 return;
8692 }
8693
8694 if (IS_IPC(conn)) {
8695 switch (tran_call) {
8696 /* List the allowed trans2 calls on IPC$ */
8697 case TRANSACT2_OPEN:
8698 case TRANSACT2_GET_DFS_REFERRAL:
8699 case TRANSACT2_QFILEINFO:
8700 case TRANSACT2_QFSINFO:
8701 case TRANSACT2_SETFSINFO:
8702 break;
8703 default:
8704 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8705 END_PROFILE(SMBtrans2);
8706 return;
8707 }
8708 }
8709
8710 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8711 DEBUG(0, ("talloc failed\n"));
8712 reply_nterror(req, NT_STATUS_NO_MEMORY);
8713 END_PROFILE(SMBtrans2);
8714 return;
8715 }
8716
8717 state->cmd = SMBtrans2;
8718
8719 state->mid = req->mid;
8720 state->vuid = req->vuid;
8721 state->setup_count = SVAL(req->vwv+13, 0);
8722 state->setup = NULL;
8723 state->total_param = SVAL(req->vwv+0, 0);
8724 state->param = NULL;
8725 state->total_data = SVAL(req->vwv+1, 0);
8726 state->data = NULL;
8727 state->max_param_return = SVAL(req->vwv+2, 0);
8728 state->max_data_return = SVAL(req->vwv+3, 0);
8729 state->max_setup_return = SVAL(req->vwv+4, 0);
8730 state->close_on_completion = BITSETW(req->vwv+5, 0);
8731 state->one_way = BITSETW(req->vwv+5, 1);
8732
8733 state->call = tran_call;
8734
8735 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8736 is so as a sanity check */
8737 if (state->setup_count != 1) {
8738 /*
8739 * Need to have rc=0 for ioctl to get job id for OS/2.
8740 * Network printing will fail if function is not successful.
8741 * Similar function in reply.c will be used if protocol
8742 * is LANMAN1.0 instead of LM1.2X002.
8743 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8744 * outbuf doesn't have to be set(only job id is used).
8745 */
8746 if ( (state->setup_count == 4)
8747 && (tran_call == TRANSACT2_IOCTL)
8748 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8749 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8750 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8751 } else {
8752 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8753 DEBUG(2,("Transaction is %d\n",tran_call));
8754 TALLOC_FREE(state);
8755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8756 END_PROFILE(SMBtrans2);
8757 return;
8758 }
8759 }
8760
8761 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8762 goto bad_param;
8763
8764 if (state->total_data) {
8765
8766 if (trans_oob(state->total_data, 0, dscnt)
8767 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8768 goto bad_param;
8769 }
8770
8771 /* Can't use talloc here, the core routines do realloc on the
8772 * params and data. */
8773 state->data = (char *)SMB_MALLOC(state->total_data);
8774 if (state->data == NULL) {
8775 DEBUG(0,("reply_trans2: data malloc fail for %u "
8776 "bytes !\n", (unsigned int)state->total_data));
8777 TALLOC_FREE(state);
8778 reply_nterror(req, NT_STATUS_NO_MEMORY);
8779 END_PROFILE(SMBtrans2);
8780 return;
8781 }
8782
8783 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8784 }
8785
8786 if (state->total_param) {
8787
8788 if (trans_oob(state->total_param, 0, pscnt)
8789 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8790 goto bad_param;
8791 }
8792
8793 /* Can't use talloc here, the core routines do realloc on the
8794 * params and data. */
8795 state->param = (char *)SMB_MALLOC(state->total_param);
8796 if (state->param == NULL) {
8797 DEBUG(0,("reply_trans: param malloc fail for %u "
8798 "bytes !\n", (unsigned int)state->total_param));
8799 SAFE_FREE(state->data);
8800 TALLOC_FREE(state);
8801 reply_nterror(req, NT_STATUS_NO_MEMORY);
8802 END_PROFILE(SMBtrans2);
8803 return;
8804 }
8805
8806 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8807 }
8808
8809 state->received_data = dscnt;
8810 state->received_param = pscnt;
8811
8812 if ((state->received_param == state->total_param) &&
8813 (state->received_data == state->total_data)) {
8814
8815 handle_trans2(conn, req, state);
8816
8817 SAFE_FREE(state->data);
8818 SAFE_FREE(state->param);
8819 TALLOC_FREE(state);
8820 END_PROFILE(SMBtrans2);
8821 return;
8822 }
8823
8824 DLIST_ADD(conn->pending_trans, state);
8825
8826 /* We need to send an interim response then receive the rest
8827 of the parameter/data bytes */
8828 reply_outbuf(req, 0, 0);
8829 show_msg((char *)req->outbuf);
8830 END_PROFILE(SMBtrans2);
8831 return;
8832
8833 bad_param:
8834
8835 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8836 SAFE_FREE(state->data);
8837 SAFE_FREE(state->param);
8838 TALLOC_FREE(state);
8839 END_PROFILE(SMBtrans2);
8840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8841}
8842
8843
8844/****************************************************************************
8845 Reply to a SMBtranss2
8846 ****************************************************************************/
8847
8848void reply_transs2(struct smb_request *req)
8849{
8850 connection_struct *conn = req->conn;
8851 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8852 struct trans_state *state;
8853
8854 START_PROFILE(SMBtranss2);
8855
8856 show_msg((char *)req->inbuf);
8857
8858 /* Windows clients expect all replies to
8859 a transact secondary (SMBtranss2 0x33)
8860 to have a command code of transact
8861 (SMBtrans2 0x32). See bug #8989
8862 and also [MS-CIFS] section 2.2.4.47.2
8863 for details.
8864 */
8865 req->cmd = SMBtrans2;
8866
8867 if (req->wct < 8) {
8868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8869 END_PROFILE(SMBtranss2);
8870 return;
8871 }
8872
8873 for (state = conn->pending_trans; state != NULL;
8874 state = state->next) {
8875 if (state->mid == req->mid) {
8876 break;
8877 }
8878 }
8879
8880 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8882 END_PROFILE(SMBtranss2);
8883 return;
8884 }
8885
8886 /* Revise state->total_param and state->total_data in case they have
8887 changed downwards */
8888
8889 if (SVAL(req->vwv+0, 0) < state->total_param)
8890 state->total_param = SVAL(req->vwv+0, 0);
8891 if (SVAL(req->vwv+1, 0) < state->total_data)
8892 state->total_data = SVAL(req->vwv+1, 0);
8893
8894 pcnt = SVAL(req->vwv+2, 0);
8895 poff = SVAL(req->vwv+3, 0);
8896 pdisp = SVAL(req->vwv+4, 0);
8897
8898 dcnt = SVAL(req->vwv+5, 0);
8899 doff = SVAL(req->vwv+6, 0);
8900 ddisp = SVAL(req->vwv+7, 0);
8901
8902 state->received_param += pcnt;
8903 state->received_data += dcnt;
8904
8905 if ((state->received_data > state->total_data) ||
8906 (state->received_param > state->total_param))
8907 goto bad_param;
8908
8909 if (pcnt) {
8910 if (trans_oob(state->total_param, pdisp, pcnt)
8911 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8912 goto bad_param;
8913 }
8914 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8915 }
8916
8917 if (dcnt) {
8918 if (trans_oob(state->total_data, ddisp, dcnt)
8919 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8920 goto bad_param;
8921 }
8922 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8923 }
8924
8925 if ((state->received_param < state->total_param) ||
8926 (state->received_data < state->total_data)) {
8927 END_PROFILE(SMBtranss2);
8928 return;
8929 }
8930
8931 handle_trans2(conn, req, state);
8932
8933 DLIST_REMOVE(conn->pending_trans, state);
8934 SAFE_FREE(state->data);
8935 SAFE_FREE(state->param);
8936 TALLOC_FREE(state);
8937
8938 END_PROFILE(SMBtranss2);
8939 return;
8940
8941 bad_param:
8942
8943 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8944 DLIST_REMOVE(conn->pending_trans, state);
8945 SAFE_FREE(state->data);
8946 SAFE_FREE(state->param);
8947 TALLOC_FREE(state);
8948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8949 END_PROFILE(SMBtranss2);
8950 return;
8951}
Note: See TracBrowser for help on using the repository browser.