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

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

Update Samba 3.3 to 3.3.10 (source)

File size: 217.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#ifdef __OS2__
4964 /* YD ticket#60, the file is opened, we cannot write to it,
4965 * so we can return immediately (see above for more comments).
4966 */
4967 else {
4968#endif
4969 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4970
4971 if (fsp && fsp->base_fsp) {
4972 fname = fsp->base_fsp->fsp_name;
4973 }
4974
4975 if(file_ntimes(conn, fname, ts)!=0) {
4976 return map_nt_error_from_unix(errno);
4977 }
4978#ifdef __OS2__
4979 }
4980#endif
4981 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4982
4983 return NT_STATUS_OK;
4984}
4985
4986/****************************************************************************
4987 Deal with setting the dosmode from any of the setfilepathinfo functions.
4988****************************************************************************/
4989
4990static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4991 files_struct *fsp,
4992 const char *fname,
4993 SMB_STRUCT_STAT *psbuf,
4994 uint32 dosmode)
4995{
4996 if (!VALID_STAT(*psbuf)) {
4997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4998 }
4999
5000 if (fsp) {
5001 if (fsp->base_fsp) {
5002 fname = fsp->base_fsp->fsp_name;
5003 } else {
5004 fname = fsp->fsp_name;
5005 }
5006 }
5007
5008 if (dosmode) {
5009 if (S_ISDIR(psbuf->st_mode)) {
5010 dosmode |= aDIR;
5011 } else {
5012 dosmode &= ~aDIR;
5013 }
5014 }
5015
5016 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5017
5018 /* check the mode isn't different, before changing it */
5019 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5020
5021 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5022 fname, (unsigned int)dosmode ));
5023
5024 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5025 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5026 fname, strerror(errno)));
5027 return map_nt_error_from_unix(errno);
5028 }
5029 }
5030 return NT_STATUS_OK;
5031}
5032
5033/****************************************************************************
5034 Deal with setting the size from any of the setfilepathinfo functions.
5035****************************************************************************/
5036
5037static NTSTATUS smb_set_file_size(connection_struct *conn,
5038 struct smb_request *req,
5039 files_struct *fsp,
5040 const char *fname,
5041 SMB_STRUCT_STAT *psbuf,
5042 SMB_OFF_T size)
5043{
5044 NTSTATUS status = NT_STATUS_OK;
5045 files_struct *new_fsp = NULL;
5046
5047 if (!VALID_STAT(*psbuf)) {
5048 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5049 }
5050
5051 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5052
5053 if (size == get_file_size(*psbuf)) {
5054 return NT_STATUS_OK;
5055 }
5056
5057 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5058 fname, (double)size ));
5059
5060 if (fsp && fsp->fh->fd != -1) {
5061 /* Handle based call. */
5062 if (vfs_set_filelen(fsp, size) == -1) {
5063 return map_nt_error_from_unix(errno);
5064 }
5065 trigger_write_time_update_immediate(fsp);
5066 return NT_STATUS_OK;
5067 }
5068
5069 status = open_file_ntcreate(conn, req, fname, psbuf,
5070 FILE_WRITE_ATTRIBUTES,
5071 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5072 FILE_OPEN,
5073 0,
5074 FILE_ATTRIBUTE_NORMAL,
5075 FORCE_OPLOCK_BREAK_TO_NONE,
5076 NULL, &new_fsp);
5077
5078 if (!NT_STATUS_IS_OK(status)) {
5079 /* NB. We check for open_was_deferred in the caller. */
5080 return status;
5081 }
5082
5083 if (vfs_set_filelen(new_fsp, size) == -1) {
5084 status = map_nt_error_from_unix(errno);
5085 close_file(new_fsp,NORMAL_CLOSE);
5086 return status;
5087 }
5088
5089 trigger_write_time_update_immediate(new_fsp);
5090 close_file(new_fsp,NORMAL_CLOSE);
5091 return NT_STATUS_OK;
5092}
5093
5094/****************************************************************************
5095 Deal with SMB_INFO_SET_EA.
5096****************************************************************************/
5097
5098static NTSTATUS smb_info_set_ea(connection_struct *conn,
5099 const char *pdata,
5100 int total_data,
5101 files_struct *fsp,
5102 const char *fname)
5103{
5104 struct ea_list *ea_list = NULL;
5105 TALLOC_CTX *ctx = NULL;
5106 NTSTATUS status = NT_STATUS_OK;
5107
5108 if (total_data < 10) {
5109
5110 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5111 length. They seem to have no effect. Bug #3212. JRA */
5112
5113 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5114 /* We're done. We only get EA info in this call. */
5115 return NT_STATUS_OK;
5116 }
5117
5118 return NT_STATUS_INVALID_PARAMETER;
5119 }
5120
5121 if (IVAL(pdata,0) > total_data) {
5122 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5123 IVAL(pdata,0), (unsigned int)total_data));
5124 return NT_STATUS_INVALID_PARAMETER;
5125 }
5126
5127 ctx = talloc_tos();
5128 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5129 if (!ea_list) {
5130 return NT_STATUS_INVALID_PARAMETER;
5131 }
5132 status = set_ea(conn, fsp, fname, ea_list);
5133
5134 return status;
5135}
5136
5137/****************************************************************************
5138 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5139****************************************************************************/
5140
5141static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5142 const char *pdata,
5143 int total_data,
5144 files_struct *fsp,
5145 const char *fname,
5146 SMB_STRUCT_STAT *psbuf)
5147{
5148 NTSTATUS status = NT_STATUS_OK;
5149 bool delete_on_close;
5150 uint32 dosmode = 0;
5151
5152 if (total_data < 1) {
5153 return NT_STATUS_INVALID_PARAMETER;
5154 }
5155
5156 if (fsp == NULL) {
5157 return NT_STATUS_INVALID_HANDLE;
5158 }
5159
5160 delete_on_close = (CVAL(pdata,0) ? True : False);
5161 dosmode = dos_mode(conn, fname, psbuf);
5162
5163 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5164 "delete_on_close = %u\n",
5165 fsp->fsp_name,
5166 (unsigned int)dosmode,
5167 (unsigned int)delete_on_close ));
5168
5169 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5170
5171 if (!NT_STATUS_IS_OK(status)) {
5172 return status;
5173 }
5174
5175 /* The set is across all open files on this dev/inode pair. */
5176 if (!set_delete_on_close(fsp, delete_on_close,
5177 &conn->server_info->utok)) {
5178 return NT_STATUS_ACCESS_DENIED;
5179 }
5180 return NT_STATUS_OK;
5181}
5182
5183/****************************************************************************
5184 Deal with SMB_FILE_POSITION_INFORMATION.
5185****************************************************************************/
5186
5187static NTSTATUS smb_file_position_information(connection_struct *conn,
5188 const char *pdata,
5189 int total_data,
5190 files_struct *fsp)
5191{
5192 SMB_BIG_UINT position_information;
5193
5194 if (total_data < 8) {
5195 return NT_STATUS_INVALID_PARAMETER;
5196 }
5197
5198 if (fsp == NULL) {
5199 /* Ignore on pathname based set. */
5200 return NT_STATUS_OK;
5201 }
5202
5203 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5204#ifdef LARGE_SMB_OFF_T
5205 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5206#else /* LARGE_SMB_OFF_T */
5207 if (IVAL(pdata,4) != 0) {
5208 /* more than 32 bits? */
5209 return NT_STATUS_INVALID_PARAMETER;
5210 }
5211#endif /* LARGE_SMB_OFF_T */
5212
5213 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5214 fsp->fsp_name, (double)position_information ));
5215 fsp->fh->position_information = position_information;
5216 return NT_STATUS_OK;
5217}
5218
5219/****************************************************************************
5220 Deal with SMB_FILE_MODE_INFORMATION.
5221****************************************************************************/
5222
5223static NTSTATUS smb_file_mode_information(connection_struct *conn,
5224 const char *pdata,
5225 int total_data)
5226{
5227 uint32 mode;
5228
5229 if (total_data < 4) {
5230 return NT_STATUS_INVALID_PARAMETER;
5231 }
5232 mode = IVAL(pdata,0);
5233 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5234 return NT_STATUS_INVALID_PARAMETER;
5235 }
5236 return NT_STATUS_OK;
5237}
5238
5239/****************************************************************************
5240 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5241****************************************************************************/
5242
5243static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5244 struct smb_request *req,
5245 const char *pdata,
5246 int total_data,
5247 const char *fname)
5248{
5249 char *link_target = NULL;
5250 const char *newname = fname;
5251 NTSTATUS status = NT_STATUS_OK;
5252 TALLOC_CTX *ctx = talloc_tos();
5253
5254 /* Set a symbolic link. */
5255 /* Don't allow this if follow links is false. */
5256
5257 if (total_data == 0) {
5258 return NT_STATUS_INVALID_PARAMETER;
5259 }
5260
5261 if (!lp_symlinks(SNUM(conn))) {
5262 return NT_STATUS_ACCESS_DENIED;
5263 }
5264
5265 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5266 total_data, STR_TERMINATE);
5267
5268 if (!link_target) {
5269 return NT_STATUS_INVALID_PARAMETER;
5270 }
5271
5272 /* !widelinks forces the target path to be within the share. */
5273 /* This means we can interpret the target as a pathname. */
5274 if (!lp_widelinks(SNUM(conn))) {
5275 char *rel_name = NULL;
5276 char *last_dirp = NULL;
5277
5278 if (*link_target == '/') {
5279 /* No absolute paths allowed. */
5280 return NT_STATUS_ACCESS_DENIED;
5281 }
5282 rel_name = talloc_strdup(ctx,newname);
5283 if (!rel_name) {
5284 return NT_STATUS_NO_MEMORY;
5285 }
5286 last_dirp = strrchr_m(rel_name, '/');
5287 if (last_dirp) {
5288 last_dirp[1] = '\0';
5289 } else {
5290 rel_name = talloc_strdup(ctx,"./");
5291 if (!rel_name) {
5292 return NT_STATUS_NO_MEMORY;
5293 }
5294 }
5295 rel_name = talloc_asprintf_append(rel_name,
5296 "%s",
5297 link_target);
5298 if (!rel_name) {
5299 return NT_STATUS_NO_MEMORY;
5300 }
5301
5302 status = check_name(conn, rel_name);
5303 if (!NT_STATUS_IS_OK(status)) {
5304 return status;
5305 }
5306 }
5307
5308 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5309 newname, link_target ));
5310
5311 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5312 return map_nt_error_from_unix(errno);
5313 }
5314
5315 return NT_STATUS_OK;
5316}
5317
5318/****************************************************************************
5319 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5320****************************************************************************/
5321
5322static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5323 struct smb_request *req,
5324 const char *pdata, int total_data,
5325 const char *fname)
5326{
5327 char *oldname = NULL;
5328 TALLOC_CTX *ctx = talloc_tos();
5329 NTSTATUS status = NT_STATUS_OK;
5330
5331 /* Set a hard link. */
5332 if (total_data == 0) {
5333 return NT_STATUS_INVALID_PARAMETER;
5334 }
5335
5336 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5337 total_data, STR_TERMINATE, &status);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 return status;
5340 }
5341
5342 status = resolve_dfspath(ctx, conn,
5343 req->flags2 & FLAGS2_DFS_PATHNAMES,
5344 oldname,
5345 &oldname);
5346 if (!NT_STATUS_IS_OK(status)) {
5347 return status;
5348 }
5349
5350 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5351 fname, oldname));
5352
5353 return hardlink_internals(ctx, conn, oldname, fname);
5354}
5355
5356/****************************************************************************
5357 Deal with SMB_FILE_RENAME_INFORMATION.
5358****************************************************************************/
5359
5360static NTSTATUS smb_file_rename_information(connection_struct *conn,
5361 struct smb_request *req,
5362 const char *pdata,
5363 int total_data,
5364 files_struct *fsp,
5365 const char *fname)
5366{
5367 bool overwrite;
5368 uint32 root_fid;
5369 uint32 len;
5370 char *newname = NULL;
5371 char *base_name = NULL;
5372 bool dest_has_wcard = False;
5373 SMB_STRUCT_STAT sbuf;
5374 char *newname_last_component = NULL;
5375 NTSTATUS status = NT_STATUS_OK;
5376 char *p;
5377 TALLOC_CTX *ctx = talloc_tos();
5378
5379 if (total_data < 13) {
5380 return NT_STATUS_INVALID_PARAMETER;
5381 }
5382
5383 ZERO_STRUCT(sbuf);
5384
5385 overwrite = (CVAL(pdata,0) ? True : False);
5386 root_fid = IVAL(pdata,4);
5387 len = IVAL(pdata,8);
5388
5389 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5390 return NT_STATUS_INVALID_PARAMETER;
5391 }
5392
5393 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5394 len, 0, &status,
5395 &dest_has_wcard);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 return status;
5398 }
5399
5400 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5401 newname));
5402
5403 status = resolve_dfspath_wcard(ctx, conn,
5404 req->flags2 & FLAGS2_DFS_PATHNAMES,
5405 newname,
5406 &newname,
5407 &dest_has_wcard);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 return status;
5410 }
5411
5412 /* Check the new name has no '/' characters. */
5413 if (strchr_m(newname, '/')) {
5414 return NT_STATUS_NOT_SUPPORTED;
5415 }
5416
5417 if (fsp && fsp->base_fsp) {
5418 /* newname must be a stream name. */
5419 if (newname[0] != ':') {
5420 return NT_STATUS_NOT_SUPPORTED;
5421 }
5422 base_name = talloc_asprintf(ctx, "%s%s",
5423 fsp->base_fsp->fsp_name,
5424 newname);
5425 if (!base_name) {
5426 return NT_STATUS_NO_MEMORY;
5427 }
5428 } else {
5429 /* newname must *not* be a stream name. */
5430 if (is_ntfs_stream_name(newname)) {
5431 return NT_STATUS_NOT_SUPPORTED;
5432 }
5433
5434 /* Create the base directory. */
5435 base_name = talloc_strdup(ctx, fname);
5436 if (!base_name) {
5437 return NT_STATUS_NO_MEMORY;
5438 }
5439 p = strrchr_m(base_name, '/');
5440 if (p) {
5441 p[1] = '\0';
5442 } else {
5443 base_name = talloc_strdup(ctx, "./");
5444 if (!base_name) {
5445 return NT_STATUS_NO_MEMORY;
5446 }
5447 }
5448 /* Append the new name. */
5449 base_name = talloc_asprintf_append(base_name,
5450 "%s",
5451 newname);
5452 if (!base_name) {
5453 return NT_STATUS_NO_MEMORY;
5454 }
5455
5456 status = unix_convert(ctx, conn, newname, False,
5457 &newname,
5458 &newname_last_component,
5459 &sbuf);
5460
5461 /* If an error we expect this to be
5462 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5463
5464 if (!NT_STATUS_IS_OK(status)
5465 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5466 status)) {
5467 return status;
5468 }
5469 }
5470
5471 if (fsp) {
5472 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5473 fsp->fnum, fsp->fsp_name, base_name ));
5474 status = rename_internals_fsp(conn, fsp, base_name,
5475 newname_last_component, 0,
5476 overwrite);
5477 } else {
5478 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5479 fname, base_name ));
5480 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5481 overwrite, False, dest_has_wcard,
5482 FILE_WRITE_ATTRIBUTES);
5483 }
5484
5485 return status;
5486}
5487
5488/****************************************************************************
5489 Deal with SMB_SET_POSIX_ACL.
5490****************************************************************************/
5491
5492#if defined(HAVE_POSIX_ACLS)
5493static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5494 const char *pdata,
5495 int total_data,
5496 files_struct *fsp,
5497 const char *fname,
5498 SMB_STRUCT_STAT *psbuf)
5499{
5500 uint16 posix_acl_version;
5501 uint16 num_file_acls;
5502 uint16 num_def_acls;
5503 bool valid_file_acls = True;
5504 bool valid_def_acls = True;
5505
5506 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5507 return NT_STATUS_INVALID_PARAMETER;
5508 }
5509 posix_acl_version = SVAL(pdata,0);
5510 num_file_acls = SVAL(pdata,2);
5511 num_def_acls = SVAL(pdata,4);
5512
5513 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5514 valid_file_acls = False;
5515 num_file_acls = 0;
5516 }
5517
5518 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5519 valid_def_acls = False;
5520 num_def_acls = 0;
5521 }
5522
5523 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5524 return NT_STATUS_INVALID_PARAMETER;
5525 }
5526
5527 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5528 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5529 return NT_STATUS_INVALID_PARAMETER;
5530 }
5531
5532 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5533 fname ? fname : fsp->fsp_name,
5534 (unsigned int)num_file_acls,
5535 (unsigned int)num_def_acls));
5536
5537 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5538 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5539 return map_nt_error_from_unix(errno);
5540 }
5541
5542 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5543 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5544 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5545 return map_nt_error_from_unix(errno);
5546 }
5547 return NT_STATUS_OK;
5548}
5549#endif
5550
5551/****************************************************************************
5552 Deal with SMB_SET_POSIX_LOCK.
5553****************************************************************************/
5554
5555static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5556 const struct smb_request *req,
5557 const char *pdata,
5558 int total_data,
5559 files_struct *fsp)
5560{
5561 SMB_BIG_UINT count;
5562 SMB_BIG_UINT offset;
5563 uint32 lock_pid;
5564 bool blocking_lock = False;
5565 enum brl_type lock_type;
5566
5567 NTSTATUS status = NT_STATUS_OK;
5568
5569 if (fsp == NULL || fsp->fh->fd == -1) {
5570 return NT_STATUS_INVALID_HANDLE;
5571 }
5572
5573 if (total_data != POSIX_LOCK_DATA_SIZE) {
5574 return NT_STATUS_INVALID_PARAMETER;
5575 }
5576
5577 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5578 case POSIX_LOCK_TYPE_READ:
5579 lock_type = READ_LOCK;
5580 break;
5581 case POSIX_LOCK_TYPE_WRITE:
5582 /* Return the right POSIX-mappable error code for files opened read-only. */
5583 if (!fsp->can_write) {
5584 return NT_STATUS_INVALID_HANDLE;
5585 }
5586 lock_type = WRITE_LOCK;
5587 break;
5588 case POSIX_LOCK_TYPE_UNLOCK:
5589 lock_type = UNLOCK_LOCK;
5590 break;
5591 default:
5592 return NT_STATUS_INVALID_PARAMETER;
5593 }
5594
5595 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5596 blocking_lock = False;
5597 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5598 blocking_lock = True;
5599 } else {
5600 return NT_STATUS_INVALID_PARAMETER;
5601 }
5602
5603 if (!lp_blocking_locks(SNUM(conn))) {
5604 blocking_lock = False;
5605 }
5606
5607 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5608#if defined(HAVE_LONGLONG)
5609 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5610 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5611 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5612 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5613#else /* HAVE_LONGLONG */
5614 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5615 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5616#endif /* HAVE_LONGLONG */
5617
5618 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5619 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5620 fsp->fsp_name,
5621 (unsigned int)lock_type,
5622 (unsigned int)lock_pid,
5623 (double)count,
5624 (double)offset ));
5625
5626 if (lock_type == UNLOCK_LOCK) {
5627 status = do_unlock(smbd_messaging_context(),
5628 fsp,
5629 lock_pid,
5630 count,
5631 offset,
5632 POSIX_LOCK);
5633 } else {
5634 uint32 block_smbpid;
5635
5636 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5637 fsp,
5638 lock_pid,
5639 count,
5640 offset,
5641 lock_type,
5642 POSIX_LOCK,
5643 blocking_lock,
5644 &status,
5645 &block_smbpid);
5646
5647 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5648 /*
5649 * A blocking lock was requested. Package up
5650 * this smb into a queued request and push it
5651 * onto the blocking lock queue.
5652 */
5653 if(push_blocking_lock_request(br_lck,
5654 req,
5655 fsp,
5656 -1, /* infinite timeout. */
5657 0,
5658 lock_pid,
5659 lock_type,
5660 POSIX_LOCK,
5661 offset,
5662 count,
5663 block_smbpid)) {
5664 TALLOC_FREE(br_lck);
5665 return status;
5666 }
5667 }
5668 TALLOC_FREE(br_lck);
5669 }
5670
5671 return status;
5672}
5673
5674/****************************************************************************
5675 Deal with SMB_INFO_STANDARD.
5676****************************************************************************/
5677
5678static NTSTATUS smb_set_info_standard(connection_struct *conn,
5679 const char *pdata,
5680 int total_data,
5681 files_struct *fsp,
5682 const char *fname,
5683 const SMB_STRUCT_STAT *psbuf)
5684{
5685 struct timespec ts[2];
5686
5687 if (total_data < 12) {
5688 return NT_STATUS_INVALID_PARAMETER;
5689 }
5690
5691 /* access time */
5692 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5693 /* write time */
5694 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5695
5696 DEBUG(10,("smb_set_info_standard: file %s\n",
5697 fname ? fname : fsp->fsp_name ));
5698
5699 return smb_set_file_time(conn,
5700 fsp,
5701 fname,
5702 psbuf,
5703 ts,
5704 true);
5705}
5706
5707/****************************************************************************
5708 Deal with SMB_SET_FILE_BASIC_INFO.
5709****************************************************************************/
5710
5711static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5712 const char *pdata,
5713 int total_data,
5714 files_struct *fsp,
5715 const char *fname,
5716 SMB_STRUCT_STAT *psbuf)
5717{
5718 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5719 struct timespec write_time;
5720 struct timespec changed_time;
5721 uint32 dosmode = 0;
5722 struct timespec ts[2];
5723 NTSTATUS status = NT_STATUS_OK;
5724 bool setting_write_time = true;
5725
5726 if (total_data < 36) {
5727 return NT_STATUS_INVALID_PARAMETER;
5728 }
5729
5730 /* Set the attributes */
5731 dosmode = IVAL(pdata,32);
5732 status = smb_set_file_dosmode(conn,
5733 fsp,
5734 fname,
5735 psbuf,
5736 dosmode);
5737
5738 if (!NT_STATUS_IS_OK(status)) {
5739 return status;
5740 }
5741
5742 /* Ignore create time at offset pdata. */
5743
5744 /* access time */
5745 ts[0] = interpret_long_date(pdata+8);
5746
5747 write_time = interpret_long_date(pdata+16);
5748 changed_time = interpret_long_date(pdata+24);
5749
5750 /* mtime */
5751 ts[1] = timespec_min(&write_time, &changed_time);
5752
5753 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5754 ts[1] = write_time;
5755 }
5756
5757 /* Prefer a defined time to an undefined one. */
5758 if (null_timespec(ts[1])) {
5759 if (null_timespec(write_time)) {
5760 ts[1] = changed_time;
5761 setting_write_time = false;
5762 } else {
5763 ts[1] = write_time;
5764 }
5765 }
5766
5767 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5768 fname ? fname : fsp->fsp_name ));
5769
5770 return smb_set_file_time(conn,
5771 fsp,
5772 fname,
5773 psbuf,
5774 ts,
5775 setting_write_time);
5776}
5777
5778/****************************************************************************
5779 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5780****************************************************************************/
5781
5782static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5783 struct smb_request *req,
5784 const char *pdata,
5785 int total_data,
5786 files_struct *fsp,
5787 const char *fname,
5788 SMB_STRUCT_STAT *psbuf)
5789{
5790 SMB_BIG_UINT allocation_size = 0;
5791 NTSTATUS status = NT_STATUS_OK;
5792 files_struct *new_fsp = NULL;
5793
5794 if (!VALID_STAT(*psbuf)) {
5795 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5796 }
5797
5798 if (total_data < 8) {
5799 return NT_STATUS_INVALID_PARAMETER;
5800 }
5801
5802 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5803#ifdef LARGE_SMB_OFF_T
5804 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5805#else /* LARGE_SMB_OFF_T */
5806 if (IVAL(pdata,4) != 0) {
5807 /* more than 32 bits? */
5808 return NT_STATUS_INVALID_PARAMETER;
5809 }
5810#endif /* LARGE_SMB_OFF_T */
5811
5812 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5813 fname, (double)allocation_size ));
5814
5815 if (allocation_size) {
5816 allocation_size = smb_roundup(conn, allocation_size);
5817 }
5818
5819 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5820 fname, (double)allocation_size ));
5821
5822 if (fsp && fsp->fh->fd != -1) {
5823 /* Open file handle. */
5824 /* Only change if needed. */
5825 if (allocation_size != get_file_size(*psbuf)) {
5826 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5827 return map_nt_error_from_unix(errno);
5828 }
5829 }
5830 /* But always update the time. */
5831 /*
5832 * This is equivalent to a write. Ensure it's seen immediately
5833 * if there are no pending writes.
5834 */
5835 trigger_write_time_update_immediate(fsp);
5836 return NT_STATUS_OK;
5837 }
5838
5839 /* Pathname or stat or directory file. */
5840
5841 status = open_file_ntcreate(conn, req, fname, psbuf,
5842 FILE_WRITE_DATA,
5843 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5844 FILE_OPEN,
5845 0,
5846 FILE_ATTRIBUTE_NORMAL,
5847 FORCE_OPLOCK_BREAK_TO_NONE,
5848 NULL, &new_fsp);
5849
5850 if (!NT_STATUS_IS_OK(status)) {
5851 /* NB. We check for open_was_deferred in the caller. */
5852 return status;
5853 }
5854
5855 /* Only change if needed. */
5856 if (allocation_size != get_file_size(*psbuf)) {
5857 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5858 status = map_nt_error_from_unix(errno);
5859 close_file(new_fsp,NORMAL_CLOSE);
5860 return status;
5861 }
5862 }
5863
5864 /* Changing the allocation size should set the last mod time. */
5865 /*
5866 * This is equivalent to a write. Ensure it's seen immediately
5867 * if there are no pending writes.
5868 */
5869 trigger_write_time_update_immediate(new_fsp);
5870
5871 close_file(new_fsp,NORMAL_CLOSE);
5872 return NT_STATUS_OK;
5873}
5874
5875/****************************************************************************
5876 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5877****************************************************************************/
5878
5879static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5880 struct smb_request *req,
5881 const char *pdata,
5882 int total_data,
5883 files_struct *fsp,
5884 const char *fname,
5885 SMB_STRUCT_STAT *psbuf)
5886{
5887 SMB_OFF_T size;
5888
5889 if (total_data < 8) {
5890 return NT_STATUS_INVALID_PARAMETER;
5891 }
5892
5893 size = IVAL(pdata,0);
5894#ifdef LARGE_SMB_OFF_T
5895 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5896#else /* LARGE_SMB_OFF_T */
5897 if (IVAL(pdata,4) != 0) {
5898 /* more than 32 bits? */
5899 return NT_STATUS_INVALID_PARAMETER;
5900 }
5901#endif /* LARGE_SMB_OFF_T */
5902 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5903 "file %s to %.0f\n", fname, (double)size ));
5904
5905 return smb_set_file_size(conn, req,
5906 fsp,
5907 fname,
5908 psbuf,
5909 size);
5910}
5911
5912/****************************************************************************
5913 Allow a UNIX info mknod.
5914****************************************************************************/
5915
5916static NTSTATUS smb_unix_mknod(connection_struct *conn,
5917 const char *pdata,
5918 int total_data,
5919 const char *fname,
5920 SMB_STRUCT_STAT *psbuf)
5921{
5922 uint32 file_type = IVAL(pdata,56);
5923#if defined(HAVE_MAKEDEV)
5924 uint32 dev_major = IVAL(pdata,60);
5925 uint32 dev_minor = IVAL(pdata,68);
5926#endif
5927 SMB_DEV_T dev = (SMB_DEV_T)0;
5928 uint32 raw_unixmode = IVAL(pdata,84);
5929 NTSTATUS status;
5930 mode_t unixmode;
5931
5932 if (total_data < 100) {
5933 return NT_STATUS_INVALID_PARAMETER;
5934 }
5935
5936 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 return status;
5939 }
5940
5941#if defined(HAVE_MAKEDEV)
5942 dev = makedev(dev_major, dev_minor);
5943#endif
5944
5945 switch (file_type) {
5946#if defined(S_IFIFO)
5947 case UNIX_TYPE_FIFO:
5948 unixmode |= S_IFIFO;
5949 break;
5950#endif
5951#if defined(S_IFSOCK)
5952 case UNIX_TYPE_SOCKET:
5953 unixmode |= S_IFSOCK;
5954 break;
5955#endif
5956#if defined(S_IFCHR)
5957 case UNIX_TYPE_CHARDEV:
5958 unixmode |= S_IFCHR;
5959 break;
5960#endif
5961#if defined(S_IFBLK)
5962 case UNIX_TYPE_BLKDEV:
5963 unixmode |= S_IFBLK;
5964 break;
5965#endif
5966 default:
5967 return NT_STATUS_INVALID_PARAMETER;
5968 }
5969
5970 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
59710%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5972
5973 /* Ok - do the mknod. */
5974 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5975 return map_nt_error_from_unix(errno);
5976 }
5977
5978 /* If any of the other "set" calls fail we
5979 * don't want to end up with a half-constructed mknod.
5980 */
5981
5982 if (lp_inherit_perms(SNUM(conn))) {
5983 inherit_access_posix_acl(
5984 conn, parent_dirname(fname),
5985 fname, unixmode);
5986 }
5987
5988 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5989 status = map_nt_error_from_unix(errno);
5990 SMB_VFS_UNLINK(conn,fname);
5991 return status;
5992 }
5993 return NT_STATUS_OK;
5994}
5995
5996/****************************************************************************
5997 Deal with SMB_SET_FILE_UNIX_BASIC.
5998****************************************************************************/
5999
6000static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6001 struct smb_request *req,
6002 const char *pdata,
6003 int total_data,
6004 files_struct *fsp,
6005 const char *fname,
6006 SMB_STRUCT_STAT *psbuf)
6007{
6008 struct timespec ts[2];
6009 uint32 raw_unixmode;
6010 mode_t unixmode;
6011 SMB_OFF_T size = 0;
6012 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6013 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6014 NTSTATUS status = NT_STATUS_OK;
6015 bool delete_on_fail = False;
6016 enum perm_type ptype;
6017 files_struct *all_fsps = NULL;
6018 bool modify_mtime = true;
6019 struct file_id id;
6020
6021 if (total_data < 100) {
6022 return NT_STATUS_INVALID_PARAMETER;
6023 }
6024
6025 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6026 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6027 size=IVAL(pdata,0); /* first 8 Bytes are size */
6028#ifdef LARGE_SMB_OFF_T
6029 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6030#else /* LARGE_SMB_OFF_T */
6031 if (IVAL(pdata,4) != 0) {
6032 /* more than 32 bits? */
6033 return NT_STATUS_INVALID_PARAMETER;
6034 }
6035#endif /* LARGE_SMB_OFF_T */
6036 }
6037
6038 ts[0] = interpret_long_date(pdata+24); /* access_time */
6039 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6040 set_owner = (uid_t)IVAL(pdata,40);
6041 set_grp = (gid_t)IVAL(pdata,48);
6042 raw_unixmode = IVAL(pdata,84);
6043
6044 if (VALID_STAT(*psbuf)) {
6045 if (S_ISDIR(psbuf->st_mode)) {
6046 ptype = PERM_EXISTING_DIR;
6047 } else {
6048 ptype = PERM_EXISTING_FILE;
6049 }
6050 } else {
6051 ptype = PERM_NEW_FILE;
6052 }
6053
6054 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6055 if (!NT_STATUS_IS_OK(status)) {
6056 return status;
6057 }
6058
6059 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6060size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6061 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6062
6063 if (!VALID_STAT(*psbuf)) {
6064 /*
6065 * The only valid use of this is to create character and block
6066 * devices, and named pipes. This is deprecated (IMHO) and
6067 * a new info level should be used for mknod. JRA.
6068 */
6069
6070 status = smb_unix_mknod(conn,
6071 pdata,
6072 total_data,
6073 fname,
6074 psbuf);
6075 if (!NT_STATUS_IS_OK(status)) {
6076 return status;
6077 }
6078
6079 /* Ensure we don't try and change anything else. */
6080 raw_unixmode = SMB_MODE_NO_CHANGE;
6081 size = get_file_size(*psbuf);
6082 ts[0] = get_atimespec(psbuf);
6083 ts[1] = get_mtimespec(psbuf);
6084 /*
6085 * We continue here as we might want to change the
6086 * owner uid/gid.
6087 */
6088 delete_on_fail = True;
6089 }
6090
6091#if 1
6092 /* Horrible backwards compatibility hack as an old server bug
6093 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6094 * */
6095
6096 if (!size) {
6097 size = get_file_size(*psbuf);
6098 }
6099#endif
6100
6101 /*
6102 * Deal with the UNIX specific mode set.
6103 */
6104
6105 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6106 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6107 (unsigned int)unixmode, fname ));
6108 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6109 return map_nt_error_from_unix(errno);
6110 }
6111 }
6112
6113 /*
6114 * Deal with the UNIX specific uid set.
6115 */
6116
6117 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6118 int ret;
6119
6120 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6121 (unsigned int)set_owner, fname ));
6122
6123 if (S_ISLNK(psbuf->st_mode)) {
6124 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6125 } else {
6126 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6127 }
6128
6129 if (ret != 0) {
6130 status = map_nt_error_from_unix(errno);
6131 if (delete_on_fail) {
6132 SMB_VFS_UNLINK(conn,fname);
6133 }
6134 return status;
6135 }
6136 }
6137
6138 /*
6139 * Deal with the UNIX specific gid set.
6140 */
6141
6142 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6144 (unsigned int)set_owner, fname ));
6145 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6146 status = map_nt_error_from_unix(errno);
6147 if (delete_on_fail) {
6148 SMB_VFS_UNLINK(conn,fname);
6149 }
6150 return status;
6151 }
6152 }
6153
6154 /* Deal with any size changes. */
6155
6156 status = smb_set_file_size(conn, req,
6157 fsp,
6158 fname,
6159 psbuf,
6160 size);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 return status;
6163 }
6164
6165 /* Deal with any time changes. */
6166 id = vfs_file_id_from_sbuf(conn, psbuf);
6167 for(all_fsps = file_find_di_first(id); all_fsps;
6168 all_fsps = file_find_di_next(all_fsps)) {
6169 /*
6170 * We're setting the time explicitly for UNIX.
6171 * Cancel any pending changes over all handles.
6172 */
6173 all_fsps->update_write_time_on_close = false;
6174 TALLOC_FREE(all_fsps->update_write_time_event);
6175 }
6176
6177 /*
6178 * Override the "setting_write_time"
6179 * parameter here as it almost does what
6180 * we need. Just remember if we modified
6181 * mtime and send the notify ourselves.
6182 */
6183 if (null_timespec(ts[1])) {
6184 modify_mtime = false;
6185 }
6186
6187 status = smb_set_file_time(conn,
6188 fsp,
6189 fname,
6190 psbuf,
6191 ts,
6192 false);
6193
6194 if (modify_mtime) {
6195 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6196 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6197 }
6198 return status;
6199}
6200
6201/****************************************************************************
6202 Deal with SMB_SET_FILE_UNIX_INFO2.
6203****************************************************************************/
6204
6205static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6206 struct smb_request *req,
6207 const char *pdata,
6208 int total_data,
6209 files_struct *fsp,
6210 const char *fname,
6211 SMB_STRUCT_STAT *psbuf)
6212{
6213 NTSTATUS status;
6214 uint32 smb_fflags;
6215 uint32 smb_fmask;
6216
6217 if (total_data < 116) {
6218 return NT_STATUS_INVALID_PARAMETER;
6219 }
6220
6221 /* Start by setting all the fields that are common between UNIX_BASIC
6222 * and UNIX_INFO2.
6223 */
6224 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6225 fsp, fname, psbuf);
6226 if (!NT_STATUS_IS_OK(status)) {
6227 return status;
6228 }
6229
6230 smb_fflags = IVAL(pdata, 108);
6231 smb_fmask = IVAL(pdata, 112);
6232
6233 /* NB: We should only attempt to alter the file flags if the client
6234 * sends a non-zero mask.
6235 */
6236 if (smb_fmask != 0) {
6237 int stat_fflags = 0;
6238
6239 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6240 &stat_fflags)) {
6241 /* Client asked to alter a flag we don't understand. */
6242 return NT_STATUS_INVALID_PARAMETER;
6243 }
6244
6245 if (fsp && fsp->fh->fd != -1) {
6246 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6247 return NT_STATUS_NOT_SUPPORTED;
6248 } else {
6249 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6250 return map_nt_error_from_unix(errno);
6251 }
6252 }
6253 }
6254
6255 /* XXX: need to add support for changing the create_time here. You
6256 * can do this for paths on Darwin with setattrlist(2). The right way
6257 * to hook this up is probably by extending the VFS utimes interface.
6258 */
6259
6260 return NT_STATUS_OK;
6261}
6262
6263/****************************************************************************
6264 Create a directory with POSIX semantics.
6265****************************************************************************/
6266
6267static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6268 struct smb_request *req,
6269 char **ppdata,
6270 int total_data,
6271 const char *fname,
6272 SMB_STRUCT_STAT *psbuf,
6273 int *pdata_return_size)
6274{
6275 NTSTATUS status = NT_STATUS_OK;
6276 uint32 raw_unixmode = 0;
6277 uint32 mod_unixmode = 0;
6278 mode_t unixmode = (mode_t)0;
6279 files_struct *fsp = NULL;
6280 uint16 info_level_return = 0;
6281 int info;
6282 char *pdata = *ppdata;
6283
6284 if (total_data < 18) {
6285 return NT_STATUS_INVALID_PARAMETER;
6286 }
6287
6288 raw_unixmode = IVAL(pdata,8);
6289 /* Next 4 bytes are not yet defined. */
6290
6291 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 return status;
6294 }
6295
6296 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6297
6298 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6299 fname, (unsigned int)unixmode ));
6300
6301 status = open_directory(conn, req,
6302 fname,
6303 psbuf,
6304 FILE_READ_ATTRIBUTES, /* Just a stat open */
6305 FILE_SHARE_NONE, /* Ignored for stat opens */
6306 FILE_CREATE,
6307 0,
6308 mod_unixmode,
6309 &info,
6310 &fsp);
6311
6312 if (NT_STATUS_IS_OK(status)) {
6313 close_file(fsp, NORMAL_CLOSE);
6314 }
6315
6316 info_level_return = SVAL(pdata,16);
6317
6318 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6319 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6320 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6321 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6322 } else {
6323 *pdata_return_size = 12;
6324 }
6325
6326 /* Realloc the data size */
6327 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6328 if (*ppdata == NULL) {
6329 *pdata_return_size = 0;
6330 return NT_STATUS_NO_MEMORY;
6331 }
6332 pdata = *ppdata;
6333
6334 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6335 SSVAL(pdata,2,0); /* No fnum. */
6336 SIVAL(pdata,4,info); /* Was directory created. */
6337
6338 switch (info_level_return) {
6339 case SMB_QUERY_FILE_UNIX_BASIC:
6340 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6341 SSVAL(pdata,10,0); /* Padding. */
6342 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6343 break;
6344 case SMB_QUERY_FILE_UNIX_INFO2:
6345 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6346 SSVAL(pdata,10,0); /* Padding. */
6347 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6348 break;
6349 default:
6350 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6351 SSVAL(pdata,10,0); /* Padding. */
6352 break;
6353 }
6354
6355 return status;
6356}
6357
6358/****************************************************************************
6359 Open/Create a file with POSIX semantics.
6360****************************************************************************/
6361
6362static NTSTATUS smb_posix_open(connection_struct *conn,
6363 struct smb_request *req,
6364 char **ppdata,
6365 int total_data,
6366 const char *fname,
6367 SMB_STRUCT_STAT *psbuf,
6368 int *pdata_return_size)
6369{
6370 bool extended_oplock_granted = False;
6371 char *pdata = *ppdata;
6372 uint32 flags = 0;
6373 uint32 wire_open_mode = 0;
6374 uint32 raw_unixmode = 0;
6375 uint32 mod_unixmode = 0;
6376 uint32 create_disp = 0;
6377 uint32 access_mask = 0;
6378 uint32 create_options = 0;
6379 NTSTATUS status = NT_STATUS_OK;
6380 mode_t unixmode = (mode_t)0;
6381 files_struct *fsp = NULL;
6382 int oplock_request = 0;
6383 int info = 0;
6384 uint16 info_level_return = 0;
6385
6386 if (total_data < 18) {
6387 return NT_STATUS_INVALID_PARAMETER;
6388 }
6389
6390 flags = IVAL(pdata,0);
6391 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6392 if (oplock_request) {
6393 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6394 }
6395
6396 wire_open_mode = IVAL(pdata,4);
6397
6398 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6399 return smb_posix_mkdir(conn, req,
6400 ppdata,
6401 total_data,
6402 fname,
6403 psbuf,
6404 pdata_return_size);
6405 }
6406
6407 switch (wire_open_mode & SMB_ACCMODE) {
6408 case SMB_O_RDONLY:
6409 access_mask = FILE_READ_DATA;
6410 break;
6411 case SMB_O_WRONLY:
6412 access_mask = FILE_WRITE_DATA;
6413 break;
6414 case SMB_O_RDWR:
6415 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6416 break;
6417 default:
6418 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6419 (unsigned int)wire_open_mode ));
6420 return NT_STATUS_INVALID_PARAMETER;
6421 }
6422
6423 wire_open_mode &= ~SMB_ACCMODE;
6424
6425 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6426 create_disp = FILE_CREATE;
6427 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6428 create_disp = FILE_OVERWRITE_IF;
6429 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6430 create_disp = FILE_OPEN_IF;
6431 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6432 create_disp = FILE_OPEN;
6433 } else {
6434 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6435 (unsigned int)wire_open_mode ));
6436 return NT_STATUS_INVALID_PARAMETER;
6437 }
6438
6439 raw_unixmode = IVAL(pdata,8);
6440 /* Next 4 bytes are not yet defined. */
6441
6442 status = unix_perms_from_wire(conn,
6443 psbuf,
6444 raw_unixmode,
6445 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6446 &unixmode);
6447
6448 if (!NT_STATUS_IS_OK(status)) {
6449 return status;
6450 }
6451
6452 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6453
6454 if (wire_open_mode & SMB_O_SYNC) {
6455 create_options |= FILE_WRITE_THROUGH;
6456 }
6457 if (wire_open_mode & SMB_O_APPEND) {
6458 access_mask |= FILE_APPEND_DATA;
6459 }
6460 if (wire_open_mode & SMB_O_DIRECT) {
6461 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6462 }
6463
6464 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6465 fname,
6466 (unsigned int)wire_open_mode,
6467 (unsigned int)unixmode ));
6468
6469 status = open_file_ntcreate(conn, req,
6470 fname,
6471 psbuf,
6472 access_mask,
6473 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6474 create_disp,
6475 0, /* no create options yet. */
6476 mod_unixmode,
6477 oplock_request,
6478 &info,
6479 &fsp);
6480
6481 if (!NT_STATUS_IS_OK(status)) {
6482 return status;
6483 }
6484
6485 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6486 extended_oplock_granted = True;
6487 }
6488
6489 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6490 extended_oplock_granted = True;
6491 }
6492
6493 info_level_return = SVAL(pdata,16);
6494
6495 /* Allocate the correct return size. */
6496
6497 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6498 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6499 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6500 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6501 } else {
6502 *pdata_return_size = 12;
6503 }
6504
6505 /* Realloc the data size */
6506 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6507 if (*ppdata == NULL) {
6508 close_file(fsp,ERROR_CLOSE);
6509 *pdata_return_size = 0;
6510 return NT_STATUS_NO_MEMORY;
6511 }
6512 pdata = *ppdata;
6513
6514 if (extended_oplock_granted) {
6515 if (flags & REQUEST_BATCH_OPLOCK) {
6516 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6517 } else {
6518 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6519 }
6520 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6521 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6522 } else {
6523 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6524 }
6525
6526 SSVAL(pdata,2,fsp->fnum);
6527 SIVAL(pdata,4,info); /* Was file created etc. */
6528
6529 switch (info_level_return) {
6530 case SMB_QUERY_FILE_UNIX_BASIC:
6531 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6532 SSVAL(pdata,10,0); /* padding. */
6533 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6534 break;
6535 case SMB_QUERY_FILE_UNIX_INFO2:
6536 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6537 SSVAL(pdata,10,0); /* padding. */
6538 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6539 break;
6540 default:
6541 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6542 SSVAL(pdata,10,0); /* padding. */
6543 break;
6544 }
6545 return NT_STATUS_OK;
6546}
6547
6548/****************************************************************************
6549 Delete a file with POSIX semantics.
6550****************************************************************************/
6551
6552static NTSTATUS smb_posix_unlink(connection_struct *conn,
6553 struct smb_request *req,
6554 const char *pdata,
6555 int total_data,
6556 const char *fname,
6557 SMB_STRUCT_STAT *psbuf)
6558{
6559 NTSTATUS status = NT_STATUS_OK;
6560 files_struct *fsp = NULL;
6561 uint16 flags = 0;
6562 char del = 1;
6563 int info = 0;
6564 int i;
6565 struct share_mode_lock *lck = NULL;
6566
6567 if (total_data < 2) {
6568 return NT_STATUS_INVALID_PARAMETER;
6569 }
6570
6571 flags = SVAL(pdata,0);
6572
6573 if (!VALID_STAT(*psbuf)) {
6574 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6575 }
6576
6577 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6578 !VALID_STAT_OF_DIR(*psbuf)) {
6579 return NT_STATUS_NOT_A_DIRECTORY;
6580 }
6581
6582 DEBUG(10,("smb_posix_unlink: %s %s\n",
6583 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6584 fname));
6585
6586 if (VALID_STAT_OF_DIR(*psbuf)) {
6587 status = open_directory(conn, req,
6588 fname,
6589 psbuf,
6590 DELETE_ACCESS,
6591 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6592 FILE_OPEN,
6593 0,
6594 FILE_FLAG_POSIX_SEMANTICS|0777,
6595 &info,
6596 &fsp);
6597 } else {
6598
6599 status = open_file_ntcreate(conn, req,
6600 fname,
6601 psbuf,
6602 DELETE_ACCESS,
6603 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6604 FILE_OPEN,
6605 0,
6606 FILE_FLAG_POSIX_SEMANTICS|0777,
6607 0, /* No oplock, but break existing ones. */
6608 &info,
6609 &fsp);
6610 }
6611
6612 if (!NT_STATUS_IS_OK(status)) {
6613 return status;
6614 }
6615
6616 /*
6617 * Don't lie to client. If we can't really delete due to
6618 * non-POSIX opens return SHARING_VIOLATION.
6619 */
6620
6621 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6622 NULL);
6623 if (lck == NULL) {
6624 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6625 "lock for file %s\n", fsp->fsp_name));
6626 close_file(fsp, NORMAL_CLOSE);
6627 return NT_STATUS_INVALID_PARAMETER;
6628 }
6629
6630 /*
6631 * See if others still have the file open. If this is the case, then
6632 * don't delete. If all opens are POSIX delete we can set the delete
6633 * on close disposition.
6634 */
6635 for (i=0; i<lck->num_share_modes; i++) {
6636 struct share_mode_entry *e = &lck->share_modes[i];
6637 if (is_valid_share_mode_entry(e)) {
6638 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6639 continue;
6640 }
6641 /* Fail with sharing violation. */
6642 close_file(fsp, NORMAL_CLOSE);
6643 TALLOC_FREE(lck);
6644 return NT_STATUS_SHARING_VIOLATION;
6645 }
6646 }
6647
6648 /*
6649 * Set the delete on close.
6650 */
6651 status = smb_set_file_disposition_info(conn,
6652 &del,
6653 1,
6654 fsp,
6655 fname,
6656 psbuf);
6657
6658 if (!NT_STATUS_IS_OK(status)) {
6659 close_file(fsp, NORMAL_CLOSE);
6660 TALLOC_FREE(lck);
6661 return status;
6662 }
6663 TALLOC_FREE(lck);
6664 return close_file(fsp, NORMAL_CLOSE);
6665}
6666
6667/****************************************************************************
6668 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6669****************************************************************************/
6670
6671static void call_trans2setfilepathinfo(connection_struct *conn,
6672 struct smb_request *req,
6673 unsigned int tran_call,
6674 char **pparams, int total_params,
6675 char **ppdata, int total_data,
6676 unsigned int max_data_bytes)
6677{
6678 char *params = *pparams;
6679 char *pdata = *ppdata;
6680 uint16 info_level;
6681 SMB_STRUCT_STAT sbuf;
6682 char *fname = NULL;
6683 files_struct *fsp = NULL;
6684 NTSTATUS status = NT_STATUS_OK;
6685 int data_return_size = 0;
6686 TALLOC_CTX *ctx = talloc_tos();
6687
6688 if (!params) {
6689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6690 return;
6691 }
6692
6693 ZERO_STRUCT(sbuf);
6694
6695 if (tran_call == TRANSACT2_SETFILEINFO) {
6696 if (total_params < 4) {
6697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6698 return;
6699 }
6700
6701 fsp = file_fsp(SVAL(params,0));
6702 /* Basic check for non-null fsp. */
6703 if (!check_fsp_open(conn, req, fsp)) {
6704 return;
6705 }
6706 info_level = SVAL(params,2);
6707
6708 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6709 if (!fname) {
6710 reply_nterror(req, NT_STATUS_NO_MEMORY);
6711 return;
6712 }
6713
6714 if(fsp->is_directory || fsp->fh->fd == -1) {
6715 /*
6716 * This is actually a SETFILEINFO on a directory
6717 * handle (returned from an NT SMB). NT5.0 seems
6718 * to do this call. JRA.
6719 */
6720 if (INFO_LEVEL_IS_UNIX(info_level)) {
6721 /* Always do lstat for UNIX calls. */
6722 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6723 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6724 reply_unixerror(req,ERRDOS,ERRbadpath);
6725 return;
6726 }
6727 } else {
6728 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6729 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6730 reply_unixerror(req,ERRDOS,ERRbadpath);
6731 return;
6732 }
6733 }
6734 } else if (fsp->print_file) {
6735 /*
6736 * Doing a DELETE_ON_CLOSE should cancel a print job.
6737 */
6738 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6739 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6740
6741 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6742
6743 SSVAL(params,0,0);
6744 send_trans2_replies(conn, req, params, 2,
6745 *ppdata, 0,
6746 max_data_bytes);
6747 return;
6748 } else {
6749 reply_unixerror(req, ERRDOS, ERRbadpath);
6750 return;
6751 }
6752 } else {
6753 /*
6754 * Original code - this is an open file.
6755 */
6756 if (!check_fsp(conn, req, fsp)) {
6757 return;
6758 }
6759
6760 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6761 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6762 reply_unixerror(req, ERRDOS, ERRbadfid);
6763 return;
6764 }
6765 }
6766 } else {
6767 /* set path info */
6768 if (total_params < 7) {
6769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6770 return;
6771 }
6772
6773 info_level = SVAL(params,0);
6774 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6775 total_params - 6, STR_TERMINATE,
6776 &status);
6777 if (!NT_STATUS_IS_OK(status)) {
6778 reply_nterror(req, status);
6779 return;
6780 }
6781
6782 status = resolve_dfspath(ctx, conn,
6783 req->flags2 & FLAGS2_DFS_PATHNAMES,
6784 fname,
6785 &fname);
6786 if (!NT_STATUS_IS_OK(status)) {
6787 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6788 reply_botherror(req,
6789 NT_STATUS_PATH_NOT_COVERED,
6790 ERRSRV, ERRbadpath);
6791 return;
6792 }
6793 reply_nterror(req, status);
6794 return;
6795 }
6796
6797 status = unix_convert(ctx, conn, fname, False,
6798 &fname, NULL, &sbuf);
6799 if (!NT_STATUS_IS_OK(status)) {
6800 reply_nterror(req, status);
6801 return;
6802 }
6803
6804 status = check_name(conn, fname);
6805 if (!NT_STATUS_IS_OK(status)) {
6806 reply_nterror(req, status);
6807 return;
6808 }
6809
6810 if (INFO_LEVEL_IS_UNIX(info_level)) {
6811 /*
6812 * For CIFS UNIX extensions the target name may not exist.
6813 */
6814
6815 /* Always do lstat for UNIX calls. */
6816 SMB_VFS_LSTAT(conn,fname,&sbuf);
6817
6818 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6819 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6820 reply_unixerror(req, ERRDOS, ERRbadpath);
6821 return;
6822 }
6823 }
6824
6825 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6826 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6827 return;
6828 }
6829
6830 if (!CAN_WRITE(conn)) {
6831 /* Allow POSIX opens. The open path will deny
6832 * any non-readonly opens. */
6833 if (info_level != SMB_POSIX_PATH_OPEN) {
6834 reply_doserror(req, ERRSRV, ERRaccess);
6835 return;
6836 }
6837 }
6838
6839 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6840 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6841
6842 /* Realloc the parameter size */
6843 *pparams = (char *)SMB_REALLOC(*pparams,2);
6844 if (*pparams == NULL) {
6845 reply_nterror(req, NT_STATUS_NO_MEMORY);
6846 return;
6847 }
6848 params = *pparams;
6849
6850 SSVAL(params,0,0);
6851
6852 switch (info_level) {
6853
6854 case SMB_INFO_STANDARD:
6855 {
6856 status = smb_set_info_standard(conn,
6857 pdata,
6858 total_data,
6859 fsp,
6860 fname,
6861 &sbuf);
6862 break;
6863 }
6864
6865 case SMB_INFO_SET_EA:
6866 {
6867 status = smb_info_set_ea(conn,
6868 pdata,
6869 total_data,
6870 fsp,
6871 fname);
6872 break;
6873 }
6874
6875 case SMB_SET_FILE_BASIC_INFO:
6876 case SMB_FILE_BASIC_INFORMATION:
6877 {
6878 status = smb_set_file_basic_info(conn,
6879 pdata,
6880 total_data,
6881 fsp,
6882 fname,
6883 &sbuf);
6884 break;
6885 }
6886
6887 case SMB_FILE_ALLOCATION_INFORMATION:
6888 case SMB_SET_FILE_ALLOCATION_INFO:
6889 {
6890 status = smb_set_file_allocation_info(conn, req,
6891 pdata,
6892 total_data,
6893 fsp,
6894 fname,
6895 &sbuf);
6896 break;
6897 }
6898
6899 case SMB_FILE_END_OF_FILE_INFORMATION:
6900 case SMB_SET_FILE_END_OF_FILE_INFO:
6901 {
6902 status = smb_set_file_end_of_file_info(conn, req,
6903 pdata,
6904 total_data,
6905 fsp,
6906 fname,
6907 &sbuf);
6908 break;
6909 }
6910
6911 case SMB_FILE_DISPOSITION_INFORMATION:
6912 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6913 {
6914#if 0
6915 /* JRA - We used to just ignore this on a path ?
6916 * Shouldn't this be invalid level on a pathname
6917 * based call ?
6918 */
6919 if (tran_call != TRANSACT2_SETFILEINFO) {
6920 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6921 }
6922#endif
6923 status = smb_set_file_disposition_info(conn,
6924 pdata,
6925 total_data,
6926 fsp,
6927 fname,
6928 &sbuf);
6929 break;
6930 }
6931
6932 case SMB_FILE_POSITION_INFORMATION:
6933 {
6934 status = smb_file_position_information(conn,
6935 pdata,
6936 total_data,
6937 fsp);
6938 break;
6939 }
6940
6941 /* From tridge Samba4 :
6942 * MODE_INFORMATION in setfileinfo (I have no
6943 * idea what "mode information" on a file is - it takes a value of 0,
6944 * 2, 4 or 6. What could it be?).
6945 */
6946
6947 case SMB_FILE_MODE_INFORMATION:
6948 {
6949 status = smb_file_mode_information(conn,
6950 pdata,
6951 total_data);
6952 break;
6953 }
6954
6955 /*
6956 * CIFS UNIX extensions.
6957 */
6958
6959 case SMB_SET_FILE_UNIX_BASIC:
6960 {
6961 status = smb_set_file_unix_basic(conn, req,
6962 pdata,
6963 total_data,
6964 fsp,
6965 fname,
6966 &sbuf);
6967 break;
6968 }
6969
6970 case SMB_SET_FILE_UNIX_INFO2:
6971 {
6972 status = smb_set_file_unix_info2(conn, req,
6973 pdata,
6974 total_data,
6975 fsp,
6976 fname,
6977 &sbuf);
6978 break;
6979 }
6980
6981 case SMB_SET_FILE_UNIX_LINK:
6982 {
6983 if (tran_call != TRANSACT2_SETPATHINFO) {
6984 /* We must have a pathname for this. */
6985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6986 return;
6987 }
6988 status = smb_set_file_unix_link(conn, req, pdata,
6989 total_data, fname);
6990 break;
6991 }
6992
6993 case SMB_SET_FILE_UNIX_HLINK:
6994 {
6995 if (tran_call != TRANSACT2_SETPATHINFO) {
6996 /* We must have a pathname for this. */
6997 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6998 return;
6999 }
7000 status = smb_set_file_unix_hlink(conn, req,
7001 pdata, total_data,
7002 fname);
7003 break;
7004 }
7005
7006 case SMB_FILE_RENAME_INFORMATION:
7007 {
7008 status = smb_file_rename_information(conn, req,
7009 pdata, total_data,
7010 fsp, fname);
7011 break;
7012 }
7013
7014#if defined(HAVE_POSIX_ACLS)
7015 case SMB_SET_POSIX_ACL:
7016 {
7017 status = smb_set_posix_acl(conn,
7018 pdata,
7019 total_data,
7020 fsp,
7021 fname,
7022 &sbuf);
7023 break;
7024 }
7025#endif
7026
7027 case SMB_SET_POSIX_LOCK:
7028 {
7029 if (tran_call != TRANSACT2_SETFILEINFO) {
7030 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7031 return;
7032 }
7033 status = smb_set_posix_lock(conn, req,
7034 pdata, total_data, fsp);
7035 break;
7036 }
7037
7038 case SMB_POSIX_PATH_OPEN:
7039 {
7040 if (tran_call != TRANSACT2_SETPATHINFO) {
7041 /* We must have a pathname for this. */
7042 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7043 return;
7044 }
7045
7046 status = smb_posix_open(conn, req,
7047 ppdata,
7048 total_data,
7049 fname,
7050 &sbuf,
7051 &data_return_size);
7052 break;
7053 }
7054
7055 case SMB_POSIX_PATH_UNLINK:
7056 {
7057 if (tran_call != TRANSACT2_SETPATHINFO) {
7058 /* We must have a pathname for this. */
7059 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7060 return;
7061 }
7062
7063 status = smb_posix_unlink(conn, req,
7064 pdata,
7065 total_data,
7066 fname,
7067 &sbuf);
7068 break;
7069 }
7070
7071 default:
7072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7073 return;
7074 }
7075
7076
7077 if (!NT_STATUS_IS_OK(status)) {
7078 if (open_was_deferred(req->mid)) {
7079 /* We have re-scheduled this call. */
7080 return;
7081 }
7082 if (blocking_lock_was_deferred(req->mid)) {
7083 /* We have re-scheduled this call. */
7084 return;
7085 }
7086 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7087 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7088 ERRSRV, ERRbadpath);
7089 return;
7090 }
7091 if (info_level == SMB_POSIX_PATH_OPEN) {
7092 reply_openerror(req, status);
7093 return;
7094 }
7095
7096 reply_nterror(req, status);
7097 return;
7098 }
7099
7100 SSVAL(params,0,0);
7101 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7102 max_data_bytes);
7103
7104 return;
7105}
7106
7107/****************************************************************************
7108 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7109****************************************************************************/
7110
7111static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7112 char **pparams, int total_params,
7113 char **ppdata, int total_data,
7114 unsigned int max_data_bytes)
7115{
7116 char *params = *pparams;
7117 char *pdata = *ppdata;
7118 char *directory = NULL;
7119 SMB_STRUCT_STAT sbuf;
7120 NTSTATUS status = NT_STATUS_OK;
7121 struct ea_list *ea_list = NULL;
7122 TALLOC_CTX *ctx = talloc_tos();
7123
7124 if (!CAN_WRITE(conn)) {
7125 reply_doserror(req, ERRSRV, ERRaccess);
7126 return;
7127 }
7128
7129 if (total_params < 5) {
7130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7131 return;
7132 }
7133
7134 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7135 total_params - 4, STR_TERMINATE,
7136 &status);
7137 if (!NT_STATUS_IS_OK(status)) {
7138 reply_nterror(req, status);
7139 return;
7140 }
7141
7142 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7143
7144 status = resolve_dfspath(ctx,
7145 conn,
7146 req->flags2 & FLAGS2_DFS_PATHNAMES,
7147 directory,
7148 &directory);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7151 reply_botherror(req,
7152 NT_STATUS_PATH_NOT_COVERED,
7153 ERRSRV, ERRbadpath);
7154 }
7155 reply_nterror(req, status);
7156 return;
7157 }
7158
7159 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 reply_nterror(req, status);
7162 return;
7163 }
7164
7165 status = check_name(conn, directory);
7166 if (!NT_STATUS_IS_OK(status)) {
7167 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7168 reply_nterror(req, status);
7169 return;
7170 }
7171
7172 /* Any data in this call is an EA list. */
7173 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7174 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7175 return;
7176 }
7177
7178 /*
7179 * OS/2 workplace shell seems to send SET_EA requests of "null"
7180 * length (4 bytes containing IVAL 4).
7181 * They seem to have no effect. Bug #3212. JRA.
7182 */
7183
7184 if (total_data != 4) {
7185 if (total_data < 10) {
7186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7187 return;
7188 }
7189
7190 if (IVAL(pdata,0) > total_data) {
7191 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7192 IVAL(pdata,0), (unsigned int)total_data));
7193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7194 return;
7195 }
7196
7197 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7198 total_data - 4);
7199 if (!ea_list) {
7200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7201 return;
7202 }
7203 }
7204 /* If total_data == 4 Windows doesn't care what values
7205 * are placed in that field, it just ignores them.
7206 * The System i QNTC IBM SMB client puts bad values here,
7207 * so ignore them. */
7208
7209 status = create_directory(conn, req, directory);
7210
7211 if (!NT_STATUS_IS_OK(status)) {
7212 reply_nterror(req, status);
7213 return;
7214 }
7215
7216 /* Try and set any given EA. */
7217 if (ea_list) {
7218 status = set_ea(conn, NULL, directory, ea_list);
7219 if (!NT_STATUS_IS_OK(status)) {
7220 reply_nterror(req, status);
7221 return;
7222 }
7223 }
7224
7225 /* Realloc the parameter and data sizes */
7226 *pparams = (char *)SMB_REALLOC(*pparams,2);
7227 if(*pparams == NULL) {
7228 reply_nterror(req, NT_STATUS_NO_MEMORY);
7229 return;
7230 }
7231 params = *pparams;
7232
7233 SSVAL(params,0,0);
7234
7235 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7236
7237 return;
7238}
7239
7240/****************************************************************************
7241 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7242 We don't actually do this - we just send a null response.
7243****************************************************************************/
7244
7245static void call_trans2findnotifyfirst(connection_struct *conn,
7246 struct smb_request *req,
7247 char **pparams, int total_params,
7248 char **ppdata, int total_data,
7249 unsigned int max_data_bytes)
7250{
7251 static uint16 fnf_handle = 257;
7252 char *params = *pparams;
7253 uint16 info_level;
7254
7255 if (total_params < 6) {
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257 return;
7258 }
7259
7260 info_level = SVAL(params,4);
7261 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7262
7263 switch (info_level) {
7264 case 1:
7265 case 2:
7266 break;
7267 default:
7268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7269 return;
7270 }
7271
7272 /* Realloc the parameter and data sizes */
7273 *pparams = (char *)SMB_REALLOC(*pparams,6);
7274 if (*pparams == NULL) {
7275 reply_nterror(req, NT_STATUS_NO_MEMORY);
7276 return;
7277 }
7278 params = *pparams;
7279
7280 SSVAL(params,0,fnf_handle);
7281 SSVAL(params,2,0); /* No changes */
7282 SSVAL(params,4,0); /* No EA errors */
7283
7284 fnf_handle++;
7285
7286 if(fnf_handle == 0)
7287 fnf_handle = 257;
7288
7289 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7290
7291 return;
7292}
7293
7294/****************************************************************************
7295 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7296 changes). Currently this does nothing.
7297****************************************************************************/
7298
7299static void call_trans2findnotifynext(connection_struct *conn,
7300 struct smb_request *req,
7301 char **pparams, int total_params,
7302 char **ppdata, int total_data,
7303 unsigned int max_data_bytes)
7304{
7305 char *params = *pparams;
7306
7307 DEBUG(3,("call_trans2findnotifynext\n"));
7308
7309 /* Realloc the parameter and data sizes */
7310 *pparams = (char *)SMB_REALLOC(*pparams,4);
7311 if (*pparams == NULL) {
7312 reply_nterror(req, NT_STATUS_NO_MEMORY);
7313 return;
7314 }
7315 params = *pparams;
7316
7317 SSVAL(params,0,0); /* No changes */
7318 SSVAL(params,2,0); /* No EA errors */
7319
7320 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7321
7322 return;
7323}
7324
7325/****************************************************************************
7326 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7327****************************************************************************/
7328
7329static void call_trans2getdfsreferral(connection_struct *conn,
7330 struct smb_request *req,
7331 char **pparams, int total_params,
7332 char **ppdata, int total_data,
7333 unsigned int max_data_bytes)
7334{
7335 char *params = *pparams;
7336 char *pathname = NULL;
7337 int reply_size = 0;
7338 int max_referral_level;
7339 NTSTATUS status = NT_STATUS_OK;
7340 TALLOC_CTX *ctx = talloc_tos();
7341
7342 DEBUG(10,("call_trans2getdfsreferral\n"));
7343
7344 if (total_params < 3) {
7345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7346 return;
7347 }
7348
7349 max_referral_level = SVAL(params,0);
7350
7351 if(!lp_host_msdfs()) {
7352 reply_doserror(req, ERRDOS, ERRbadfunc);
7353 return;
7354 }
7355
7356 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7357 total_params - 2, STR_TERMINATE);
7358 if (!pathname) {
7359 reply_nterror(req, NT_STATUS_NOT_FOUND);
7360 return;
7361 }
7362 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7363 ppdata,&status)) < 0) {
7364 reply_nterror(req, status);
7365 return;
7366 }
7367
7368 SSVAL(req->inbuf, smb_flg2,
7369 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7370 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7371
7372 return;
7373}
7374
7375#define LMCAT_SPL 0x53
7376#define LMFUNC_GETJOBID 0x60
7377
7378/****************************************************************************
7379 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7380****************************************************************************/
7381
7382static void call_trans2ioctl(connection_struct *conn,
7383 struct smb_request *req,
7384 char **pparams, int total_params,
7385 char **ppdata, int total_data,
7386 unsigned int max_data_bytes)
7387{
7388 char *pdata = *ppdata;
7389 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7390
7391 /* check for an invalid fid before proceeding */
7392
7393 if (!fsp) {
7394 reply_doserror(req, ERRDOS, ERRbadfid);
7395 return;
7396 }
7397
7398 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7399 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7400 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7401 if (*ppdata == NULL) {
7402 reply_nterror(req, NT_STATUS_NO_MEMORY);
7403 return;
7404 }
7405 pdata = *ppdata;
7406
7407 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7408 CAN ACCEPT THIS IN UNICODE. JRA. */
7409
7410 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7411 srvstr_push(pdata, req->flags2, pdata + 2,
7412 global_myname(), 15,
7413 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7414 srvstr_push(pdata, req->flags2, pdata+18,
7415 lp_servicename(SNUM(conn)), 13,
7416 STR_ASCII|STR_TERMINATE); /* Service name */
7417 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7418 max_data_bytes);
7419 return;
7420 }
7421
7422 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7423 reply_doserror(req, ERRSRV, ERRerror);
7424}
7425
7426/****************************************************************************
7427 Reply to a SMBfindclose (stop trans2 directory search).
7428****************************************************************************/
7429
7430void reply_findclose(struct smb_request *req)
7431{
7432 int dptr_num;
7433
7434 START_PROFILE(SMBfindclose);
7435
7436 if (req->wct < 1) {
7437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7438 END_PROFILE(SMBfindclose);
7439 return;
7440 }
7441
7442 dptr_num = SVALS(req->inbuf,smb_vwv0);
7443
7444 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7445
7446 dptr_close(&dptr_num);
7447
7448 reply_outbuf(req, 0, 0);
7449
7450 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7451
7452 END_PROFILE(SMBfindclose);
7453 return;
7454}
7455
7456/****************************************************************************
7457 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7458****************************************************************************/
7459
7460void reply_findnclose(struct smb_request *req)
7461{
7462 int dptr_num;
7463
7464 START_PROFILE(SMBfindnclose);
7465
7466 if (req->wct < 1) {
7467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7468 END_PROFILE(SMBfindnclose);
7469 return;
7470 }
7471
7472 dptr_num = SVAL(req->inbuf,smb_vwv0);
7473
7474 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7475
7476 /* We never give out valid handles for a
7477 findnotifyfirst - so any dptr_num is ok here.
7478 Just ignore it. */
7479
7480 reply_outbuf(req, 0, 0);
7481
7482 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7483
7484 END_PROFILE(SMBfindnclose);
7485 return;
7486}
7487
7488static void handle_trans2(connection_struct *conn, struct smb_request *req,
7489 struct trans_state *state)
7490{
7491 if (Protocol >= PROTOCOL_NT1) {
7492 req->flags2 |= 0x40; /* IS_LONG_NAME */
7493 SSVAL(req->inbuf,smb_flg2,req->flags2);
7494 }
7495
7496 if (conn->encrypt_level == Required && !req->encrypted) {
7497 if (state->call != TRANSACT2_QFSINFO &&
7498 state->call != TRANSACT2_SETFSINFO) {
7499 DEBUG(0,("handle_trans2: encryption required "
7500 "with call 0x%x\n",
7501 (unsigned int)state->call));
7502 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7503 return;
7504 }
7505 }
7506
7507 /* Now we must call the relevant TRANS2 function */
7508 switch(state->call) {
7509 case TRANSACT2_OPEN:
7510 {
7511 START_PROFILE(Trans2_open);
7512 call_trans2open(conn, req,
7513 &state->param, state->total_param,
7514 &state->data, state->total_data,
7515 state->max_data_return);
7516 END_PROFILE(Trans2_open);
7517 break;
7518 }
7519
7520 case TRANSACT2_FINDFIRST:
7521 {
7522 START_PROFILE(Trans2_findfirst);
7523 call_trans2findfirst(conn, req,
7524 &state->param, state->total_param,
7525 &state->data, state->total_data,
7526 state->max_data_return);
7527 END_PROFILE(Trans2_findfirst);
7528 break;
7529 }
7530
7531 case TRANSACT2_FINDNEXT:
7532 {
7533 START_PROFILE(Trans2_findnext);
7534 call_trans2findnext(conn, req,
7535 &state->param, state->total_param,
7536 &state->data, state->total_data,
7537 state->max_data_return);
7538 END_PROFILE(Trans2_findnext);
7539 break;
7540 }
7541
7542 case TRANSACT2_QFSINFO:
7543 {
7544 START_PROFILE(Trans2_qfsinfo);
7545 call_trans2qfsinfo(conn, req,
7546 &state->param, state->total_param,
7547 &state->data, state->total_data,
7548 state->max_data_return);
7549 END_PROFILE(Trans2_qfsinfo);
7550 break;
7551 }
7552
7553 case TRANSACT2_SETFSINFO:
7554 {
7555 START_PROFILE(Trans2_setfsinfo);
7556 call_trans2setfsinfo(conn, req,
7557 &state->param, state->total_param,
7558 &state->data, state->total_data,
7559 state->max_data_return);
7560 END_PROFILE(Trans2_setfsinfo);
7561 break;
7562 }
7563
7564 case TRANSACT2_QPATHINFO:
7565 case TRANSACT2_QFILEINFO:
7566 {
7567 START_PROFILE(Trans2_qpathinfo);
7568 call_trans2qfilepathinfo(conn, req, state->call,
7569 &state->param, state->total_param,
7570 &state->data, state->total_data,
7571 state->max_data_return);
7572 END_PROFILE(Trans2_qpathinfo);
7573 break;
7574 }
7575
7576 case TRANSACT2_SETPATHINFO:
7577 case TRANSACT2_SETFILEINFO:
7578 {
7579 START_PROFILE(Trans2_setpathinfo);
7580 call_trans2setfilepathinfo(conn, req, state->call,
7581 &state->param, state->total_param,
7582 &state->data, state->total_data,
7583 state->max_data_return);
7584 END_PROFILE(Trans2_setpathinfo);
7585 break;
7586 }
7587
7588 case TRANSACT2_FINDNOTIFYFIRST:
7589 {
7590 START_PROFILE(Trans2_findnotifyfirst);
7591 call_trans2findnotifyfirst(conn, req,
7592 &state->param, state->total_param,
7593 &state->data, state->total_data,
7594 state->max_data_return);
7595 END_PROFILE(Trans2_findnotifyfirst);
7596 break;
7597 }
7598
7599 case TRANSACT2_FINDNOTIFYNEXT:
7600 {
7601 START_PROFILE(Trans2_findnotifynext);
7602 call_trans2findnotifynext(conn, req,
7603 &state->param, state->total_param,
7604 &state->data, state->total_data,
7605 state->max_data_return);
7606 END_PROFILE(Trans2_findnotifynext);
7607 break;
7608 }
7609
7610 case TRANSACT2_MKDIR:
7611 {
7612 START_PROFILE(Trans2_mkdir);
7613 call_trans2mkdir(conn, req,
7614 &state->param, state->total_param,
7615 &state->data, state->total_data,
7616 state->max_data_return);
7617 END_PROFILE(Trans2_mkdir);
7618 break;
7619 }
7620
7621 case TRANSACT2_GET_DFS_REFERRAL:
7622 {
7623 START_PROFILE(Trans2_get_dfs_referral);
7624 call_trans2getdfsreferral(conn, req,
7625 &state->param, state->total_param,
7626 &state->data, state->total_data,
7627 state->max_data_return);
7628 END_PROFILE(Trans2_get_dfs_referral);
7629 break;
7630 }
7631
7632 case TRANSACT2_IOCTL:
7633 {
7634 START_PROFILE(Trans2_ioctl);
7635 call_trans2ioctl(conn, req,
7636 &state->param, state->total_param,
7637 &state->data, state->total_data,
7638 state->max_data_return);
7639 END_PROFILE(Trans2_ioctl);
7640 break;
7641 }
7642
7643 default:
7644 /* Error in request */
7645 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7646 reply_doserror(req, ERRSRV,ERRerror);
7647 }
7648}
7649
7650/****************************************************************************
7651 Reply to a SMBtrans2.
7652 ****************************************************************************/
7653
7654void reply_trans2(struct smb_request *req)
7655{
7656 connection_struct *conn = req->conn;
7657 unsigned int dsoff;
7658 unsigned int dscnt;
7659 unsigned int psoff;
7660 unsigned int pscnt;
7661 unsigned int tran_call;
7662 unsigned int size;
7663 unsigned int av_size;
7664 struct trans_state *state;
7665 NTSTATUS result;
7666
7667 START_PROFILE(SMBtrans2);
7668
7669 if (req->wct < 14) {
7670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671 END_PROFILE(SMBtrans2);
7672 return;
7673 }
7674
7675 dsoff = SVAL(req->inbuf, smb_dsoff);
7676 dscnt = SVAL(req->inbuf, smb_dscnt);
7677 psoff = SVAL(req->inbuf, smb_psoff);
7678 pscnt = SVAL(req->inbuf, smb_pscnt);
7679 tran_call = SVAL(req->inbuf, smb_setup0);
7680 size = smb_len(req->inbuf) + 4;
7681 av_size = smb_len(req->inbuf);
7682
7683 result = allow_new_trans(conn->pending_trans, req->mid);
7684 if (!NT_STATUS_IS_OK(result)) {
7685 DEBUG(2, ("Got invalid trans2 request: %s\n",
7686 nt_errstr(result)));
7687 reply_nterror(req, result);
7688 END_PROFILE(SMBtrans2);
7689 return;
7690 }
7691
7692 if (IS_IPC(conn)) {
7693 switch (tran_call) {
7694 /* List the allowed trans2 calls on IPC$ */
7695 case TRANSACT2_OPEN:
7696 case TRANSACT2_GET_DFS_REFERRAL:
7697 case TRANSACT2_QFILEINFO:
7698 case TRANSACT2_QFSINFO:
7699 case TRANSACT2_SETFSINFO:
7700 break;
7701 default:
7702 reply_doserror(req, ERRSRV, ERRaccess);
7703 END_PROFILE(SMBtrans2);
7704 return;
7705 }
7706 }
7707
7708 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7709 DEBUG(0, ("talloc failed\n"));
7710 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 END_PROFILE(SMBtrans2);
7712 return;
7713 }
7714
7715 state->cmd = SMBtrans2;
7716
7717 state->mid = req->mid;
7718 state->vuid = req->vuid;
7719 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7720 state->setup = NULL;
7721 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7722 state->param = NULL;
7723 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7724 state->data = NULL;
7725 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7726 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7727 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7728 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7729 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7730
7731 state->call = tran_call;
7732
7733 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7734 is so as a sanity check */
7735 if (state->setup_count != 1) {
7736 /*
7737 * Need to have rc=0 for ioctl to get job id for OS/2.
7738 * Network printing will fail if function is not successful.
7739 * Similar function in reply.c will be used if protocol
7740 * is LANMAN1.0 instead of LM1.2X002.
7741 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7742 * outbuf doesn't have to be set(only job id is used).
7743 */
7744 if ( (state->setup_count == 4)
7745 && (tran_call == TRANSACT2_IOCTL)
7746 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7747 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7748 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7749 } else {
7750 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7751 DEBUG(2,("Transaction is %d\n",tran_call));
7752 TALLOC_FREE(state);
7753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754 END_PROFILE(SMBtrans2);
7755 return;
7756 }
7757 }
7758
7759 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7760 goto bad_param;
7761
7762 if (state->total_data) {
7763 /* Can't use talloc here, the core routines do realloc on the
7764 * params and data. */
7765 state->data = (char *)SMB_MALLOC(state->total_data);
7766 if (state->data == NULL) {
7767 DEBUG(0,("reply_trans2: data malloc fail for %u "
7768 "bytes !\n", (unsigned int)state->total_data));
7769 TALLOC_FREE(state);
7770 reply_nterror(req, NT_STATUS_NO_MEMORY);
7771 END_PROFILE(SMBtrans2);
7772 return;
7773 }
7774
7775 if (dscnt > state->total_data ||
7776 dsoff+dscnt < dsoff) {
7777 goto bad_param;
7778 }
7779
7780 if (dsoff > av_size ||
7781 dscnt > av_size ||
7782 dsoff+dscnt > av_size) {
7783 goto bad_param;
7784 }
7785
7786 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7787 }
7788
7789 if (state->total_param) {
7790 /* Can't use talloc here, the core routines do realloc on the
7791 * params and data. */
7792 state->param = (char *)SMB_MALLOC(state->total_param);
7793 if (state->param == NULL) {
7794 DEBUG(0,("reply_trans: param malloc fail for %u "
7795 "bytes !\n", (unsigned int)state->total_param));
7796 SAFE_FREE(state->data);
7797 TALLOC_FREE(state);
7798 reply_nterror(req, NT_STATUS_NO_MEMORY);
7799 END_PROFILE(SMBtrans2);
7800 return;
7801 }
7802
7803 if (pscnt > state->total_param ||
7804 psoff+pscnt < psoff) {
7805 goto bad_param;
7806 }
7807
7808 if (psoff > av_size ||
7809 pscnt > av_size ||
7810 psoff+pscnt > av_size) {
7811 goto bad_param;
7812 }
7813
7814 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7815 }
7816
7817 state->received_data = dscnt;
7818 state->received_param = pscnt;
7819
7820 if ((state->received_param == state->total_param) &&
7821 (state->received_data == state->total_data)) {
7822
7823 handle_trans2(conn, req, state);
7824
7825 SAFE_FREE(state->data);
7826 SAFE_FREE(state->param);
7827 TALLOC_FREE(state);
7828 END_PROFILE(SMBtrans2);
7829 return;
7830 }
7831
7832 DLIST_ADD(conn->pending_trans, state);
7833
7834 /* We need to send an interim response then receive the rest
7835 of the parameter/data bytes */
7836 reply_outbuf(req, 0, 0);
7837 show_msg((char *)req->outbuf);
7838 END_PROFILE(SMBtrans2);
7839 return;
7840
7841 bad_param:
7842
7843 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7844 SAFE_FREE(state->data);
7845 SAFE_FREE(state->param);
7846 TALLOC_FREE(state);
7847 END_PROFILE(SMBtrans2);
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849}
7850
7851
7852/****************************************************************************
7853 Reply to a SMBtranss2
7854 ****************************************************************************/
7855
7856void reply_transs2(struct smb_request *req)
7857{
7858 connection_struct *conn = req->conn;
7859 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7860 struct trans_state *state;
7861 unsigned int size;
7862 unsigned int av_size;
7863
7864 START_PROFILE(SMBtranss2);
7865
7866 show_msg((char *)req->inbuf);
7867
7868 if (req->wct < 8) {
7869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7870 END_PROFILE(SMBtranss2);
7871 return;
7872 }
7873
7874 size = smb_len(req->inbuf)+4;
7875 av_size = smb_len(req->inbuf);
7876
7877 for (state = conn->pending_trans; state != NULL;
7878 state = state->next) {
7879 if (state->mid == req->mid) {
7880 break;
7881 }
7882 }
7883
7884 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7886 END_PROFILE(SMBtranss2);
7887 return;
7888 }
7889
7890 /* Revise state->total_param and state->total_data in case they have
7891 changed downwards */
7892
7893 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7894 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7895 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7896 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7897
7898 pcnt = SVAL(req->inbuf, smb_spscnt);
7899 poff = SVAL(req->inbuf, smb_spsoff);
7900 pdisp = SVAL(req->inbuf, smb_spsdisp);
7901
7902 dcnt = SVAL(req->inbuf, smb_sdscnt);
7903 doff = SVAL(req->inbuf, smb_sdsoff);
7904 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7905
7906 state->received_param += pcnt;
7907 state->received_data += dcnt;
7908
7909 if ((state->received_data > state->total_data) ||
7910 (state->received_param > state->total_param))
7911 goto bad_param;
7912
7913 if (pcnt) {
7914 if (pdisp > state->total_param ||
7915 pcnt > state->total_param ||
7916 pdisp+pcnt > state->total_param ||
7917 pdisp+pcnt < pdisp) {
7918 goto bad_param;
7919 }
7920
7921 if (poff > av_size ||
7922 pcnt > av_size ||
7923 poff+pcnt > av_size ||
7924 poff+pcnt < poff) {
7925 goto bad_param;
7926 }
7927
7928 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7929 pcnt);
7930 }
7931
7932 if (dcnt) {
7933 if (ddisp > state->total_data ||
7934 dcnt > state->total_data ||
7935 ddisp+dcnt > state->total_data ||
7936 ddisp+dcnt < ddisp) {
7937 goto bad_param;
7938 }
7939
7940 if (doff > av_size ||
7941 dcnt > av_size ||
7942 doff+dcnt > av_size ||
7943 doff+dcnt < doff) {
7944 goto bad_param;
7945 }
7946
7947 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7948 dcnt);
7949 }
7950
7951 if ((state->received_param < state->total_param) ||
7952 (state->received_data < state->total_data)) {
7953 END_PROFILE(SMBtranss2);
7954 return;
7955 }
7956
7957 /*
7958 * construct_reply_common will copy smb_com from inbuf to
7959 * outbuf. SMBtranss2 is wrong here.
7960 */
7961 SCVAL(req->inbuf,smb_com,SMBtrans2);
7962
7963 handle_trans2(conn, req, state);
7964
7965 DLIST_REMOVE(conn->pending_trans, state);
7966 SAFE_FREE(state->data);
7967 SAFE_FREE(state->param);
7968 TALLOC_FREE(state);
7969
7970 END_PROFILE(SMBtranss2);
7971 return;
7972
7973 bad_param:
7974
7975 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7976 DLIST_REMOVE(conn->pending_trans, state);
7977 SAFE_FREE(state->data);
7978 SAFE_FREE(state->param);
7979 TALLOC_FREE(state);
7980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7981 END_PROFILE(SMBtranss2);
7982 return;
7983}
Note: See TracBrowser for help on using the repository browser.