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

Last change on this file since 144 was 134, checked in by Paul Smedley, 17 years ago

Update source to 3.0.29

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