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