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

Last change on this file since 198 was 154, checked in by Yuri Dario, 17 years ago

If a pending time is stored, do not change also the file. Fixes ticket:60.

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