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