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

Last change on this file since 223 was 165, checked in by Paul Smedley, 16 years ago

Add 'missing' 3.0.34 diffs

File size: 197.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 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 {
5485 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5486 (unsigned int)wire_open_mode ));
5487 return NT_STATUS_INVALID_PARAMETER;
5488 }
5489
5490 raw_unixmode = IVAL(pdata,8);
5491 /* Next 4 bytes are not yet defined. */
5492
5493 status = unix_perms_from_wire(conn,
5494 psbuf,
5495 raw_unixmode,
5496 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5497 &unixmode);
5498
5499 if (!NT_STATUS_IS_OK(status)) {
5500 return status;
5501 }
5502
5503 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5504
5505 if (wire_open_mode & SMB_O_SYNC) {
5506 create_options |= FILE_WRITE_THROUGH;
5507 }
5508 if (wire_open_mode & SMB_O_APPEND) {
5509 access_mask |= FILE_APPEND_DATA;
5510 }
5511 if (wire_open_mode & SMB_O_DIRECT) {
5512 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5513 }
5514
5515 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5516 fname,
5517 (unsigned int)wire_open_mode,
5518 (unsigned int)unixmode ));
5519
5520 status = open_file_ntcreate(conn,
5521 fname,
5522 psbuf,
5523 access_mask,
5524 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5525 create_disp,
5526 0, /* no create options yet. */
5527 mod_unixmode,
5528 oplock_request,
5529 &info,
5530 &fsp);
5531
5532 if (!NT_STATUS_IS_OK(status)) {
5533 return status;
5534 }
5535
5536 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5537 extended_oplock_granted = True;
5538 }
5539
5540 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5541 extended_oplock_granted = True;
5542 }
5543
5544 info_level_return = SVAL(pdata,16);
5545
5546 /* Allocate the correct return size. */
5547
5548 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5549 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5550 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5551 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5552 } else {
5553 *pdata_return_size = 12;
5554 }
5555
5556 /* Realloc the data size */
5557 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5558 if (*ppdata == NULL) {
5559 close_file(fsp,ERROR_CLOSE);
5560 *pdata_return_size = 0;
5561 return NT_STATUS_NO_MEMORY;
5562 }
5563 pdata = *ppdata;
5564
5565 if (extended_oplock_granted) {
5566 if (flags & REQUEST_BATCH_OPLOCK) {
5567 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5568 } else {
5569 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5570 }
5571 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5572 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5573 } else {
5574 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5575 }
5576
5577 SSVAL(pdata,2,fsp->fnum);
5578 SIVAL(pdata,4,info); /* Was file created etc. */
5579
5580 switch (info_level_return) {
5581 case SMB_QUERY_FILE_UNIX_BASIC:
5582 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5583 SSVAL(pdata,10,0); /* padding. */
5584 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5585 break;
5586 case SMB_QUERY_FILE_UNIX_INFO2:
5587 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5588 SSVAL(pdata,10,0); /* padding. */
5589 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5590 break;
5591 default:
5592 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5593 SSVAL(pdata,10,0); /* padding. */
5594 break;
5595 }
5596 return NT_STATUS_OK;
5597}
5598
5599/****************************************************************************
5600 Delete a file with POSIX semantics.
5601****************************************************************************/
5602
5603static NTSTATUS smb_posix_unlink(connection_struct *conn,
5604 const char *pdata,
5605 int total_data,
5606 const char *fname,
5607 SMB_STRUCT_STAT *psbuf)
5608{
5609 NTSTATUS status = NT_STATUS_OK;
5610 files_struct *fsp = NULL;
5611 uint16 flags = 0;
5612 char del = 1;
5613 int info = 0;
5614 int i;
5615 struct share_mode_lock *lck = NULL;
5616
5617 if (total_data < 2) {
5618 return NT_STATUS_INVALID_PARAMETER;
5619 }
5620
5621 flags = SVAL(pdata,0);
5622
5623 if (!VALID_STAT(*psbuf)) {
5624 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5625 }
5626
5627 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5628 !VALID_STAT_OF_DIR(*psbuf)) {
5629 return NT_STATUS_NOT_A_DIRECTORY;
5630 }
5631
5632 DEBUG(10,("smb_posix_unlink: %s %s\n",
5633 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5634 fname));
5635
5636 if (VALID_STAT_OF_DIR(*psbuf)) {
5637 status = open_directory(conn,
5638 fname,
5639 psbuf,
5640 DELETE_ACCESS,
5641 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5642 FILE_OPEN,
5643 0,
5644 FILE_FLAG_POSIX_SEMANTICS|0777,
5645 &info,
5646 &fsp);
5647 } else {
5648
5649 status = open_file_ntcreate(conn,
5650 fname,
5651 psbuf,
5652 DELETE_ACCESS,
5653 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5654 FILE_OPEN,
5655 0,
5656 FILE_FLAG_POSIX_SEMANTICS|0777,
5657 0, /* No oplock, but break existing ones. */
5658 &info,
5659 &fsp);
5660 }
5661
5662 if (!NT_STATUS_IS_OK(status)) {
5663 return status;
5664 }
5665
5666 /*
5667 * Don't lie to client. If we can't really delete due to
5668 * non-POSIX opens return SHARING_VIOLATION.
5669 */
5670
5671 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5672 if (lck == NULL) {
5673 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5674 "lock for file %s\n", fsp->fsp_name));
5675 close_file(fsp, NORMAL_CLOSE);
5676 return NT_STATUS_INVALID_PARAMETER;
5677 }
5678
5679 /*
5680 * See if others still have the file open. If this is the case, then
5681 * don't delete. If all opens are POSIX delete we can set the delete
5682 * on close disposition.
5683 */
5684 for (i=0; i<lck->num_share_modes; i++) {
5685 struct share_mode_entry *e = &lck->share_modes[i];
5686 if (is_valid_share_mode_entry(e)) {
5687 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5688 continue;
5689 }
5690 /* Fail with sharing violation. */
5691 close_file(fsp, NORMAL_CLOSE);
5692 TALLOC_FREE(lck);
5693 return NT_STATUS_SHARING_VIOLATION;
5694 }
5695 }
5696
5697 /*
5698 * Set the delete on close.
5699 */
5700 status = smb_set_file_disposition_info(conn,
5701 &del,
5702 1,
5703 fsp,
5704 fname,
5705 psbuf);
5706
5707 if (!NT_STATUS_IS_OK(status)) {
5708 close_file(fsp, NORMAL_CLOSE);
5709 TALLOC_FREE(lck);
5710 return status;
5711 }
5712 TALLOC_FREE(lck);
5713 return close_file(fsp, NORMAL_CLOSE);
5714}
5715
5716/****************************************************************************
5717 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5718****************************************************************************/
5719
5720static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5721 unsigned int tran_call,
5722 char **pparams, int total_params, char **ppdata, int total_data,
5723 unsigned int max_data_bytes)
5724{
5725 char *params = *pparams;
5726 char *pdata = *ppdata;
5727 uint16 info_level;
5728 SMB_STRUCT_STAT sbuf;
5729 pstring fname;
5730 files_struct *fsp = NULL;
5731 NTSTATUS status = NT_STATUS_OK;
5732 int data_return_size = 0;
5733
5734 if (!params) {
5735 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5736 }
5737
5738 ZERO_STRUCT(sbuf);
5739
5740 if (tran_call == TRANSACT2_SETFILEINFO) {
5741 if (total_params < 4) {
5742 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5743 }
5744
5745 fsp = file_fsp(params,0);
5746 info_level = SVAL(params,2);
5747
5748 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5749 /*
5750 * This is actually a SETFILEINFO on a directory
5751 * handle (returned from an NT SMB). NT5.0 seems
5752 * to do this call. JRA.
5753 */
5754 pstrcpy(fname, fsp->fsp_name);
5755 if (INFO_LEVEL_IS_UNIX(info_level)) {
5756 /* Always do lstat for UNIX calls. */
5757 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5758 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5759 return UNIXERROR(ERRDOS,ERRbadpath);
5760 }
5761 } else {
5762 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5763 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5764 return UNIXERROR(ERRDOS,ERRbadpath);
5765 }
5766 }
5767 } else if (fsp && fsp->print_file) {
5768 /*
5769 * Doing a DELETE_ON_CLOSE should cancel a print job.
5770 */
5771 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5772 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5773
5774 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5775
5776 SSVAL(params,0,0);
5777 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5778 return(-1);
5779 } else
5780 return (UNIXERROR(ERRDOS,ERRbadpath));
5781 } else {
5782 /*
5783 * Original code - this is an open file.
5784 */
5785 CHECK_FSP(fsp,conn);
5786
5787 pstrcpy(fname, fsp->fsp_name);
5788
5789 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5790 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5791 return(UNIXERROR(ERRDOS,ERRbadfid));
5792 }
5793 }
5794 } else {
5795 /* set path info */
5796 if (total_params < 7) {
5797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5798 }
5799
5800 info_level = SVAL(params,0);
5801 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5802 if (!NT_STATUS_IS_OK(status)) {
5803 return ERROR_NT(status);
5804 }
5805
5806 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5807 if (!NT_STATUS_IS_OK(status)) {
5808 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5809 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5810 }
5811 return ERROR_NT(status);
5812 }
5813
5814 status = unix_convert(conn, fname, False, NULL, &sbuf);
5815 if (!NT_STATUS_IS_OK(status)) {
5816 return ERROR_NT(status);
5817 }
5818
5819 status = check_name(conn, fname);
5820 if (!NT_STATUS_IS_OK(status)) {
5821 return ERROR_NT(status);
5822 }
5823
5824 if (INFO_LEVEL_IS_UNIX(info_level)) {
5825 /*
5826 * For CIFS UNIX extensions the target name may not exist.
5827 */
5828
5829 /* Always do lstat for UNIX calls. */
5830 SMB_VFS_LSTAT(conn,fname,&sbuf);
5831
5832 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5833 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5834 return UNIXERROR(ERRDOS,ERRbadpath);
5835 }
5836 }
5837
5838 if (!CAN_WRITE(conn)) {
5839 return ERROR_DOS(ERRSRV,ERRaccess);
5840 }
5841
5842 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5843 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5844 }
5845
5846 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5847 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5848
5849 /* Realloc the parameter size */
5850 *pparams = (char *)SMB_REALLOC(*pparams,2);
5851 if (*pparams == NULL) {
5852 return ERROR_NT(NT_STATUS_NO_MEMORY);
5853 }
5854 params = *pparams;
5855
5856 SSVAL(params,0,0);
5857
5858 if (fsp && !null_timespec(fsp->pending_modtime)) {
5859 /* the pending modtime overrides the current modtime */
5860 set_mtimespec(&sbuf, fsp->pending_modtime);
5861 }
5862
5863 switch (info_level) {
5864
5865 case SMB_INFO_STANDARD:
5866 {
5867 status = smb_set_info_standard(conn,
5868 pdata,
5869 total_data,
5870 fsp,
5871 fname,
5872 &sbuf);
5873 break;
5874 }
5875
5876 case SMB_INFO_SET_EA:
5877 {
5878 status = smb_info_set_ea(conn,
5879 pdata,
5880 total_data,
5881 fsp,
5882 fname);
5883 break;
5884 }
5885
5886 case SMB_SET_FILE_BASIC_INFO:
5887 case SMB_FILE_BASIC_INFORMATION:
5888 {
5889 status = smb_set_file_basic_info(conn,
5890 pdata,
5891 total_data,
5892 fsp,
5893 fname,
5894 &sbuf);
5895 break;
5896 }
5897
5898 case SMB_FILE_ALLOCATION_INFORMATION:
5899 case SMB_SET_FILE_ALLOCATION_INFO:
5900 {
5901 status = smb_set_file_allocation_info(conn,
5902 pdata,
5903 total_data,
5904 fsp,
5905 fname,
5906 &sbuf);
5907 break;
5908 }
5909
5910 case SMB_FILE_END_OF_FILE_INFORMATION:
5911 case SMB_SET_FILE_END_OF_FILE_INFO:
5912 {
5913 status = smb_set_file_end_of_file_info(conn,
5914 pdata,
5915 total_data,
5916 fsp,
5917 fname,
5918 &sbuf);
5919 break;
5920 }
5921
5922 case SMB_FILE_DISPOSITION_INFORMATION:
5923 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5924 {
5925#if 0
5926 /* JRA - We used to just ignore this on a path ?
5927 * Shouldn't this be invalid level on a pathname
5928 * based call ?
5929 */
5930 if (tran_call != TRANSACT2_SETFILEINFO) {
5931 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5932 }
5933#endif
5934 status = smb_set_file_disposition_info(conn,
5935 pdata,
5936 total_data,
5937 fsp,
5938 fname,
5939 &sbuf);
5940 break;
5941 }
5942
5943 case SMB_FILE_POSITION_INFORMATION:
5944 {
5945 status = smb_file_position_information(conn,
5946 pdata,
5947 total_data,
5948 fsp);
5949 break;
5950 }
5951
5952 /* From tridge Samba4 :
5953 * MODE_INFORMATION in setfileinfo (I have no
5954 * idea what "mode information" on a file is - it takes a value of 0,
5955 * 2, 4 or 6. What could it be?).
5956 */
5957
5958 case SMB_FILE_MODE_INFORMATION:
5959 {
5960 status = smb_file_mode_information(conn,
5961 pdata,
5962 total_data);
5963 break;
5964 }
5965
5966 /*
5967 * CIFS UNIX extensions.
5968 */
5969
5970 case SMB_SET_FILE_UNIX_BASIC:
5971 {
5972 status = smb_set_file_unix_basic(conn,
5973 pdata,
5974 total_data,
5975 fsp,
5976 fname,
5977 &sbuf);
5978 break;
5979 }
5980
5981 case SMB_SET_FILE_UNIX_INFO2:
5982 {
5983 status = smb_set_file_unix_info2(conn,
5984 pdata,
5985 total_data,
5986 fsp,
5987 fname,
5988 &sbuf);
5989 break;
5990 }
5991
5992 case SMB_SET_FILE_UNIX_LINK:
5993 {
5994 if (tran_call != TRANSACT2_SETPATHINFO) {
5995 /* We must have a pathname for this. */
5996 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5997 }
5998 status = smb_set_file_unix_link(conn,
5999 inbuf,
6000 pdata,
6001 total_data,
6002 fname);
6003 break;
6004 }
6005
6006 case SMB_SET_FILE_UNIX_HLINK:
6007 {
6008 if (tran_call != TRANSACT2_SETPATHINFO) {
6009 /* We must have a pathname for this. */
6010 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6011 }
6012 status = smb_set_file_unix_hlink(conn,
6013 inbuf,
6014 outbuf,
6015 pdata,
6016 total_data,
6017 fname);
6018 break;
6019 }
6020
6021 case SMB_FILE_RENAME_INFORMATION:
6022 {
6023 status = smb_file_rename_information(conn,
6024 inbuf,
6025 outbuf,
6026 pdata,
6027 total_data,
6028 fsp,
6029 fname);
6030 break;
6031 }
6032
6033#if defined(HAVE_POSIX_ACLS)
6034 case SMB_SET_POSIX_ACL:
6035 {
6036 status = smb_set_posix_acl(conn,
6037 pdata,
6038 total_data,
6039 fsp,
6040 fname,
6041 &sbuf);
6042 break;
6043 }
6044#endif
6045
6046 case SMB_SET_POSIX_LOCK:
6047 {
6048 if (tran_call != TRANSACT2_SETFILEINFO) {
6049 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6050 }
6051 status = smb_set_posix_lock(conn,
6052 inbuf,
6053 length,
6054 pdata,
6055 total_data,
6056 fsp);
6057 break;
6058 }
6059
6060 case SMB_POSIX_PATH_OPEN:
6061 {
6062 if (tran_call != TRANSACT2_SETPATHINFO) {
6063 /* We must have a pathname for this. */
6064 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6065 }
6066
6067 status = smb_posix_open(conn,
6068 ppdata,
6069 total_data,
6070 fname,
6071 &sbuf,
6072 &data_return_size);
6073 break;
6074 }
6075
6076 case SMB_POSIX_PATH_UNLINK:
6077 {
6078 if (tran_call != TRANSACT2_SETPATHINFO) {
6079 /* We must have a pathname for this. */
6080 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6081 }
6082
6083 status = smb_posix_unlink(conn,
6084 pdata,
6085 total_data,
6086 fname,
6087 &sbuf);
6088 break;
6089 }
6090
6091 default:
6092 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6093 }
6094
6095
6096 if (!NT_STATUS_IS_OK(status)) {
6097 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6098 /* We have re-scheduled this call. */
6099 return -1;
6100 }
6101 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6102 /* We have re-scheduled this call. */
6103 return -1;
6104 }
6105 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6106 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6107 }
6108 if (info_level == SMB_POSIX_PATH_OPEN) {
6109 return ERROR_OPEN(status);
6110 }
6111 return ERROR_NT(status);
6112 }
6113
6114 SSVAL(params,0,0);
6115 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6116
6117 return -1;
6118}
6119
6120/****************************************************************************
6121 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6122****************************************************************************/
6123
6124static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6125 char **pparams, int total_params, char **ppdata, int total_data,
6126 unsigned int max_data_bytes)
6127{
6128 char *params = *pparams;
6129 char *pdata = *ppdata;
6130 pstring directory;
6131 SMB_STRUCT_STAT sbuf;
6132 NTSTATUS status = NT_STATUS_OK;
6133 struct ea_list *ea_list = NULL;
6134
6135 if (!CAN_WRITE(conn))
6136 return ERROR_DOS(ERRSRV,ERRaccess);
6137
6138 if (total_params < 5) {
6139 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6140 }
6141
6142 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6143 if (!NT_STATUS_IS_OK(status)) {
6144 return ERROR_NT(status);
6145 }
6146
6147 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6148
6149 status = unix_convert(conn, directory, False, NULL, &sbuf);
6150 if (!NT_STATUS_IS_OK(status)) {
6151 return ERROR_NT(status);
6152 }
6153
6154 status = check_name(conn, directory);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6157 return ERROR_NT(status);
6158 }
6159
6160 /* Any data in this call is an EA list. */
6161 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6162 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6163 }
6164
6165 /*
6166 * OS/2 workplace shell seems to send SET_EA requests of "null"
6167 * length (4 bytes containing IVAL 4).
6168 * They seem to have no effect. Bug #3212. JRA.
6169 */
6170
6171 if (total_data != 4) {
6172 if (total_data < 10) {
6173 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6174 }
6175
6176 if (IVAL(pdata,0) > total_data) {
6177 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6178 IVAL(pdata,0), (unsigned int)total_data));
6179 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6180 }
6181
6182 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6183 total_data - 4);
6184 if (!ea_list) {
6185 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6186 }
6187 } else if (IVAL(pdata,0) != 4) {
6188 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6189 }
6190 /* If total_data == 4 Windows doesn't care what values
6191 * are placed in that field, it just ignores them.
6192 * The System i QNTC IBM SMB client puts bad values here,
6193 * so ignore them. */
6194
6195 status = create_directory(conn, directory);
6196
6197 if (!NT_STATUS_IS_OK(status)) {
6198 return ERROR_NT(status);
6199 }
6200
6201 /* Try and set any given EA. */
6202 if (ea_list) {
6203 status = set_ea(conn, NULL, directory, ea_list);
6204 if (!NT_STATUS_IS_OK(status)) {
6205 return ERROR_NT(status);
6206 }
6207 }
6208
6209 /* Realloc the parameter and data sizes */
6210 *pparams = (char *)SMB_REALLOC(*pparams,2);
6211 if(*pparams == NULL) {
6212 return ERROR_NT(NT_STATUS_NO_MEMORY);
6213 }
6214 params = *pparams;
6215
6216 SSVAL(params,0,0);
6217
6218 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6219
6220 return(-1);
6221}
6222
6223/****************************************************************************
6224 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6225 We don't actually do this - we just send a null response.
6226****************************************************************************/
6227
6228static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6229 char **pparams, int total_params, char **ppdata, int total_data,
6230 unsigned int max_data_bytes)
6231{
6232 static uint16 fnf_handle = 257;
6233 char *params = *pparams;
6234 uint16 info_level;
6235
6236 if (total_params < 6) {
6237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6238 }
6239
6240 info_level = SVAL(params,4);
6241 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6242
6243 switch (info_level) {
6244 case 1:
6245 case 2:
6246 break;
6247 default:
6248 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6249 }
6250
6251 /* Realloc the parameter and data sizes */
6252 *pparams = (char *)SMB_REALLOC(*pparams,6);
6253 if (*pparams == NULL) {
6254 return ERROR_NT(NT_STATUS_NO_MEMORY);
6255 }
6256 params = *pparams;
6257
6258 SSVAL(params,0,fnf_handle);
6259 SSVAL(params,2,0); /* No changes */
6260 SSVAL(params,4,0); /* No EA errors */
6261
6262 fnf_handle++;
6263
6264 if(fnf_handle == 0)
6265 fnf_handle = 257;
6266
6267 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6268
6269 return(-1);
6270}
6271
6272/****************************************************************************
6273 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6274 changes). Currently this does nothing.
6275****************************************************************************/
6276
6277static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6278 char **pparams, int total_params, char **ppdata, int total_data,
6279 unsigned int max_data_bytes)
6280{
6281 char *params = *pparams;
6282
6283 DEBUG(3,("call_trans2findnotifynext\n"));
6284
6285 /* Realloc the parameter and data sizes */
6286 *pparams = (char *)SMB_REALLOC(*pparams,4);
6287 if (*pparams == NULL) {
6288 return ERROR_NT(NT_STATUS_NO_MEMORY);
6289 }
6290 params = *pparams;
6291
6292 SSVAL(params,0,0); /* No changes */
6293 SSVAL(params,2,0); /* No EA errors */
6294
6295 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6296
6297 return(-1);
6298}
6299
6300/****************************************************************************
6301 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6302****************************************************************************/
6303
6304static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6305 char **pparams, int total_params, char **ppdata, int total_data,
6306 unsigned int max_data_bytes)
6307{
6308 char *params = *pparams;
6309 pstring pathname;
6310 int reply_size = 0;
6311 int max_referral_level;
6312 NTSTATUS status = NT_STATUS_OK;
6313
6314 DEBUG(10,("call_trans2getdfsreferral\n"));
6315
6316 if (total_params < 3) {
6317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6318 }
6319
6320 max_referral_level = SVAL(params,0);
6321
6322 if(!lp_host_msdfs())
6323 return ERROR_DOS(ERRDOS,ERRbadfunc);
6324
6325 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6326 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6327 return ERROR_NT(status);
6328
6329 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6330 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6331
6332 return(-1);
6333}
6334
6335#define LMCAT_SPL 0x53
6336#define LMFUNC_GETJOBID 0x60
6337
6338/****************************************************************************
6339 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6340****************************************************************************/
6341
6342static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6343 char **pparams, int total_params, char **ppdata, int total_data,
6344 unsigned int max_data_bytes)
6345{
6346 char *pdata = *ppdata;
6347 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6348
6349 /* check for an invalid fid before proceeding */
6350
6351 if (!fsp)
6352 return(ERROR_DOS(ERRDOS,ERRbadfid));
6353
6354 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6355 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6356 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6357 if (*ppdata == NULL) {
6358 return ERROR_NT(NT_STATUS_NO_MEMORY);
6359 }
6360 pdata = *ppdata;
6361
6362 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6363 CAN ACCEPT THIS IN UNICODE. JRA. */
6364
6365 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6366 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6367 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6368 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6369 return(-1);
6370 } else {
6371 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6372 return ERROR_DOS(ERRSRV,ERRerror);
6373 }
6374}
6375
6376/****************************************************************************
6377 Reply to a SMBfindclose (stop trans2 directory search).
6378****************************************************************************/
6379
6380int reply_findclose(connection_struct *conn,
6381 char *inbuf,char *outbuf,int length,int bufsize)
6382{
6383 int outsize = 0;
6384 int dptr_num=SVALS(inbuf,smb_vwv0);
6385 START_PROFILE(SMBfindclose);
6386
6387 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6388
6389 dptr_close(&dptr_num);
6390
6391 outsize = set_message(outbuf,0,0,False);
6392
6393 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6394
6395 END_PROFILE(SMBfindclose);
6396 return(outsize);
6397}
6398
6399/****************************************************************************
6400 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6401****************************************************************************/
6402
6403int reply_findnclose(connection_struct *conn,
6404 char *inbuf,char *outbuf,int length,int bufsize)
6405{
6406 int outsize = 0;
6407 int dptr_num= -1;
6408 START_PROFILE(SMBfindnclose);
6409
6410 dptr_num = SVAL(inbuf,smb_vwv0);
6411
6412 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6413
6414 /* We never give out valid handles for a
6415 findnotifyfirst - so any dptr_num is ok here.
6416 Just ignore it. */
6417
6418 outsize = set_message(outbuf,0,0,False);
6419
6420 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6421
6422 END_PROFILE(SMBfindnclose);
6423 return(outsize);
6424}
6425
6426int handle_trans2(connection_struct *conn,
6427 struct trans_state *state,
6428 char *inbuf, char *outbuf, int size, int bufsize)
6429{
6430 int outsize;
6431
6432 if (Protocol >= PROTOCOL_NT1) {
6433 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6434 }
6435
6436 /* Now we must call the relevant TRANS2 function */
6437 switch(state->call) {
6438 case TRANSACT2_OPEN:
6439 {
6440 START_PROFILE(Trans2_open);
6441 outsize = call_trans2open(
6442 conn, inbuf, outbuf, bufsize,
6443 &state->param, state->total_param,
6444 &state->data, state->total_data,
6445 state->max_data_return);
6446 END_PROFILE(Trans2_open);
6447 break;
6448 }
6449
6450 case TRANSACT2_FINDFIRST:
6451 {
6452 START_PROFILE(Trans2_findfirst);
6453 outsize = call_trans2findfirst(
6454 conn, inbuf, outbuf, bufsize,
6455 &state->param, state->total_param,
6456 &state->data, state->total_data,
6457 state->max_data_return);
6458 END_PROFILE(Trans2_findfirst);
6459 break;
6460 }
6461
6462 case TRANSACT2_FINDNEXT:
6463 {
6464 START_PROFILE(Trans2_findnext);
6465 outsize = call_trans2findnext(
6466 conn, inbuf, outbuf, size, bufsize,
6467 &state->param, state->total_param,
6468 &state->data, state->total_data,
6469 state->max_data_return);
6470 END_PROFILE(Trans2_findnext);
6471 break;
6472 }
6473
6474 case TRANSACT2_QFSINFO:
6475 {
6476 START_PROFILE(Trans2_qfsinfo);
6477 outsize = call_trans2qfsinfo(
6478 conn, inbuf, outbuf, size, bufsize,
6479 &state->param, state->total_param,
6480 &state->data, state->total_data,
6481 state->max_data_return);
6482 END_PROFILE(Trans2_qfsinfo);
6483 break;
6484 }
6485
6486 case TRANSACT2_SETFSINFO:
6487 {
6488 START_PROFILE(Trans2_setfsinfo);
6489 outsize = call_trans2setfsinfo(
6490 conn, inbuf, outbuf, size, bufsize,
6491 &state->param, state->total_param,
6492 &state->data, state->total_data,
6493 state->max_data_return);
6494 END_PROFILE(Trans2_setfsinfo);
6495 break;
6496 }
6497
6498 case TRANSACT2_QPATHINFO:
6499 case TRANSACT2_QFILEINFO:
6500 {
6501 START_PROFILE(Trans2_qpathinfo);
6502 outsize = call_trans2qfilepathinfo(
6503 conn, inbuf, outbuf, size, bufsize, state->call,
6504 &state->param, state->total_param,
6505 &state->data, state->total_data,
6506 state->max_data_return);
6507 END_PROFILE(Trans2_qpathinfo);
6508 break;
6509 }
6510
6511 case TRANSACT2_SETPATHINFO:
6512 case TRANSACT2_SETFILEINFO:
6513 {
6514 START_PROFILE(Trans2_setpathinfo);
6515 outsize = call_trans2setfilepathinfo(
6516 conn, inbuf, outbuf, size, bufsize, state->call,
6517 &state->param, state->total_param,
6518 &state->data, state->total_data,
6519 state->max_data_return);
6520 END_PROFILE(Trans2_setpathinfo);
6521 break;
6522 }
6523
6524 case TRANSACT2_FINDNOTIFYFIRST:
6525 {
6526 START_PROFILE(Trans2_findnotifyfirst);
6527 outsize = call_trans2findnotifyfirst(
6528 conn, inbuf, outbuf, size, bufsize,
6529 &state->param, state->total_param,
6530 &state->data, state->total_data,
6531 state->max_data_return);
6532 END_PROFILE(Trans2_findnotifyfirst);
6533 break;
6534 }
6535
6536 case TRANSACT2_FINDNOTIFYNEXT:
6537 {
6538 START_PROFILE(Trans2_findnotifynext);
6539 outsize = call_trans2findnotifynext(
6540 conn, inbuf, outbuf, size, bufsize,
6541 &state->param, state->total_param,
6542 &state->data, state->total_data,
6543 state->max_data_return);
6544 END_PROFILE(Trans2_findnotifynext);
6545 break;
6546 }
6547
6548 case TRANSACT2_MKDIR:
6549 {
6550 START_PROFILE(Trans2_mkdir);
6551 outsize = call_trans2mkdir(
6552 conn, inbuf, outbuf, size, bufsize,
6553 &state->param, state->total_param,
6554 &state->data, state->total_data,
6555 state->max_data_return);
6556 END_PROFILE(Trans2_mkdir);
6557 break;
6558 }
6559
6560 case TRANSACT2_GET_DFS_REFERRAL:
6561 {
6562 START_PROFILE(Trans2_get_dfs_referral);
6563 outsize = call_trans2getdfsreferral(
6564 conn, inbuf, outbuf, size, bufsize,
6565 &state->param, state->total_param,
6566 &state->data, state->total_data,
6567 state->max_data_return);
6568 END_PROFILE(Trans2_get_dfs_referral);
6569 break;
6570 }
6571
6572 case TRANSACT2_IOCTL:
6573 {
6574 START_PROFILE(Trans2_ioctl);
6575 outsize = call_trans2ioctl(
6576 conn, inbuf, outbuf, size, bufsize,
6577 &state->param, state->total_param,
6578 &state->data, state->total_data,
6579 state->max_data_return);
6580 END_PROFILE(Trans2_ioctl);
6581 break;
6582 }
6583
6584 default:
6585 /* Error in request */
6586 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6587 outsize = ERROR_DOS(ERRSRV,ERRerror);
6588 }
6589
6590 return outsize;
6591}
6592
6593/****************************************************************************
6594 Reply to a SMBtrans2.
6595 ****************************************************************************/
6596
6597int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6598 int size, int bufsize)
6599{
6600 int outsize = 0;
6601 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6602 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6603 unsigned int psoff = SVAL(inbuf, smb_psoff);
6604 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6605 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6606 unsigned int av_size = size-4;
6607 struct trans_state *state;
6608 NTSTATUS result;
6609
6610 START_PROFILE(SMBtrans2);
6611
6612 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6613 if (!NT_STATUS_IS_OK(result)) {
6614 DEBUG(2, ("Got invalid trans2 request: %s\n",
6615 nt_errstr(result)));
6616 END_PROFILE(SMBtrans2);
6617 return ERROR_NT(result);
6618 }
6619
6620 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6621 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6622 END_PROFILE(SMBtrans2);
6623 return ERROR_DOS(ERRSRV,ERRaccess);
6624 }
6625
6626 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6627 DEBUG(0, ("talloc failed\n"));
6628 END_PROFILE(SMBtrans2);
6629 return ERROR_NT(NT_STATUS_NO_MEMORY);
6630 }
6631
6632 state->cmd = SMBtrans2;
6633
6634 state->mid = SVAL(inbuf, smb_mid);
6635 state->vuid = SVAL(inbuf, smb_uid);
6636 state->setup_count = SVAL(inbuf, smb_suwcnt);
6637 state->setup = NULL;
6638 state->total_param = SVAL(inbuf, smb_tpscnt);
6639 state->param = NULL;
6640 state->total_data = SVAL(inbuf, smb_tdscnt);
6641 state->data = NULL;
6642 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6643 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6644 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6645 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6646 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6647
6648 state->call = tran_call;
6649
6650 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6651 is so as a sanity check */
6652 if (state->setup_count != 1) {
6653 /*
6654 * Need to have rc=0 for ioctl to get job id for OS/2.
6655 * Network printing will fail if function is not successful.
6656 * Similar function in reply.c will be used if protocol
6657 * is LANMAN1.0 instead of LM1.2X002.
6658 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6659 * outbuf doesn't have to be set(only job id is used).
6660 */
6661 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6662 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6663 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6664 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6665 } else {
6666 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6667 DEBUG(2,("Transaction is %d\n",tran_call));
6668 TALLOC_FREE(state);
6669 END_PROFILE(SMBtrans2);
6670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6671 }
6672 }
6673
6674 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6675 goto bad_param;
6676
6677 if (state->total_data) {
6678 /* Can't use talloc here, the core routines do realloc on the
6679 * params and data. */
6680 state->data = (char *)SMB_MALLOC(state->total_data);
6681 if (state->data == NULL) {
6682 DEBUG(0,("reply_trans2: data malloc fail for %u "
6683 "bytes !\n", (unsigned int)state->total_data));
6684 TALLOC_FREE(state);
6685 END_PROFILE(SMBtrans2);
6686 return(ERROR_DOS(ERRDOS,ERRnomem));
6687 }
6688
6689 if (dscnt > state->total_data ||
6690 dsoff+dscnt < dsoff) {
6691 goto bad_param;
6692 }
6693
6694 if (dsoff > av_size ||
6695 dscnt > av_size ||
6696 dsoff+dscnt > av_size) {
6697 goto bad_param;
6698 }
6699
6700 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6701 }
6702
6703 if (state->total_param) {
6704 /* Can't use talloc here, the core routines do realloc on the
6705 * params and data. */
6706 state->param = (char *)SMB_MALLOC(state->total_param);
6707 if (state->param == NULL) {
6708 DEBUG(0,("reply_trans: param malloc fail for %u "
6709 "bytes !\n", (unsigned int)state->total_param));
6710 SAFE_FREE(state->data);
6711 TALLOC_FREE(state);
6712 END_PROFILE(SMBtrans2);
6713 return(ERROR_DOS(ERRDOS,ERRnomem));
6714 }
6715
6716 if (pscnt > state->total_param ||
6717 psoff+pscnt < psoff) {
6718 goto bad_param;
6719 }
6720
6721 if (psoff > av_size ||
6722 pscnt > av_size ||
6723 psoff+pscnt > av_size) {
6724 goto bad_param;
6725 }
6726
6727 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6728 }
6729
6730 state->received_data = dscnt;
6731 state->received_param = pscnt;
6732
6733 if ((state->received_param == state->total_param) &&
6734 (state->received_data == state->total_data)) {
6735
6736 outsize = handle_trans2(conn, state, inbuf, outbuf,
6737 size, bufsize);
6738 SAFE_FREE(state->data);
6739 SAFE_FREE(state->param);
6740 TALLOC_FREE(state);
6741 END_PROFILE(SMBtrans2);
6742 return outsize;
6743 }
6744
6745 DLIST_ADD(conn->pending_trans, state);
6746
6747 /* We need to send an interim response then receive the rest
6748 of the parameter/data bytes */
6749 outsize = set_message(outbuf,0,0,False);
6750 show_msg(outbuf);
6751 END_PROFILE(SMBtrans2);
6752 return outsize;
6753
6754 bad_param:
6755
6756 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6757 SAFE_FREE(state->data);
6758 SAFE_FREE(state->param);
6759 TALLOC_FREE(state);
6760 END_PROFILE(SMBtrans2);
6761 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6762}
6763
6764
6765/****************************************************************************
6766 Reply to a SMBtranss2
6767 ****************************************************************************/
6768
6769int reply_transs2(connection_struct *conn,
6770 char *inbuf,char *outbuf,int size,int bufsize)
6771{
6772 int outsize = 0;
6773 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6774 unsigned int av_size = size-4;
6775 struct trans_state *state;
6776
6777 START_PROFILE(SMBtranss2);
6778
6779 show_msg(inbuf);
6780
6781 for (state = conn->pending_trans; state != NULL;
6782 state = state->next) {
6783 if (state->mid == SVAL(inbuf,smb_mid)) {
6784 break;
6785 }
6786 }
6787
6788 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6789 END_PROFILE(SMBtranss2);
6790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6791 }
6792
6793 /* Revise state->total_param and state->total_data in case they have
6794 changed downwards */
6795
6796 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6797 state->total_param = SVAL(inbuf, smb_tpscnt);
6798 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6799 state->total_data = SVAL(inbuf, smb_tdscnt);
6800
6801 pcnt = SVAL(inbuf, smb_spscnt);
6802 poff = SVAL(inbuf, smb_spsoff);
6803 pdisp = SVAL(inbuf, smb_spsdisp);
6804
6805 dcnt = SVAL(inbuf, smb_sdscnt);
6806 doff = SVAL(inbuf, smb_sdsoff);
6807 ddisp = SVAL(inbuf, smb_sdsdisp);
6808
6809 state->received_param += pcnt;
6810 state->received_data += dcnt;
6811
6812 if ((state->received_data > state->total_data) ||
6813 (state->received_param > state->total_param))
6814 goto bad_param;
6815
6816 if (pcnt) {
6817 if (pdisp > state->total_param ||
6818 pcnt > state->total_param ||
6819 pdisp+pcnt > state->total_param ||
6820 pdisp+pcnt < pdisp) {
6821 goto bad_param;
6822 }
6823
6824 if (poff > av_size ||
6825 pcnt > av_size ||
6826 poff+pcnt > av_size ||
6827 poff+pcnt < poff) {
6828 goto bad_param;
6829 }
6830
6831 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6832 pcnt);
6833 }
6834
6835 if (dcnt) {
6836 if (ddisp > state->total_data ||
6837 dcnt > state->total_data ||
6838 ddisp+dcnt > state->total_data ||
6839 ddisp+dcnt < ddisp) {
6840 goto bad_param;
6841 }
6842
6843 if (doff > av_size ||
6844 dcnt > av_size ||
6845 doff+dcnt > av_size ||
6846 doff+dcnt < doff) {
6847 goto bad_param;
6848 }
6849
6850 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6851 dcnt);
6852 }
6853
6854 if ((state->received_param < state->total_param) ||
6855 (state->received_data < state->total_data)) {
6856 END_PROFILE(SMBtranss2);
6857 return -1;
6858 }
6859
6860 /* construct_reply_common has done us the favor to pre-fill the
6861 * command field with SMBtranss2 which is wrong :-)
6862 */
6863 SCVAL(outbuf,smb_com,SMBtrans2);
6864
6865 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6866
6867 DLIST_REMOVE(conn->pending_trans, state);
6868 SAFE_FREE(state->data);
6869 SAFE_FREE(state->param);
6870 TALLOC_FREE(state);
6871
6872 if (outsize == 0) {
6873 END_PROFILE(SMBtranss2);
6874 return(ERROR_DOS(ERRSRV,ERRnosupport));
6875 }
6876
6877 END_PROFILE(SMBtranss2);
6878 return(outsize);
6879
6880 bad_param:
6881
6882 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6883 DLIST_REMOVE(conn->pending_trans, state);
6884 SAFE_FREE(state->data);
6885 SAFE_FREE(state->param);
6886 TALLOC_FREE(state);
6887 END_PROFILE(SMBtranss2);
6888 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6889}
Note: See TracBrowser for help on using the repository browser.