source: trunk/samba-3.0.25pre1/source/smbd/trans2.c@ 1

Last change on this file since 1 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

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