source: branches/samba-3.2.x/source/smbd/trans2.c@ 814

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

Update 3.2 to 3.2.14 (final)

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