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

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

Update source to 3.0.33

File size: 197.6 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#ifdef __OS2__
4166 /* YD ticket#60, the file is opened, we cannot write to it,
4167 * so we can return immediately (see above for more comments).
4168 */
4169 else {
4170#endif
4171 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4172
4173 if(file_ntimes(conn, fname, ts)!=0) {
4174 return map_nt_error_from_unix(errno);
4175 }
4176#ifdef __OS2__
4177 }
4178#endif
4179 if (action != 0) {
4180 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4181 }
4182 return NT_STATUS_OK;
4183}
4184
4185/****************************************************************************
4186 Deal with setting the dosmode from any of the setfilepathinfo functions.
4187****************************************************************************/
4188
4189static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4190 const char *fname,
4191 SMB_STRUCT_STAT *psbuf,
4192 uint32 dosmode)
4193{
4194 if (!VALID_STAT(*psbuf)) {
4195 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4196 }
4197
4198 if (dosmode) {
4199 if (S_ISDIR(psbuf->st_mode)) {
4200 dosmode |= aDIR;
4201 } else {
4202 dosmode &= ~aDIR;
4203 }
4204 }
4205
4206 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4207
4208 /* check the mode isn't different, before changing it */
4209 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4210
4211 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4212 fname, (unsigned int)dosmode ));
4213
4214 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4215 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4216 fname, strerror(errno)));
4217 return map_nt_error_from_unix(errno);
4218 }
4219 }
4220 return NT_STATUS_OK;
4221}
4222
4223/****************************************************************************
4224 Deal with setting the size from any of the setfilepathinfo functions.
4225****************************************************************************/
4226
4227static NTSTATUS smb_set_file_size(connection_struct *conn,
4228 files_struct *fsp,
4229 const char *fname,
4230 SMB_STRUCT_STAT *psbuf,
4231 SMB_OFF_T size)
4232{
4233 NTSTATUS status = NT_STATUS_OK;
4234 files_struct *new_fsp = NULL;
4235
4236 if (!VALID_STAT(*psbuf)) {
4237 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4238 }
4239
4240 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4241
4242 if (size == get_file_size(*psbuf)) {
4243 return NT_STATUS_OK;
4244 }
4245
4246 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4247 fname, (double)size ));
4248
4249 if (fsp && fsp->fh->fd != -1) {
4250 /* Handle based call. */
4251 if (vfs_set_filelen(fsp, size) == -1) {
4252 return map_nt_error_from_unix(errno);
4253 }
4254 return NT_STATUS_OK;
4255 }
4256
4257 status = open_file_ntcreate(conn, fname, psbuf,
4258 FILE_WRITE_DATA,
4259 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4260 FILE_OPEN,
4261 0,
4262 FILE_ATTRIBUTE_NORMAL,
4263 FORCE_OPLOCK_BREAK_TO_NONE,
4264 NULL, &new_fsp);
4265
4266 if (!NT_STATUS_IS_OK(status)) {
4267 /* NB. We check for open_was_deferred in the caller. */
4268 return status;
4269 }
4270
4271 if (vfs_set_filelen(new_fsp, size) == -1) {
4272 status = map_nt_error_from_unix(errno);
4273 close_file(new_fsp,NORMAL_CLOSE);
4274 return status;
4275 }
4276
4277 close_file(new_fsp,NORMAL_CLOSE);
4278 return NT_STATUS_OK;
4279}
4280
4281/****************************************************************************
4282 Deal with SMB_INFO_SET_EA.
4283****************************************************************************/
4284
4285static NTSTATUS smb_info_set_ea(connection_struct *conn,
4286 const char *pdata,
4287 int total_data,
4288 files_struct *fsp,
4289 const char *fname)
4290{
4291 struct ea_list *ea_list = NULL;
4292 TALLOC_CTX *ctx = NULL;
4293 NTSTATUS status = NT_STATUS_OK;
4294
4295 if (total_data < 10) {
4296
4297 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4298 length. They seem to have no effect. Bug #3212. JRA */
4299
4300 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4301 /* We're done. We only get EA info in this call. */
4302 return NT_STATUS_OK;
4303 }
4304
4305 return NT_STATUS_INVALID_PARAMETER;
4306 }
4307
4308 if (IVAL(pdata,0) > total_data) {
4309 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4310 IVAL(pdata,0), (unsigned int)total_data));
4311 return NT_STATUS_INVALID_PARAMETER;
4312 }
4313
4314 ctx = talloc_init("SMB_INFO_SET_EA");
4315 if (!ctx) {
4316 return NT_STATUS_NO_MEMORY;
4317 }
4318 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4319 if (!ea_list) {
4320 talloc_destroy(ctx);
4321 return NT_STATUS_INVALID_PARAMETER;
4322 }
4323 status = set_ea(conn, fsp, fname, ea_list);
4324 talloc_destroy(ctx);
4325
4326 return status;
4327}
4328
4329/****************************************************************************
4330 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4331****************************************************************************/
4332
4333static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4334 const char *pdata,
4335 int total_data,
4336 files_struct *fsp,
4337 const char *fname,
4338 SMB_STRUCT_STAT *psbuf)
4339{
4340 NTSTATUS status = NT_STATUS_OK;
4341 BOOL delete_on_close;
4342 uint32 dosmode = 0;
4343
4344 if (total_data < 1) {
4345 return NT_STATUS_INVALID_PARAMETER;
4346 }
4347
4348 if (fsp == NULL) {
4349 return NT_STATUS_INVALID_HANDLE;
4350 }
4351
4352 delete_on_close = (CVAL(pdata,0) ? True : False);
4353 dosmode = dos_mode(conn, fname, psbuf);
4354
4355 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4356 "delete_on_close = %u\n",
4357 fsp->fsp_name,
4358 (unsigned int)dosmode,
4359 (unsigned int)delete_on_close ));
4360
4361 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4362
4363 if (!NT_STATUS_IS_OK(status)) {
4364 return status;
4365 }
4366
4367 /* The set is across all open files on this dev/inode pair. */
4368 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4369 return NT_STATUS_ACCESS_DENIED;
4370 }
4371 return NT_STATUS_OK;
4372}
4373
4374/****************************************************************************
4375 Deal with SMB_FILE_POSITION_INFORMATION.
4376****************************************************************************/
4377
4378static NTSTATUS smb_file_position_information(connection_struct *conn,
4379 const char *pdata,
4380 int total_data,
4381 files_struct *fsp)
4382{
4383 SMB_BIG_UINT position_information;
4384
4385 if (total_data < 8) {
4386 return NT_STATUS_INVALID_PARAMETER;
4387 }
4388
4389 if (fsp == NULL) {
4390 /* Ignore on pathname based set. */
4391 return NT_STATUS_OK;
4392 }
4393
4394 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4395#ifdef LARGE_SMB_OFF_T
4396 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4397#else /* LARGE_SMB_OFF_T */
4398 if (IVAL(pdata,4) != 0) {
4399 /* more than 32 bits? */
4400 return NT_STATUS_INVALID_PARAMETER;
4401 }
4402#endif /* LARGE_SMB_OFF_T */
4403
4404 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4405 fsp->fsp_name, (double)position_information ));
4406 fsp->fh->position_information = position_information;
4407 return NT_STATUS_OK;
4408}
4409
4410/****************************************************************************
4411 Deal with SMB_FILE_MODE_INFORMATION.
4412****************************************************************************/
4413
4414static NTSTATUS smb_file_mode_information(connection_struct *conn,
4415 const char *pdata,
4416 int total_data)
4417{
4418 uint32 mode;
4419
4420 if (total_data < 4) {
4421 return NT_STATUS_INVALID_PARAMETER;
4422 }
4423 mode = IVAL(pdata,0);
4424 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4425 return NT_STATUS_INVALID_PARAMETER;
4426 }
4427 return NT_STATUS_OK;
4428}
4429
4430/****************************************************************************
4431 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4432****************************************************************************/
4433
4434static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4435 char *inbuf,
4436 const char *pdata,
4437 int total_data,
4438 const char *fname)
4439{
4440 pstring link_target;
4441 const char *newname = fname;
4442 NTSTATUS status = NT_STATUS_OK;
4443
4444 /* Set a symbolic link. */
4445 /* Don't allow this if follow links is false. */
4446
4447 if (total_data == 0) {
4448 return NT_STATUS_INVALID_PARAMETER;
4449 }
4450
4451 if (!lp_symlinks(SNUM(conn))) {
4452 return NT_STATUS_ACCESS_DENIED;
4453 }
4454
4455 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4456
4457 /* !widelinks forces the target path to be within the share. */
4458 /* This means we can interpret the target as a pathname. */
4459 if (!lp_widelinks(SNUM(conn))) {
4460 pstring rel_name;
4461 char *last_dirp = NULL;
4462
4463 if (*link_target == '/') {
4464 /* No absolute paths allowed. */
4465 return NT_STATUS_ACCESS_DENIED;
4466 }
4467 pstrcpy(rel_name, newname);
4468 last_dirp = strrchr_m(rel_name, '/');
4469 if (last_dirp) {
4470 last_dirp[1] = '\0';
4471 } else {
4472 pstrcpy(rel_name, "./");
4473 }
4474 pstrcat(rel_name, link_target);
4475
4476 status = check_name(conn, rel_name);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 return status;
4479 }
4480 }
4481
4482 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4483 newname, link_target ));
4484
4485 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4486 return map_nt_error_from_unix(errno);
4487 }
4488
4489 return NT_STATUS_OK;
4490}
4491
4492/****************************************************************************
4493 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4494****************************************************************************/
4495
4496static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4497 char *inbuf,
4498 char *outbuf,
4499 const char *pdata,
4500 int total_data,
4501 pstring fname)
4502{
4503 pstring oldname;
4504 NTSTATUS status = NT_STATUS_OK;
4505
4506 /* Set a hard link. */
4507 if (total_data == 0) {
4508 return NT_STATUS_INVALID_PARAMETER;
4509 }
4510
4511 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 return status;
4514 }
4515
4516 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 return status;
4519 }
4520
4521 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4522 fname, oldname));
4523
4524 return hardlink_internals(conn, oldname, fname);
4525}
4526
4527/****************************************************************************
4528 Deal with SMB_FILE_RENAME_INFORMATION.
4529****************************************************************************/
4530
4531static NTSTATUS smb_file_rename_information(connection_struct *conn,
4532 char *inbuf,
4533 char *outbuf,
4534 const char *pdata,
4535 int total_data,
4536 files_struct *fsp,
4537 pstring fname)
4538{
4539 BOOL overwrite;
4540 /* uint32 root_fid; */ /* Not used */
4541 uint32 len;
4542 pstring newname;
4543 pstring base_name;
4544 BOOL dest_has_wcard = False;
4545 NTSTATUS status = NT_STATUS_OK;
4546 char *p;
4547
4548 if (total_data < 13) {
4549 return NT_STATUS_INVALID_PARAMETER;
4550 }
4551
4552 overwrite = (CVAL(pdata,0) ? True : False);
4553 /* root_fid = IVAL(pdata,4); */
4554 len = IVAL(pdata,8);
4555
4556 if (len > (total_data - 12) || (len == 0)) {
4557 return NT_STATUS_INVALID_PARAMETER;
4558 }
4559
4560 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4561 if (!NT_STATUS_IS_OK(status)) {
4562 return status;
4563 }
4564
4565 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4566 if (!NT_STATUS_IS_OK(status)) {
4567 return status;
4568 }
4569
4570 /* Check the new name has no '/' characters. */
4571 if (strchr_m(newname, '/')) {
4572 return NT_STATUS_NOT_SUPPORTED;
4573 }
4574
4575 /* Create the base directory. */
4576 pstrcpy(base_name, fname);
4577 p = strrchr_m(base_name, '/');
4578 if (p) {
4579 p[1] = '\0';
4580 } else {
4581 pstrcpy(base_name, "./");
4582 }
4583 /* Append the new name. */
4584 pstrcat(base_name, newname);
4585
4586 if (fsp) {
4587 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4588 fsp->fnum, fsp->fsp_name, base_name ));
4589 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4590 } else {
4591 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4592 fname, newname ));
4593 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4594 }
4595
4596 return status;
4597}
4598
4599/****************************************************************************
4600 Deal with SMB_SET_POSIX_ACL.
4601****************************************************************************/
4602
4603#if defined(HAVE_POSIX_ACLS)
4604static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4605 const char *pdata,
4606 int total_data,
4607 files_struct *fsp,
4608 const char *fname,
4609 SMB_STRUCT_STAT *psbuf)
4610{
4611 uint16 posix_acl_version;
4612 uint16 num_file_acls;
4613 uint16 num_def_acls;
4614 BOOL valid_file_acls = True;
4615 BOOL valid_def_acls = True;
4616
4617 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4618 return NT_STATUS_INVALID_PARAMETER;
4619 }
4620 posix_acl_version = SVAL(pdata,0);
4621 num_file_acls = SVAL(pdata,2);
4622 num_def_acls = SVAL(pdata,4);
4623
4624 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4625 valid_file_acls = False;
4626 num_file_acls = 0;
4627 }
4628
4629 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4630 valid_def_acls = False;
4631 num_def_acls = 0;
4632 }
4633
4634 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4635 return NT_STATUS_INVALID_PARAMETER;
4636 }
4637
4638 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4639 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4640 return NT_STATUS_INVALID_PARAMETER;
4641 }
4642
4643 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4644 fname ? fname : fsp->fsp_name,
4645 (unsigned int)num_file_acls,
4646 (unsigned int)num_def_acls));
4647
4648 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4649 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4650 return map_nt_error_from_unix(errno);
4651 }
4652
4653 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4654 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4655 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4656 return map_nt_error_from_unix(errno);
4657 }
4658 return NT_STATUS_OK;
4659}
4660#endif
4661
4662/****************************************************************************
4663 Deal with SMB_SET_POSIX_LOCK.
4664****************************************************************************/
4665
4666static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4667 char *inbuf,
4668 int length,
4669 const char *pdata,
4670 int total_data,
4671 files_struct *fsp)
4672{
4673 SMB_BIG_UINT count;
4674 SMB_BIG_UINT offset;
4675 uint32 lock_pid;
4676 BOOL blocking_lock = False;
4677 enum brl_type lock_type;
4678 NTSTATUS status = NT_STATUS_OK;
4679
4680 if (fsp == NULL || fsp->fh->fd == -1) {
4681 return NT_STATUS_INVALID_HANDLE;
4682 }
4683
4684 if (total_data != POSIX_LOCK_DATA_SIZE) {
4685 return NT_STATUS_INVALID_PARAMETER;
4686 }
4687
4688 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4689 case POSIX_LOCK_TYPE_READ:
4690 lock_type = READ_LOCK;
4691 break;
4692 case POSIX_LOCK_TYPE_WRITE:
4693 /* Return the right POSIX-mappable error code for files opened read-only. */
4694 if (!fsp->can_write) {
4695 return NT_STATUS_INVALID_HANDLE;
4696 }
4697 lock_type = WRITE_LOCK;
4698 break;
4699 case POSIX_LOCK_TYPE_UNLOCK:
4700 lock_type = UNLOCK_LOCK;
4701 break;
4702 default:
4703 return NT_STATUS_INVALID_PARAMETER;
4704 }
4705
4706 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4707 blocking_lock = False;
4708 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4709 blocking_lock = True;
4710 } else {
4711 return NT_STATUS_INVALID_PARAMETER;
4712 }
4713
4714 if (!lp_blocking_locks(SNUM(conn))) {
4715 blocking_lock = False;
4716 }
4717
4718 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4719#if defined(HAVE_LONGLONG)
4720 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4721 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4722 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4723 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4724#else /* HAVE_LONGLONG */
4725 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4726 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4727#endif /* HAVE_LONGLONG */
4728
4729 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4730 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4731 fsp->fsp_name,
4732 (unsigned int)lock_type,
4733 (unsigned int)lock_pid,
4734 (double)count,
4735 (double)offset ));
4736
4737 if (lock_type == UNLOCK_LOCK) {
4738 status = do_unlock(fsp,
4739 lock_pid,
4740 count,
4741 offset,
4742 POSIX_LOCK);
4743 } else {
4744 uint32 block_smbpid;
4745
4746 struct byte_range_lock *br_lck = do_lock(fsp,
4747 lock_pid,
4748 count,
4749 offset,
4750 lock_type,
4751 POSIX_LOCK,
4752 blocking_lock,
4753 &status,
4754 &block_smbpid);
4755
4756 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4757 /*
4758 * A blocking lock was requested. Package up
4759 * this smb into a queued request and push it
4760 * onto the blocking lock queue.
4761 */
4762 if(push_blocking_lock_request(br_lck,
4763 inbuf, length,
4764 fsp,
4765 -1, /* infinite timeout. */
4766 0,
4767 lock_pid,
4768 lock_type,
4769 POSIX_LOCK,
4770 offset,
4771 count,
4772 block_smbpid)) {
4773 TALLOC_FREE(br_lck);
4774 return status;
4775 }
4776 }
4777 TALLOC_FREE(br_lck);
4778 }
4779
4780 return status;
4781}
4782
4783/****************************************************************************
4784 Deal with SMB_INFO_STANDARD.
4785****************************************************************************/
4786
4787static NTSTATUS smb_set_info_standard(connection_struct *conn,
4788 const char *pdata,
4789 int total_data,
4790 files_struct *fsp,
4791 const char *fname,
4792 const SMB_STRUCT_STAT *psbuf)
4793{
4794 struct timespec ts[2];
4795
4796 if (total_data < 12) {
4797 return NT_STATUS_INVALID_PARAMETER;
4798 }
4799
4800 /* access time */
4801 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4802 /* write time */
4803 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4804
4805 DEBUG(10,("smb_set_info_standard: file %s\n",
4806 fname ? fname : fsp->fsp_name ));
4807
4808 return smb_set_file_time(conn,
4809 fsp,
4810 fname,
4811 psbuf,
4812 ts);
4813}
4814
4815/****************************************************************************
4816 Deal with SMB_SET_FILE_BASIC_INFO.
4817****************************************************************************/
4818
4819static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4820 const char *pdata,
4821 int total_data,
4822 files_struct *fsp,
4823 const char *fname,
4824 SMB_STRUCT_STAT *psbuf)
4825{
4826 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4827 struct timespec write_time;
4828 struct timespec changed_time;
4829 uint32 dosmode = 0;
4830 struct timespec ts[2];
4831 NTSTATUS status = NT_STATUS_OK;
4832
4833 if (total_data < 36) {
4834 return NT_STATUS_INVALID_PARAMETER;
4835 }
4836
4837 /* Set the attributes */
4838 dosmode = IVAL(pdata,32);
4839 status = smb_set_file_dosmode(conn,
4840 fname,
4841 psbuf,
4842 dosmode);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 return status;
4845 }
4846
4847 /* Ignore create time at offset pdata. */
4848
4849 /* access time */
4850 ts[0] = interpret_long_date(pdata+8);
4851
4852 write_time = interpret_long_date(pdata+16);
4853 changed_time = interpret_long_date(pdata+24);
4854
4855 /* mtime */
4856 ts[1] = timespec_min(&write_time, &changed_time);
4857
4858 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4859 ts[1] = write_time;
4860 }
4861
4862 /* Prefer a defined time to an undefined one. */
4863 if (null_timespec(ts[1])) {
4864 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4865 }
4866
4867 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4868 fname ? fname : fsp->fsp_name ));
4869
4870 return smb_set_file_time(conn,
4871 fsp,
4872 fname,
4873 psbuf,
4874 ts);
4875}
4876
4877/****************************************************************************
4878 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4879****************************************************************************/
4880
4881static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4882 const char *pdata,
4883 int total_data,
4884 files_struct *fsp,
4885 const char *fname,
4886 SMB_STRUCT_STAT *psbuf)
4887{
4888 SMB_BIG_UINT allocation_size = 0;
4889 NTSTATUS status = NT_STATUS_OK;
4890 files_struct *new_fsp = NULL;
4891
4892 if (!VALID_STAT(*psbuf)) {
4893 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4894 }
4895
4896 if (total_data < 8) {
4897 return NT_STATUS_INVALID_PARAMETER;
4898 }
4899
4900 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4901#ifdef LARGE_SMB_OFF_T
4902 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4903#else /* LARGE_SMB_OFF_T */
4904 if (IVAL(pdata,4) != 0) {
4905 /* more than 32 bits? */
4906 return NT_STATUS_INVALID_PARAMETER;
4907 }
4908#endif /* LARGE_SMB_OFF_T */
4909
4910 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4911 fname, (double)allocation_size ));
4912
4913 if (allocation_size) {
4914 allocation_size = smb_roundup(conn, allocation_size);
4915 }
4916
4917 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4918 fname, (double)allocation_size ));
4919
4920 if (fsp && fsp->fh->fd != -1) {
4921 /* Open file handle. */
4922 /* Only change if needed. */
4923 if (allocation_size != get_file_size(*psbuf)) {
4924 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4925 return map_nt_error_from_unix(errno);
4926 }
4927 }
4928 /* But always update the time. */
4929 if (null_timespec(fsp->pending_modtime)) {
4930 /*
4931 * This is equivalent to a write. Ensure it's seen immediately
4932 * if there are no pending writes.
4933 */
4934 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
4935 }
4936 return NT_STATUS_OK;
4937 }
4938
4939 /* Pathname or stat or directory file. */
4940
4941 status = open_file_ntcreate(conn, fname, psbuf,
4942 FILE_WRITE_DATA,
4943 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4944 FILE_OPEN,
4945 0,
4946 FILE_ATTRIBUTE_NORMAL,
4947 FORCE_OPLOCK_BREAK_TO_NONE,
4948 NULL, &new_fsp);
4949
4950 if (!NT_STATUS_IS_OK(status)) {
4951 /* NB. We check for open_was_deferred in the caller. */
4952 return status;
4953 }
4954
4955 /* Only change if needed. */
4956 if (allocation_size != get_file_size(*psbuf)) {
4957 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4958 status = map_nt_error_from_unix(errno);
4959 close_file(new_fsp,NORMAL_CLOSE);
4960 return status;
4961 }
4962 }
4963
4964 /* Changing the allocation size should set the last mod time. */
4965 /* Don't need to call set_filetime as this will be flushed on
4966 * close. */
4967
4968 fsp_set_pending_modtime(new_fsp, timespec_current());
4969
4970 close_file(new_fsp,NORMAL_CLOSE);
4971 return NT_STATUS_OK;
4972}
4973
4974/****************************************************************************
4975 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4976****************************************************************************/
4977
4978static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4979 const char *pdata,
4980 int total_data,
4981 files_struct *fsp,
4982 const char *fname,
4983 SMB_STRUCT_STAT *psbuf)
4984{
4985 SMB_OFF_T size;
4986
4987 if (total_data < 8) {
4988 return NT_STATUS_INVALID_PARAMETER;
4989 }
4990
4991 size = IVAL(pdata,0);
4992#ifdef LARGE_SMB_OFF_T
4993 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4994#else /* LARGE_SMB_OFF_T */
4995 if (IVAL(pdata,4) != 0) {
4996 /* more than 32 bits? */
4997 return NT_STATUS_INVALID_PARAMETER;
4998 }
4999#endif /* LARGE_SMB_OFF_T */
5000 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5001 "file %s to %.0f\n", fname, (double)size ));
5002
5003 return smb_set_file_size(conn,
5004 fsp,
5005 fname,
5006 psbuf,
5007 size);
5008}
5009
5010/****************************************************************************
5011 Allow a UNIX info mknod.
5012****************************************************************************/
5013
5014static NTSTATUS smb_unix_mknod(connection_struct *conn,
5015 const char *pdata,
5016 int total_data,
5017 const char *fname,
5018 SMB_STRUCT_STAT *psbuf)
5019{
5020 uint32 file_type = IVAL(pdata,56);
5021#if defined(HAVE_MAKEDEV)
5022 uint32 dev_major = IVAL(pdata,60);
5023 uint32 dev_minor = IVAL(pdata,68);
5024#endif
5025 SMB_DEV_T dev = (SMB_DEV_T)0;
5026 uint32 raw_unixmode = IVAL(pdata,84);
5027 NTSTATUS status;
5028 mode_t unixmode;
5029
5030 if (total_data < 100) {
5031 return NT_STATUS_INVALID_PARAMETER;
5032 }
5033
5034 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5035 if (!NT_STATUS_IS_OK(status)) {
5036 return status;
5037 }
5038
5039#if defined(HAVE_MAKEDEV)
5040 dev = makedev(dev_major, dev_minor);
5041#endif
5042
5043 switch (file_type) {
5044#if defined(S_IFIFO)
5045 case UNIX_TYPE_FIFO:
5046 unixmode |= S_IFIFO;
5047 break;
5048#endif
5049#if defined(S_IFSOCK)
5050 case UNIX_TYPE_SOCKET:
5051 unixmode |= S_IFSOCK;
5052 break;
5053#endif
5054#if defined(S_IFCHR)
5055 case UNIX_TYPE_CHARDEV:
5056 unixmode |= S_IFCHR;
5057 break;
5058#endif
5059#if defined(S_IFBLK)
5060 case UNIX_TYPE_BLKDEV:
5061 unixmode |= S_IFBLK;
5062 break;
5063#endif
5064 default:
5065 return NT_STATUS_INVALID_PARAMETER;
5066 }
5067
5068 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
50690%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5070
5071 /* Ok - do the mknod. */
5072 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5073 return map_nt_error_from_unix(errno);
5074 }
5075
5076 /* If any of the other "set" calls fail we
5077 * don't want to end up with a half-constructed mknod.
5078 */
5079
5080 if (lp_inherit_perms(SNUM(conn))) {
5081 inherit_access_acl(
5082 conn, parent_dirname(fname),
5083 fname, unixmode);
5084 }
5085
5086 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5087 status = map_nt_error_from_unix(errno);
5088 SMB_VFS_UNLINK(conn,fname);
5089 return status;
5090 }
5091 return NT_STATUS_OK;
5092}
5093
5094/****************************************************************************
5095 Deal with SMB_SET_FILE_UNIX_BASIC.
5096****************************************************************************/
5097
5098static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5099 const char *pdata,
5100 int total_data,
5101 files_struct *fsp,
5102 const char *fname,
5103 SMB_STRUCT_STAT *psbuf)
5104{
5105 struct timespec ts[2];
5106 uint32 raw_unixmode;
5107 mode_t unixmode;
5108 SMB_OFF_T size = 0;
5109 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5110 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5111 NTSTATUS status = NT_STATUS_OK;
5112 BOOL delete_on_fail = False;
5113 enum perm_type ptype;
5114
5115 if (total_data < 100) {
5116 return NT_STATUS_INVALID_PARAMETER;
5117 }
5118
5119 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5120 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5121 size=IVAL(pdata,0); /* first 8 Bytes are size */
5122#ifdef LARGE_SMB_OFF_T
5123 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5124#else /* LARGE_SMB_OFF_T */
5125 if (IVAL(pdata,4) != 0) {
5126 /* more than 32 bits? */
5127 return NT_STATUS_INVALID_PARAMETER;
5128 }
5129#endif /* LARGE_SMB_OFF_T */
5130 }
5131
5132 ts[0] = interpret_long_date(pdata+24); /* access_time */
5133 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5134 set_owner = (uid_t)IVAL(pdata,40);
5135 set_grp = (gid_t)IVAL(pdata,48);
5136 raw_unixmode = IVAL(pdata,84);
5137
5138 if (VALID_STAT(*psbuf)) {
5139 if (S_ISDIR(psbuf->st_mode)) {
5140 ptype = PERM_EXISTING_DIR;
5141 } else {
5142 ptype = PERM_EXISTING_FILE;
5143 }
5144 } else {
5145 ptype = PERM_NEW_FILE;
5146 }
5147
5148 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 return status;
5151 }
5152
5153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5154size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5155 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5156
5157 if (!VALID_STAT(*psbuf)) {
5158 /*
5159 * The only valid use of this is to create character and block
5160 * devices, and named pipes. This is deprecated (IMHO) and
5161 * a new info level should be used for mknod. JRA.
5162 */
5163
5164 status = smb_unix_mknod(conn,
5165 pdata,
5166 total_data,
5167 fname,
5168 psbuf);
5169 if (!NT_STATUS_IS_OK(status)) {
5170 return status;
5171 }
5172
5173 /* Ensure we don't try and change anything else. */
5174 raw_unixmode = SMB_MODE_NO_CHANGE;
5175 size = get_file_size(*psbuf);
5176 ts[0] = get_atimespec(psbuf);
5177 ts[1] = get_mtimespec(psbuf);
5178 /*
5179 * We continue here as we might want to change the
5180 * owner uid/gid.
5181 */
5182 delete_on_fail = True;
5183 }
5184
5185#if 1
5186 /* Horrible backwards compatibility hack as an old server bug
5187 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5188 * */
5189
5190 if (!size) {
5191 size = get_file_size(*psbuf);
5192 }
5193#endif
5194
5195 /*
5196 * Deal with the UNIX specific mode set.
5197 */
5198
5199 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5200 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5201 (unsigned int)unixmode, fname ));
5202 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5203 return map_nt_error_from_unix(errno);
5204 }
5205 }
5206
5207 /*
5208 * Deal with the UNIX specific uid set.
5209 */
5210
5211 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5212 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5213 (unsigned int)set_owner, fname ));
5214 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5215 status = map_nt_error_from_unix(errno);
5216 if (delete_on_fail) {
5217 SMB_VFS_UNLINK(conn,fname);
5218 }
5219 return status;
5220 }
5221 }
5222
5223 /*
5224 * Deal with the UNIX specific gid set.
5225 */
5226
5227 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5228 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5229 (unsigned int)set_owner, fname ));
5230 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5231 status = map_nt_error_from_unix(errno);
5232 if (delete_on_fail) {
5233 SMB_VFS_UNLINK(conn,fname);
5234 }
5235 return status;
5236 }
5237 }
5238
5239 /* Deal with any size changes. */
5240
5241 status = smb_set_file_size(conn,
5242 fsp,
5243 fname,
5244 psbuf,
5245 size);
5246 if (!NT_STATUS_IS_OK(status)) {
5247 return status;
5248 }
5249
5250 /* Deal with any time changes. */
5251
5252 return smb_set_file_time(conn,
5253 fsp,
5254 fname,
5255 psbuf,
5256 ts);
5257}
5258
5259/****************************************************************************
5260 Deal with SMB_SET_FILE_UNIX_INFO2.
5261****************************************************************************/
5262
5263static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5264 const char *pdata,
5265 int total_data,
5266 files_struct *fsp,
5267 const char *fname,
5268 SMB_STRUCT_STAT *psbuf)
5269{
5270 NTSTATUS status;
5271 uint32 smb_fflags;
5272 uint32 smb_fmask;
5273
5274 if (total_data < 116) {
5275 return NT_STATUS_INVALID_PARAMETER;
5276 }
5277
5278 /* Start by setting all the fields that are common between UNIX_BASIC
5279 * and UNIX_INFO2.
5280 */
5281 status = smb_set_file_unix_basic(conn, pdata, total_data,
5282 fsp, fname, psbuf);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 return status;
5285 }
5286
5287 smb_fflags = IVAL(pdata, 108);
5288 smb_fmask = IVAL(pdata, 112);
5289
5290 /* NB: We should only attempt to alter the file flags if the client
5291 * sends a non-zero mask.
5292 */
5293 if (smb_fmask != 0) {
5294 int stat_fflags = 0;
5295
5296 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5297 &stat_fflags)) {
5298 /* Client asked to alter a flag we don't understand. */
5299 return NT_STATUS_INVALID_PARAMETER;
5300 }
5301
5302 if (fsp && fsp->fh->fd != -1) {
5303 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5304 return NT_STATUS_NOT_SUPPORTED;
5305 } else {
5306 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5307 return map_nt_error_from_unix(errno);
5308 }
5309 }
5310 }
5311
5312 /* XXX: need to add support for changing the create_time here. You
5313 * can do this for paths on Darwin with setattrlist(2). The right way
5314 * to hook this up is probably by extending the VFS utimes interface.
5315 */
5316
5317 return NT_STATUS_OK;
5318}
5319
5320/****************************************************************************
5321 Create a directory with POSIX semantics.
5322****************************************************************************/
5323
5324static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5325 char **ppdata,
5326 int total_data,
5327 const char *fname,
5328 SMB_STRUCT_STAT *psbuf,
5329 int *pdata_return_size)
5330{
5331 NTSTATUS status = NT_STATUS_OK;
5332 uint32 raw_unixmode = 0;
5333 uint32 mod_unixmode = 0;
5334 mode_t unixmode = (mode_t)0;
5335 files_struct *fsp = NULL;
5336 uint16 info_level_return = 0;
5337 int info;
5338 char *pdata = *ppdata;
5339
5340 if (total_data < 18) {
5341 return NT_STATUS_INVALID_PARAMETER;
5342 }
5343
5344 raw_unixmode = IVAL(pdata,8);
5345 /* Next 4 bytes are not yet defined. */
5346
5347 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5348 if (!NT_STATUS_IS_OK(status)) {
5349 return status;
5350 }
5351
5352 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5353
5354 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5355 fname, (unsigned int)unixmode ));
5356
5357 status = open_directory(conn,
5358 fname,
5359 psbuf,
5360 FILE_READ_ATTRIBUTES, /* Just a stat open */
5361 FILE_SHARE_NONE, /* Ignored for stat opens */
5362 FILE_CREATE,
5363 0,
5364 mod_unixmode,
5365 &info,
5366 &fsp);
5367
5368 if (NT_STATUS_IS_OK(status)) {
5369 close_file(fsp, NORMAL_CLOSE);
5370 }
5371
5372 info_level_return = SVAL(pdata,16);
5373
5374 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5375 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5376 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5377 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5378 } else {
5379 *pdata_return_size = 12;
5380 }
5381
5382 /* Realloc the data size */
5383 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5384 if (*ppdata == NULL) {
5385 *pdata_return_size = 0;
5386 return NT_STATUS_NO_MEMORY;
5387 }
5388 pdata = *ppdata;
5389
5390 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5391 SSVAL(pdata,2,0); /* No fnum. */
5392 SIVAL(pdata,4,info); /* Was directory created. */
5393
5394 switch (info_level_return) {
5395 case SMB_QUERY_FILE_UNIX_BASIC:
5396 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5397 SSVAL(pdata,10,0); /* Padding. */
5398 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5399 break;
5400 case SMB_QUERY_FILE_UNIX_INFO2:
5401 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5402 SSVAL(pdata,10,0); /* Padding. */
5403 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5404 break;
5405 default:
5406 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5407 SSVAL(pdata,10,0); /* Padding. */
5408 break;
5409 }
5410
5411 return status;
5412}
5413
5414/****************************************************************************
5415 Open/Create a file with POSIX semantics.
5416****************************************************************************/
5417
5418static NTSTATUS smb_posix_open(connection_struct *conn,
5419 char **ppdata,
5420 int total_data,
5421 const char *fname,
5422 SMB_STRUCT_STAT *psbuf,
5423 int *pdata_return_size)
5424{
5425 BOOL extended_oplock_granted = False;
5426 char *pdata = *ppdata;
5427 uint32 flags = 0;
5428 uint32 wire_open_mode = 0;
5429 uint32 raw_unixmode = 0;
5430 uint32 mod_unixmode = 0;
5431 uint32 create_disp = 0;
5432 uint32 access_mask = 0;
5433 uint32 create_options = 0;
5434 NTSTATUS status = NT_STATUS_OK;
5435 mode_t unixmode = (mode_t)0;
5436 files_struct *fsp = NULL;
5437 int oplock_request = 0;
5438 int info = 0;
5439 uint16 info_level_return = 0;
5440
5441 if (total_data < 18) {
5442 return NT_STATUS_INVALID_PARAMETER;
5443 }
5444
5445 flags = IVAL(pdata,0);
5446 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5447 if (oplock_request) {
5448 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5449 }
5450
5451 wire_open_mode = IVAL(pdata,4);
5452
5453 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5454 return smb_posix_mkdir(conn,
5455 ppdata,
5456 total_data,
5457 fname,
5458 psbuf,
5459 pdata_return_size);
5460 }
5461
5462 switch (wire_open_mode & SMB_ACCMODE) {
5463 case SMB_O_RDONLY:
5464 access_mask = FILE_READ_DATA;
5465 break;
5466 case SMB_O_WRONLY:
5467 access_mask = FILE_WRITE_DATA;
5468 break;
5469 case SMB_O_RDWR:
5470 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5471 break;
5472 default:
5473 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5474 (unsigned int)wire_open_mode ));
5475 return NT_STATUS_INVALID_PARAMETER;
5476 }
5477
5478 wire_open_mode &= ~SMB_ACCMODE;
5479
5480 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5481 create_disp = FILE_CREATE;
5482 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5483 create_disp = FILE_OVERWRITE_IF;
5484 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5485 create_disp = FILE_OPEN_IF;
5486 } else {
5487 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5488 (unsigned int)wire_open_mode ));
5489 return NT_STATUS_INVALID_PARAMETER;
5490 }
5491
5492 raw_unixmode = IVAL(pdata,8);
5493 /* Next 4 bytes are not yet defined. */
5494
5495 status = unix_perms_from_wire(conn,
5496 psbuf,
5497 raw_unixmode,
5498 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5499 &unixmode);
5500
5501 if (!NT_STATUS_IS_OK(status)) {
5502 return status;
5503 }
5504
5505 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5506
5507 if (wire_open_mode & SMB_O_SYNC) {
5508 create_options |= FILE_WRITE_THROUGH;
5509 }
5510 if (wire_open_mode & SMB_O_APPEND) {
5511 access_mask |= FILE_APPEND_DATA;
5512 }
5513 if (wire_open_mode & SMB_O_DIRECT) {
5514 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5515 }
5516
5517 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5518 fname,
5519 (unsigned int)wire_open_mode,
5520 (unsigned int)unixmode ));
5521
5522 status = open_file_ntcreate(conn,
5523 fname,
5524 psbuf,
5525 access_mask,
5526 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5527 create_disp,
5528 0, /* no create options yet. */
5529 mod_unixmode,
5530 oplock_request,
5531 &info,
5532 &fsp);
5533
5534 if (!NT_STATUS_IS_OK(status)) {
5535 return status;
5536 }
5537
5538 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5539 extended_oplock_granted = True;
5540 }
5541
5542 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5543 extended_oplock_granted = True;
5544 }
5545
5546 info_level_return = SVAL(pdata,16);
5547
5548 /* Allocate the correct return size. */
5549
5550 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5551 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5552 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5553 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5554 } else {
5555 *pdata_return_size = 12;
5556 }
5557
5558 /* Realloc the data size */
5559 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5560 if (*ppdata == NULL) {
5561 close_file(fsp,ERROR_CLOSE);
5562 *pdata_return_size = 0;
5563 return NT_STATUS_NO_MEMORY;
5564 }
5565 pdata = *ppdata;
5566
5567 if (extended_oplock_granted) {
5568 if (flags & REQUEST_BATCH_OPLOCK) {
5569 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5570 } else {
5571 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5572 }
5573 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5574 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5575 } else {
5576 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5577 }
5578
5579 SSVAL(pdata,2,fsp->fnum);
5580 SIVAL(pdata,4,info); /* Was file created etc. */
5581
5582 switch (info_level_return) {
5583 case SMB_QUERY_FILE_UNIX_BASIC:
5584 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5585 SSVAL(pdata,10,0); /* padding. */
5586 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5587 break;
5588 case SMB_QUERY_FILE_UNIX_INFO2:
5589 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5590 SSVAL(pdata,10,0); /* padding. */
5591 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5592 break;
5593 default:
5594 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5595 SSVAL(pdata,10,0); /* padding. */
5596 break;
5597 }
5598 return NT_STATUS_OK;
5599}
5600
5601/****************************************************************************
5602 Delete a file with POSIX semantics.
5603****************************************************************************/
5604
5605static NTSTATUS smb_posix_unlink(connection_struct *conn,
5606 const char *pdata,
5607 int total_data,
5608 const char *fname,
5609 SMB_STRUCT_STAT *psbuf)
5610{
5611 NTSTATUS status = NT_STATUS_OK;
5612 files_struct *fsp = NULL;
5613 uint16 flags = 0;
5614 char del = 1;
5615 int info = 0;
5616 int i;
5617 struct share_mode_lock *lck = NULL;
5618
5619 if (total_data < 2) {
5620 return NT_STATUS_INVALID_PARAMETER;
5621 }
5622
5623 flags = SVAL(pdata,0);
5624
5625 if (!VALID_STAT(*psbuf)) {
5626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5627 }
5628
5629 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5630 !VALID_STAT_OF_DIR(*psbuf)) {
5631 return NT_STATUS_NOT_A_DIRECTORY;
5632 }
5633
5634 DEBUG(10,("smb_posix_unlink: %s %s\n",
5635 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5636 fname));
5637
5638 if (VALID_STAT_OF_DIR(*psbuf)) {
5639 status = open_directory(conn,
5640 fname,
5641 psbuf,
5642 DELETE_ACCESS,
5643 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5644 FILE_OPEN,
5645 0,
5646 FILE_FLAG_POSIX_SEMANTICS|0777,
5647 &info,
5648 &fsp);
5649 } else {
5650
5651 status = open_file_ntcreate(conn,
5652 fname,
5653 psbuf,
5654 DELETE_ACCESS,
5655 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5656 FILE_OPEN,
5657 0,
5658 FILE_FLAG_POSIX_SEMANTICS|0777,
5659 0, /* No oplock, but break existing ones. */
5660 &info,
5661 &fsp);
5662 }
5663
5664 if (!NT_STATUS_IS_OK(status)) {
5665 return status;
5666 }
5667
5668 /*
5669 * Don't lie to client. If we can't really delete due to
5670 * non-POSIX opens return SHARING_VIOLATION.
5671 */
5672
5673 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5674 if (lck == NULL) {
5675 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5676 "lock for file %s\n", fsp->fsp_name));
5677 close_file(fsp, NORMAL_CLOSE);
5678 return NT_STATUS_INVALID_PARAMETER;
5679 }
5680
5681 /*
5682 * See if others still have the file open. If this is the case, then
5683 * don't delete. If all opens are POSIX delete we can set the delete
5684 * on close disposition.
5685 */
5686 for (i=0; i<lck->num_share_modes; i++) {
5687 struct share_mode_entry *e = &lck->share_modes[i];
5688 if (is_valid_share_mode_entry(e)) {
5689 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5690 continue;
5691 }
5692 /* Fail with sharing violation. */
5693 close_file(fsp, NORMAL_CLOSE);
5694 TALLOC_FREE(lck);
5695 return NT_STATUS_SHARING_VIOLATION;
5696 }
5697 }
5698
5699 /*
5700 * Set the delete on close.
5701 */
5702 status = smb_set_file_disposition_info(conn,
5703 &del,
5704 1,
5705 fsp,
5706 fname,
5707 psbuf);
5708
5709 if (!NT_STATUS_IS_OK(status)) {
5710 close_file(fsp, NORMAL_CLOSE);
5711 TALLOC_FREE(lck);
5712 return status;
5713 }
5714 TALLOC_FREE(lck);
5715 return close_file(fsp, NORMAL_CLOSE);
5716}
5717
5718/****************************************************************************
5719 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5720****************************************************************************/
5721
5722static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5723 unsigned int tran_call,
5724 char **pparams, int total_params, char **ppdata, int total_data,
5725 unsigned int max_data_bytes)
5726{
5727 char *params = *pparams;
5728 char *pdata = *ppdata;
5729 uint16 info_level;
5730 SMB_STRUCT_STAT sbuf;
5731 pstring fname;
5732 files_struct *fsp = NULL;
5733 NTSTATUS status = NT_STATUS_OK;
5734 int data_return_size = 0;
5735
5736 if (!params) {
5737 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5738 }
5739
5740 ZERO_STRUCT(sbuf);
5741
5742 if (tran_call == TRANSACT2_SETFILEINFO) {
5743 if (total_params < 4) {
5744 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5745 }
5746
5747 fsp = file_fsp(params,0);
5748 info_level = SVAL(params,2);
5749
5750 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5751 /*
5752 * This is actually a SETFILEINFO on a directory
5753 * handle (returned from an NT SMB). NT5.0 seems
5754 * to do this call. JRA.
5755 */
5756 pstrcpy(fname, fsp->fsp_name);
5757 if (INFO_LEVEL_IS_UNIX(info_level)) {
5758 /* Always do lstat for UNIX calls. */
5759 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5760 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5761 return UNIXERROR(ERRDOS,ERRbadpath);
5762 }
5763 } else {
5764 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5765 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5766 return UNIXERROR(ERRDOS,ERRbadpath);
5767 }
5768 }
5769 } else if (fsp && fsp->print_file) {
5770 /*
5771 * Doing a DELETE_ON_CLOSE should cancel a print job.
5772 */
5773 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5774 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5775
5776 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5777
5778 SSVAL(params,0,0);
5779 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5780 return(-1);
5781 } else
5782 return (UNIXERROR(ERRDOS,ERRbadpath));
5783 } else {
5784 /*
5785 * Original code - this is an open file.
5786 */
5787 CHECK_FSP(fsp,conn);
5788
5789 pstrcpy(fname, fsp->fsp_name);
5790
5791 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5792 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5793 return(UNIXERROR(ERRDOS,ERRbadfid));
5794 }
5795 }
5796 } else {
5797 /* set path info */
5798 if (total_params < 7) {
5799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5800 }
5801
5802 info_level = SVAL(params,0);
5803 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 return ERROR_NT(status);
5806 }
5807
5808 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5809 if (!NT_STATUS_IS_OK(status)) {
5810 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5811 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5812 }
5813 return ERROR_NT(status);
5814 }
5815
5816 status = unix_convert(conn, fname, False, NULL, &sbuf);
5817 if (!NT_STATUS_IS_OK(status)) {
5818 return ERROR_NT(status);
5819 }
5820
5821 status = check_name(conn, fname);
5822 if (!NT_STATUS_IS_OK(status)) {
5823 return ERROR_NT(status);
5824 }
5825
5826 if (INFO_LEVEL_IS_UNIX(info_level)) {
5827 /*
5828 * For CIFS UNIX extensions the target name may not exist.
5829 */
5830
5831 /* Always do lstat for UNIX calls. */
5832 SMB_VFS_LSTAT(conn,fname,&sbuf);
5833
5834 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5835 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5836 return UNIXERROR(ERRDOS,ERRbadpath);
5837 }
5838 }
5839
5840 if (!CAN_WRITE(conn)) {
5841 return ERROR_DOS(ERRSRV,ERRaccess);
5842 }
5843
5844 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5845 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5846 }
5847
5848 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5849 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5850
5851 /* Realloc the parameter size */
5852 *pparams = (char *)SMB_REALLOC(*pparams,2);
5853 if (*pparams == NULL) {
5854 return ERROR_NT(NT_STATUS_NO_MEMORY);
5855 }
5856 params = *pparams;
5857
5858 SSVAL(params,0,0);
5859
5860 if (fsp && !null_timespec(fsp->pending_modtime)) {
5861 /* the pending modtime overrides the current modtime */
5862 set_mtimespec(&sbuf, fsp->pending_modtime);
5863 }
5864
5865 switch (info_level) {
5866
5867 case SMB_INFO_STANDARD:
5868 {
5869 status = smb_set_info_standard(conn,
5870 pdata,
5871 total_data,
5872 fsp,
5873 fname,
5874 &sbuf);
5875 break;
5876 }
5877
5878 case SMB_INFO_SET_EA:
5879 {
5880 status = smb_info_set_ea(conn,
5881 pdata,
5882 total_data,
5883 fsp,
5884 fname);
5885 break;
5886 }
5887
5888 case SMB_SET_FILE_BASIC_INFO:
5889 case SMB_FILE_BASIC_INFORMATION:
5890 {
5891 status = smb_set_file_basic_info(conn,
5892 pdata,
5893 total_data,
5894 fsp,
5895 fname,
5896 &sbuf);
5897 break;
5898 }
5899
5900 case SMB_FILE_ALLOCATION_INFORMATION:
5901 case SMB_SET_FILE_ALLOCATION_INFO:
5902 {
5903 status = smb_set_file_allocation_info(conn,
5904 pdata,
5905 total_data,
5906 fsp,
5907 fname,
5908 &sbuf);
5909 break;
5910 }
5911
5912 case SMB_FILE_END_OF_FILE_INFORMATION:
5913 case SMB_SET_FILE_END_OF_FILE_INFO:
5914 {
5915 status = smb_set_file_end_of_file_info(conn,
5916 pdata,
5917 total_data,
5918 fsp,
5919 fname,
5920 &sbuf);
5921 break;
5922 }
5923
5924 case SMB_FILE_DISPOSITION_INFORMATION:
5925 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5926 {
5927#if 0
5928 /* JRA - We used to just ignore this on a path ?
5929 * Shouldn't this be invalid level on a pathname
5930 * based call ?
5931 */
5932 if (tran_call != TRANSACT2_SETFILEINFO) {
5933 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5934 }
5935#endif
5936 status = smb_set_file_disposition_info(conn,
5937 pdata,
5938 total_data,
5939 fsp,
5940 fname,
5941 &sbuf);
5942 break;
5943 }
5944
5945 case SMB_FILE_POSITION_INFORMATION:
5946 {
5947 status = smb_file_position_information(conn,
5948 pdata,
5949 total_data,
5950 fsp);
5951 break;
5952 }
5953
5954 /* From tridge Samba4 :
5955 * MODE_INFORMATION in setfileinfo (I have no
5956 * idea what "mode information" on a file is - it takes a value of 0,
5957 * 2, 4 or 6. What could it be?).
5958 */
5959
5960 case SMB_FILE_MODE_INFORMATION:
5961 {
5962 status = smb_file_mode_information(conn,
5963 pdata,
5964 total_data);
5965 break;
5966 }
5967
5968 /*
5969 * CIFS UNIX extensions.
5970 */
5971
5972 case SMB_SET_FILE_UNIX_BASIC:
5973 {
5974 status = smb_set_file_unix_basic(conn,
5975 pdata,
5976 total_data,
5977 fsp,
5978 fname,
5979 &sbuf);
5980 break;
5981 }
5982
5983 case SMB_SET_FILE_UNIX_INFO2:
5984 {
5985 status = smb_set_file_unix_info2(conn,
5986 pdata,
5987 total_data,
5988 fsp,
5989 fname,
5990 &sbuf);
5991 break;
5992 }
5993
5994 case SMB_SET_FILE_UNIX_LINK:
5995 {
5996 if (tran_call != TRANSACT2_SETPATHINFO) {
5997 /* We must have a pathname for this. */
5998 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5999 }
6000 status = smb_set_file_unix_link(conn,
6001 inbuf,
6002 pdata,
6003 total_data,
6004 fname);
6005 break;
6006 }
6007
6008 case SMB_SET_FILE_UNIX_HLINK:
6009 {
6010 if (tran_call != TRANSACT2_SETPATHINFO) {
6011 /* We must have a pathname for this. */
6012 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6013 }
6014 status = smb_set_file_unix_hlink(conn,
6015 inbuf,
6016 outbuf,
6017 pdata,
6018 total_data,
6019 fname);
6020 break;
6021 }
6022
6023 case SMB_FILE_RENAME_INFORMATION:
6024 {
6025 status = smb_file_rename_information(conn,
6026 inbuf,
6027 outbuf,
6028 pdata,
6029 total_data,
6030 fsp,
6031 fname);
6032 break;
6033 }
6034
6035#if defined(HAVE_POSIX_ACLS)
6036 case SMB_SET_POSIX_ACL:
6037 {
6038 status = smb_set_posix_acl(conn,
6039 pdata,
6040 total_data,
6041 fsp,
6042 fname,
6043 &sbuf);
6044 break;
6045 }
6046#endif
6047
6048 case SMB_SET_POSIX_LOCK:
6049 {
6050 if (tran_call != TRANSACT2_SETFILEINFO) {
6051 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6052 }
6053 status = smb_set_posix_lock(conn,
6054 inbuf,
6055 length,
6056 pdata,
6057 total_data,
6058 fsp);
6059 break;
6060 }
6061
6062 case SMB_POSIX_PATH_OPEN:
6063 {
6064 if (tran_call != TRANSACT2_SETPATHINFO) {
6065 /* We must have a pathname for this. */
6066 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6067 }
6068
6069 status = smb_posix_open(conn,
6070 ppdata,
6071 total_data,
6072 fname,
6073 &sbuf,
6074 &data_return_size);
6075 break;
6076 }
6077
6078 case SMB_POSIX_PATH_UNLINK:
6079 {
6080 if (tran_call != TRANSACT2_SETPATHINFO) {
6081 /* We must have a pathname for this. */
6082 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6083 }
6084
6085 status = smb_posix_unlink(conn,
6086 pdata,
6087 total_data,
6088 fname,
6089 &sbuf);
6090 break;
6091 }
6092
6093 default:
6094 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6095 }
6096
6097
6098 if (!NT_STATUS_IS_OK(status)) {
6099 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6100 /* We have re-scheduled this call. */
6101 return -1;
6102 }
6103 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6104 /* We have re-scheduled this call. */
6105 return -1;
6106 }
6107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6108 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6109 }
6110 if (info_level == SMB_POSIX_PATH_OPEN) {
6111 return ERROR_OPEN(status);
6112 }
6113 return ERROR_NT(status);
6114 }
6115
6116 SSVAL(params,0,0);
6117 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6118
6119 return -1;
6120}
6121
6122/****************************************************************************
6123 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6124****************************************************************************/
6125
6126static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6127 char **pparams, int total_params, char **ppdata, int total_data,
6128 unsigned int max_data_bytes)
6129{
6130 char *params = *pparams;
6131 char *pdata = *ppdata;
6132 pstring directory;
6133 SMB_STRUCT_STAT sbuf;
6134 NTSTATUS status = NT_STATUS_OK;
6135 struct ea_list *ea_list = NULL;
6136
6137 if (!CAN_WRITE(conn))
6138 return ERROR_DOS(ERRSRV,ERRaccess);
6139
6140 if (total_params < 5) {
6141 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6142 }
6143
6144 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 return ERROR_NT(status);
6147 }
6148
6149 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6150
6151 status = unix_convert(conn, directory, False, NULL, &sbuf);
6152 if (!NT_STATUS_IS_OK(status)) {
6153 return ERROR_NT(status);
6154 }
6155
6156 status = check_name(conn, directory);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6159 return ERROR_NT(status);
6160 }
6161
6162 /* Any data in this call is an EA list. */
6163 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6164 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6165 }
6166
6167 /*
6168 * OS/2 workplace shell seems to send SET_EA requests of "null"
6169 * length (4 bytes containing IVAL 4).
6170 * They seem to have no effect. Bug #3212. JRA.
6171 */
6172
6173 if (total_data != 4) {
6174 if (total_data < 10) {
6175 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6176 }
6177
6178 if (IVAL(pdata,0) > total_data) {
6179 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6180 IVAL(pdata,0), (unsigned int)total_data));
6181 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6182 }
6183
6184 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6185 total_data - 4);
6186 if (!ea_list) {
6187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6188 }
6189 } else if (IVAL(pdata,0) != 4) {
6190 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6191 }
6192
6193 status = create_directory(conn, directory);
6194
6195 if (!NT_STATUS_IS_OK(status)) {
6196 return ERROR_NT(status);
6197 }
6198
6199 /* Try and set any given EA. */
6200 if (ea_list) {
6201 status = set_ea(conn, NULL, directory, ea_list);
6202 if (!NT_STATUS_IS_OK(status)) {
6203 return ERROR_NT(status);
6204 }
6205 }
6206
6207 /* Realloc the parameter and data sizes */
6208 *pparams = (char *)SMB_REALLOC(*pparams,2);
6209 if(*pparams == NULL) {
6210 return ERROR_NT(NT_STATUS_NO_MEMORY);
6211 }
6212 params = *pparams;
6213
6214 SSVAL(params,0,0);
6215
6216 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6217
6218 return(-1);
6219}
6220
6221/****************************************************************************
6222 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6223 We don't actually do this - we just send a null response.
6224****************************************************************************/
6225
6226static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6227 char **pparams, int total_params, char **ppdata, int total_data,
6228 unsigned int max_data_bytes)
6229{
6230 static uint16 fnf_handle = 257;
6231 char *params = *pparams;
6232 uint16 info_level;
6233
6234 if (total_params < 6) {
6235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6236 }
6237
6238 info_level = SVAL(params,4);
6239 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6240
6241 switch (info_level) {
6242 case 1:
6243 case 2:
6244 break;
6245 default:
6246 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6247 }
6248
6249 /* Realloc the parameter and data sizes */
6250 *pparams = (char *)SMB_REALLOC(*pparams,6);
6251 if (*pparams == NULL) {
6252 return ERROR_NT(NT_STATUS_NO_MEMORY);
6253 }
6254 params = *pparams;
6255
6256 SSVAL(params,0,fnf_handle);
6257 SSVAL(params,2,0); /* No changes */
6258 SSVAL(params,4,0); /* No EA errors */
6259
6260 fnf_handle++;
6261
6262 if(fnf_handle == 0)
6263 fnf_handle = 257;
6264
6265 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6266
6267 return(-1);
6268}
6269
6270/****************************************************************************
6271 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6272 changes). Currently this does nothing.
6273****************************************************************************/
6274
6275static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6276 char **pparams, int total_params, char **ppdata, int total_data,
6277 unsigned int max_data_bytes)
6278{
6279 char *params = *pparams;
6280
6281 DEBUG(3,("call_trans2findnotifynext\n"));
6282
6283 /* Realloc the parameter and data sizes */
6284 *pparams = (char *)SMB_REALLOC(*pparams,4);
6285 if (*pparams == NULL) {
6286 return ERROR_NT(NT_STATUS_NO_MEMORY);
6287 }
6288 params = *pparams;
6289
6290 SSVAL(params,0,0); /* No changes */
6291 SSVAL(params,2,0); /* No EA errors */
6292
6293 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6294
6295 return(-1);
6296}
6297
6298/****************************************************************************
6299 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6300****************************************************************************/
6301
6302static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6303 char **pparams, int total_params, char **ppdata, int total_data,
6304 unsigned int max_data_bytes)
6305{
6306 char *params = *pparams;
6307 pstring pathname;
6308 int reply_size = 0;
6309 int max_referral_level;
6310 NTSTATUS status = NT_STATUS_OK;
6311
6312 DEBUG(10,("call_trans2getdfsreferral\n"));
6313
6314 if (total_params < 3) {
6315 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6316 }
6317
6318 max_referral_level = SVAL(params,0);
6319
6320 if(!lp_host_msdfs())
6321 return ERROR_DOS(ERRDOS,ERRbadfunc);
6322
6323 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6324 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6325 return ERROR_NT(status);
6326
6327 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6328 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6329
6330 return(-1);
6331}
6332
6333#define LMCAT_SPL 0x53
6334#define LMFUNC_GETJOBID 0x60
6335
6336/****************************************************************************
6337 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6338****************************************************************************/
6339
6340static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6341 char **pparams, int total_params, char **ppdata, int total_data,
6342 unsigned int max_data_bytes)
6343{
6344 char *pdata = *ppdata;
6345 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6346
6347 /* check for an invalid fid before proceeding */
6348
6349 if (!fsp)
6350 return(ERROR_DOS(ERRDOS,ERRbadfid));
6351
6352 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6353 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6354 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6355 if (*ppdata == NULL) {
6356 return ERROR_NT(NT_STATUS_NO_MEMORY);
6357 }
6358 pdata = *ppdata;
6359
6360 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6361 CAN ACCEPT THIS IN UNICODE. JRA. */
6362
6363 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6364 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6365 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6366 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6367 return(-1);
6368 } else {
6369 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6370 return ERROR_DOS(ERRSRV,ERRerror);
6371 }
6372}
6373
6374/****************************************************************************
6375 Reply to a SMBfindclose (stop trans2 directory search).
6376****************************************************************************/
6377
6378int reply_findclose(connection_struct *conn,
6379 char *inbuf,char *outbuf,int length,int bufsize)
6380{
6381 int outsize = 0;
6382 int dptr_num=SVALS(inbuf,smb_vwv0);
6383 START_PROFILE(SMBfindclose);
6384
6385 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6386
6387 dptr_close(&dptr_num);
6388
6389 outsize = set_message(outbuf,0,0,False);
6390
6391 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6392
6393 END_PROFILE(SMBfindclose);
6394 return(outsize);
6395}
6396
6397/****************************************************************************
6398 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6399****************************************************************************/
6400
6401int reply_findnclose(connection_struct *conn,
6402 char *inbuf,char *outbuf,int length,int bufsize)
6403{
6404 int outsize = 0;
6405 int dptr_num= -1;
6406 START_PROFILE(SMBfindnclose);
6407
6408 dptr_num = SVAL(inbuf,smb_vwv0);
6409
6410 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6411
6412 /* We never give out valid handles for a
6413 findnotifyfirst - so any dptr_num is ok here.
6414 Just ignore it. */
6415
6416 outsize = set_message(outbuf,0,0,False);
6417
6418 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6419
6420 END_PROFILE(SMBfindnclose);
6421 return(outsize);
6422}
6423
6424int handle_trans2(connection_struct *conn,
6425 struct trans_state *state,
6426 char *inbuf, char *outbuf, int size, int bufsize)
6427{
6428 int outsize;
6429
6430 if (Protocol >= PROTOCOL_NT1) {
6431 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6432 }
6433
6434 /* Now we must call the relevant TRANS2 function */
6435 switch(state->call) {
6436 case TRANSACT2_OPEN:
6437 {
6438 START_PROFILE(Trans2_open);
6439 outsize = call_trans2open(
6440 conn, inbuf, outbuf, bufsize,
6441 &state->param, state->total_param,
6442 &state->data, state->total_data,
6443 state->max_data_return);
6444 END_PROFILE(Trans2_open);
6445 break;
6446 }
6447
6448 case TRANSACT2_FINDFIRST:
6449 {
6450 START_PROFILE(Trans2_findfirst);
6451 outsize = call_trans2findfirst(
6452 conn, inbuf, outbuf, bufsize,
6453 &state->param, state->total_param,
6454 &state->data, state->total_data,
6455 state->max_data_return);
6456 END_PROFILE(Trans2_findfirst);
6457 break;
6458 }
6459
6460 case TRANSACT2_FINDNEXT:
6461 {
6462 START_PROFILE(Trans2_findnext);
6463 outsize = call_trans2findnext(
6464 conn, inbuf, outbuf, size, bufsize,
6465 &state->param, state->total_param,
6466 &state->data, state->total_data,
6467 state->max_data_return);
6468 END_PROFILE(Trans2_findnext);
6469 break;
6470 }
6471
6472 case TRANSACT2_QFSINFO:
6473 {
6474 START_PROFILE(Trans2_qfsinfo);
6475 outsize = call_trans2qfsinfo(
6476 conn, inbuf, outbuf, size, bufsize,
6477 &state->param, state->total_param,
6478 &state->data, state->total_data,
6479 state->max_data_return);
6480 END_PROFILE(Trans2_qfsinfo);
6481 break;
6482 }
6483
6484 case TRANSACT2_SETFSINFO:
6485 {
6486 START_PROFILE(Trans2_setfsinfo);
6487 outsize = call_trans2setfsinfo(
6488 conn, inbuf, outbuf, size, bufsize,
6489 &state->param, state->total_param,
6490 &state->data, state->total_data,
6491 state->max_data_return);
6492 END_PROFILE(Trans2_setfsinfo);
6493 break;
6494 }
6495
6496 case TRANSACT2_QPATHINFO:
6497 case TRANSACT2_QFILEINFO:
6498 {
6499 START_PROFILE(Trans2_qpathinfo);
6500 outsize = call_trans2qfilepathinfo(
6501 conn, inbuf, outbuf, size, bufsize, state->call,
6502 &state->param, state->total_param,
6503 &state->data, state->total_data,
6504 state->max_data_return);
6505 END_PROFILE(Trans2_qpathinfo);
6506 break;
6507 }
6508
6509 case TRANSACT2_SETPATHINFO:
6510 case TRANSACT2_SETFILEINFO:
6511 {
6512 START_PROFILE(Trans2_setpathinfo);
6513 outsize = call_trans2setfilepathinfo(
6514 conn, inbuf, outbuf, size, bufsize, state->call,
6515 &state->param, state->total_param,
6516 &state->data, state->total_data,
6517 state->max_data_return);
6518 END_PROFILE(Trans2_setpathinfo);
6519 break;
6520 }
6521
6522 case TRANSACT2_FINDNOTIFYFIRST:
6523 {
6524 START_PROFILE(Trans2_findnotifyfirst);
6525 outsize = call_trans2findnotifyfirst(
6526 conn, inbuf, outbuf, size, bufsize,
6527 &state->param, state->total_param,
6528 &state->data, state->total_data,
6529 state->max_data_return);
6530 END_PROFILE(Trans2_findnotifyfirst);
6531 break;
6532 }
6533
6534 case TRANSACT2_FINDNOTIFYNEXT:
6535 {
6536 START_PROFILE(Trans2_findnotifynext);
6537 outsize = call_trans2findnotifynext(
6538 conn, inbuf, outbuf, size, bufsize,
6539 &state->param, state->total_param,
6540 &state->data, state->total_data,
6541 state->max_data_return);
6542 END_PROFILE(Trans2_findnotifynext);
6543 break;
6544 }
6545
6546 case TRANSACT2_MKDIR:
6547 {
6548 START_PROFILE(Trans2_mkdir);
6549 outsize = call_trans2mkdir(
6550 conn, inbuf, outbuf, size, bufsize,
6551 &state->param, state->total_param,
6552 &state->data, state->total_data,
6553 state->max_data_return);
6554 END_PROFILE(Trans2_mkdir);
6555 break;
6556 }
6557
6558 case TRANSACT2_GET_DFS_REFERRAL:
6559 {
6560 START_PROFILE(Trans2_get_dfs_referral);
6561 outsize = call_trans2getdfsreferral(
6562 conn, inbuf, outbuf, size, bufsize,
6563 &state->param, state->total_param,
6564 &state->data, state->total_data,
6565 state->max_data_return);
6566 END_PROFILE(Trans2_get_dfs_referral);
6567 break;
6568 }
6569
6570 case TRANSACT2_IOCTL:
6571 {
6572 START_PROFILE(Trans2_ioctl);
6573 outsize = call_trans2ioctl(
6574 conn, inbuf, outbuf, size, bufsize,
6575 &state->param, state->total_param,
6576 &state->data, state->total_data,
6577 state->max_data_return);
6578 END_PROFILE(Trans2_ioctl);
6579 break;
6580 }
6581
6582 default:
6583 /* Error in request */
6584 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6585 outsize = ERROR_DOS(ERRSRV,ERRerror);
6586 }
6587
6588 return outsize;
6589}
6590
6591/****************************************************************************
6592 Reply to a SMBtrans2.
6593 ****************************************************************************/
6594
6595int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6596 int size, int bufsize)
6597{
6598 int outsize = 0;
6599 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6600 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6601 unsigned int psoff = SVAL(inbuf, smb_psoff);
6602 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6603 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6604 unsigned int av_size = size-4;
6605 struct trans_state *state;
6606 NTSTATUS result;
6607
6608 START_PROFILE(SMBtrans2);
6609
6610 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6611 if (!NT_STATUS_IS_OK(result)) {
6612 DEBUG(2, ("Got invalid trans2 request: %s\n",
6613 nt_errstr(result)));
6614 END_PROFILE(SMBtrans2);
6615 return ERROR_NT(result);
6616 }
6617
6618 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6619 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6620 END_PROFILE(SMBtrans2);
6621 return ERROR_DOS(ERRSRV,ERRaccess);
6622 }
6623
6624 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6625 DEBUG(0, ("talloc failed\n"));
6626 END_PROFILE(SMBtrans2);
6627 return ERROR_NT(NT_STATUS_NO_MEMORY);
6628 }
6629
6630 state->cmd = SMBtrans2;
6631
6632 state->mid = SVAL(inbuf, smb_mid);
6633 state->vuid = SVAL(inbuf, smb_uid);
6634 state->setup_count = SVAL(inbuf, smb_suwcnt);
6635 state->setup = NULL;
6636 state->total_param = SVAL(inbuf, smb_tpscnt);
6637 state->param = NULL;
6638 state->total_data = SVAL(inbuf, smb_tdscnt);
6639 state->data = NULL;
6640 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6641 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6642 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6643 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6644 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6645
6646 state->call = tran_call;
6647
6648 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6649 is so as a sanity check */
6650 if (state->setup_count != 1) {
6651 /*
6652 * Need to have rc=0 for ioctl to get job id for OS/2.
6653 * Network printing will fail if function is not successful.
6654 * Similar function in reply.c will be used if protocol
6655 * is LANMAN1.0 instead of LM1.2X002.
6656 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6657 * outbuf doesn't have to be set(only job id is used).
6658 */
6659 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6660 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6661 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6662 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6663 } else {
6664 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6665 DEBUG(2,("Transaction is %d\n",tran_call));
6666 TALLOC_FREE(state);
6667 END_PROFILE(SMBtrans2);
6668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6669 }
6670 }
6671
6672 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6673 goto bad_param;
6674
6675 if (state->total_data) {
6676 /* Can't use talloc here, the core routines do realloc on the
6677 * params and data. */
6678 state->data = (char *)SMB_MALLOC(state->total_data);
6679 if (state->data == NULL) {
6680 DEBUG(0,("reply_trans2: data malloc fail for %u "
6681 "bytes !\n", (unsigned int)state->total_data));
6682 TALLOC_FREE(state);
6683 END_PROFILE(SMBtrans2);
6684 return(ERROR_DOS(ERRDOS,ERRnomem));
6685 }
6686
6687 if (dscnt > state->total_data ||
6688 dsoff+dscnt < dsoff) {
6689 goto bad_param;
6690 }
6691
6692 if (dsoff > av_size ||
6693 dscnt > av_size ||
6694 dsoff+dscnt > av_size) {
6695 goto bad_param;
6696 }
6697
6698 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6699 }
6700
6701 if (state->total_param) {
6702 /* Can't use talloc here, the core routines do realloc on the
6703 * params and data. */
6704 state->param = (char *)SMB_MALLOC(state->total_param);
6705 if (state->param == NULL) {
6706 DEBUG(0,("reply_trans: param malloc fail for %u "
6707 "bytes !\n", (unsigned int)state->total_param));
6708 SAFE_FREE(state->data);
6709 TALLOC_FREE(state);
6710 END_PROFILE(SMBtrans2);
6711 return(ERROR_DOS(ERRDOS,ERRnomem));
6712 }
6713
6714 if (pscnt > state->total_param ||
6715 psoff+pscnt < psoff) {
6716 goto bad_param;
6717 }
6718
6719 if (psoff > av_size ||
6720 pscnt > av_size ||
6721 psoff+pscnt > av_size) {
6722 goto bad_param;
6723 }
6724
6725 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6726 }
6727
6728 state->received_data = dscnt;
6729 state->received_param = pscnt;
6730
6731 if ((state->received_param == state->total_param) &&
6732 (state->received_data == state->total_data)) {
6733
6734 outsize = handle_trans2(conn, state, inbuf, outbuf,
6735 size, bufsize);
6736 SAFE_FREE(state->data);
6737 SAFE_FREE(state->param);
6738 TALLOC_FREE(state);
6739 END_PROFILE(SMBtrans2);
6740 return outsize;
6741 }
6742
6743 DLIST_ADD(conn->pending_trans, state);
6744
6745 /* We need to send an interim response then receive the rest
6746 of the parameter/data bytes */
6747 outsize = set_message(outbuf,0,0,False);
6748 show_msg(outbuf);
6749 END_PROFILE(SMBtrans2);
6750 return outsize;
6751
6752 bad_param:
6753
6754 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6755 SAFE_FREE(state->data);
6756 SAFE_FREE(state->param);
6757 TALLOC_FREE(state);
6758 END_PROFILE(SMBtrans2);
6759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6760}
6761
6762
6763/****************************************************************************
6764 Reply to a SMBtranss2
6765 ****************************************************************************/
6766
6767int reply_transs2(connection_struct *conn,
6768 char *inbuf,char *outbuf,int size,int bufsize)
6769{
6770 int outsize = 0;
6771 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6772 unsigned int av_size = size-4;
6773 struct trans_state *state;
6774
6775 START_PROFILE(SMBtranss2);
6776
6777 show_msg(inbuf);
6778
6779 for (state = conn->pending_trans; state != NULL;
6780 state = state->next) {
6781 if (state->mid == SVAL(inbuf,smb_mid)) {
6782 break;
6783 }
6784 }
6785
6786 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6787 END_PROFILE(SMBtranss2);
6788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6789 }
6790
6791 /* Revise state->total_param and state->total_data in case they have
6792 changed downwards */
6793
6794 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6795 state->total_param = SVAL(inbuf, smb_tpscnt);
6796 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6797 state->total_data = SVAL(inbuf, smb_tdscnt);
6798
6799 pcnt = SVAL(inbuf, smb_spscnt);
6800 poff = SVAL(inbuf, smb_spsoff);
6801 pdisp = SVAL(inbuf, smb_spsdisp);
6802
6803 dcnt = SVAL(inbuf, smb_sdscnt);
6804 doff = SVAL(inbuf, smb_sdsoff);
6805 ddisp = SVAL(inbuf, smb_sdsdisp);
6806
6807 state->received_param += pcnt;
6808 state->received_data += dcnt;
6809
6810 if ((state->received_data > state->total_data) ||
6811 (state->received_param > state->total_param))
6812 goto bad_param;
6813
6814 if (pcnt) {
6815 if (pdisp > state->total_param ||
6816 pcnt > state->total_param ||
6817 pdisp+pcnt > state->total_param ||
6818 pdisp+pcnt < pdisp) {
6819 goto bad_param;
6820 }
6821
6822 if (poff > av_size ||
6823 pcnt > av_size ||
6824 poff+pcnt > av_size ||
6825 poff+pcnt < poff) {
6826 goto bad_param;
6827 }
6828
6829 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6830 pcnt);
6831 }
6832
6833 if (dcnt) {
6834 if (ddisp > state->total_data ||
6835 dcnt > state->total_data ||
6836 ddisp+dcnt > state->total_data ||
6837 ddisp+dcnt < ddisp) {
6838 goto bad_param;
6839 }
6840
6841 if (doff > av_size ||
6842 dcnt > av_size ||
6843 doff+dcnt > av_size ||
6844 doff+dcnt < doff) {
6845 goto bad_param;
6846 }
6847
6848 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6849 dcnt);
6850 }
6851
6852 if ((state->received_param < state->total_param) ||
6853 (state->received_data < state->total_data)) {
6854 END_PROFILE(SMBtranss2);
6855 return -1;
6856 }
6857
6858 /* construct_reply_common has done us the favor to pre-fill the
6859 * command field with SMBtranss2 which is wrong :-)
6860 */
6861 SCVAL(outbuf,smb_com,SMBtrans2);
6862
6863 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6864
6865 DLIST_REMOVE(conn->pending_trans, state);
6866 SAFE_FREE(state->data);
6867 SAFE_FREE(state->param);
6868 TALLOC_FREE(state);
6869
6870 if (outsize == 0) {
6871 END_PROFILE(SMBtranss2);
6872 return(ERROR_DOS(ERRSRV,ERRnosupport));
6873 }
6874
6875 END_PROFILE(SMBtranss2);
6876 return(outsize);
6877
6878 bad_param:
6879
6880 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6881 DLIST_REMOVE(conn->pending_trans, state);
6882 SAFE_FREE(state->data);
6883 SAFE_FREE(state->param);
6884 TALLOC_FREE(state);
6885 END_PROFILE(SMBtranss2);
6886 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6887}
Note: See TracBrowser for help on using the repository browser.