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