source: trunk-3.0/source/smbd/trans2.c@ 101

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

Attempt to fix EA writing problem

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