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

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

Update 3.2 branch to 3.2.6

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