source: branches/samba-3.0/source/smbd/trans2.c

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

Update 3.0 to final 3.0.36 (source)

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