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

Last change on this file since 302 was 222, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 branch to 3.3.2

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