source: branches/samba-3.3.x/source/smbd/trans2.c@ 715

Last change on this file since 715 was 411, checked in by Herwig Bauernfeind, 15 years ago

Update Samba 3.3.x to 3.3.11

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