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

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

Update source to 3.0.27a

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