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

Last change on this file since 790 was 790, checked in by Silvan Scherrer, 12 years ago

Samba Server 3.3: fix for ticket #165

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