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

Last change on this file since 456 was 454, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: merged changes from 3.3

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