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

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

Update 3.2 branch to 3.2.9

File size: 215.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-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 files_struct *fsp,
4975 const char *fname,
4976 SMB_STRUCT_STAT *psbuf,
4977 uint32 dosmode)
4978{
4979 if (!VALID_STAT(*psbuf)) {
4980 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4981 }
4982
4983 if (fsp) {
4984 if (fsp->base_fsp) {
4985 fname = fsp->base_fsp->fsp_name;
4986 } else {
4987 fname = fsp->fsp_name;
4988 }
4989 }
4990
4991 if (dosmode) {
4992 if (S_ISDIR(psbuf->st_mode)) {
4993 dosmode |= aDIR;
4994 } else {
4995 dosmode &= ~aDIR;
4996 }
4997 }
4998
4999 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5000
5001 /* check the mode isn't different, before changing it */
5002 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5003
5004 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5005 fname, (unsigned int)dosmode ));
5006
5007 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5008 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5009 fname, strerror(errno)));
5010 return map_nt_error_from_unix(errno);
5011 }
5012 }
5013 return NT_STATUS_OK;
5014}
5015
5016/****************************************************************************
5017 Deal with setting the size from any of the setfilepathinfo functions.
5018****************************************************************************/
5019
5020static NTSTATUS smb_set_file_size(connection_struct *conn,
5021 struct smb_request *req,
5022 files_struct *fsp,
5023 const char *fname,
5024 SMB_STRUCT_STAT *psbuf,
5025 SMB_OFF_T size)
5026{
5027 NTSTATUS status = NT_STATUS_OK;
5028 files_struct *new_fsp = NULL;
5029
5030 if (!VALID_STAT(*psbuf)) {
5031 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5032 }
5033
5034 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5035
5036 if (size == get_file_size(*psbuf)) {
5037 return NT_STATUS_OK;
5038 }
5039
5040 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5041 fname, (double)size ));
5042
5043 if (fsp && fsp->fh->fd != -1) {
5044 /* Handle based call. */
5045 if (vfs_set_filelen(fsp, size) == -1) {
5046 return map_nt_error_from_unix(errno);
5047 }
5048 trigger_write_time_update_immediate(fsp);
5049 return NT_STATUS_OK;
5050 }
5051
5052 status = open_file_ntcreate(conn, req, fname, psbuf,
5053 FILE_WRITE_ATTRIBUTES,
5054 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5055 FILE_OPEN,
5056 0,
5057 FILE_ATTRIBUTE_NORMAL,
5058 FORCE_OPLOCK_BREAK_TO_NONE,
5059 NULL, &new_fsp);
5060
5061 if (!NT_STATUS_IS_OK(status)) {
5062 /* NB. We check for open_was_deferred in the caller. */
5063 return status;
5064 }
5065
5066 if (vfs_set_filelen(new_fsp, size) == -1) {
5067 status = map_nt_error_from_unix(errno);
5068 close_file(new_fsp,NORMAL_CLOSE);
5069 return status;
5070 }
5071
5072 trigger_write_time_update_immediate(new_fsp);
5073 close_file(new_fsp,NORMAL_CLOSE);
5074 return NT_STATUS_OK;
5075}
5076
5077/****************************************************************************
5078 Deal with SMB_INFO_SET_EA.
5079****************************************************************************/
5080
5081static NTSTATUS smb_info_set_ea(connection_struct *conn,
5082 const char *pdata,
5083 int total_data,
5084 files_struct *fsp,
5085 const char *fname)
5086{
5087 struct ea_list *ea_list = NULL;
5088 TALLOC_CTX *ctx = NULL;
5089 NTSTATUS status = NT_STATUS_OK;
5090
5091 if (total_data < 10) {
5092
5093 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5094 length. They seem to have no effect. Bug #3212. JRA */
5095
5096 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5097 /* We're done. We only get EA info in this call. */
5098 return NT_STATUS_OK;
5099 }
5100
5101 return NT_STATUS_INVALID_PARAMETER;
5102 }
5103
5104 if (IVAL(pdata,0) > total_data) {
5105 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5106 IVAL(pdata,0), (unsigned int)total_data));
5107 return NT_STATUS_INVALID_PARAMETER;
5108 }
5109
5110 ctx = talloc_tos();
5111 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5112 if (!ea_list) {
5113 return NT_STATUS_INVALID_PARAMETER;
5114 }
5115 status = set_ea(conn, fsp, fname, ea_list);
5116
5117 return status;
5118}
5119
5120/****************************************************************************
5121 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5122****************************************************************************/
5123
5124static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5125 const char *pdata,
5126 int total_data,
5127 files_struct *fsp,
5128 const char *fname,
5129 SMB_STRUCT_STAT *psbuf)
5130{
5131 NTSTATUS status = NT_STATUS_OK;
5132 bool delete_on_close;
5133 uint32 dosmode = 0;
5134
5135 if (total_data < 1) {
5136 return NT_STATUS_INVALID_PARAMETER;
5137 }
5138
5139 if (fsp == NULL) {
5140 return NT_STATUS_INVALID_HANDLE;
5141 }
5142
5143 delete_on_close = (CVAL(pdata,0) ? True : False);
5144 dosmode = dos_mode(conn, fname, psbuf);
5145
5146 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5147 "delete_on_close = %u\n",
5148 fsp->fsp_name,
5149 (unsigned int)dosmode,
5150 (unsigned int)delete_on_close ));
5151
5152 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5153
5154 if (!NT_STATUS_IS_OK(status)) {
5155 return status;
5156 }
5157
5158 /* The set is across all open files on this dev/inode pair. */
5159 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
5160 return NT_STATUS_ACCESS_DENIED;
5161 }
5162 return NT_STATUS_OK;
5163}
5164
5165/****************************************************************************
5166 Deal with SMB_FILE_POSITION_INFORMATION.
5167****************************************************************************/
5168
5169static NTSTATUS smb_file_position_information(connection_struct *conn,
5170 const char *pdata,
5171 int total_data,
5172 files_struct *fsp)
5173{
5174 SMB_BIG_UINT position_information;
5175
5176 if (total_data < 8) {
5177 return NT_STATUS_INVALID_PARAMETER;
5178 }
5179
5180 if (fsp == NULL) {
5181 /* Ignore on pathname based set. */
5182 return NT_STATUS_OK;
5183 }
5184
5185 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5186#ifdef LARGE_SMB_OFF_T
5187 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5188#else /* LARGE_SMB_OFF_T */
5189 if (IVAL(pdata,4) != 0) {
5190 /* more than 32 bits? */
5191 return NT_STATUS_INVALID_PARAMETER;
5192 }
5193#endif /* LARGE_SMB_OFF_T */
5194
5195 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5196 fsp->fsp_name, (double)position_information ));
5197 fsp->fh->position_information = position_information;
5198 return NT_STATUS_OK;
5199}
5200
5201/****************************************************************************
5202 Deal with SMB_FILE_MODE_INFORMATION.
5203****************************************************************************/
5204
5205static NTSTATUS smb_file_mode_information(connection_struct *conn,
5206 const char *pdata,
5207 int total_data)
5208{
5209 uint32 mode;
5210
5211 if (total_data < 4) {
5212 return NT_STATUS_INVALID_PARAMETER;
5213 }
5214 mode = IVAL(pdata,0);
5215 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5216 return NT_STATUS_INVALID_PARAMETER;
5217 }
5218 return NT_STATUS_OK;
5219}
5220
5221/****************************************************************************
5222 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5223****************************************************************************/
5224
5225static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5226 struct smb_request *req,
5227 const char *pdata,
5228 int total_data,
5229 const char *fname)
5230{
5231 char *link_target = NULL;
5232 const char *newname = fname;
5233 NTSTATUS status = NT_STATUS_OK;
5234 TALLOC_CTX *ctx = talloc_tos();
5235
5236 /* Set a symbolic link. */
5237 /* Don't allow this if follow links is false. */
5238
5239 if (total_data == 0) {
5240 return NT_STATUS_INVALID_PARAMETER;
5241 }
5242
5243 if (!lp_symlinks(SNUM(conn))) {
5244 return NT_STATUS_ACCESS_DENIED;
5245 }
5246
5247 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5248 total_data, STR_TERMINATE);
5249
5250 if (!link_target) {
5251 return NT_STATUS_INVALID_PARAMETER;
5252 }
5253
5254 /* !widelinks forces the target path to be within the share. */
5255 /* This means we can interpret the target as a pathname. */
5256 if (!lp_widelinks(SNUM(conn))) {
5257 char *rel_name = NULL;
5258 char *last_dirp = NULL;
5259
5260 if (*link_target == '/') {
5261 /* No absolute paths allowed. */
5262 return NT_STATUS_ACCESS_DENIED;
5263 }
5264 rel_name = talloc_strdup(ctx,newname);
5265 if (!rel_name) {
5266 return NT_STATUS_NO_MEMORY;
5267 }
5268 last_dirp = strrchr_m(rel_name, '/');
5269 if (last_dirp) {
5270 last_dirp[1] = '\0';
5271 } else {
5272 rel_name = talloc_strdup(ctx,"./");
5273 if (!rel_name) {
5274 return NT_STATUS_NO_MEMORY;
5275 }
5276 }
5277 rel_name = talloc_asprintf_append(rel_name,
5278 "%s",
5279 link_target);
5280 if (!rel_name) {
5281 return NT_STATUS_NO_MEMORY;
5282 }
5283
5284 status = check_name(conn, rel_name);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 return status;
5287 }
5288 }
5289
5290 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5291 newname, link_target ));
5292
5293 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5294 return map_nt_error_from_unix(errno);
5295 }
5296
5297 return NT_STATUS_OK;
5298}
5299
5300/****************************************************************************
5301 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5302****************************************************************************/
5303
5304static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5305 struct smb_request *req,
5306 const char *pdata, int total_data,
5307 const char *fname)
5308{
5309 char *oldname = NULL;
5310 TALLOC_CTX *ctx = talloc_tos();
5311 NTSTATUS status = NT_STATUS_OK;
5312
5313 /* Set a hard link. */
5314 if (total_data == 0) {
5315 return NT_STATUS_INVALID_PARAMETER;
5316 }
5317
5318 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5319 total_data, STR_TERMINATE, &status);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 return status;
5322 }
5323
5324 status = resolve_dfspath(ctx, conn,
5325 req->flags2 & FLAGS2_DFS_PATHNAMES,
5326 oldname,
5327 &oldname);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 return status;
5330 }
5331
5332 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5333 fname, oldname));
5334
5335 return hardlink_internals(ctx, conn, oldname, fname);
5336}
5337
5338/****************************************************************************
5339 Deal with SMB_FILE_RENAME_INFORMATION.
5340****************************************************************************/
5341
5342static NTSTATUS smb_file_rename_information(connection_struct *conn,
5343 struct smb_request *req,
5344 const char *pdata,
5345 int total_data,
5346 files_struct *fsp,
5347 const char *fname)
5348{
5349 bool overwrite;
5350 uint32 root_fid;
5351 uint32 len;
5352 char *newname = NULL;
5353 char *base_name = NULL;
5354 bool dest_has_wcard = False;
5355 SMB_STRUCT_STAT sbuf;
5356 char *newname_last_component = NULL;
5357 NTSTATUS status = NT_STATUS_OK;
5358 char *p;
5359 TALLOC_CTX *ctx = talloc_tos();
5360
5361 if (total_data < 13) {
5362 return NT_STATUS_INVALID_PARAMETER;
5363 }
5364
5365 ZERO_STRUCT(sbuf);
5366
5367 overwrite = (CVAL(pdata,0) ? True : False);
5368 root_fid = IVAL(pdata,4);
5369 len = IVAL(pdata,8);
5370
5371 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5372 return NT_STATUS_INVALID_PARAMETER;
5373 }
5374
5375 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5376 len, 0, &status,
5377 &dest_has_wcard);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 return status;
5380 }
5381
5382 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5383 newname));
5384
5385 status = resolve_dfspath_wcard(ctx, conn,
5386 req->flags2 & FLAGS2_DFS_PATHNAMES,
5387 newname,
5388 &newname,
5389 &dest_has_wcard);
5390 if (!NT_STATUS_IS_OK(status)) {
5391 return status;
5392 }
5393
5394 /* Check the new name has no '/' characters. */
5395 if (strchr_m(newname, '/')) {
5396 return NT_STATUS_NOT_SUPPORTED;
5397 }
5398
5399 if (fsp && fsp->base_fsp) {
5400 /* newname must be a stream name. */
5401 if (newname[0] != ':') {
5402 return NT_STATUS_NOT_SUPPORTED;
5403 }
5404 base_name = talloc_asprintf(ctx, "%s%s",
5405 fsp->base_fsp->fsp_name,
5406 newname);
5407 if (!base_name) {
5408 return NT_STATUS_NO_MEMORY;
5409 }
5410 } else {
5411 /* newname must *not* be a stream name. */
5412 if (is_ntfs_stream_name(newname)) {
5413 return NT_STATUS_NOT_SUPPORTED;
5414 }
5415
5416 /* Create the base directory. */
5417 base_name = talloc_strdup(ctx, fname);
5418 if (!base_name) {
5419 return NT_STATUS_NO_MEMORY;
5420 }
5421 p = strrchr_m(base_name, '/');
5422 if (p) {
5423 p[1] = '\0';
5424 } else {
5425 base_name = talloc_strdup(ctx, "./");
5426 if (!base_name) {
5427 return NT_STATUS_NO_MEMORY;
5428 }
5429 }
5430 /* Append the new name. */
5431 base_name = talloc_asprintf_append(base_name,
5432 "%s",
5433 newname);
5434 if (!base_name) {
5435 return NT_STATUS_NO_MEMORY;
5436 }
5437
5438 status = unix_convert(ctx, conn, newname, False,
5439 &newname,
5440 &newname_last_component,
5441 &sbuf);
5442
5443 /* If an error we expect this to be
5444 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5445
5446 if (!NT_STATUS_IS_OK(status)
5447 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5448 status)) {
5449 return status;
5450 }
5451 }
5452
5453 if (fsp) {
5454 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5455 fsp->fnum, fsp->fsp_name, base_name ));
5456 status = rename_internals_fsp(conn, fsp, base_name,
5457 newname_last_component, 0,
5458 overwrite);
5459 } else {
5460 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5461 fname, base_name ));
5462 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5463 overwrite, False, dest_has_wcard,
5464 FILE_WRITE_ATTRIBUTES);
5465 }
5466
5467 return status;
5468}
5469
5470/****************************************************************************
5471 Deal with SMB_SET_POSIX_ACL.
5472****************************************************************************/
5473
5474#if defined(HAVE_POSIX_ACLS)
5475static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5476 const char *pdata,
5477 int total_data,
5478 files_struct *fsp,
5479 const char *fname,
5480 SMB_STRUCT_STAT *psbuf)
5481{
5482 uint16 posix_acl_version;
5483 uint16 num_file_acls;
5484 uint16 num_def_acls;
5485 bool valid_file_acls = True;
5486 bool valid_def_acls = True;
5487
5488 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5489 return NT_STATUS_INVALID_PARAMETER;
5490 }
5491 posix_acl_version = SVAL(pdata,0);
5492 num_file_acls = SVAL(pdata,2);
5493 num_def_acls = SVAL(pdata,4);
5494
5495 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5496 valid_file_acls = False;
5497 num_file_acls = 0;
5498 }
5499
5500 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5501 valid_def_acls = False;
5502 num_def_acls = 0;
5503 }
5504
5505 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5506 return NT_STATUS_INVALID_PARAMETER;
5507 }
5508
5509 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5510 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5511 return NT_STATUS_INVALID_PARAMETER;
5512 }
5513
5514 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5515 fname ? fname : fsp->fsp_name,
5516 (unsigned int)num_file_acls,
5517 (unsigned int)num_def_acls));
5518
5519 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5520 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5521 return map_nt_error_from_unix(errno);
5522 }
5523
5524 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5525 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5526 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5527 return map_nt_error_from_unix(errno);
5528 }
5529 return NT_STATUS_OK;
5530}
5531#endif
5532
5533/****************************************************************************
5534 Deal with SMB_SET_POSIX_LOCK.
5535****************************************************************************/
5536
5537static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5538 const struct smb_request *req,
5539 const char *pdata,
5540 int total_data,
5541 files_struct *fsp)
5542{
5543 SMB_BIG_UINT count;
5544 SMB_BIG_UINT offset;
5545 uint32 lock_pid;
5546 bool blocking_lock = False;
5547 enum brl_type lock_type;
5548
5549 NTSTATUS status = NT_STATUS_OK;
5550
5551 if (fsp == NULL || fsp->fh->fd == -1) {
5552 return NT_STATUS_INVALID_HANDLE;
5553 }
5554
5555 if (total_data != POSIX_LOCK_DATA_SIZE) {
5556 return NT_STATUS_INVALID_PARAMETER;
5557 }
5558
5559 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5560 case POSIX_LOCK_TYPE_READ:
5561 lock_type = READ_LOCK;
5562 break;
5563 case POSIX_LOCK_TYPE_WRITE:
5564 /* Return the right POSIX-mappable error code for files opened read-only. */
5565 if (!fsp->can_write) {
5566 return NT_STATUS_INVALID_HANDLE;
5567 }
5568 lock_type = WRITE_LOCK;
5569 break;
5570 case POSIX_LOCK_TYPE_UNLOCK:
5571 lock_type = UNLOCK_LOCK;
5572 break;
5573 default:
5574 return NT_STATUS_INVALID_PARAMETER;
5575 }
5576
5577 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5578 blocking_lock = False;
5579 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5580 blocking_lock = True;
5581 } else {
5582 return NT_STATUS_INVALID_PARAMETER;
5583 }
5584
5585 if (!lp_blocking_locks(SNUM(conn))) {
5586 blocking_lock = False;
5587 }
5588
5589 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5590#if defined(HAVE_LONGLONG)
5591 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5592 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5593 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5594 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5595#else /* HAVE_LONGLONG */
5596 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5597 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5598#endif /* HAVE_LONGLONG */
5599
5600 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5601 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5602 fsp->fsp_name,
5603 (unsigned int)lock_type,
5604 (unsigned int)lock_pid,
5605 (double)count,
5606 (double)offset ));
5607
5608 if (lock_type == UNLOCK_LOCK) {
5609 status = do_unlock(smbd_messaging_context(),
5610 fsp,
5611 lock_pid,
5612 count,
5613 offset,
5614 POSIX_LOCK);
5615 } else {
5616 uint32 block_smbpid;
5617
5618 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5619 fsp,
5620 lock_pid,
5621 count,
5622 offset,
5623 lock_type,
5624 POSIX_LOCK,
5625 blocking_lock,
5626 &status,
5627 &block_smbpid);
5628
5629 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5630 /*
5631 * A blocking lock was requested. Package up
5632 * this smb into a queued request and push it
5633 * onto the blocking lock queue.
5634 */
5635 if(push_blocking_lock_request(br_lck,
5636 req,
5637 fsp,
5638 -1, /* infinite timeout. */
5639 0,
5640 lock_pid,
5641 lock_type,
5642 POSIX_LOCK,
5643 offset,
5644 count,
5645 block_smbpid)) {
5646 TALLOC_FREE(br_lck);
5647 return status;
5648 }
5649 }
5650 TALLOC_FREE(br_lck);
5651 }
5652
5653 return status;
5654}
5655
5656/****************************************************************************
5657 Deal with SMB_INFO_STANDARD.
5658****************************************************************************/
5659
5660static NTSTATUS smb_set_info_standard(connection_struct *conn,
5661 const char *pdata,
5662 int total_data,
5663 files_struct *fsp,
5664 const char *fname,
5665 const SMB_STRUCT_STAT *psbuf)
5666{
5667 struct timespec ts[2];
5668
5669 if (total_data < 12) {
5670 return NT_STATUS_INVALID_PARAMETER;
5671 }
5672
5673 /* access time */
5674 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5675 /* write time */
5676 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5677
5678 DEBUG(10,("smb_set_info_standard: file %s\n",
5679 fname ? fname : fsp->fsp_name ));
5680
5681 return smb_set_file_time(conn,
5682 fsp,
5683 fname,
5684 psbuf,
5685 ts,
5686 true);
5687}
5688
5689/****************************************************************************
5690 Deal with SMB_SET_FILE_BASIC_INFO.
5691****************************************************************************/
5692
5693static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5694 const char *pdata,
5695 int total_data,
5696 files_struct *fsp,
5697 const char *fname,
5698 SMB_STRUCT_STAT *psbuf)
5699{
5700 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5701 struct timespec write_time;
5702 struct timespec changed_time;
5703 uint32 dosmode = 0;
5704 struct timespec ts[2];
5705 NTSTATUS status = NT_STATUS_OK;
5706 bool setting_write_time = true;
5707
5708 if (total_data < 36) {
5709 return NT_STATUS_INVALID_PARAMETER;
5710 }
5711
5712 /* Set the attributes */
5713 dosmode = IVAL(pdata,32);
5714 status = smb_set_file_dosmode(conn,
5715 fsp,
5716 fname,
5717 psbuf,
5718 dosmode);
5719
5720 if (!NT_STATUS_IS_OK(status)) {
5721 return status;
5722 }
5723
5724 /* Ignore create time at offset pdata. */
5725
5726 /* access time */
5727 ts[0] = interpret_long_date(pdata+8);
5728
5729 write_time = interpret_long_date(pdata+16);
5730 changed_time = interpret_long_date(pdata+24);
5731
5732 /* mtime */
5733 ts[1] = timespec_min(&write_time, &changed_time);
5734
5735 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5736 ts[1] = write_time;
5737 }
5738
5739 /* Prefer a defined time to an undefined one. */
5740 if (null_timespec(ts[1])) {
5741 if (null_timespec(write_time)) {
5742 ts[1] = changed_time;
5743 setting_write_time = false;
5744 } else {
5745 ts[1] = write_time;
5746 }
5747 }
5748
5749 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5750 fname ? fname : fsp->fsp_name ));
5751
5752 return smb_set_file_time(conn,
5753 fsp,
5754 fname,
5755 psbuf,
5756 ts,
5757 setting_write_time);
5758}
5759
5760/****************************************************************************
5761 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5762****************************************************************************/
5763
5764static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5765 struct smb_request *req,
5766 const char *pdata,
5767 int total_data,
5768 files_struct *fsp,
5769 const char *fname,
5770 SMB_STRUCT_STAT *psbuf)
5771{
5772 SMB_BIG_UINT allocation_size = 0;
5773 NTSTATUS status = NT_STATUS_OK;
5774 files_struct *new_fsp = NULL;
5775
5776 if (!VALID_STAT(*psbuf)) {
5777 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5778 }
5779
5780 if (total_data < 8) {
5781 return NT_STATUS_INVALID_PARAMETER;
5782 }
5783
5784 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5785#ifdef LARGE_SMB_OFF_T
5786 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5787#else /* LARGE_SMB_OFF_T */
5788 if (IVAL(pdata,4) != 0) {
5789 /* more than 32 bits? */
5790 return NT_STATUS_INVALID_PARAMETER;
5791 }
5792#endif /* LARGE_SMB_OFF_T */
5793
5794 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5795 fname, (double)allocation_size ));
5796
5797 if (allocation_size) {
5798 allocation_size = smb_roundup(conn, allocation_size);
5799 }
5800
5801 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5802 fname, (double)allocation_size ));
5803
5804 if (fsp && fsp->fh->fd != -1) {
5805 /* Open file handle. */
5806 /* Only change if needed. */
5807 if (allocation_size != get_file_size(*psbuf)) {
5808 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5809 return map_nt_error_from_unix(errno);
5810 }
5811 }
5812 /* But always update the time. */
5813 /*
5814 * This is equivalent to a write. Ensure it's seen immediately
5815 * if there are no pending writes.
5816 */
5817 trigger_write_time_update_immediate(fsp);
5818 return NT_STATUS_OK;
5819 }
5820
5821 /* Pathname or stat or directory file. */
5822
5823 status = open_file_ntcreate(conn, req, fname, psbuf,
5824 FILE_WRITE_DATA,
5825 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5826 FILE_OPEN,
5827 0,
5828 FILE_ATTRIBUTE_NORMAL,
5829 FORCE_OPLOCK_BREAK_TO_NONE,
5830 NULL, &new_fsp);
5831
5832 if (!NT_STATUS_IS_OK(status)) {
5833 /* NB. We check for open_was_deferred in the caller. */
5834 return status;
5835 }
5836
5837 /* Only change if needed. */
5838 if (allocation_size != get_file_size(*psbuf)) {
5839 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5840 status = map_nt_error_from_unix(errno);
5841 close_file(new_fsp,NORMAL_CLOSE);
5842 return status;
5843 }
5844 }
5845
5846 /* Changing the allocation size should set the last mod time. */
5847 /*
5848 * This is equivalent to a write. Ensure it's seen immediately
5849 * if there are no pending writes.
5850 */
5851 trigger_write_time_update_immediate(new_fsp);
5852
5853 close_file(new_fsp,NORMAL_CLOSE);
5854 return NT_STATUS_OK;
5855}
5856
5857/****************************************************************************
5858 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5859****************************************************************************/
5860
5861static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5862 struct smb_request *req,
5863 const char *pdata,
5864 int total_data,
5865 files_struct *fsp,
5866 const char *fname,
5867 SMB_STRUCT_STAT *psbuf)
5868{
5869 SMB_OFF_T size;
5870
5871 if (total_data < 8) {
5872 return NT_STATUS_INVALID_PARAMETER;
5873 }
5874
5875 size = IVAL(pdata,0);
5876#ifdef LARGE_SMB_OFF_T
5877 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5878#else /* LARGE_SMB_OFF_T */
5879 if (IVAL(pdata,4) != 0) {
5880 /* more than 32 bits? */
5881 return NT_STATUS_INVALID_PARAMETER;
5882 }
5883#endif /* LARGE_SMB_OFF_T */
5884 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5885 "file %s to %.0f\n", fname, (double)size ));
5886
5887 return smb_set_file_size(conn, req,
5888 fsp,
5889 fname,
5890 psbuf,
5891 size);
5892}
5893
5894/****************************************************************************
5895 Allow a UNIX info mknod.
5896****************************************************************************/
5897
5898static NTSTATUS smb_unix_mknod(connection_struct *conn,
5899 const char *pdata,
5900 int total_data,
5901 const char *fname,
5902 SMB_STRUCT_STAT *psbuf)
5903{
5904 uint32 file_type = IVAL(pdata,56);
5905#if defined(HAVE_MAKEDEV)
5906 uint32 dev_major = IVAL(pdata,60);
5907 uint32 dev_minor = IVAL(pdata,68);
5908#endif
5909 SMB_DEV_T dev = (SMB_DEV_T)0;
5910 uint32 raw_unixmode = IVAL(pdata,84);
5911 NTSTATUS status;
5912 mode_t unixmode;
5913
5914 if (total_data < 100) {
5915 return NT_STATUS_INVALID_PARAMETER;
5916 }
5917
5918 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 return status;
5921 }
5922
5923#if defined(HAVE_MAKEDEV)
5924 dev = makedev(dev_major, dev_minor);
5925#endif
5926
5927 switch (file_type) {
5928#if defined(S_IFIFO)
5929 case UNIX_TYPE_FIFO:
5930 unixmode |= S_IFIFO;
5931 break;
5932#endif
5933#if defined(S_IFSOCK)
5934 case UNIX_TYPE_SOCKET:
5935 unixmode |= S_IFSOCK;
5936 break;
5937#endif
5938#if defined(S_IFCHR)
5939 case UNIX_TYPE_CHARDEV:
5940 unixmode |= S_IFCHR;
5941 break;
5942#endif
5943#if defined(S_IFBLK)
5944 case UNIX_TYPE_BLKDEV:
5945 unixmode |= S_IFBLK;
5946 break;
5947#endif
5948 default:
5949 return NT_STATUS_INVALID_PARAMETER;
5950 }
5951
5952 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
59530%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5954
5955 /* Ok - do the mknod. */
5956 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5957 return map_nt_error_from_unix(errno);
5958 }
5959
5960 /* If any of the other "set" calls fail we
5961 * don't want to end up with a half-constructed mknod.
5962 */
5963
5964 if (lp_inherit_perms(SNUM(conn))) {
5965 inherit_access_acl(
5966 conn, parent_dirname(fname),
5967 fname, unixmode);
5968 }
5969
5970 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5971 status = map_nt_error_from_unix(errno);
5972 SMB_VFS_UNLINK(conn,fname);
5973 return status;
5974 }
5975 return NT_STATUS_OK;
5976}
5977
5978/****************************************************************************
5979 Deal with SMB_SET_FILE_UNIX_BASIC.
5980****************************************************************************/
5981
5982static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5983 struct smb_request *req,
5984 const char *pdata,
5985 int total_data,
5986 files_struct *fsp,
5987 const char *fname,
5988 SMB_STRUCT_STAT *psbuf)
5989{
5990 struct timespec ts[2];
5991 uint32 raw_unixmode;
5992 mode_t unixmode;
5993 SMB_OFF_T size = 0;
5994 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5995 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5996 NTSTATUS status = NT_STATUS_OK;
5997 bool delete_on_fail = False;
5998 enum perm_type ptype;
5999
6000 if (total_data < 100) {
6001 return NT_STATUS_INVALID_PARAMETER;
6002 }
6003
6004 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6005 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6006 size=IVAL(pdata,0); /* first 8 Bytes are size */
6007#ifdef LARGE_SMB_OFF_T
6008 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6009#else /* LARGE_SMB_OFF_T */
6010 if (IVAL(pdata,4) != 0) {
6011 /* more than 32 bits? */
6012 return NT_STATUS_INVALID_PARAMETER;
6013 }
6014#endif /* LARGE_SMB_OFF_T */
6015 }
6016
6017 ts[0] = interpret_long_date(pdata+24); /* access_time */
6018 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6019 set_owner = (uid_t)IVAL(pdata,40);
6020 set_grp = (gid_t)IVAL(pdata,48);
6021 raw_unixmode = IVAL(pdata,84);
6022
6023 if (VALID_STAT(*psbuf)) {
6024 if (S_ISDIR(psbuf->st_mode)) {
6025 ptype = PERM_EXISTING_DIR;
6026 } else {
6027 ptype = PERM_EXISTING_FILE;
6028 }
6029 } else {
6030 ptype = PERM_NEW_FILE;
6031 }
6032
6033 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 return status;
6036 }
6037
6038 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6039size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6040 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6041
6042 if (!VALID_STAT(*psbuf)) {
6043 /*
6044 * The only valid use of this is to create character and block
6045 * devices, and named pipes. This is deprecated (IMHO) and
6046 * a new info level should be used for mknod. JRA.
6047 */
6048
6049 status = smb_unix_mknod(conn,
6050 pdata,
6051 total_data,
6052 fname,
6053 psbuf);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 return status;
6056 }
6057
6058 /* Ensure we don't try and change anything else. */
6059 raw_unixmode = SMB_MODE_NO_CHANGE;
6060 size = get_file_size(*psbuf);
6061 ts[0] = get_atimespec(psbuf);
6062 ts[1] = get_mtimespec(psbuf);
6063 /*
6064 * We continue here as we might want to change the
6065 * owner uid/gid.
6066 */
6067 delete_on_fail = True;
6068 }
6069
6070#if 1
6071 /* Horrible backwards compatibility hack as an old server bug
6072 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6073 * */
6074
6075 if (!size) {
6076 size = get_file_size(*psbuf);
6077 }
6078#endif
6079
6080 /*
6081 * Deal with the UNIX specific mode set.
6082 */
6083
6084 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6085 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6086 (unsigned int)unixmode, fname ));
6087 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6088 return map_nt_error_from_unix(errno);
6089 }
6090 }
6091
6092 /*
6093 * Deal with the UNIX specific uid set.
6094 */
6095
6096 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6097 int ret;
6098
6099 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6100 (unsigned int)set_owner, fname ));
6101
6102 if (S_ISLNK(psbuf->st_mode)) {
6103 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6104 } else {
6105 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6106 }
6107
6108 if (ret != 0) {
6109 status = map_nt_error_from_unix(errno);
6110 if (delete_on_fail) {
6111 SMB_VFS_UNLINK(conn,fname);
6112 }
6113 return status;
6114 }
6115 }
6116
6117 /*
6118 * Deal with the UNIX specific gid set.
6119 */
6120
6121 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6123 (unsigned int)set_owner, fname ));
6124 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6125 status = map_nt_error_from_unix(errno);
6126 if (delete_on_fail) {
6127 SMB_VFS_UNLINK(conn,fname);
6128 }
6129 return status;
6130 }
6131 }
6132
6133 /* Deal with any size changes. */
6134
6135 status = smb_set_file_size(conn, req,
6136 fsp,
6137 fname,
6138 psbuf,
6139 size);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 return status;
6142 }
6143
6144 /* Deal with any time changes. */
6145
6146 return smb_set_file_time(conn,
6147 fsp,
6148 fname,
6149 psbuf,
6150 ts,
6151 true);
6152}
6153
6154/****************************************************************************
6155 Deal with SMB_SET_FILE_UNIX_INFO2.
6156****************************************************************************/
6157
6158static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6159 struct smb_request *req,
6160 const char *pdata,
6161 int total_data,
6162 files_struct *fsp,
6163 const char *fname,
6164 SMB_STRUCT_STAT *psbuf)
6165{
6166 NTSTATUS status;
6167 uint32 smb_fflags;
6168 uint32 smb_fmask;
6169
6170 if (total_data < 116) {
6171 return NT_STATUS_INVALID_PARAMETER;
6172 }
6173
6174 /* Start by setting all the fields that are common between UNIX_BASIC
6175 * and UNIX_INFO2.
6176 */
6177 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6178 fsp, fname, psbuf);
6179 if (!NT_STATUS_IS_OK(status)) {
6180 return status;
6181 }
6182
6183 smb_fflags = IVAL(pdata, 108);
6184 smb_fmask = IVAL(pdata, 112);
6185
6186 /* NB: We should only attempt to alter the file flags if the client
6187 * sends a non-zero mask.
6188 */
6189 if (smb_fmask != 0) {
6190 int stat_fflags = 0;
6191
6192 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6193 &stat_fflags)) {
6194 /* Client asked to alter a flag we don't understand. */
6195 return NT_STATUS_INVALID_PARAMETER;
6196 }
6197
6198 if (fsp && fsp->fh->fd != -1) {
6199 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6200 return NT_STATUS_NOT_SUPPORTED;
6201 } else {
6202 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6203 return map_nt_error_from_unix(errno);
6204 }
6205 }
6206 }
6207
6208 /* XXX: need to add support for changing the create_time here. You
6209 * can do this for paths on Darwin with setattrlist(2). The right way
6210 * to hook this up is probably by extending the VFS utimes interface.
6211 */
6212
6213 return NT_STATUS_OK;
6214}
6215
6216/****************************************************************************
6217 Create a directory with POSIX semantics.
6218****************************************************************************/
6219
6220static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6221 struct smb_request *req,
6222 char **ppdata,
6223 int total_data,
6224 const char *fname,
6225 SMB_STRUCT_STAT *psbuf,
6226 int *pdata_return_size)
6227{
6228 NTSTATUS status = NT_STATUS_OK;
6229 uint32 raw_unixmode = 0;
6230 uint32 mod_unixmode = 0;
6231 mode_t unixmode = (mode_t)0;
6232 files_struct *fsp = NULL;
6233 uint16 info_level_return = 0;
6234 int info;
6235 char *pdata = *ppdata;
6236
6237 if (total_data < 18) {
6238 return NT_STATUS_INVALID_PARAMETER;
6239 }
6240
6241 raw_unixmode = IVAL(pdata,8);
6242 /* Next 4 bytes are not yet defined. */
6243
6244 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6245 if (!NT_STATUS_IS_OK(status)) {
6246 return status;
6247 }
6248
6249 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6250
6251 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6252 fname, (unsigned int)unixmode ));
6253
6254 status = open_directory(conn, req,
6255 fname,
6256 psbuf,
6257 FILE_READ_ATTRIBUTES, /* Just a stat open */
6258 FILE_SHARE_NONE, /* Ignored for stat opens */
6259 FILE_CREATE,
6260 0,
6261 mod_unixmode,
6262 &info,
6263 &fsp);
6264
6265 if (NT_STATUS_IS_OK(status)) {
6266 close_file(fsp, NORMAL_CLOSE);
6267 }
6268
6269 info_level_return = SVAL(pdata,16);
6270
6271 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6272 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6273 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6274 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6275 } else {
6276 *pdata_return_size = 12;
6277 }
6278
6279 /* Realloc the data size */
6280 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6281 if (*ppdata == NULL) {
6282 *pdata_return_size = 0;
6283 return NT_STATUS_NO_MEMORY;
6284 }
6285 pdata = *ppdata;
6286
6287 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6288 SSVAL(pdata,2,0); /* No fnum. */
6289 SIVAL(pdata,4,info); /* Was directory created. */
6290
6291 switch (info_level_return) {
6292 case SMB_QUERY_FILE_UNIX_BASIC:
6293 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6294 SSVAL(pdata,10,0); /* Padding. */
6295 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6296 break;
6297 case SMB_QUERY_FILE_UNIX_INFO2:
6298 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6299 SSVAL(pdata,10,0); /* Padding. */
6300 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6301 break;
6302 default:
6303 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6304 SSVAL(pdata,10,0); /* Padding. */
6305 break;
6306 }
6307
6308 return status;
6309}
6310
6311/****************************************************************************
6312 Open/Create a file with POSIX semantics.
6313****************************************************************************/
6314
6315static NTSTATUS smb_posix_open(connection_struct *conn,
6316 struct smb_request *req,
6317 char **ppdata,
6318 int total_data,
6319 const char *fname,
6320 SMB_STRUCT_STAT *psbuf,
6321 int *pdata_return_size)
6322{
6323 bool extended_oplock_granted = False;
6324 char *pdata = *ppdata;
6325 uint32 flags = 0;
6326 uint32 wire_open_mode = 0;
6327 uint32 raw_unixmode = 0;
6328 uint32 mod_unixmode = 0;
6329 uint32 create_disp = 0;
6330 uint32 access_mask = 0;
6331 uint32 create_options = 0;
6332 NTSTATUS status = NT_STATUS_OK;
6333 mode_t unixmode = (mode_t)0;
6334 files_struct *fsp = NULL;
6335 int oplock_request = 0;
6336 int info = 0;
6337 uint16 info_level_return = 0;
6338
6339 if (total_data < 18) {
6340 return NT_STATUS_INVALID_PARAMETER;
6341 }
6342
6343 flags = IVAL(pdata,0);
6344 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6345 if (oplock_request) {
6346 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6347 }
6348
6349 wire_open_mode = IVAL(pdata,4);
6350
6351 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6352 return smb_posix_mkdir(conn, req,
6353 ppdata,
6354 total_data,
6355 fname,
6356 psbuf,
6357 pdata_return_size);
6358 }
6359
6360 switch (wire_open_mode & SMB_ACCMODE) {
6361 case SMB_O_RDONLY:
6362 access_mask = FILE_READ_DATA;
6363 break;
6364 case SMB_O_WRONLY:
6365 access_mask = FILE_WRITE_DATA;
6366 break;
6367 case SMB_O_RDWR:
6368 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6369 break;
6370 default:
6371 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6372 (unsigned int)wire_open_mode ));
6373 return NT_STATUS_INVALID_PARAMETER;
6374 }
6375
6376 wire_open_mode &= ~SMB_ACCMODE;
6377
6378 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6379 create_disp = FILE_CREATE;
6380 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6381 create_disp = FILE_OVERWRITE_IF;
6382 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6383 create_disp = FILE_OPEN_IF;
6384 } else {
6385 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6386 (unsigned int)wire_open_mode ));
6387 return NT_STATUS_INVALID_PARAMETER;
6388 }
6389
6390 raw_unixmode = IVAL(pdata,8);
6391 /* Next 4 bytes are not yet defined. */
6392
6393 status = unix_perms_from_wire(conn,
6394 psbuf,
6395 raw_unixmode,
6396 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6397 &unixmode);
6398
6399 if (!NT_STATUS_IS_OK(status)) {
6400 return status;
6401 }
6402
6403 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6404
6405 if (wire_open_mode & SMB_O_SYNC) {
6406 create_options |= FILE_WRITE_THROUGH;
6407 }
6408 if (wire_open_mode & SMB_O_APPEND) {
6409 access_mask |= FILE_APPEND_DATA;
6410 }
6411 if (wire_open_mode & SMB_O_DIRECT) {
6412 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6413 }
6414
6415 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6416 fname,
6417 (unsigned int)wire_open_mode,
6418 (unsigned int)unixmode ));
6419
6420 status = open_file_ntcreate(conn, req,
6421 fname,
6422 psbuf,
6423 access_mask,
6424 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6425 create_disp,
6426 0, /* no create options yet. */
6427 mod_unixmode,
6428 oplock_request,
6429 &info,
6430 &fsp);
6431
6432 if (!NT_STATUS_IS_OK(status)) {
6433 return status;
6434 }
6435
6436 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6437 extended_oplock_granted = True;
6438 }
6439
6440 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6441 extended_oplock_granted = True;
6442 }
6443
6444 info_level_return = SVAL(pdata,16);
6445
6446 /* Allocate the correct return size. */
6447
6448 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6449 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6450 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6451 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6452 } else {
6453 *pdata_return_size = 12;
6454 }
6455
6456 /* Realloc the data size */
6457 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6458 if (*ppdata == NULL) {
6459 close_file(fsp,ERROR_CLOSE);
6460 *pdata_return_size = 0;
6461 return NT_STATUS_NO_MEMORY;
6462 }
6463 pdata = *ppdata;
6464
6465 if (extended_oplock_granted) {
6466 if (flags & REQUEST_BATCH_OPLOCK) {
6467 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6468 } else {
6469 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6470 }
6471 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6472 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6473 } else {
6474 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6475 }
6476
6477 SSVAL(pdata,2,fsp->fnum);
6478 SIVAL(pdata,4,info); /* Was file created etc. */
6479
6480 switch (info_level_return) {
6481 case SMB_QUERY_FILE_UNIX_BASIC:
6482 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6483 SSVAL(pdata,10,0); /* padding. */
6484 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6485 break;
6486 case SMB_QUERY_FILE_UNIX_INFO2:
6487 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6488 SSVAL(pdata,10,0); /* padding. */
6489 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6490 break;
6491 default:
6492 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6493 SSVAL(pdata,10,0); /* padding. */
6494 break;
6495 }
6496 return NT_STATUS_OK;
6497}
6498
6499/****************************************************************************
6500 Delete a file with POSIX semantics.
6501****************************************************************************/
6502
6503static NTSTATUS smb_posix_unlink(connection_struct *conn,
6504 struct smb_request *req,
6505 const char *pdata,
6506 int total_data,
6507 const char *fname,
6508 SMB_STRUCT_STAT *psbuf)
6509{
6510 NTSTATUS status = NT_STATUS_OK;
6511 files_struct *fsp = NULL;
6512 uint16 flags = 0;
6513 char del = 1;
6514 int info = 0;
6515 int i;
6516 struct share_mode_lock *lck = NULL;
6517
6518 if (total_data < 2) {
6519 return NT_STATUS_INVALID_PARAMETER;
6520 }
6521
6522 flags = SVAL(pdata,0);
6523
6524 if (!VALID_STAT(*psbuf)) {
6525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6526 }
6527
6528 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6529 !VALID_STAT_OF_DIR(*psbuf)) {
6530 return NT_STATUS_NOT_A_DIRECTORY;
6531 }
6532
6533 DEBUG(10,("smb_posix_unlink: %s %s\n",
6534 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6535 fname));
6536
6537 if (VALID_STAT_OF_DIR(*psbuf)) {
6538 status = open_directory(conn, req,
6539 fname,
6540 psbuf,
6541 DELETE_ACCESS,
6542 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6543 FILE_OPEN,
6544 0,
6545 FILE_FLAG_POSIX_SEMANTICS|0777,
6546 &info,
6547 &fsp);
6548 } else {
6549
6550 status = open_file_ntcreate(conn, req,
6551 fname,
6552 psbuf,
6553 DELETE_ACCESS,
6554 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6555 FILE_OPEN,
6556 0,
6557 FILE_FLAG_POSIX_SEMANTICS|0777,
6558 0, /* No oplock, but break existing ones. */
6559 &info,
6560 &fsp);
6561 }
6562
6563 if (!NT_STATUS_IS_OK(status)) {
6564 return status;
6565 }
6566
6567 /*
6568 * Don't lie to client. If we can't really delete due to
6569 * non-POSIX opens return SHARING_VIOLATION.
6570 */
6571
6572 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6573 NULL);
6574 if (lck == NULL) {
6575 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6576 "lock for file %s\n", fsp->fsp_name));
6577 close_file(fsp, NORMAL_CLOSE);
6578 return NT_STATUS_INVALID_PARAMETER;
6579 }
6580
6581 /*
6582 * See if others still have the file open. If this is the case, then
6583 * don't delete. If all opens are POSIX delete we can set the delete
6584 * on close disposition.
6585 */
6586 for (i=0; i<lck->num_share_modes; i++) {
6587 struct share_mode_entry *e = &lck->share_modes[i];
6588 if (is_valid_share_mode_entry(e)) {
6589 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6590 continue;
6591 }
6592 /* Fail with sharing violation. */
6593 close_file(fsp, NORMAL_CLOSE);
6594 TALLOC_FREE(lck);
6595 return NT_STATUS_SHARING_VIOLATION;
6596 }
6597 }
6598
6599 /*
6600 * Set the delete on close.
6601 */
6602 status = smb_set_file_disposition_info(conn,
6603 &del,
6604 1,
6605 fsp,
6606 fname,
6607 psbuf);
6608
6609 if (!NT_STATUS_IS_OK(status)) {
6610 close_file(fsp, NORMAL_CLOSE);
6611 TALLOC_FREE(lck);
6612 return status;
6613 }
6614 TALLOC_FREE(lck);
6615 return close_file(fsp, NORMAL_CLOSE);
6616}
6617
6618/****************************************************************************
6619 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6620****************************************************************************/
6621
6622static void call_trans2setfilepathinfo(connection_struct *conn,
6623 struct smb_request *req,
6624 unsigned int tran_call,
6625 char **pparams, int total_params,
6626 char **ppdata, int total_data,
6627 unsigned int max_data_bytes)
6628{
6629 char *params = *pparams;
6630 char *pdata = *ppdata;
6631 uint16 info_level;
6632 SMB_STRUCT_STAT sbuf;
6633 char *fname = NULL;
6634 files_struct *fsp = NULL;
6635 NTSTATUS status = NT_STATUS_OK;
6636 int data_return_size = 0;
6637 TALLOC_CTX *ctx = talloc_tos();
6638
6639 if (!params) {
6640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6641 return;
6642 }
6643
6644 ZERO_STRUCT(sbuf);
6645
6646 if (tran_call == TRANSACT2_SETFILEINFO) {
6647 if (total_params < 4) {
6648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6649 return;
6650 }
6651
6652 fsp = file_fsp(SVAL(params,0));
6653 /* Basic check for non-null fsp. */
6654 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6655 return;
6656 }
6657 info_level = SVAL(params,2);
6658
6659 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6660 if (!fname) {
6661 reply_nterror(req, NT_STATUS_NO_MEMORY);
6662 return;
6663 }
6664
6665 if(fsp->is_directory || fsp->fh->fd == -1) {
6666 /*
6667 * This is actually a SETFILEINFO on a directory
6668 * handle (returned from an NT SMB). NT5.0 seems
6669 * to do this call. JRA.
6670 */
6671 if (INFO_LEVEL_IS_UNIX(info_level)) {
6672 /* Always do lstat for UNIX calls. */
6673 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6674 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6675 reply_unixerror(req,ERRDOS,ERRbadpath);
6676 return;
6677 }
6678 } else {
6679 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6680 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6681 reply_unixerror(req,ERRDOS,ERRbadpath);
6682 return;
6683 }
6684 }
6685 } else if (fsp->print_file) {
6686 /*
6687 * Doing a DELETE_ON_CLOSE should cancel a print job.
6688 */
6689 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6690 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6691
6692 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6693
6694 SSVAL(params,0,0);
6695 send_trans2_replies(conn, req, params, 2,
6696 *ppdata, 0,
6697 max_data_bytes);
6698 return;
6699 } else {
6700 reply_unixerror(req, ERRDOS, ERRbadpath);
6701 return;
6702 }
6703 } else {
6704 /*
6705 * Original code - this is an open file.
6706 */
6707 if (!check_fsp(conn, req, fsp, &current_user)) {
6708 return;
6709 }
6710
6711 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6712 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6713 reply_unixerror(req, ERRDOS, ERRbadfid);
6714 return;
6715 }
6716 }
6717 } else {
6718 /* set path info */
6719 if (total_params < 7) {
6720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6721 return;
6722 }
6723
6724 info_level = SVAL(params,0);
6725 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6726 total_params - 6, STR_TERMINATE,
6727 &status);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 reply_nterror(req, status);
6730 return;
6731 }
6732
6733 status = resolve_dfspath(ctx, conn,
6734 req->flags2 & FLAGS2_DFS_PATHNAMES,
6735 fname,
6736 &fname);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6739 reply_botherror(req,
6740 NT_STATUS_PATH_NOT_COVERED,
6741 ERRSRV, ERRbadpath);
6742 return;
6743 }
6744 reply_nterror(req, status);
6745 return;
6746 }
6747
6748 status = unix_convert(ctx, conn, fname, False,
6749 &fname, NULL, &sbuf);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 reply_nterror(req, status);
6752 return;
6753 }
6754
6755 status = check_name(conn, fname);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 reply_nterror(req, status);
6758 return;
6759 }
6760
6761 if (INFO_LEVEL_IS_UNIX(info_level)) {
6762 /*
6763 * For CIFS UNIX extensions the target name may not exist.
6764 */
6765
6766 /* Always do lstat for UNIX calls. */
6767 SMB_VFS_LSTAT(conn,fname,&sbuf);
6768
6769 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6770 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6771 reply_unixerror(req, ERRDOS, ERRbadpath);
6772 return;
6773 }
6774 }
6775
6776 if (!CAN_WRITE(conn)) {
6777 reply_doserror(req, ERRSRV, ERRaccess);
6778 return;
6779 }
6780
6781 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6782 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6783 return;
6784 }
6785
6786 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6787 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6788
6789 /* Realloc the parameter size */
6790 *pparams = (char *)SMB_REALLOC(*pparams,2);
6791 if (*pparams == NULL) {
6792 reply_nterror(req, NT_STATUS_NO_MEMORY);
6793 return;
6794 }
6795 params = *pparams;
6796
6797 SSVAL(params,0,0);
6798
6799 switch (info_level) {
6800
6801 case SMB_INFO_STANDARD:
6802 {
6803 status = smb_set_info_standard(conn,
6804 pdata,
6805 total_data,
6806 fsp,
6807 fname,
6808 &sbuf);
6809 break;
6810 }
6811
6812 case SMB_INFO_SET_EA:
6813 {
6814 status = smb_info_set_ea(conn,
6815 pdata,
6816 total_data,
6817 fsp,
6818 fname);
6819 break;
6820 }
6821
6822 case SMB_SET_FILE_BASIC_INFO:
6823 case SMB_FILE_BASIC_INFORMATION:
6824 {
6825 status = smb_set_file_basic_info(conn,
6826 pdata,
6827 total_data,
6828 fsp,
6829 fname,
6830 &sbuf);
6831 break;
6832 }
6833
6834 case SMB_FILE_ALLOCATION_INFORMATION:
6835 case SMB_SET_FILE_ALLOCATION_INFO:
6836 {
6837 status = smb_set_file_allocation_info(conn, req,
6838 pdata,
6839 total_data,
6840 fsp,
6841 fname,
6842 &sbuf);
6843 break;
6844 }
6845
6846 case SMB_FILE_END_OF_FILE_INFORMATION:
6847 case SMB_SET_FILE_END_OF_FILE_INFO:
6848 {
6849 status = smb_set_file_end_of_file_info(conn, req,
6850 pdata,
6851 total_data,
6852 fsp,
6853 fname,
6854 &sbuf);
6855 break;
6856 }
6857
6858 case SMB_FILE_DISPOSITION_INFORMATION:
6859 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6860 {
6861#if 0
6862 /* JRA - We used to just ignore this on a path ?
6863 * Shouldn't this be invalid level on a pathname
6864 * based call ?
6865 */
6866 if (tran_call != TRANSACT2_SETFILEINFO) {
6867 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6868 }
6869#endif
6870 status = smb_set_file_disposition_info(conn,
6871 pdata,
6872 total_data,
6873 fsp,
6874 fname,
6875 &sbuf);
6876 break;
6877 }
6878
6879 case SMB_FILE_POSITION_INFORMATION:
6880 {
6881 status = smb_file_position_information(conn,
6882 pdata,
6883 total_data,
6884 fsp);
6885 break;
6886 }
6887
6888 /* From tridge Samba4 :
6889 * MODE_INFORMATION in setfileinfo (I have no
6890 * idea what "mode information" on a file is - it takes a value of 0,
6891 * 2, 4 or 6. What could it be?).
6892 */
6893
6894 case SMB_FILE_MODE_INFORMATION:
6895 {
6896 status = smb_file_mode_information(conn,
6897 pdata,
6898 total_data);
6899 break;
6900 }
6901
6902 /*
6903 * CIFS UNIX extensions.
6904 */
6905
6906 case SMB_SET_FILE_UNIX_BASIC:
6907 {
6908 status = smb_set_file_unix_basic(conn, req,
6909 pdata,
6910 total_data,
6911 fsp,
6912 fname,
6913 &sbuf);
6914 break;
6915 }
6916
6917 case SMB_SET_FILE_UNIX_INFO2:
6918 {
6919 status = smb_set_file_unix_info2(conn, req,
6920 pdata,
6921 total_data,
6922 fsp,
6923 fname,
6924 &sbuf);
6925 break;
6926 }
6927
6928 case SMB_SET_FILE_UNIX_LINK:
6929 {
6930 if (tran_call != TRANSACT2_SETPATHINFO) {
6931 /* We must have a pathname for this. */
6932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6933 return;
6934 }
6935 status = smb_set_file_unix_link(conn, req, pdata,
6936 total_data, fname);
6937 break;
6938 }
6939
6940 case SMB_SET_FILE_UNIX_HLINK:
6941 {
6942 if (tran_call != TRANSACT2_SETPATHINFO) {
6943 /* We must have a pathname for this. */
6944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6945 return;
6946 }
6947 status = smb_set_file_unix_hlink(conn, req,
6948 pdata, total_data,
6949 fname);
6950 break;
6951 }
6952
6953 case SMB_FILE_RENAME_INFORMATION:
6954 {
6955 status = smb_file_rename_information(conn, req,
6956 pdata, total_data,
6957 fsp, fname);
6958 break;
6959 }
6960
6961#if defined(HAVE_POSIX_ACLS)
6962 case SMB_SET_POSIX_ACL:
6963 {
6964 status = smb_set_posix_acl(conn,
6965 pdata,
6966 total_data,
6967 fsp,
6968 fname,
6969 &sbuf);
6970 break;
6971 }
6972#endif
6973
6974 case SMB_SET_POSIX_LOCK:
6975 {
6976 if (tran_call != TRANSACT2_SETFILEINFO) {
6977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6978 return;
6979 }
6980 status = smb_set_posix_lock(conn, req,
6981 pdata, total_data, fsp);
6982 break;
6983 }
6984
6985 case SMB_POSIX_PATH_OPEN:
6986 {
6987 if (tran_call != TRANSACT2_SETPATHINFO) {
6988 /* We must have a pathname for this. */
6989 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6990 return;
6991 }
6992
6993 status = smb_posix_open(conn, req,
6994 ppdata,
6995 total_data,
6996 fname,
6997 &sbuf,
6998 &data_return_size);
6999 break;
7000 }
7001
7002 case SMB_POSIX_PATH_UNLINK:
7003 {
7004 if (tran_call != TRANSACT2_SETPATHINFO) {
7005 /* We must have a pathname for this. */
7006 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7007 return;
7008 }
7009
7010 status = smb_posix_unlink(conn, req,
7011 pdata,
7012 total_data,
7013 fname,
7014 &sbuf);
7015 break;
7016 }
7017
7018 default:
7019 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7020 return;
7021 }
7022
7023
7024 if (!NT_STATUS_IS_OK(status)) {
7025 if (open_was_deferred(req->mid)) {
7026 /* We have re-scheduled this call. */
7027 return;
7028 }
7029 if (blocking_lock_was_deferred(req->mid)) {
7030 /* We have re-scheduled this call. */
7031 return;
7032 }
7033 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7034 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7035 ERRSRV, ERRbadpath);
7036 return;
7037 }
7038 if (info_level == SMB_POSIX_PATH_OPEN) {
7039 reply_openerror(req, status);
7040 return;
7041 }
7042
7043 reply_nterror(req, status);
7044 return;
7045 }
7046
7047 SSVAL(params,0,0);
7048 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7049 max_data_bytes);
7050
7051 return;
7052}
7053
7054/****************************************************************************
7055 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7056****************************************************************************/
7057
7058static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7059 char **pparams, int total_params,
7060 char **ppdata, int total_data,
7061 unsigned int max_data_bytes)
7062{
7063 char *params = *pparams;
7064 char *pdata = *ppdata;
7065 char *directory = NULL;
7066 SMB_STRUCT_STAT sbuf;
7067 NTSTATUS status = NT_STATUS_OK;
7068 struct ea_list *ea_list = NULL;
7069 TALLOC_CTX *ctx = talloc_tos();
7070
7071 if (!CAN_WRITE(conn)) {
7072 reply_doserror(req, ERRSRV, ERRaccess);
7073 return;
7074 }
7075
7076 if (total_params < 5) {
7077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7078 return;
7079 }
7080
7081 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7082 total_params - 4, STR_TERMINATE,
7083 &status);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 reply_nterror(req, status);
7086 return;
7087 }
7088
7089 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7090
7091 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7092 if (!NT_STATUS_IS_OK(status)) {
7093 reply_nterror(req, status);
7094 return;
7095 }
7096
7097 status = check_name(conn, directory);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7100 reply_nterror(req, status);
7101 return;
7102 }
7103
7104 /* Any data in this call is an EA list. */
7105 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7106 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7107 return;
7108 }
7109
7110 /*
7111 * OS/2 workplace shell seems to send SET_EA requests of "null"
7112 * length (4 bytes containing IVAL 4).
7113 * They seem to have no effect. Bug #3212. JRA.
7114 */
7115
7116 if (total_data != 4) {
7117 if (total_data < 10) {
7118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7119 return;
7120 }
7121
7122 if (IVAL(pdata,0) > total_data) {
7123 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7124 IVAL(pdata,0), (unsigned int)total_data));
7125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7126 return;
7127 }
7128
7129 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7130 total_data - 4);
7131 if (!ea_list) {
7132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7133 return;
7134 }
7135 }
7136 /* If total_data == 4 Windows doesn't care what values
7137 * are placed in that field, it just ignores them.
7138 * The System i QNTC IBM SMB client puts bad values here,
7139 * so ignore them. */
7140
7141 status = create_directory(conn, req, directory);
7142
7143 if (!NT_STATUS_IS_OK(status)) {
7144 reply_nterror(req, status);
7145 return;
7146 }
7147
7148 /* Try and set any given EA. */
7149 if (ea_list) {
7150 status = set_ea(conn, NULL, directory, ea_list);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 reply_nterror(req, status);
7153 return;
7154 }
7155 }
7156
7157 /* Realloc the parameter and data sizes */
7158 *pparams = (char *)SMB_REALLOC(*pparams,2);
7159 if(*pparams == NULL) {
7160 reply_nterror(req, NT_STATUS_NO_MEMORY);
7161 return;
7162 }
7163 params = *pparams;
7164
7165 SSVAL(params,0,0);
7166
7167 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7168
7169 return;
7170}
7171
7172/****************************************************************************
7173 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7174 We don't actually do this - we just send a null response.
7175****************************************************************************/
7176
7177static void call_trans2findnotifyfirst(connection_struct *conn,
7178 struct smb_request *req,
7179 char **pparams, int total_params,
7180 char **ppdata, int total_data,
7181 unsigned int max_data_bytes)
7182{
7183 static uint16 fnf_handle = 257;
7184 char *params = *pparams;
7185 uint16 info_level;
7186
7187 if (total_params < 6) {
7188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7189 return;
7190 }
7191
7192 info_level = SVAL(params,4);
7193 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7194
7195 switch (info_level) {
7196 case 1:
7197 case 2:
7198 break;
7199 default:
7200 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7201 return;
7202 }
7203
7204 /* Realloc the parameter and data sizes */
7205 *pparams = (char *)SMB_REALLOC(*pparams,6);
7206 if (*pparams == NULL) {
7207 reply_nterror(req, NT_STATUS_NO_MEMORY);
7208 return;
7209 }
7210 params = *pparams;
7211
7212 SSVAL(params,0,fnf_handle);
7213 SSVAL(params,2,0); /* No changes */
7214 SSVAL(params,4,0); /* No EA errors */
7215
7216 fnf_handle++;
7217
7218 if(fnf_handle == 0)
7219 fnf_handle = 257;
7220
7221 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7222
7223 return;
7224}
7225
7226/****************************************************************************
7227 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7228 changes). Currently this does nothing.
7229****************************************************************************/
7230
7231static void call_trans2findnotifynext(connection_struct *conn,
7232 struct smb_request *req,
7233 char **pparams, int total_params,
7234 char **ppdata, int total_data,
7235 unsigned int max_data_bytes)
7236{
7237 char *params = *pparams;
7238
7239 DEBUG(3,("call_trans2findnotifynext\n"));
7240
7241 /* Realloc the parameter and data sizes */
7242 *pparams = (char *)SMB_REALLOC(*pparams,4);
7243 if (*pparams == NULL) {
7244 reply_nterror(req, NT_STATUS_NO_MEMORY);
7245 return;
7246 }
7247 params = *pparams;
7248
7249 SSVAL(params,0,0); /* No changes */
7250 SSVAL(params,2,0); /* No EA errors */
7251
7252 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7253
7254 return;
7255}
7256
7257/****************************************************************************
7258 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7259****************************************************************************/
7260
7261static void call_trans2getdfsreferral(connection_struct *conn,
7262 struct smb_request *req,
7263 char **pparams, int total_params,
7264 char **ppdata, int total_data,
7265 unsigned int max_data_bytes)
7266{
7267 char *params = *pparams;
7268 char *pathname = NULL;
7269 int reply_size = 0;
7270 int max_referral_level;
7271 NTSTATUS status = NT_STATUS_OK;
7272 TALLOC_CTX *ctx = talloc_tos();
7273
7274 DEBUG(10,("call_trans2getdfsreferral\n"));
7275
7276 if (total_params < 3) {
7277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7278 return;
7279 }
7280
7281 max_referral_level = SVAL(params,0);
7282
7283 if(!lp_host_msdfs()) {
7284 reply_doserror(req, ERRDOS, ERRbadfunc);
7285 return;
7286 }
7287
7288 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7289 total_params - 2, STR_TERMINATE);
7290 if (!pathname) {
7291 reply_nterror(req, NT_STATUS_NOT_FOUND);
7292 return;
7293 }
7294 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7295 ppdata,&status)) < 0) {
7296 reply_nterror(req, status);
7297 return;
7298 }
7299
7300 SSVAL(req->inbuf, smb_flg2,
7301 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7302 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7303
7304 return;
7305}
7306
7307#define LMCAT_SPL 0x53
7308#define LMFUNC_GETJOBID 0x60
7309
7310/****************************************************************************
7311 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7312****************************************************************************/
7313
7314static void call_trans2ioctl(connection_struct *conn,
7315 struct smb_request *req,
7316 char **pparams, int total_params,
7317 char **ppdata, int total_data,
7318 unsigned int max_data_bytes)
7319{
7320 char *pdata = *ppdata;
7321 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7322
7323 /* check for an invalid fid before proceeding */
7324
7325 if (!fsp) {
7326 reply_doserror(req, ERRDOS, ERRbadfid);
7327 return;
7328 }
7329
7330 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7331 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7332 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7333 if (*ppdata == NULL) {
7334 reply_nterror(req, NT_STATUS_NO_MEMORY);
7335 return;
7336 }
7337 pdata = *ppdata;
7338
7339 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7340 CAN ACCEPT THIS IN UNICODE. JRA. */
7341
7342 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7343 srvstr_push(pdata, req->flags2, pdata + 2,
7344 global_myname(), 15,
7345 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7346 srvstr_push(pdata, req->flags2, pdata+18,
7347 lp_servicename(SNUM(conn)), 13,
7348 STR_ASCII|STR_TERMINATE); /* Service name */
7349 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7350 max_data_bytes);
7351 return;
7352 }
7353
7354 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7355 reply_doserror(req, ERRSRV, ERRerror);
7356}
7357
7358/****************************************************************************
7359 Reply to a SMBfindclose (stop trans2 directory search).
7360****************************************************************************/
7361
7362void reply_findclose(struct smb_request *req)
7363{
7364 int dptr_num;
7365
7366 START_PROFILE(SMBfindclose);
7367
7368 if (req->wct < 1) {
7369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7370 END_PROFILE(SMBfindclose);
7371 return;
7372 }
7373
7374 dptr_num = SVALS(req->inbuf,smb_vwv0);
7375
7376 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7377
7378 dptr_close(&dptr_num);
7379
7380 reply_outbuf(req, 0, 0);
7381
7382 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7383
7384 END_PROFILE(SMBfindclose);
7385 return;
7386}
7387
7388/****************************************************************************
7389 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7390****************************************************************************/
7391
7392void reply_findnclose(struct smb_request *req)
7393{
7394 int dptr_num;
7395
7396 START_PROFILE(SMBfindnclose);
7397
7398 if (req->wct < 1) {
7399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7400 END_PROFILE(SMBfindnclose);
7401 return;
7402 }
7403
7404 dptr_num = SVAL(req->inbuf,smb_vwv0);
7405
7406 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7407
7408 /* We never give out valid handles for a
7409 findnotifyfirst - so any dptr_num is ok here.
7410 Just ignore it. */
7411
7412 reply_outbuf(req, 0, 0);
7413
7414 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7415
7416 END_PROFILE(SMBfindnclose);
7417 return;
7418}
7419
7420static void handle_trans2(connection_struct *conn, struct smb_request *req,
7421 struct trans_state *state)
7422{
7423 if (Protocol >= PROTOCOL_NT1) {
7424 req->flags2 |= 0x40; /* IS_LONG_NAME */
7425 SSVAL(req->inbuf,smb_flg2,req->flags2);
7426 }
7427
7428 if (conn->encrypt_level == Required && !req->encrypted) {
7429 if (state->call != TRANSACT2_QFSINFO &&
7430 state->call != TRANSACT2_SETFSINFO) {
7431 DEBUG(0,("handle_trans2: encryption required "
7432 "with call 0x%x\n",
7433 (unsigned int)state->call));
7434 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7435 return;
7436 }
7437 }
7438
7439 /* Now we must call the relevant TRANS2 function */
7440 switch(state->call) {
7441 case TRANSACT2_OPEN:
7442 {
7443 START_PROFILE(Trans2_open);
7444 call_trans2open(conn, req,
7445 &state->param, state->total_param,
7446 &state->data, state->total_data,
7447 state->max_data_return);
7448 END_PROFILE(Trans2_open);
7449 break;
7450 }
7451
7452 case TRANSACT2_FINDFIRST:
7453 {
7454 START_PROFILE(Trans2_findfirst);
7455 call_trans2findfirst(conn, req,
7456 &state->param, state->total_param,
7457 &state->data, state->total_data,
7458 state->max_data_return);
7459 END_PROFILE(Trans2_findfirst);
7460 break;
7461 }
7462
7463 case TRANSACT2_FINDNEXT:
7464 {
7465 START_PROFILE(Trans2_findnext);
7466 call_trans2findnext(conn, req,
7467 &state->param, state->total_param,
7468 &state->data, state->total_data,
7469 state->max_data_return);
7470 END_PROFILE(Trans2_findnext);
7471 break;
7472 }
7473
7474 case TRANSACT2_QFSINFO:
7475 {
7476 START_PROFILE(Trans2_qfsinfo);
7477 call_trans2qfsinfo(conn, req,
7478 &state->param, state->total_param,
7479 &state->data, state->total_data,
7480 state->max_data_return);
7481 END_PROFILE(Trans2_qfsinfo);
7482 break;
7483 }
7484
7485 case TRANSACT2_SETFSINFO:
7486 {
7487 START_PROFILE(Trans2_setfsinfo);
7488 call_trans2setfsinfo(conn, req,
7489 &state->param, state->total_param,
7490 &state->data, state->total_data,
7491 state->max_data_return);
7492 END_PROFILE(Trans2_setfsinfo);
7493 break;
7494 }
7495
7496 case TRANSACT2_QPATHINFO:
7497 case TRANSACT2_QFILEINFO:
7498 {
7499 START_PROFILE(Trans2_qpathinfo);
7500 call_trans2qfilepathinfo(conn, req, state->call,
7501 &state->param, state->total_param,
7502 &state->data, state->total_data,
7503 state->max_data_return);
7504 END_PROFILE(Trans2_qpathinfo);
7505 break;
7506 }
7507
7508 case TRANSACT2_SETPATHINFO:
7509 case TRANSACT2_SETFILEINFO:
7510 {
7511 START_PROFILE(Trans2_setpathinfo);
7512 call_trans2setfilepathinfo(conn, req, state->call,
7513 &state->param, state->total_param,
7514 &state->data, state->total_data,
7515 state->max_data_return);
7516 END_PROFILE(Trans2_setpathinfo);
7517 break;
7518 }
7519
7520 case TRANSACT2_FINDNOTIFYFIRST:
7521 {
7522 START_PROFILE(Trans2_findnotifyfirst);
7523 call_trans2findnotifyfirst(conn, req,
7524 &state->param, state->total_param,
7525 &state->data, state->total_data,
7526 state->max_data_return);
7527 END_PROFILE(Trans2_findnotifyfirst);
7528 break;
7529 }
7530
7531 case TRANSACT2_FINDNOTIFYNEXT:
7532 {
7533 START_PROFILE(Trans2_findnotifynext);
7534 call_trans2findnotifynext(conn, req,
7535 &state->param, state->total_param,
7536 &state->data, state->total_data,
7537 state->max_data_return);
7538 END_PROFILE(Trans2_findnotifynext);
7539 break;
7540 }
7541
7542 case TRANSACT2_MKDIR:
7543 {
7544 START_PROFILE(Trans2_mkdir);
7545 call_trans2mkdir(conn, req,
7546 &state->param, state->total_param,
7547 &state->data, state->total_data,
7548 state->max_data_return);
7549 END_PROFILE(Trans2_mkdir);
7550 break;
7551 }
7552
7553 case TRANSACT2_GET_DFS_REFERRAL:
7554 {
7555 START_PROFILE(Trans2_get_dfs_referral);
7556 call_trans2getdfsreferral(conn, req,
7557 &state->param, state->total_param,
7558 &state->data, state->total_data,
7559 state->max_data_return);
7560 END_PROFILE(Trans2_get_dfs_referral);
7561 break;
7562 }
7563
7564 case TRANSACT2_IOCTL:
7565 {
7566 START_PROFILE(Trans2_ioctl);
7567 call_trans2ioctl(conn, req,
7568 &state->param, state->total_param,
7569 &state->data, state->total_data,
7570 state->max_data_return);
7571 END_PROFILE(Trans2_ioctl);
7572 break;
7573 }
7574
7575 default:
7576 /* Error in request */
7577 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7578 reply_doserror(req, ERRSRV,ERRerror);
7579 }
7580}
7581
7582/****************************************************************************
7583 Reply to a SMBtrans2.
7584 ****************************************************************************/
7585
7586void reply_trans2(struct smb_request *req)
7587{
7588 connection_struct *conn = req->conn;
7589 unsigned int dsoff;
7590 unsigned int dscnt;
7591 unsigned int psoff;
7592 unsigned int pscnt;
7593 unsigned int tran_call;
7594 unsigned int size;
7595 unsigned int av_size;
7596 struct trans_state *state;
7597 NTSTATUS result;
7598
7599 START_PROFILE(SMBtrans2);
7600
7601 if (req->wct < 14) {
7602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7603 END_PROFILE(SMBtrans2);
7604 return;
7605 }
7606
7607 dsoff = SVAL(req->inbuf, smb_dsoff);
7608 dscnt = SVAL(req->inbuf, smb_dscnt);
7609 psoff = SVAL(req->inbuf, smb_psoff);
7610 pscnt = SVAL(req->inbuf, smb_pscnt);
7611 tran_call = SVAL(req->inbuf, smb_setup0);
7612 size = smb_len(req->inbuf) + 4;
7613 av_size = smb_len(req->inbuf);
7614
7615 result = allow_new_trans(conn->pending_trans, req->mid);
7616 if (!NT_STATUS_IS_OK(result)) {
7617 DEBUG(2, ("Got invalid trans2 request: %s\n",
7618 nt_errstr(result)));
7619 reply_nterror(req, result);
7620 END_PROFILE(SMBtrans2);
7621 return;
7622 }
7623
7624 if (IS_IPC(conn)) {
7625 switch (tran_call) {
7626 /* List the allowed trans2 calls on IPC$ */
7627 case TRANSACT2_OPEN:
7628 case TRANSACT2_GET_DFS_REFERRAL:
7629 case TRANSACT2_QFILEINFO:
7630 case TRANSACT2_QFSINFO:
7631 case TRANSACT2_SETFSINFO:
7632 break;
7633 default:
7634 reply_doserror(req, ERRSRV, ERRaccess);
7635 END_PROFILE(SMBtrans2);
7636 return;
7637 }
7638 }
7639
7640 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7641 DEBUG(0, ("talloc failed\n"));
7642 reply_nterror(req, NT_STATUS_NO_MEMORY);
7643 END_PROFILE(SMBtrans2);
7644 return;
7645 }
7646
7647 state->cmd = SMBtrans2;
7648
7649 state->mid = req->mid;
7650 state->vuid = req->vuid;
7651 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7652 state->setup = NULL;
7653 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7654 state->param = NULL;
7655 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7656 state->data = NULL;
7657 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7658 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7659 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7660 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7661 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7662
7663 state->call = tran_call;
7664
7665 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7666 is so as a sanity check */
7667 if (state->setup_count != 1) {
7668 /*
7669 * Need to have rc=0 for ioctl to get job id for OS/2.
7670 * Network printing will fail if function is not successful.
7671 * Similar function in reply.c will be used if protocol
7672 * is LANMAN1.0 instead of LM1.2X002.
7673 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7674 * outbuf doesn't have to be set(only job id is used).
7675 */
7676 if ( (state->setup_count == 4)
7677 && (tran_call == TRANSACT2_IOCTL)
7678 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7679 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7680 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7681 } else {
7682 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7683 DEBUG(2,("Transaction is %d\n",tran_call));
7684 TALLOC_FREE(state);
7685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7686 END_PROFILE(SMBtrans2);
7687 return;
7688 }
7689 }
7690
7691 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7692 goto bad_param;
7693
7694 if (state->total_data) {
7695 /* Can't use talloc here, the core routines do realloc on the
7696 * params and data. */
7697 state->data = (char *)SMB_MALLOC(state->total_data);
7698 if (state->data == NULL) {
7699 DEBUG(0,("reply_trans2: data malloc fail for %u "
7700 "bytes !\n", (unsigned int)state->total_data));
7701 TALLOC_FREE(state);
7702 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703 END_PROFILE(SMBtrans2);
7704 return;
7705 }
7706
7707 if (dscnt > state->total_data ||
7708 dsoff+dscnt < dsoff) {
7709 goto bad_param;
7710 }
7711
7712 if (dsoff > av_size ||
7713 dscnt > av_size ||
7714 dsoff+dscnt > av_size) {
7715 goto bad_param;
7716 }
7717
7718 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7719 }
7720
7721 if (state->total_param) {
7722 /* Can't use talloc here, the core routines do realloc on the
7723 * params and data. */
7724 state->param = (char *)SMB_MALLOC(state->total_param);
7725 if (state->param == NULL) {
7726 DEBUG(0,("reply_trans: param malloc fail for %u "
7727 "bytes !\n", (unsigned int)state->total_param));
7728 SAFE_FREE(state->data);
7729 TALLOC_FREE(state);
7730 reply_nterror(req, NT_STATUS_NO_MEMORY);
7731 END_PROFILE(SMBtrans2);
7732 return;
7733 }
7734
7735 if (pscnt > state->total_param ||
7736 psoff+pscnt < psoff) {
7737 goto bad_param;
7738 }
7739
7740 if (psoff > av_size ||
7741 pscnt > av_size ||
7742 psoff+pscnt > av_size) {
7743 goto bad_param;
7744 }
7745
7746 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7747 }
7748
7749 state->received_data = dscnt;
7750 state->received_param = pscnt;
7751
7752 if ((state->received_param == state->total_param) &&
7753 (state->received_data == state->total_data)) {
7754
7755 handle_trans2(conn, req, state);
7756
7757 SAFE_FREE(state->data);
7758 SAFE_FREE(state->param);
7759 TALLOC_FREE(state);
7760 END_PROFILE(SMBtrans2);
7761 return;
7762 }
7763
7764 DLIST_ADD(conn->pending_trans, state);
7765
7766 /* We need to send an interim response then receive the rest
7767 of the parameter/data bytes */
7768 reply_outbuf(req, 0, 0);
7769 show_msg((char *)req->outbuf);
7770 END_PROFILE(SMBtrans2);
7771 return;
7772
7773 bad_param:
7774
7775 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7776 SAFE_FREE(state->data);
7777 SAFE_FREE(state->param);
7778 TALLOC_FREE(state);
7779 END_PROFILE(SMBtrans2);
7780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7781}
7782
7783
7784/****************************************************************************
7785 Reply to a SMBtranss2
7786 ****************************************************************************/
7787
7788void reply_transs2(struct smb_request *req)
7789{
7790 connection_struct *conn = req->conn;
7791 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7792 struct trans_state *state;
7793 unsigned int size;
7794 unsigned int av_size;
7795
7796 START_PROFILE(SMBtranss2);
7797
7798 show_msg((char *)req->inbuf);
7799
7800 if (req->wct < 8) {
7801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7802 END_PROFILE(SMBtranss2);
7803 return;
7804 }
7805
7806 size = smb_len(req->inbuf)+4;
7807 av_size = smb_len(req->inbuf);
7808
7809 for (state = conn->pending_trans; state != NULL;
7810 state = state->next) {
7811 if (state->mid == req->mid) {
7812 break;
7813 }
7814 }
7815
7816 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7818 END_PROFILE(SMBtranss2);
7819 return;
7820 }
7821
7822 /* Revise state->total_param and state->total_data in case they have
7823 changed downwards */
7824
7825 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7826 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7827 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7828 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7829
7830 pcnt = SVAL(req->inbuf, smb_spscnt);
7831 poff = SVAL(req->inbuf, smb_spsoff);
7832 pdisp = SVAL(req->inbuf, smb_spsdisp);
7833
7834 dcnt = SVAL(req->inbuf, smb_sdscnt);
7835 doff = SVAL(req->inbuf, smb_sdsoff);
7836 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7837
7838 state->received_param += pcnt;
7839 state->received_data += dcnt;
7840
7841 if ((state->received_data > state->total_data) ||
7842 (state->received_param > state->total_param))
7843 goto bad_param;
7844
7845 if (pcnt) {
7846 if (pdisp > state->total_param ||
7847 pcnt > state->total_param ||
7848 pdisp+pcnt > state->total_param ||
7849 pdisp+pcnt < pdisp) {
7850 goto bad_param;
7851 }
7852
7853 if (poff > av_size ||
7854 pcnt > av_size ||
7855 poff+pcnt > av_size ||
7856 poff+pcnt < poff) {
7857 goto bad_param;
7858 }
7859
7860 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7861 pcnt);
7862 }
7863
7864 if (dcnt) {
7865 if (ddisp > state->total_data ||
7866 dcnt > state->total_data ||
7867 ddisp+dcnt > state->total_data ||
7868 ddisp+dcnt < ddisp) {
7869 goto bad_param;
7870 }
7871
7872 if (doff > av_size ||
7873 dcnt > av_size ||
7874 doff+dcnt > av_size ||
7875 doff+dcnt < doff) {
7876 goto bad_param;
7877 }
7878
7879 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7880 dcnt);
7881 }
7882
7883 if ((state->received_param < state->total_param) ||
7884 (state->received_data < state->total_data)) {
7885 END_PROFILE(SMBtranss2);
7886 return;
7887 }
7888
7889 /*
7890 * construct_reply_common will copy smb_com from inbuf to
7891 * outbuf. SMBtranss2 is wrong here.
7892 */
7893 SCVAL(req->inbuf,smb_com,SMBtrans2);
7894
7895 handle_trans2(conn, req, state);
7896
7897 DLIST_REMOVE(conn->pending_trans, state);
7898 SAFE_FREE(state->data);
7899 SAFE_FREE(state->param);
7900 TALLOC_FREE(state);
7901
7902 END_PROFILE(SMBtranss2);
7903 return;
7904
7905 bad_param:
7906
7907 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7908 DLIST_REMOVE(conn->pending_trans, state);
7909 SAFE_FREE(state->data);
7910 SAFE_FREE(state->param);
7911 TALLOC_FREE(state);
7912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7913 END_PROFILE(SMBtranss2);
7914 return;
7915}
Note: See TracBrowser for help on using the repository browser.