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