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

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

Update 3.2 branch to 3.2.5

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