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

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

Samba Server: updated trunk to 3.6.0

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