source: branches/samba-3.2.x/source/smbd/trans2.c@ 232

Last change on this file since 232 was 232, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.8

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