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

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

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

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