dbad71be3b759ef8109f9f5da21f60d5e942e36d
[sfrench/samba-autobuild/.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
46
47 static char *store_file_unix_basic(connection_struct *conn,
48                                 char *pdata,
49                                 files_struct *fsp,
50                                 const SMB_STRUCT_STAT *psbuf);
51
52 static char *store_file_unix_basic_info2(connection_struct *conn,
53                                 char *pdata,
54                                 files_struct *fsp,
55                                 const SMB_STRUCT_STAT *psbuf);
56
57 /****************************************************************************
58  Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
60
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62                         const files_struct *fsp,
63                         const struct smb_filename *smb_fname)
64 {
65         SMB_STRUCT_STAT sbuf;
66         const SMB_STRUCT_STAT *pst = NULL;
67
68         if (fsp) {
69                 pst = &fsp->fsp_name->st;
70         } else {
71                 pst = &smb_fname->st;
72         }
73
74         if (!VALID_STAT(*pst)) {
75                 int ret = vfs_stat_smb_basename(conn,
76                                 smb_fname,
77                                 &sbuf);
78                 if (ret == -1 && errno != ENOENT) {
79                         return map_nt_error_from_unix(errno);
80                 } else if (ret == -1) {
81                         /* it's not a symlink.. */
82                         return NT_STATUS_OK;
83                 }
84                 pst = &sbuf;
85         }
86
87         if (S_ISLNK(pst->st_ex_mode)) {
88                 return NT_STATUS_ACCESS_DENIED;
89         }
90         return NT_STATUS_OK;
91 }
92
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
94                           uint32_t access_mask)
95 {
96         if (!(fsp->access_mask & access_mask)) {
97                 return NT_STATUS_ACCESS_DENIED;
98         }
99         return NT_STATUS_OK;
100 }
101
102 /********************************************************************
103  The canonical "check access" based on object handle or path function.
104 ********************************************************************/
105
106 NTSTATUS check_access(connection_struct *conn,
107                                 files_struct *fsp,
108                                 const struct smb_filename *smb_fname,
109                                 uint32_t access_mask)
110 {
111         NTSTATUS status;
112
113         if (fsp) {
114                 status = check_access_fsp(fsp, access_mask);
115         } else {
116                 status = smbd_check_access_rights(conn, smb_fname,
117                                                   false, access_mask);
118         }
119
120         return status;
121 }
122
123 /********************************************************************
124  Roundup a value to the nearest allocation roundup size boundary.
125  Only do this for Windows clients.
126 ********************************************************************/
127
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
129 {
130         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
131
132         /* Only roundup for Windows clients. */
133         enum remote_arch_types ra_type = get_remote_arch();
134         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135                 val = SMB_ROUNDUP(val,rval);
136         }
137         return val;
138 }
139
140 /********************************************************************
141  Create a 64 bit FileIndex. If the file is on the same device as
142  the root of the share, just return the 64-bit inode. If it isn't,
143  mangle as we used to do.
144 ********************************************************************/
145
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
147 {
148         uint64_t file_index;
149         if (conn->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                         /* drop through */
4036                 default:
4037                         return NT_STATUS_INVALID_LEVEL;
4038         }
4039
4040         *ret_data_len = data_len;
4041         return status;
4042 }
4043
4044 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4045                         struct smb_request *req,
4046                         files_struct *fsp,
4047                         const DATA_BLOB *qdata)
4048 {
4049         NTSTATUS status;
4050         SMB_NTQUOTA_STRUCT quotas;
4051
4052         ZERO_STRUCT(quotas);
4053
4054         /* access check */
4055         if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4056                 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4057                           lp_servicename(talloc_tos(), SNUM(conn)),
4058                           conn->session_info->unix_info->unix_name));
4059                 return NT_STATUS_ACCESS_DENIED;
4060         }
4061
4062         if (!check_fsp_ntquota_handle(conn, req,
4063                                       fsp)) {
4064                 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4065                 return NT_STATUS_INVALID_HANDLE;
4066         }
4067
4068         /* note: normally there're 48 bytes,
4069          * but we didn't use the last 6 bytes for now
4070          * --metze
4071          */
4072         if (qdata->length < 42) {
4073                 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4074                         (unsigned int)qdata->length));
4075                 return NT_STATUS_INVALID_PARAMETER;
4076         }
4077
4078         /* unknown_1 24 NULL bytes in pdata*/
4079
4080         /* the soft quotas 8 bytes (uint64_t)*/
4081         quotas.softlim = BVAL(qdata->data,24);
4082
4083         /* the hard quotas 8 bytes (uint64_t)*/
4084         quotas.hardlim = BVAL(qdata->data,32);
4085
4086         /* quota_flags 2 bytes **/
4087         quotas.qflags = SVAL(qdata->data,40);
4088
4089         /* unknown_2 6 NULL bytes follow*/
4090
4091         /* now set the quotas */
4092         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4093                 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4094                           lp_servicename(talloc_tos(), SNUM(conn))));
4095                 status =  map_nt_error_from_unix(errno);
4096         } else {
4097                 status = NT_STATUS_OK;
4098         }
4099         return status;
4100 }
4101
4102 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4103                                 struct smb_request *req,
4104                                 TALLOC_CTX *mem_ctx,
4105                                 uint16_t info_level,
4106                                 files_struct *fsp,
4107                                 const DATA_BLOB *pdata)
4108 {
4109         switch (info_level) {
4110                 case SMB_FS_QUOTA_INFORMATION:
4111                 {
4112                         return smb_set_fsquota(conn,
4113                                                 req,
4114                                                 fsp,
4115                                                 pdata);
4116                 }
4117
4118                 default:
4119                         break;
4120         }
4121         return NT_STATUS_INVALID_LEVEL;
4122 }
4123
4124 /****************************************************************************
4125  Reply to a TRANS2_QFSINFO (query filesystem info).
4126 ****************************************************************************/
4127
4128 static void call_trans2qfsinfo(connection_struct *conn,
4129                                struct smb_request *req,
4130                                char **pparams, int total_params,
4131                                char **ppdata, int total_data,
4132                                unsigned int max_data_bytes)
4133 {
4134         char *params = *pparams;
4135         uint16_t info_level;
4136         int data_len = 0;
4137         size_t fixed_portion;
4138         NTSTATUS status;
4139
4140         if (total_params < 2) {
4141                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4142                 return;
4143         }
4144
4145         info_level = SVAL(params,0);
4146
4147         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4148                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4149                         DEBUG(0,("call_trans2qfsinfo: encryption required "
4150                                 "and info level 0x%x sent.\n",
4151                                 (unsigned int)info_level));
4152                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4153                         return;
4154                 }
4155         }
4156
4157         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4158
4159         status = smbd_do_qfsinfo(req->xconn, conn, req,
4160                                  info_level,
4161                                  req->flags2,
4162                                  max_data_bytes,
4163                                  &fixed_portion,
4164                                  NULL,
4165                                  ppdata, &data_len);
4166         if (!NT_STATUS_IS_OK(status)) {
4167                 reply_nterror(req, status);
4168                 return;
4169         }
4170
4171         send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4172                             max_data_bytes);
4173
4174         DEBUG( 4, ( "%s info_level = %d\n",
4175                     smb_fn_name(req->cmd), info_level) );
4176
4177         return;
4178 }
4179
4180 /****************************************************************************
4181  Reply to a TRANS2_SETFSINFO (set filesystem info).
4182 ****************************************************************************/
4183
4184 static void call_trans2setfsinfo(connection_struct *conn,
4185                                  struct smb_request *req,
4186                                  char **pparams, int total_params,
4187                                  char **ppdata, int total_data,
4188                                  unsigned int max_data_bytes)
4189 {
4190         struct smbXsrv_connection *xconn = req->xconn;
4191         char *pdata = *ppdata;
4192         char *params = *pparams;
4193         uint16_t info_level;
4194
4195         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4196                   lp_servicename(talloc_tos(), SNUM(conn))));
4197
4198         /*  */
4199         if (total_params < 4) {
4200                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4201                         total_params));
4202                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4203                 return;
4204         }
4205
4206         info_level = SVAL(params,2);
4207
4208         if (IS_IPC(conn)) {
4209                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4210                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
4211                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
4212                                 "info level (0x%x) on IPC$.\n",
4213                                 (unsigned int)info_level));
4214                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4215                         return;
4216                 }
4217         }
4218
4219         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4220                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4221                         DEBUG(0,("call_trans2setfsinfo: encryption required "
4222                                 "and info level 0x%x sent.\n",
4223                                 (unsigned int)info_level));
4224                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4225                         return;
4226                 }
4227         }
4228
4229         switch(info_level) {
4230                 case SMB_SET_CIFS_UNIX_INFO:
4231                         if (!lp_unix_extensions()) {
4232                                 DEBUG(2,("call_trans2setfsinfo: "
4233                                         "SMB_SET_CIFS_UNIX_INFO is invalid with "
4234                                         "unix extensions off\n"));
4235                                 reply_nterror(req,
4236                                               NT_STATUS_INVALID_LEVEL);
4237                                 return;
4238                         }
4239
4240                         /* There should be 12 bytes of capabilities set. */
4241                         if (total_data < 12) {
4242                                 reply_nterror(
4243                                         req,
4244                                         NT_STATUS_INVALID_PARAMETER);
4245                                 return;
4246                         }
4247                         xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4248                         xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4249                         xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4250                         xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4251                         /* Just print these values for now. */
4252                         DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4253                                    "major = %u, minor = %u cap_low = 0x%x, "
4254                                    "cap_high = 0x%xn",
4255                                    (unsigned int)xconn->
4256                                    smb1.unix_info.client_major,
4257                                    (unsigned int)xconn->
4258                                    smb1.unix_info.client_minor,
4259                                    (unsigned int)xconn->
4260                                    smb1.unix_info.client_cap_low,
4261                                    (unsigned int)xconn->
4262                                    smb1.unix_info.client_cap_high));
4263
4264                         /* Here is where we must switch to posix pathname processing... */
4265                         if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4266                                 lp_set_posix_pathnames();
4267                                 mangle_change_to_posix();
4268                         }
4269
4270                         if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4271                             !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4272                                 /* Client that knows how to do posix locks,
4273                                  * but not posix open/mkdir operations. Set a
4274                                  * default type for read/write checks. */
4275
4276                                 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4277
4278                         }
4279                         break;
4280
4281                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4282                         {
4283                                 NTSTATUS status;
4284                                 size_t param_len = 0;
4285                                 size_t data_len = total_data;
4286
4287                                 if (!lp_unix_extensions()) {
4288                                         reply_nterror(
4289                                                 req,
4290                                                 NT_STATUS_INVALID_LEVEL);
4291                                         return;
4292                                 }
4293
4294                                 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4295                                         reply_nterror(
4296                                                 req,
4297                                                 NT_STATUS_NOT_SUPPORTED);
4298                                         return;
4299                                 }
4300
4301                                 if (xconn->smb1.echo_handler.trusted_fde) {
4302                                         DEBUG( 2,("call_trans2setfsinfo: "
4303                                                 "request transport encryption disabled"
4304                                                 "with 'fork echo handler = yes'\n"));
4305                                         reply_nterror(
4306                                                 req,
4307                                                 NT_STATUS_NOT_SUPPORTED);
4308                                         return;
4309                                 }
4310
4311                                 DEBUG( 4,("call_trans2setfsinfo: "
4312                                         "request transport encryption.\n"));
4313
4314                                 status = srv_request_encryption_setup(conn,
4315                                                                 (unsigned char **)ppdata,
4316                                                                 &data_len,
4317                                                                 (unsigned char **)pparams,
4318                                                                 &param_len);
4319
4320                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4321                                                 !NT_STATUS_IS_OK(status)) {
4322                                         reply_nterror(req, status);
4323                                         return;
4324                                 }
4325
4326                                 send_trans2_replies(conn, req,
4327                                                 NT_STATUS_OK,
4328                                                 *pparams,
4329                                                 param_len,
4330                                                 *ppdata,
4331                                                 data_len,
4332                                                 max_data_bytes);
4333
4334                                 if (NT_STATUS_IS_OK(status)) {
4335                                         /* Server-side transport
4336                                          * encryption is now *on*. */
4337                                         status = srv_encryption_start(conn);
4338                                         if (!NT_STATUS_IS_OK(status)) {
4339                                                 char *reason = talloc_asprintf(talloc_tos(),
4340                                                                                "Failure in setting "
4341                                                                                "up encrypted transport: %s",
4342                                                                                nt_errstr(status));
4343                                                 exit_server_cleanly(reason);
4344                                         }
4345                                 }
4346                                 return;
4347                         }
4348
4349                 case SMB_FS_QUOTA_INFORMATION:
4350                         {
4351                                 NTSTATUS status;
4352                                 DATA_BLOB qdata = {
4353                                                 .data = (uint8_t *)pdata,
4354                                                 .length = total_data
4355                                 };
4356                                 files_struct *fsp = NULL;
4357                                 fsp = file_fsp(req, SVAL(params,0));
4358
4359                                 status = smb_set_fsquota(conn,
4360                                                         req,
4361                                                         fsp,
4362                                                         &qdata);
4363                                 if (!NT_STATUS_IS_OK(status)) {
4364                                         reply_nterror(req, status);
4365                                         return;
4366                                 }
4367                                 break;
4368                         }
4369                 default:
4370                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4371                                 info_level));
4372                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4373                         return;
4374                         break;
4375         }
4376
4377         /* 
4378          * sending this reply works fine, 
4379          * but I'm not sure it's the same 
4380          * like windows do...
4381          * --metze
4382          */
4383         reply_outbuf(req, 10, 0);
4384 }
4385
4386 #if defined(HAVE_POSIX_ACLS)
4387 /****************************************************************************
4388  Utility function to count the number of entries in a POSIX acl.
4389 ****************************************************************************/
4390
4391 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4392 {
4393         unsigned int ace_count = 0;
4394         int entry_id = SMB_ACL_FIRST_ENTRY;
4395         SMB_ACL_ENTRY_T entry;
4396
4397         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4398                 /* get_next... */
4399                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4400                         entry_id = SMB_ACL_NEXT_ENTRY;
4401                 }
4402                 ace_count++;
4403         }
4404         return ace_count;
4405 }
4406
4407 /****************************************************************************
4408  Utility function to marshall a POSIX acl into wire format.
4409 ****************************************************************************/
4410
4411 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4412 {
4413         int entry_id = SMB_ACL_FIRST_ENTRY;
4414         SMB_ACL_ENTRY_T entry;
4415
4416         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4417                 SMB_ACL_TAG_T tagtype;
4418                 SMB_ACL_PERMSET_T permset;
4419                 unsigned char perms = 0;
4420                 unsigned int own_grp;
4421
4422                 /* get_next... */
4423                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4424                         entry_id = SMB_ACL_NEXT_ENTRY;
4425                 }
4426
4427                 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4428                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4429                         return False;
4430                 }
4431
4432                 if (sys_acl_get_permset(entry, &permset) == -1) {
4433                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4434                         return False;
4435                 }
4436
4437                 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4438                 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4439                 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4440
4441                 SCVAL(pdata,1,perms);
4442
4443                 switch (tagtype) {
4444                         case SMB_ACL_USER_OBJ:
4445                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4446                                 own_grp = (unsigned int)pst->st_ex_uid;
4447                                 SIVAL(pdata,2,own_grp);
4448                                 SIVAL(pdata,6,0);
4449                                 break;
4450                         case SMB_ACL_USER:
4451                                 {
4452                                         uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4453                                         if (!puid) {
4454                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4455                                                 return False;
4456                                         }
4457                                         own_grp = (unsigned int)*puid;
4458                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4459                                         SIVAL(pdata,2,own_grp);
4460                                         SIVAL(pdata,6,0);
4461                                         break;
4462                                 }
4463                         case SMB_ACL_GROUP_OBJ:
4464                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4465                                 own_grp = (unsigned int)pst->st_ex_gid;
4466                                 SIVAL(pdata,2,own_grp);
4467                                 SIVAL(pdata,6,0);
4468                                 break;
4469                         case SMB_ACL_GROUP:
4470                                 {
4471                                         gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4472                                         if (!pgid) {
4473                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4474                                                 return False;
4475                                         }
4476                                         own_grp = (unsigned int)*pgid;
4477                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4478                                         SIVAL(pdata,2,own_grp);
4479                                         SIVAL(pdata,6,0);
4480                                         break;
4481                                 }
4482                         case SMB_ACL_MASK:
4483                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4484                                 SIVAL(pdata,2,0xFFFFFFFF);
4485                                 SIVAL(pdata,6,0xFFFFFFFF);
4486                                 break;
4487                         case SMB_ACL_OTHER:
4488                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4489                                 SIVAL(pdata,2,0xFFFFFFFF);
4490                                 SIVAL(pdata,6,0xFFFFFFFF);
4491                                 break;
4492                         default:
4493                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4494                                 return False;
4495                 }
4496                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4497         }
4498
4499         return True;
4500 }
4501 #endif
4502
4503 /****************************************************************************
4504  Store the FILE_UNIX_BASIC info.
4505 ****************************************************************************/
4506
4507 static char *store_file_unix_basic(connection_struct *conn,
4508                                 char *pdata,
4509                                 files_struct *fsp,
4510                                 const SMB_STRUCT_STAT *psbuf)
4511 {
4512         uint64_t file_index = get_FileIndex(conn, psbuf);
4513         dev_t devno;
4514
4515         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4516         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4517
4518         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
4519         pdata += 8;
4520
4521         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4522         pdata += 8;
4523
4524         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
4525         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
4526         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
4527         pdata += 24;
4528
4529         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
4530         SIVAL(pdata,4,0);
4531         pdata += 8;
4532
4533         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
4534         SIVAL(pdata,4,0);
4535         pdata += 8;
4536
4537         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4538         pdata += 4;
4539
4540         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4541                 devno = psbuf->st_ex_rdev;
4542         } else {
4543                 devno = psbuf->st_ex_dev;
4544         }
4545
4546         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
4547         SIVAL(pdata,4,0);
4548         pdata += 8;
4549
4550         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
4551         SIVAL(pdata,4,0);
4552         pdata += 8;
4553
4554         SINO_T_VAL(pdata,0,(SMB_INO_T)file_index);   /* inode number */
4555         pdata += 8;
4556
4557         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
4558         SIVAL(pdata,4,0);
4559         pdata += 8;
4560
4561         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
4562         SIVAL(pdata,4,0);
4563         pdata += 8;
4564
4565         return pdata;
4566 }
4567
4568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4569  * the chflags(2) (or equivalent) flags.
4570  *
4571  * XXX: this really should be behind the VFS interface. To do this, we would
4572  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4573  * Each VFS module could then implement its own mapping as appropriate for the
4574  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4575  */
4576 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4577         info2_flags_map[] =
4578 {
4579 #ifdef UF_NODUMP
4580     { UF_NODUMP, EXT_DO_NOT_BACKUP },
4581 #endif
4582
4583 #ifdef UF_IMMUTABLE
4584     { UF_IMMUTABLE, EXT_IMMUTABLE },
4585 #endif
4586
4587 #ifdef UF_APPEND
4588     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4589 #endif
4590
4591 #ifdef UF_HIDDEN
4592     { UF_HIDDEN, EXT_HIDDEN },
4593 #endif
4594
4595     /* Do not remove. We need to guarantee that this array has at least one
4596      * entry to build on HP-UX.
4597      */
4598     { 0, 0 }
4599
4600 };
4601
4602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4603                                 uint32_t *smb_fflags, uint32_t *smb_fmask)
4604 {
4605         int i;
4606
4607         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4608             *smb_fmask |= info2_flags_map[i].smb_fflag;
4609             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4610                     *smb_fflags |= info2_flags_map[i].smb_fflag;
4611             }
4612         }
4613 }
4614
4615 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4616                                 const uint32_t smb_fflags,
4617                                 const uint32_t smb_fmask,
4618                                 int *stat_fflags)
4619 {
4620         uint32_t max_fmask = 0;
4621         int i;
4622
4623         *stat_fflags = psbuf->st_ex_flags;
4624
4625         /* For each flags requested in smb_fmask, check the state of the
4626          * corresponding flag in smb_fflags and set or clear the matching
4627          * stat flag.
4628          */
4629
4630         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4631             max_fmask |= info2_flags_map[i].smb_fflag;
4632             if (smb_fmask & info2_flags_map[i].smb_fflag) {
4633                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
4634                             *stat_fflags |= info2_flags_map[i].stat_fflag;
4635                     } else {
4636                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4637                     }
4638             }
4639         }
4640
4641         /* If smb_fmask is asking to set any bits that are not supported by
4642          * our flag mappings, we should fail.
4643          */
4644         if ((smb_fmask & max_fmask) != smb_fmask) {
4645                 return False;
4646         }
4647
4648         return True;
4649 }
4650
4651
4652 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4653  * of file flags and birth (create) time.
4654  */
4655 static char *store_file_unix_basic_info2(connection_struct *conn,
4656                                 char *pdata,
4657                                 files_struct *fsp,
4658                                 const SMB_STRUCT_STAT *psbuf)
4659 {
4660         uint32_t file_flags = 0;
4661         uint32_t flags_mask = 0;
4662
4663         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4664
4665         /* Create (birth) time 64 bit */
4666         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4667         pdata += 8;
4668
4669         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4670         SIVAL(pdata, 0, file_flags); /* flags */
4671         SIVAL(pdata, 4, flags_mask); /* mask */
4672         pdata += 8;
4673
4674         return pdata;
4675 }
4676
4677 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4678                                      const struct stream_struct *streams,
4679                                      char *data,
4680                                      unsigned int max_data_bytes,
4681                                      unsigned int *data_size)
4682 {
4683         unsigned int i;
4684         unsigned int ofs = 0;
4685
4686         if (max_data_bytes < 32) {
4687                 return NT_STATUS_INFO_LENGTH_MISMATCH;
4688         }
4689
4690         for (i = 0; i < num_streams; i++) {
4691                 unsigned int next_offset;
4692                 size_t namelen;
4693                 smb_ucs2_t *namebuf;
4694
4695                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4696                                       streams[i].name, &namelen) ||
4697                     namelen <= 2)
4698                 {
4699                         return NT_STATUS_INVALID_PARAMETER;
4700                 }
4701
4702                 /*
4703                  * name_buf is now null-terminated, we need to marshall as not
4704                  * terminated
4705                  */
4706
4707                 namelen -= 2;
4708
4709                 /*
4710                  * We cannot overflow ...
4711                  */
4712                 if ((ofs + 24 + namelen) > max_data_bytes) {
4713                         DEBUG(10, ("refusing to overflow reply at stream %u\n",
4714                                 i));
4715                         TALLOC_FREE(namebuf);
4716                         return STATUS_BUFFER_OVERFLOW;
4717                 }
4718
4719                 SIVAL(data, ofs+4, namelen);
4720                 SOFF_T(data, ofs+8, streams[i].size);
4721                 SOFF_T(data, ofs+16, streams[i].alloc_size);
4722                 memcpy(data+ofs+24, namebuf, namelen);
4723                 TALLOC_FREE(namebuf);
4724
4725                 next_offset = ofs + 24 + namelen;
4726
4727                 if (i == num_streams-1) {
4728                         SIVAL(data, ofs, 0);
4729                 }
4730                 else {
4731                         unsigned int align = ndr_align_size(next_offset, 8);
4732
4733                         if ((next_offset + align) > max_data_bytes) {
4734                                 DEBUG(10, ("refusing to overflow align "
4735                                         "reply at stream %u\n",
4736                                         i));
4737                                 TALLOC_FREE(namebuf);
4738                                 return STATUS_BUFFER_OVERFLOW;
4739                         }
4740
4741                         memset(data+next_offset, 0, align);
4742                         next_offset += align;
4743
4744                         SIVAL(data, ofs, next_offset - ofs);
4745                         ofs = next_offset;
4746                 }
4747
4748                 ofs = next_offset;
4749         }
4750
4751         DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4752
4753         *data_size = ofs;
4754
4755         return NT_STATUS_OK;
4756 }
4757
4758 /****************************************************************************
4759  Reply to a TRANSACT2_QFILEINFO on a PIPE !
4760 ****************************************************************************/
4761
4762 static void call_trans2qpipeinfo(connection_struct *conn,
4763                                  struct smb_request *req,
4764                                  unsigned int tran_call,
4765                                  char **pparams, int total_params,
4766                                  char **ppdata, int total_data,
4767                                  unsigned int max_data_bytes)
4768 {
4769         char *params = *pparams;
4770         char *pdata = *ppdata;
4771         unsigned int data_size = 0;
4772         unsigned int param_size = 2;
4773         uint16_t info_level;
4774         files_struct *fsp;
4775
4776         if (!params) {
4777                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778                 return;
4779         }
4780
4781         if (total_params < 4) {
4782                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783                 return;
4784         }
4785
4786         fsp = file_fsp(req, SVAL(params,0));
4787         if (!fsp_is_np(fsp)) {
4788                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4789                 return;
4790         }
4791
4792         info_level = SVAL(params,2);
4793
4794         *pparams = (char *)SMB_REALLOC(*pparams,2);
4795         if (*pparams == NULL) {
4796                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4797                 return;
4798         }
4799         params = *pparams;
4800         SSVAL(params,0,0);
4801         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4802                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4803                 return;
4804         }
4805         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4806         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4807         if (*ppdata == NULL ) {
4808                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4809                 return;
4810         }
4811         pdata = *ppdata;
4812
4813         switch (info_level) {
4814                 case SMB_FILE_STANDARD_INFORMATION:
4815                         memset(pdata,0,24);
4816                         SOFF_T(pdata,0,4096LL);
4817                         SIVAL(pdata,16,1);
4818                         SIVAL(pdata,20,1);
4819                         data_size = 24;
4820                         break;
4821
4822                 default:
4823                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4824                         return;
4825         }
4826
4827         send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4828                             max_data_bytes);
4829
4830         return;
4831 }
4832
4833 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4834                                TALLOC_CTX *mem_ctx,
4835                                uint16_t info_level,
4836                                files_struct *fsp,
4837                                struct smb_filename *smb_fname,
4838                                bool delete_pending,
4839                                struct timespec write_time_ts,
4840                                struct ea_list *ea_list,
4841                                int lock_data_count,
4842                                char *lock_data,
4843                                uint16_t flags2,
4844                                unsigned int max_data_bytes,
4845                                size_t *fixed_portion,
4846                                char **ppdata,
4847                                unsigned int *pdata_size)
4848 {
4849         char *pdata = *ppdata;
4850         char *dstart, *dend;
4851         unsigned int data_size;
4852         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4853         time_t create_time, mtime, atime, c_time;
4854         SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4855         char *p;
4856         char *base_name;
4857         char *dos_fname;
4858         int mode;
4859         int nlink;
4860         NTSTATUS status;
4861         uint64_t file_size = 0;
4862         uint64_t pos = 0;
4863         uint64_t allocation_size = 0;
4864         uint64_t file_index = 0;
4865         uint32_t access_mask = 0;
4866         size_t len = 0;
4867
4868         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4869                 return NT_STATUS_INVALID_LEVEL;
4870         }
4871
4872         DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4873                  smb_fname_str_dbg(smb_fname),
4874                  fsp_fnum_dbg(fsp),
4875                  info_level, max_data_bytes));
4876
4877         mode = dos_mode(conn, smb_fname);
4878         nlink = psbuf->st_ex_nlink;
4879
4880         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4881                 nlink = 1;
4882         }
4883
4884         if ((nlink > 0) && delete_pending) {
4885                 nlink -= 1;
4886         }
4887
4888         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4889                 return NT_STATUS_INVALID_PARAMETER;
4890         }
4891
4892         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4893         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4894         if (*ppdata == NULL) {
4895                 return NT_STATUS_NO_MEMORY;
4896         }
4897         pdata = *ppdata;
4898         dstart = pdata;
4899         dend = dstart + data_size - 1;
4900
4901         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4902                 update_stat_ex_mtime(psbuf, write_time_ts);
4903         }
4904
4905         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4906         mtime_ts = psbuf->st_ex_mtime;
4907         atime_ts = psbuf->st_ex_atime;
4908         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4909
4910         if (lp_dos_filetime_resolution(SNUM(conn))) {
4911                 dos_filetime_timespec(&create_time_ts);
4912                 dos_filetime_timespec(&mtime_ts);
4913                 dos_filetime_timespec(&atime_ts);
4914                 dos_filetime_timespec(&ctime_ts);
4915         }
4916
4917         create_time = convert_timespec_to_time_t(create_time_ts);
4918         mtime = convert_timespec_to_time_t(mtime_ts);
4919         atime = convert_timespec_to_time_t(atime_ts);
4920         c_time = convert_timespec_to_time_t(ctime_ts);
4921
4922         p = strrchr_m(smb_fname->base_name,'/');
4923         if (!p)
4924                 base_name = smb_fname->base_name;
4925         else
4926                 base_name = p+1;
4927
4928         /* NT expects the name to be in an exact form of the *full*
4929            filename. See the trans2 torture test */
4930         if (ISDOT(base_name)) {
4931                 dos_fname = talloc_strdup(mem_ctx, "\\");
4932                 if (!dos_fname) {
4933                         return NT_STATUS_NO_MEMORY;
4934                 }
4935         } else {
4936                 dos_fname = talloc_asprintf(mem_ctx,
4937                                 "\\%s",
4938                                 smb_fname->base_name);
4939                 if (!dos_fname) {
4940                         return NT_STATUS_NO_MEMORY;
4941                 }
4942                 if (is_ntfs_stream_smb_fname(smb_fname)) {
4943                         dos_fname = talloc_asprintf(dos_fname, "%s",
4944                                                     smb_fname->stream_name);
4945                         if (!dos_fname) {
4946                                 return NT_STATUS_NO_MEMORY;
4947                         }
4948                 }
4949
4950                 string_replace(dos_fname, '/', '\\');
4951         }
4952
4953         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4954
4955         if (!fsp) {
4956                 /* Do we have this path open ? */
4957                 files_struct *fsp1;
4958                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4959                 fsp1 = file_find_di_first(conn->sconn, fileid);
4960                 if (fsp1 && fsp1->initial_allocation_size) {
4961                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4962                 }
4963         }
4964
4965         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4966                 file_size = get_file_size_stat(psbuf);
4967         }
4968
4969         if (fsp) {
4970                 pos = fsp->fh->position_information;
4971         }
4972
4973         if (fsp) {
4974                 access_mask = fsp->access_mask;
4975         } else {
4976                 /* GENERIC_EXECUTE mapping from Windows */
4977                 access_mask = 0x12019F;
4978         }
4979
4980         /* This should be an index number - looks like
4981            dev/ino to me :-)
4982
4983            I think this causes us to fail the IFSKIT
4984            BasicFileInformationTest. -tpot */
4985         file_index = get_FileIndex(conn, psbuf);
4986
4987         *fixed_portion = 0;
4988
4989         switch (info_level) {
4990                 case SMB_INFO_STANDARD:
4991                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4992                         data_size = 22;
4993                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4994                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4995                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4996                         SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4997                         SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4998                         SSVAL(pdata,l1_attrFile,mode);
4999                         break;
5000
5001                 case SMB_INFO_QUERY_EA_SIZE:
5002                 {
5003                         unsigned int ea_size =
5004                             estimate_ea_size(conn, fsp,
5005                                              smb_fname);
5006                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5007                         data_size = 26;
5008                         srv_put_dos_date2(pdata,0,create_time);
5009                         srv_put_dos_date2(pdata,4,atime);
5010                         srv_put_dos_date2(pdata,8,mtime); /* write time */
5011                         SIVAL(pdata,12,(uint32_t)file_size);
5012                         SIVAL(pdata,16,(uint32_t)allocation_size);
5013                         SSVAL(pdata,20,mode);
5014                         SIVAL(pdata,22,ea_size);
5015                         break;
5016                 }
5017
5018                 case SMB_INFO_IS_NAME_VALID:
5019                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5020                         if (fsp) {
5021                                 /* os/2 needs this ? really ?*/
5022                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5023                         }
5024                         /* This is only reached for qpathinfo */
5025                         data_size = 0;
5026                         break;
5027
5028                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5029                 {
5030                         size_t total_ea_len = 0;
5031                         struct ea_list *ea_file_list = NULL;
5032                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5033
5034                         status =
5035                             get_ea_list_from_file(mem_ctx, conn, fsp,
5036                                                   smb_fname,
5037                                                   &total_ea_len, &ea_file_list);
5038                         if (!NT_STATUS_IS_OK(status)) {
5039                                 return status;
5040                         }
5041
5042                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5043
5044                         if (!ea_list || (total_ea_len > data_size)) {
5045                                 data_size = 4;
5046                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
5047                                 break;
5048                         }
5049
5050                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5051                         break;
5052                 }
5053
5054                 case SMB_INFO_QUERY_ALL_EAS:
5055                 {
5056                         /* We have data_size bytes to put EA's into. */
5057                         size_t total_ea_len = 0;
5058                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5059
5060                         status = get_ea_list_from_file(mem_ctx, conn, fsp,
5061                                                         smb_fname,
5062                                                         &total_ea_len, &ea_list);
5063                         if (!NT_STATUS_IS_OK(status)) {
5064                                 return status;
5065                         }
5066
5067                         if (!ea_list || (total_ea_len > data_size)) {
5068                                 data_size = 4;
5069                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
5070                                 break;
5071                         }
5072
5073                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5074                         break;
5075                 }
5076
5077                 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5078                 {
5079                         /* This is FileFullEaInformation - 0xF which maps to
5080                          * 1015 (decimal) in smbd_do_setfilepathinfo. */
5081
5082                         /* We have data_size bytes to put EA's into. */
5083                         size_t total_ea_len = 0;
5084                         struct ea_list *ea_file_list = NULL;
5085
5086                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5087
5088                         /*TODO: add filtering and index handling */
5089
5090                         status  =
5091                                 get_ea_list_from_file(mem_ctx, conn, fsp,
5092                                                   smb_fname,
5093                                                   &total_ea_len, &ea_file_list);
5094                         if (!NT_STATUS_IS_OK(status)) {
5095                                 return status;
5096                         }
5097                         if (!ea_file_list) {
5098                                 return NT_STATUS_NO_EAS_ON_FILE;
5099                         }
5100
5101                         status = fill_ea_chained_buffer(mem_ctx,
5102                                                         pdata,
5103                                                         data_size,
5104                                                         &data_size,
5105                                                         conn, ea_file_list);
5106                         if (!NT_STATUS_IS_OK(status)) {
5107                                 return status;
5108                         }
5109                         break;
5110                 }
5111
5112                 case SMB_FILE_BASIC_INFORMATION:
5113                 case SMB_QUERY_FILE_BASIC_INFO:
5114
5115                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5116                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5117                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5118                         } else {
5119                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5120                                 data_size = 40;
5121                                 SIVAL(pdata,36,0);
5122                         }
5123                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5124                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5125                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5126                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5127                         SIVAL(pdata,32,mode);
5128
5129                         DEBUG(5,("SMB_QFBI - "));
5130                         DEBUG(5,("create: %s ", ctime(&create_time)));
5131                         DEBUG(5,("access: %s ", ctime(&atime)));
5132                         DEBUG(5,("write: %s ", ctime(&mtime)));
5133                         DEBUG(5,("change: %s ", ctime(&c_time)));
5134                         DEBUG(5,("mode: %x\n", mode));
5135                         *fixed_portion = data_size;
5136                         break;
5137
5138                 case SMB_FILE_STANDARD_INFORMATION:
5139                 case SMB_QUERY_FILE_STANDARD_INFO:
5140
5141                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5142                         data_size = 24;
5143                         SOFF_T(pdata,0,allocation_size);
5144                         SOFF_T(pdata,8,file_size);
5145                         SIVAL(pdata,16,nlink);
5146                         SCVAL(pdata,20,delete_pending?1:0);
5147                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5148                         SSVAL(pdata,22,0); /* Padding. */
5149                         *fixed_portion = 24;
5150                         break;
5151
5152                 case SMB_FILE_EA_INFORMATION:
5153                 case SMB_QUERY_FILE_EA_INFO:
5154                 {
5155                         unsigned int ea_size =
5156                             estimate_ea_size(conn, fsp, smb_fname);
5157                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5158                         data_size = 4;
5159                         *fixed_portion = 4;
5160                         SIVAL(pdata,0,ea_size);
5161                         break;
5162                 }
5163
5164                 /* Get the 8.3 name - used if NT SMB was negotiated. */
5165                 case SMB_QUERY_FILE_ALT_NAME_INFO:
5166                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5167                 {
5168                         char mangled_name[13];
5169                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5170                         if (!name_to_8_3(base_name,mangled_name,
5171                                                 True,conn->params)) {
5172                                 return NT_STATUS_NO_MEMORY;
5173                         }
5174                         status = srvstr_push(dstart, flags2,
5175                                           pdata+4, mangled_name,
5176                                           PTR_DIFF(dend, pdata+4),
5177                                           STR_UNICODE, &len);
5178                         if (!NT_STATUS_IS_OK(status)) {
5179                                 return status;
5180                         }
5181                         data_size = 4 + len;
5182                         SIVAL(pdata,0,len);
5183                         *fixed_portion = 8;
5184                         break;
5185                 }
5186
5187                 case SMB_QUERY_FILE_NAME_INFO:
5188                 {
5189                         /*
5190                           this must be *exactly* right for ACLs on mapped drives to work
5191                          */
5192                         status = srvstr_push(dstart, flags2,
5193                                           pdata+4, dos_fname,
5194                                           PTR_DIFF(dend, pdata+4),
5195                                           STR_UNICODE, &len);
5196                         if (!NT_STATUS_IS_OK(status)) {
5197                                 return status;
5198                         }
5199                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5200                         data_size = 4 + len;
5201                         SIVAL(pdata,0,len);
5202                         break;
5203                 }
5204
5205                 case SMB_FILE_ALLOCATION_INFORMATION:
5206                 case SMB_QUERY_FILE_ALLOCATION_INFO:
5207                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5208                         data_size = 8;
5209                         SOFF_T(pdata,0,allocation_size);
5210                         break;
5211
5212                 case SMB_FILE_END_OF_FILE_INFORMATION:
5213                 case SMB_QUERY_FILE_END_OF_FILEINFO:
5214                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5215                         data_size = 8;
5216                         SOFF_T(pdata,0,file_size);
5217                         break;
5218
5219                 case SMB_QUERY_FILE_ALL_INFO:
5220                 case SMB_FILE_ALL_INFORMATION:
5221                 {
5222                         unsigned int ea_size =
5223                             estimate_ea_size(conn, fsp, smb_fname);
5224                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5225                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5226                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5227                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5228                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5229                         SIVAL(pdata,32,mode);
5230                         SIVAL(pdata,36,0); /* padding. */
5231                         pdata += 40;
5232                         SOFF_T(pdata,0,allocation_size);
5233                         SOFF_T(pdata,8,file_size);
5234                         SIVAL(pdata,16,nlink);
5235                         SCVAL(pdata,20,delete_pending);
5236                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5237                         SSVAL(pdata,22,0);
5238                         pdata += 24;
5239                         SIVAL(pdata,0,ea_size);
5240                         pdata += 4; /* EA info */
5241                         status = srvstr_push(dstart, flags2,
5242                                           pdata+4, dos_fname,
5243                                           PTR_DIFF(dend, pdata+4),
5244                                           STR_UNICODE, &len);
5245                         if (!NT_STATUS_IS_OK(status)) {
5246                                 return status;
5247                         }
5248                         SIVAL(pdata,0,len);
5249                         pdata += 4 + len;
5250                         data_size = PTR_DIFF(pdata,(*ppdata));
5251                         *fixed_portion = 10;
5252                         break;
5253                 }
5254
5255                 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5256                 {
5257                         unsigned int ea_size =
5258                             estimate_ea_size(conn, fsp, smb_fname);
5259                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5260                         put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5261                         put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5262                         put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5263                         put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5264                         SIVAL(pdata,    0x20, mode);
5265                         SIVAL(pdata,    0x24, 0); /* padding. */
5266                         SBVAL(pdata,    0x28, allocation_size);
5267                         SBVAL(pdata,    0x30, file_size);
5268                         SIVAL(pdata,    0x38, nlink);
5269                         SCVAL(pdata,    0x3C, delete_pending);
5270                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5271                         SSVAL(pdata,    0x3E, 0); /* padding */
5272                         SBVAL(pdata,    0x40, file_index);
5273                         SIVAL(pdata,    0x48, ea_size);
5274                         SIVAL(pdata,    0x4C, access_mask);
5275                         SBVAL(pdata,    0x50, pos);
5276                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
5277                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
5278
5279                         pdata += 0x60;
5280
5281                         status = srvstr_push(dstart, flags2,
5282                                           pdata+4, dos_fname,
5283                                           PTR_DIFF(dend, pdata+4),
5284                                           STR_UNICODE, &len);
5285                         if (!NT_STATUS_IS_OK(status)) {
5286                                 return status;
5287                         }
5288                         SIVAL(pdata,0,len);
5289                         pdata += 4 + len;
5290                         data_size = PTR_DIFF(pdata,(*ppdata));
5291                         *fixed_portion = 104;
5292                         break;
5293                 }
5294                 case SMB_FILE_INTERNAL_INFORMATION:
5295
5296                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5297                         SBVAL(pdata, 0, file_index);
5298                         data_size = 8;
5299                         *fixed_portion = 8;
5300                         break;
5301
5302                 case SMB_FILE_ACCESS_INFORMATION:
5303                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5304                         SIVAL(pdata, 0, access_mask);
5305                         data_size = 4;
5306                         *fixed_portion = 4;
5307                         break;
5308
5309                 case SMB_FILE_NAME_INFORMATION:
5310                         /* Pathname with leading '\'. */
5311                         {
5312                                 size_t byte_len;
5313                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5314                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5315                                 SIVAL(pdata,0,byte_len);
5316                                 data_size = 4 + byte_len;
5317                                 break;
5318                         }
5319
5320                 case SMB_FILE_DISPOSITION_INFORMATION:
5321                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5322                         data_size = 1;
5323                         SCVAL(pdata,0,delete_pending);
5324                         *fixed_portion = 1;
5325                         break;
5326
5327                 case SMB_FILE_POSITION_INFORMATION:
5328                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5329                         data_size = 8;
5330                         SOFF_T(pdata,0,pos);
5331                         *fixed_portion = 8;
5332                         break;
5333
5334                 case SMB_FILE_MODE_INFORMATION:
5335                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5336                         SIVAL(pdata,0,mode);
5337                         data_size = 4;
5338                         *fixed_portion = 4;
5339                         break;
5340
5341                 case SMB_FILE_ALIGNMENT_INFORMATION:
5342                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5343                         SIVAL(pdata,0,0); /* No alignment needed. */
5344                         data_size = 4;
5345                         *fixed_portion = 4;
5346                         break;
5347
5348                 /*
5349                  * NT4 server just returns "invalid query" to this - if we try
5350                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
5351                  * want this. JRA.
5352                  */
5353                 /* The first statement above is false - verified using Thursby
5354                  * client against NT4 -- gcolley.
5355                  */
5356                 case SMB_QUERY_FILE_STREAM_INFO:
5357                 case SMB_FILE_STREAM_INFORMATION: {
5358                         unsigned int num_streams = 0;
5359                         struct stream_struct *streams = NULL;
5360
5361                         DEBUG(10,("smbd_do_qfilepathinfo: "
5362                                   "SMB_FILE_STREAM_INFORMATION\n"));
5363
5364                         if (is_ntfs_stream_smb_fname(smb_fname)) {
5365                                 return NT_STATUS_INVALID_PARAMETER;
5366                         }
5367
5368                         status = vfs_streaminfo(conn,
5369                                                 fsp,
5370                                                 smb_fname,
5371                                                 talloc_tos(),
5372                                                 &num_streams,
5373                                                 &streams);
5374
5375                         if (!NT_STATUS_IS_OK(status)) {
5376                                 DEBUG(10, ("could not get stream info: %s\n",
5377                                            nt_errstr(status)));
5378                                 return status;
5379                         }
5380
5381                         status = marshall_stream_info(num_streams, streams,
5382                                                       pdata, max_data_bytes,
5383                                                       &data_size);
5384
5385                         if (!NT_STATUS_IS_OK(status)) {
5386                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
5387                                            nt_errstr(status)));
5388                                 TALLOC_FREE(streams);
5389                                 return status;
5390                         }
5391
5392                         TALLOC_FREE(streams);
5393
5394                         *fixed_portion = 32;
5395
5396                         break;
5397                 }
5398                 case SMB_QUERY_COMPRESSION_INFO:
5399                 case SMB_FILE_COMPRESSION_INFORMATION:
5400                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5401                         SOFF_T(pdata,0,file_size);
5402                         SIVAL(pdata,8,0); /* ??? */
5403                         SIVAL(pdata,12,0); /* ??? */
5404                         data_size = 16;
5405                         *fixed_portion = 16;
5406                         break;
5407
5408                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5409                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5410                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5411                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5412                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5413                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5414                         SOFF_T(pdata,32,allocation_size);
5415                         SOFF_T(pdata,40,file_size);
5416                         SIVAL(pdata,48,mode);
5417                         SIVAL(pdata,52,0); /* ??? */
5418                         data_size = 56;
5419                         *fixed_portion = 56;
5420                         break;
5421
5422                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5423                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5424                         SIVAL(pdata,0,mode);
5425                         SIVAL(pdata,4,0);
5426                         data_size = 8;
5427                         *fixed_portion = 8;
5428                         break;
5429
5430                 /*
5431                  * CIFS UNIX Extensions.
5432                  */
5433
5434                 case SMB_QUERY_FILE_UNIX_BASIC:
5435
5436                         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5437                         data_size = PTR_DIFF(pdata,(*ppdata));
5438
5439                         DEBUG(4,("smbd_do_qfilepathinfo: "
5440                                  "SMB_QUERY_FILE_UNIX_BASIC\n"));
5441                         dump_data(4, (uint8_t *)(*ppdata), data_size);
5442
5443                         break;
5444
5445                 case SMB_QUERY_FILE_UNIX_INFO2:
5446
5447                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5448                         data_size = PTR_DIFF(pdata,(*ppdata));
5449
5450                         {
5451                                 int i;
5452                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5453
5454                                 for (i=0; i<100; i++)
5455                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5456                                 DEBUG(4,("\n"));
5457                         }
5458
5459                         break;
5460
5461                 case SMB_QUERY_FILE_UNIX_LINK:
5462                         {
5463                                 int link_len = 0;
5464                                 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5465
5466                                 if (!buffer) {
5467                                         return NT_STATUS_NO_MEMORY;
5468                                 }
5469
5470                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5471 #ifdef S_ISLNK
5472                                 if(!S_ISLNK(psbuf->st_ex_mode)) {
5473                                         return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5474                                 }
5475 #else
5476                                 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5477 #endif
5478                                 link_len = SMB_VFS_READLINK(conn,
5479                                                        smb_fname,
5480                                                        buffer, PATH_MAX);
5481                                 if (link_len == -1) {
5482                                         return map_nt_error_from_unix(errno);
5483                                 }
5484                                 buffer[link_len] = 0;
5485                                 status = srvstr_push(dstart, flags2,
5486                                                   pdata, buffer,
5487                                                   PTR_DIFF(dend, pdata),
5488                                                   STR_TERMINATE, &len);
5489                                 if (!NT_STATUS_IS_OK(status)) {
5490                                         return status;
5491                                 }
5492                                 pdata += len;
5493                                 data_size = PTR_DIFF(pdata,(*ppdata));
5494
5495                                 break;
5496                         }
5497
5498 #if defined(HAVE_POSIX_ACLS)
5499                 case SMB_QUERY_POSIX_ACL:
5500                         {
5501                                 SMB_ACL_T file_acl = NULL;
5502                                 SMB_ACL_T def_acl = NULL;
5503                                 uint16_t num_file_acls = 0;
5504                                 uint16_t num_def_acls = 0;
5505
5506                                 status = refuse_symlink(conn,
5507                                                 fsp,
5508                                                 smb_fname);
5509                                 if (!NT_STATUS_IS_OK(status)) {
5510                                         return status;
5511                                 }
5512
5513                                 if (fsp && fsp->fh->fd != -1) {
5514                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5515                                                 talloc_tos());
5516                                 } else {
5517                                         file_acl =
5518                                             SMB_VFS_SYS_ACL_GET_FILE(conn,
5519                                                 smb_fname,
5520                                                 SMB_ACL_TYPE_ACCESS,
5521                                                 talloc_tos());
5522                                 }
5523
5524                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5525                                         DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5526                                                  "not implemented on "
5527                                                  "filesystem containing %s\n",
5528                                                  smb_fname->base_name));
5529                                         return NT_STATUS_NOT_IMPLEMENTED;
5530                                 }
5531
5532                                 if (S_ISDIR(psbuf->st_ex_mode)) {
5533                                         if (fsp && fsp->is_directory) {
5534                                                 def_acl =
5535                                                     SMB_VFS_SYS_ACL_GET_FILE(
5536                                                             conn,
5537                                                             fsp->fsp_name,
5538                                                             SMB_ACL_TYPE_DEFAULT,
5539                                                             talloc_tos());
5540                                         } else {
5541                                                 def_acl =
5542                                                     SMB_VFS_SYS_ACL_GET_FILE(
5543                                                             conn,
5544                                                             smb_fname,
5545                                                             SMB_ACL_TYPE_DEFAULT,
5546                                                             talloc_tos());
5547                                         }
5548                                         def_acl = free_empty_sys_acl(conn, def_acl);
5549                                 }
5550
5551                                 num_file_acls = count_acl_entries(conn, file_acl);
5552                                 num_def_acls = count_acl_entries(conn, def_acl);
5553
5554                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5555                                         DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5556                                                 data_size,
5557                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5558                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
5559                                         if (file_acl) {
5560                                                 TALLOC_FREE(file_acl);
5561                                         }
5562                                         if (def_acl) {
5563                                                 TALLOC_FREE(def_acl);
5564                                         }
5565                                         return NT_STATUS_BUFFER_TOO_SMALL;
5566                                 }
5567
5568                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5569                                 SSVAL(pdata,2,num_file_acls);
5570                                 SSVAL(pdata,4,num_def_acls);
5571                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5572                                         if (file_acl) {
5573                                                 TALLOC_FREE(file_acl);
5574                                         }
5575                                         if (def_acl) {
5576                                                 TALLOC_FREE(def_acl);
5577                                         }
5578                                         return NT_STATUS_INTERNAL_ERROR;
5579                                 }
5580                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5581                                         if (file_acl) {
5582                                                 TALLOC_FREE(file_acl);
5583                                         }
5584                                         if (def_acl) {
5585                                                 TALLOC_FREE(def_acl);
5586                                         }
5587                                         return NT_STATUS_INTERNAL_ERROR;
5588                                 }
5589
5590                                 if (file_acl) {
5591                                         TALLOC_FREE(file_acl);
5592                                 }
5593                                 if (def_acl) {
5594                                         TALLOC_FREE(def_acl);
5595                                 }
5596                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5597                                 break;
5598                         }
5599 #endif
5600
5601
5602                 case SMB_QUERY_POSIX_LOCK:
5603                 {
5604                         uint64_t count;
5605                         uint64_t offset;
5606                         uint64_t smblctx;
5607                         enum brl_type lock_type;
5608
5609                         /* We need an open file with a real fd for this. */
5610                         if (!fsp || fsp->fh->fd == -1) {
5611                                 return NT_STATUS_INVALID_LEVEL;
5612                         }
5613
5614                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5615                                 return NT_STATUS_INVALID_PARAMETER;
5616                         }
5617
5618                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5619                                 case POSIX_LOCK_TYPE_READ:
5620                                         lock_type = READ_LOCK;
5621                                         break;
5622                                 case POSIX_LOCK_TYPE_WRITE:
5623                                         lock_type = WRITE_LOCK;
5624                                         break;
5625                                 case POSIX_LOCK_TYPE_UNLOCK:
5626                                 default:
5627                                         /* There's no point in asking for an unlock... */
5628                                         return NT_STATUS_INVALID_PARAMETER;
5629                         }
5630
5631                         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5632                         offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5633                         count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5634
5635                         status = query_lock(fsp,
5636                                         &smblctx,
5637                                         &count,
5638                                         &offset,
5639                                         &lock_type,
5640                                         POSIX_LOCK);
5641
5642                         if (ERROR_WAS_LOCK_DENIED(status)) {
5643                                 /* Here we need to report who has it locked... */
5644                                 data_size = POSIX_LOCK_DATA_SIZE;
5645
5646                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5647                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5648                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5649                                 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5650                                 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5651
5652                         } else if (NT_STATUS_IS_OK(status)) {
5653                                 /* For success we just return a copy of what we sent
5654                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5655                                 data_size = POSIX_LOCK_DATA_SIZE;
5656                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5657                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5658                         } else {
5659                                 return status;
5660                         }
5661                         break;
5662                 }
5663
5664                 default:
5665                         return NT_STATUS_INVALID_LEVEL;
5666         }
5667
5668         *pdata_size = data_size;
5669         return NT_STATUS_OK;
5670 }
5671
5672 /****************************************************************************
5673  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5674  file name or file id).
5675 ****************************************************************************/
5676
5677 static void call_trans2qfilepathinfo(connection_struct *conn,
5678                                      struct smb_request *req,
5679                                      unsigned int tran_call,
5680                                      char **pparams, int total_params,
5681                                      char **ppdata, int total_data,
5682                                      unsigned int max_data_bytes)
5683 {
5684         char *params = *pparams;
5685         char *pdata = *ppdata;
5686         uint16_t info_level;
5687         unsigned int data_size = 0;
5688         unsigned int param_size = 2;
5689         struct smb_filename *smb_fname = NULL;
5690         bool delete_pending = False;
5691         struct timespec write_time_ts;
5692         files_struct *fsp = NULL;
5693         struct file_id fileid;
5694         struct ea_list *ea_list = NULL;
5695         int lock_data_count = 0;
5696         char *lock_data = NULL;
5697         size_t fixed_portion;
5698         NTSTATUS status = NT_STATUS_OK;
5699
5700         if (!params) {
5701                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5702                 return;
5703         }
5704
5705         ZERO_STRUCT(write_time_ts);
5706
5707         if (tran_call == TRANSACT2_QFILEINFO) {
5708                 if (total_params < 4) {
5709                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5710                         return;
5711                 }
5712
5713                 if (IS_IPC(conn)) {
5714                         call_trans2qpipeinfo(conn, req, tran_call,
5715                                              pparams, total_params,
5716                                              ppdata, total_data,
5717                                              max_data_bytes);
5718                         return;
5719                 }
5720
5721                 fsp = file_fsp(req, SVAL(params,0));
5722                 info_level = SVAL(params,2);
5723
5724                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5725
5726                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5727                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5728                         return;
5729                 }
5730
5731                 /* Initial check for valid fsp ptr. */
5732                 if (!check_fsp_open(conn, req, fsp)) {
5733                         return;
5734                 }
5735
5736                 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5737                 if (smb_fname == NULL) {
5738                         reply_nterror(req, NT_STATUS_NO_MEMORY);
5739                         return;
5740                 }
5741
5742                 if(fsp->fake_file_handle) {
5743                         /*
5744                          * This is actually for the QUOTA_FAKE_FILE --metze
5745                          */
5746
5747                         /* We know this name is ok, it's already passed the checks. */
5748
5749                 } else if(fsp->fh->fd == -1) {
5750                         /*
5751                          * This is actually a QFILEINFO on a directory
5752                          * handle (returned from an NT SMB). NT5.0 seems
5753                          * to do this call. JRA.
5754                          */
5755
5756                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5757                                 /* Always do lstat for UNIX calls. */
5758                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5759                                         DEBUG(3,("call_trans2qfilepathinfo: "
5760                                                  "SMB_VFS_LSTAT of %s failed "
5761                                                  "(%s)\n",
5762                                                  smb_fname_str_dbg(smb_fname),
5763                                                  strerror(errno)));
5764                                         reply_nterror(req,
5765                                                 map_nt_error_from_unix(errno));
5766                                         return;
5767                                 }
5768                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
5769                                 DEBUG(3,("call_trans2qfilepathinfo: "
5770                                          "SMB_VFS_STAT of %s failed (%s)\n",
5771                                          smb_fname_str_dbg(smb_fname),
5772                                          strerror(errno)));
5773                                 reply_nterror(req,
5774                                         map_nt_error_from_unix(errno));
5775                                 return;
5776                         }
5777
5778                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5779                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5780                 } else {
5781                         /*
5782                          * Original code - this is an open file.
5783                          */
5784                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5785                                 DEBUG(3, ("fstat of %s failed (%s)\n",
5786                                           fsp_fnum_dbg(fsp), strerror(errno)));
5787                                 reply_nterror(req,
5788                                         map_nt_error_from_unix(errno));
5789                                 return;
5790                         }
5791                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5792                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5793                 }
5794
5795         } else {
5796                 uint32_t name_hash;
5797                 char *fname = NULL;
5798                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5799
5800                 /* qpathinfo */
5801                 if (total_params < 7) {
5802                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5803                         return;
5804                 }
5805
5806                 info_level = SVAL(params,0);
5807
5808                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5809
5810                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5811                         if (!lp_unix_extensions()) {
5812                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5813                                 return;
5814                         }
5815                         if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5816                                         info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5817                                         info_level == SMB_QUERY_FILE_UNIX_LINK ||
5818                                         req->posix_pathnames) {
5819                                 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5820                         }
5821                 }
5822
5823                 if (req->posix_pathnames) {
5824                         srvstr_get_path_posix(req,
5825                                 params,
5826                                 req->flags2,
5827                                 &fname,
5828                                 &params[6],
5829                                 total_params - 6,
5830                                 STR_TERMINATE,
5831                                 &status);
5832                 } else {
5833                         srvstr_get_path(req,
5834                                 params,
5835                                 req->flags2,
5836                                 &fname,
5837                                 &params[6],
5838                                 total_params - 6,
5839                                 STR_TERMINATE,
5840                                 &status);
5841                 }
5842                 if (!NT_STATUS_IS_OK(status)) {
5843                         reply_nterror(req, status);
5844                         return;
5845                 }
5846
5847                 status = filename_convert(req,
5848                                         conn,
5849                                         fname,
5850                                         ucf_flags,
5851                                         NULL,
5852                                         &smb_fname);
5853                 if (!NT_STATUS_IS_OK(status)) {
5854                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5855                                 reply_botherror(req,
5856                                                 NT_STATUS_PATH_NOT_COVERED,
5857                                                 ERRSRV, ERRbadpath);
5858                                 return;
5859                         }
5860                         reply_nterror(req, status);
5861                         return;
5862                 }
5863
5864                 /* If this is a stream, check if there is a delete_pending. */
5865                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5866                     && is_ntfs_stream_smb_fname(smb_fname)) {
5867                         struct smb_filename *smb_fname_base;
5868
5869                         /* Create an smb_filename with stream_name == NULL. */
5870                         smb_fname_base = synthetic_smb_fname(
5871                                                 talloc_tos(),
5872                                                 smb_fname->base_name,
5873                                                 NULL,
5874                                                 NULL,
5875                                                 smb_fname->flags);
5876                         if (smb_fname_base == NULL) {
5877                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5878                                 return;
5879                         }
5880
5881                         if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5882                                 /* Always do lstat for UNIX calls. */
5883                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5884                                         DEBUG(3,("call_trans2qfilepathinfo: "
5885                                                  "SMB_VFS_LSTAT of %s failed "
5886                                                  "(%s)\n",
5887                                                  smb_fname_str_dbg(smb_fname_base),
5888                                                  strerror(errno)));
5889                                         TALLOC_FREE(smb_fname_base);
5890                                         reply_nterror(req,
5891                                                 map_nt_error_from_unix(errno));
5892                                         return;
5893                                 }
5894                         } else {
5895                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5896                                         DEBUG(3,("call_trans2qfilepathinfo: "
5897                                                  "fileinfo of %s failed "
5898                                                  "(%s)\n",
5899                                                  smb_fname_str_dbg(smb_fname_base),
5900                                                  strerror(errno)));
5901                                         TALLOC_FREE(smb_fname_base);
5902                                         reply_nterror(req,
5903                                                 map_nt_error_from_unix(errno));
5904                                         return;
5905                                 }
5906                         }
5907
5908                         status = file_name_hash(conn,
5909                                         smb_fname_str_dbg(smb_fname_base),
5910                                         &name_hash);
5911                         if (!NT_STATUS_IS_OK(status)) {
5912                                 TALLOC_FREE(smb_fname_base);
5913                                 reply_nterror(req, status);
5914                                 return;
5915                         }
5916
5917                         fileid = vfs_file_id_from_sbuf(conn,
5918                                                        &smb_fname_base->st);
5919                         TALLOC_FREE(smb_fname_base);
5920                         get_file_infos(fileid, name_hash, &delete_pending, NULL);
5921                         if (delete_pending) {
5922                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5923                                 return;
5924                         }
5925                 }
5926
5927                 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5928                         /* Always do lstat for UNIX calls. */
5929                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
5930                                 DEBUG(3,("call_trans2qfilepathinfo: "
5931                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
5932                                          smb_fname_str_dbg(smb_fname),
5933                                          strerror(errno)));
5934                                 reply_nterror(req,
5935                                         map_nt_error_from_unix(errno));
5936                                 return;
5937                         }
5938
5939                 } else {
5940                         if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5941                                 DEBUG(3,("call_trans2qfilepathinfo: "
5942                                          "SMB_VFS_STAT of %s failed (%s)\n",
5943                                          smb_fname_str_dbg(smb_fname),
5944                                          strerror(errno)));
5945                                 reply_nterror(req,
5946                                         map_nt_error_from_unix(errno));
5947                                 return;
5948                         }
5949                 }
5950
5951                 status = file_name_hash(conn,
5952                                 smb_fname_str_dbg(smb_fname),
5953                                 &name_hash);
5954                 if (!NT_STATUS_IS_OK(status)) {
5955                         reply_nterror(req, status);
5956                         return;
5957                 }
5958
5959                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5960                 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5961                 if (delete_pending) {
5962                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
5963                         return;
5964                 }
5965         }
5966
5967         DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5968                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5969                  fsp_fnum_dbg(fsp),
5970                  info_level,tran_call,total_data));
5971
5972         /* Pull out any data sent here before we realloc. */
5973         switch (info_level) {
5974                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5975                 {
5976                         /* Pull any EA list from the data portion. */
5977                         uint32_t ea_size;
5978
5979                         if (total_data < 4) {
5980                                 reply_nterror(
5981                                         req, NT_STATUS_INVALID_PARAMETER);
5982                                 return;
5983                         }
5984                         ea_size = IVAL(pdata,0);
5985
5986                         if (total_data > 0 && ea_size != total_data) {
5987                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5988 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5989                                 reply_nterror(
5990                                         req, NT_STATUS_INVALID_PARAMETER);
5991                                 return;
5992                         }
5993
5994                         if (!lp_ea_support(SNUM(conn))) {
5995                                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5996                                 return;
5997                         }
5998
5999                         /* Pull out the list of names. */
6000                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6001                         if (!ea_list) {
6002                                 reply_nterror(
6003                                         req, NT_STATUS_INVALID_PARAMETER);
6004                                 return;
6005                         }
6006                         break;
6007                 }
6008
6009                 case SMB_QUERY_POSIX_LOCK:
6010                 {
6011                         if (fsp == NULL || fsp->fh->fd == -1) {
6012                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6013                                 return;
6014                         }
6015
6016                         if (total_data != POSIX_LOCK_DATA_SIZE) {
6017                                 reply_nterror(
6018                                         req, NT_STATUS_INVALID_PARAMETER);
6019                                 return;
6020                         }
6021
6022                         /* Copy the lock range data. */
6023                         lock_data = (char *)talloc_memdup(
6024                                 req, pdata, total_data);
6025                         if (!lock_data) {
6026                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6027                                 return;
6028                         }
6029                         lock_data_count = total_data;
6030                 }
6031                 default:
6032                         break;
6033         }
6034
6035         *pparams = (char *)SMB_REALLOC(*pparams,2);
6036         if (*pparams == NULL) {
6037                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6038                 return;
6039         }
6040         params = *pparams;
6041         SSVAL(params,0,0);
6042
6043         /*
6044          * draft-leach-cifs-v1-spec-02.txt
6045          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6046          * says:
6047          *
6048          *  The requested information is placed in the Data portion of the
6049          *  transaction response. For the information levels greater than 0x100,
6050          *  the transaction response has 1 parameter word which should be
6051          *  ignored by the client.
6052          *
6053          * However Windows only follows this rule for the IS_NAME_VALID call.
6054          */
6055         switch (info_level) {
6056         case SMB_INFO_IS_NAME_VALID:
6057                 param_size = 0;
6058                 break;
6059         }
6060
6061         if ((info_level & 0xFF00) == 0xFF00) {
6062                 /*
6063                  * We use levels that start with 0xFF00
6064                  * internally to represent SMB2 specific levels
6065                  */
6066                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6067                 return;
6068         }
6069
6070         status = smbd_do_qfilepathinfo(conn, req, info_level,
6071                                        fsp, smb_fname,
6072                                        delete_pending, write_time_ts,
6073                                        ea_list,
6074                                        lock_data_count, lock_data,
6075                                        req->flags2, max_data_bytes,
6076                                        &fixed_portion,
6077                                        ppdata, &data_size);
6078         if (!NT_STATUS_IS_OK(status)) {
6079                 reply_nterror(req, status);
6080                 return;
6081         }
6082         if (fixed_portion > max_data_bytes) {
6083                 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6084                 return;
6085         }
6086
6087         send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6088                             max_data_bytes);
6089
6090         return;
6091 }
6092
6093 /****************************************************************************
6094  Set a hard link (called by UNIX extensions and by NT rename with HARD link
6095  code.
6096 ****************************************************************************/
6097
6098 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6099                 connection_struct *conn,
6100                 struct smb_request *req,
6101                 bool overwrite_if_exists,
6102                 const struct smb_filename *smb_fname_old,
6103                 struct smb_filename *smb_fname_new)
6104 {
6105         NTSTATUS status = NT_STATUS_OK;
6106
6107         /* source must already exist. */
6108         if (!VALID_STAT(smb_fname_old->st)) {
6109                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6110         }
6111
6112         if (VALID_STAT(smb_fname_new->st)) {
6113                 if (overwrite_if_exists) {
6114                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6115                                 return NT_STATUS_FILE_IS_A_DIRECTORY;
6116                         }
6117                         status = unlink_internals(conn,
6118                                                 req,
6119                                                 FILE_ATTRIBUTE_NORMAL,
6120                                                 smb_fname_new,
6121                                                 false);
6122                         if (!NT_STATUS_IS_OK(status)) {
6123                                 return status;
6124                         }
6125                 } else {
6126                         /* Disallow if newname already exists. */
6127                         return NT_STATUS_OBJECT_NAME_COLLISION;
6128                 }
6129         }
6130
6131         /* No links from a directory. */
6132         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6133                 return NT_STATUS_FILE_IS_A_DIRECTORY;
6134         }
6135
6136         /* Setting a hardlink to/from a stream isn't currently supported. */
6137         if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6138             is_ntfs_stream_smb_fname(smb_fname_new)) {
6139                 return NT_STATUS_INVALID_PARAMETER;
6140         }
6141
6142         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6143                   smb_fname_old->base_name, smb_fname_new->base_name));
6144
6145         if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6146                 status = map_nt_error_from_unix(errno);
6147                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6148                          nt_errstr(status), smb_fname_old->base_name,
6149                          smb_fname_new->base_name));
6150         }
6151         return status;
6152 }
6153
6154 /****************************************************************************
6155  Deal with setting the time from any of the setfilepathinfo functions.
6156  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6157  calling this function.
6158 ****************************************************************************/
6159
6160 NTSTATUS smb_set_file_time(connection_struct *conn,
6161                            files_struct *fsp,
6162                            const struct smb_filename *smb_fname,
6163                            struct smb_file_time *ft,
6164                            bool setting_write_time)
6165 {
6166         struct smb_filename smb_fname_base;
6167         uint32_t action =
6168                 FILE_NOTIFY_CHANGE_LAST_ACCESS
6169                 |FILE_NOTIFY_CHANGE_LAST_WRITE
6170                 |FILE_NOTIFY_CHANGE_CREATION;
6171
6172         if (!VALID_STAT(smb_fname->st)) {
6173                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6174         }
6175
6176         /* get some defaults (no modifications) if any info is zero or -1. */
6177         if (null_timespec(ft->create_time)) {
6178                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6179         }
6180
6181         if (null_timespec(ft->atime)) {
6182                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6183         }
6184
6185         if (null_timespec(ft->mtime)) {
6186                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6187         }
6188
6189         if (!setting_write_time) {
6190                 /* ft->mtime comes from change time, not write time. */
6191                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6192         }
6193
6194         /* Ensure the resolution is the correct for
6195          * what we can store on this filesystem. */
6196
6197         round_timespec(conn->ts_res, &ft->create_time);
6198         round_timespec(conn->ts_res, &ft->ctime);
6199         round_timespec(conn->ts_res, &ft->atime);
6200         round_timespec(conn->ts_res, &ft->mtime);
6201
6202         DEBUG(5,("smb_set_filetime: actime: %s\n ",
6203                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6204         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6205                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6206         DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6207                 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6208         DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6209                 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6210
6211         if (setting_write_time) {
6212                 /*
6213                  * This was a Windows setfileinfo on an open file.
6214                  * NT does this a lot. We also need to 
6215                  * set the time here, as it can be read by 
6216                  * FindFirst/FindNext and with the patch for bug #2045
6217                  * in smbd/fileio.c it ensures that this timestamp is
6218                  * kept sticky even after a write. We save the request
6219                  * away and will set it on file close and after a write. JRA.
6220                  */
6221
6222                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6223                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6224
6225                 if (fsp != NULL) {
6226                         if (fsp->base_fsp) {
6227                                 set_sticky_write_time_fsp(fsp->base_fsp,
6228                                                           ft->mtime);
6229                         } else {
6230                                 set_sticky_write_time_fsp(fsp, ft->mtime);
6231                         }
6232                 } else {
6233                         set_sticky_write_time_path(
6234                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6235                                 ft->mtime);
6236                 }
6237         }
6238
6239         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6240
6241         /* Always call ntimes on the base, even if a stream was passed in. */
6242         smb_fname_base = *smb_fname;
6243         smb_fname_base.stream_name = NULL;
6244
6245         if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6246                 return map_nt_error_from_unix(errno);
6247         }
6248
6249         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6250                      smb_fname->base_name);
6251         return NT_STATUS_OK;
6252 }
6253
6254 /****************************************************************************
6255  Deal with setting the dosmode from any of the setfilepathinfo functions.
6256  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6257  done before calling this function.
6258 ****************************************************************************/
6259
6260 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6261                                      const struct smb_filename *smb_fname,
6262                                      uint32_t dosmode)
6263 {
6264         struct smb_filename *smb_fname_base;
6265         NTSTATUS status;
6266
6267         if (!VALID_STAT(smb_fname->st)) {
6268                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6269         }
6270
6271         /* Always operate on the base_name, even if a stream was passed in. */
6272         smb_fname_base = synthetic_smb_fname(talloc_tos(),
6273                                         smb_fname->base_name,
6274                                         NULL,
6275                                         &smb_fname->st,
6276                                         smb_fname->flags);
6277         if (smb_fname_base == NULL) {
6278                 return NT_STATUS_NO_MEMORY;
6279         }
6280
6281         if (dosmode) {
6282                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6283                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6284                 } else {
6285                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6286                 }
6287         }
6288
6289         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6290
6291         /* check the mode isn't different, before changing it */
6292         if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6293                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6294                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6295                           (unsigned int)dosmode));
6296
6297                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6298                                     false)) {
6299                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6300                                  "%s failed (%s)\n",
6301                                  smb_fname_str_dbg(smb_fname_base),
6302                                  strerror(errno)));
6303                         status = map_nt_error_from_unix(errno);
6304                         goto out;
6305                 }
6306         }
6307         status = NT_STATUS_OK;
6308  out:
6309         TALLOC_FREE(smb_fname_base);
6310         return status;
6311 }
6312
6313 /****************************************************************************
6314  Deal with setting the size from any of the setfilepathinfo functions.
6315 ****************************************************************************/
6316
6317 static NTSTATUS smb_set_file_size(connection_struct *conn,
6318                                   struct smb_request *req,
6319                                   files_struct *fsp,
6320                                   const struct smb_filename *smb_fname,
6321                                   const SMB_STRUCT_STAT *psbuf,
6322                                   off_t size,
6323                                   bool fail_after_createfile)
6324 {
6325         NTSTATUS status = NT_STATUS_OK;
6326         struct smb_filename *smb_fname_tmp = NULL;
6327         files_struct *new_fsp = NULL;
6328
6329         if (!VALID_STAT(*psbuf)) {
6330                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6331         }
6332
6333         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6334
6335         if (size == get_file_size_stat(psbuf)) {
6336                 return NT_STATUS_OK;
6337         }
6338
6339         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6340                   smb_fname_str_dbg(smb_fname), (double)size));
6341
6342         if (fsp && fsp->fh->fd != -1) {
6343                 /* Handle based call. */
6344                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6345                         return NT_STATUS_ACCESS_DENIED;
6346                 }
6347
6348                 if (vfs_set_filelen(fsp, size) == -1) {
6349                         return map_nt_error_from_unix(errno);
6350                 }
6351                 trigger_write_time_update_immediate(fsp);
6352                 return NT_STATUS_OK;
6353         }
6354
6355         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6356         if (smb_fname_tmp == NULL) {
6357                 return NT_STATUS_NO_MEMORY;
6358         }
6359
6360         smb_fname_tmp->st = *psbuf;
6361
6362         status = SMB_VFS_CREATE_FILE(
6363                 conn,                                   /* conn */
6364                 req,                                    /* req */
6365                 0,                                      /* root_dir_fid */
6366                 smb_fname_tmp,                          /* fname */
6367                 FILE_WRITE_DATA,                        /* access_mask */
6368                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6369                     FILE_SHARE_DELETE),
6370                 FILE_OPEN,                              /* create_disposition*/
6371                 0,                                      /* create_options */
6372                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6373                 0,                                      /* oplock_request */
6374                 NULL,                                   /* lease */
6375                 0,                                      /* allocation_size */
6376                 0,                                      /* private_flags */
6377                 NULL,                                   /* sd */
6378                 NULL,                                   /* ea_list */
6379                 &new_fsp,                               /* result */
6380                 NULL,                                   /* pinfo */
6381                 NULL, NULL);                            /* create context */
6382
6383         TALLOC_FREE(smb_fname_tmp);
6384
6385         if (!NT_STATUS_IS_OK(status)) {
6386                 /* NB. We check for open_was_deferred in the caller. */
6387                 return status;
6388         }
6389
6390         /* See RAW-SFILEINFO-END-OF-FILE */
6391         if (fail_after_createfile) {
6392                 close_file(req, new_fsp,NORMAL_CLOSE);
6393                 return NT_STATUS_INVALID_LEVEL;
6394         }
6395
6396         if (vfs_set_filelen(new_fsp, size) == -1) {
6397                 status = map_nt_error_from_unix(errno);
6398                 close_file(req, new_fsp,NORMAL_CLOSE);
6399                 return status;
6400         }
6401
6402         trigger_write_time_update_immediate(new_fsp);
6403         close_file(req, new_fsp,NORMAL_CLOSE);
6404         return NT_STATUS_OK;
6405 }
6406
6407 /****************************************************************************
6408  Deal with SMB_INFO_SET_EA.
6409 ****************************************************************************/
6410
6411 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6412                                 const char *pdata,
6413                                 int total_data,
6414                                 files_struct *fsp,
6415                                 const struct smb_filename *smb_fname)
6416 {
6417         struct ea_list *ea_list = NULL;
6418         TALLOC_CTX *ctx = NULL;
6419         NTSTATUS status = NT_STATUS_OK;
6420
6421         if (total_data < 10) {
6422
6423                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6424                    length. They seem to have no effect. Bug #3212. JRA */
6425
6426                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6427                         /* We're done. We only get EA info in this call. */
6428                         return NT_STATUS_OK;
6429                 }
6430
6431                 return NT_STATUS_INVALID_PARAMETER;
6432         }
6433
6434         if (IVAL(pdata,0) > total_data) {
6435                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6436                         IVAL(pdata,0), (unsigned int)total_data));
6437                 return NT_STATUS_INVALID_PARAMETER;
6438         }
6439
6440         ctx = talloc_tos();
6441         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6442         if (!ea_list) {
6443                 return NT_STATUS_INVALID_PARAMETER;
6444         }
6445
6446         status = set_ea(conn, fsp, smb_fname, ea_list);
6447
6448         return status;
6449 }
6450
6451 /****************************************************************************
6452  Deal with SMB_FILE_FULL_EA_INFORMATION set.
6453 ****************************************************************************/
6454
6455 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6456                                 const char *pdata,
6457                                 int total_data,
6458                                 files_struct *fsp)
6459 {
6460         struct ea_list *ea_list = NULL;
6461         NTSTATUS status;
6462
6463         if (!fsp) {
6464                 return NT_STATUS_INVALID_HANDLE;
6465         }
6466
6467         if (!lp_ea_support(SNUM(conn))) {
6468                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6469                         "EA's not supported.\n",
6470                         (unsigned int)total_data));
6471                 return NT_STATUS_EAS_NOT_SUPPORTED;
6472         }
6473
6474         if (total_data < 10) {
6475                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6476                         "too small.\n",
6477                         (unsigned int)total_data));
6478                 return NT_STATUS_INVALID_PARAMETER;
6479         }
6480
6481         ea_list = read_nttrans_ea_list(talloc_tos(),
6482                                 pdata,
6483                                 total_data);
6484
6485         if (!ea_list) {
6486                 return NT_STATUS_INVALID_PARAMETER;
6487         }
6488
6489         status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6490
6491         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6492                 smb_fname_str_dbg(fsp->fsp_name),
6493                 nt_errstr(status) ));
6494
6495         return status;
6496 }
6497
6498
6499 /****************************************************************************
6500  Deal with SMB_SET_FILE_DISPOSITION_INFO.
6501 ****************************************************************************/
6502
6503 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6504                                 const char *pdata,
6505                                 int total_data,
6506                                 files_struct *fsp,
6507                                 struct smb_filename *smb_fname)
6508 {
6509         NTSTATUS status = NT_STATUS_OK;
6510         bool delete_on_close;
6511         uint32_t dosmode = 0;
6512
6513         if (total_data < 1) {
6514                 return NT_STATUS_INVALID_PARAMETER;
6515         }
6516
6517         if (fsp == NULL) {
6518                 return NT_STATUS_INVALID_HANDLE;
6519         }
6520
6521         delete_on_close = (CVAL(pdata,0) ? True : False);
6522         dosmode = dos_mode(conn, smb_fname);
6523
6524         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6525                 "delete_on_close = %u\n",
6526                 smb_fname_str_dbg(smb_fname),
6527                 (unsigned int)dosmode,
6528                 (unsigned int)delete_on_close ));
6529
6530         if (delete_on_close) {
6531                 status = can_set_delete_on_close(fsp, dosmode);
6532                 if (!NT_STATUS_IS_OK(status)) {
6533                         return status;
6534                 }
6535         }
6536
6537         /* The set is across all open files on this dev/inode pair. */
6538         if (!set_delete_on_close(fsp, delete_on_close,
6539                                  conn->session_info->security_token,
6540                                  conn->session_info->unix_token)) {
6541                 return NT_STATUS_ACCESS_DENIED;
6542         }
6543         return NT_STATUS_OK;
6544 }
6545
6546 /****************************************************************************
6547  Deal with SMB_FILE_POSITION_INFORMATION.
6548 ****************************************************************************/
6549
6550 static NTSTATUS smb_file_position_information(connection_struct *conn,
6551                                 const char *pdata,
6552                                 int total_data,
6553                                 files_struct *fsp)
6554 {
6555         uint64_t position_information;
6556
6557         if (total_data < 8) {
6558                 return NT_STATUS_INVALID_PARAMETER;
6559         }
6560
6561         if (fsp == NULL) {
6562                 /* Ignore on pathname based set. */
6563                 return NT_STATUS_OK;
6564         }
6565
6566         position_information = (uint64_t)IVAL(pdata,0);
6567         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6568
6569         DEBUG(10,("smb_file_position_information: Set file position "
6570                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6571                   (double)position_information));
6572         fsp->fh->position_information = position_information;
6573         return NT_STATUS_OK;
6574 }
6575
6576 /****************************************************************************
6577  Deal with SMB_FILE_MODE_INFORMATION.
6578 ****************************************************************************/
6579
6580 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6581                                 const char *pdata,
6582                                 int total_data)
6583 {
6584         uint32_t mode;
6585
6586         if (total_data < 4) {
6587                 return NT_STATUS_INVALID_PARAMETER;
6588         }
6589         mode = IVAL(pdata,0);
6590         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6591                 return NT_STATUS_INVALID_PARAMETER;
6592         }
6593         return NT_STATUS_OK;
6594 }
6595
6596 /****************************************************************************
6597  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6598 ****************************************************************************/
6599
6600 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6601                                        struct smb_request *req,
6602                                        const char *pdata,
6603                                        int total_data,
6604                                        const struct smb_filename *new_smb_fname)
6605 {
6606         char *link_target = NULL;
6607         TALLOC_CTX *ctx = talloc_tos();
6608
6609         /* Set a symbolic link. */
6610         /* Don't allow this if follow links is false. */
6611
6612         if (total_data == 0) {
6613                 return NT_STATUS_INVALID_PARAMETER;
6614         }
6615
6616         if (!lp_follow_symlinks(SNUM(conn))) {
6617                 return NT_STATUS_ACCESS_DENIED;
6618         }
6619
6620         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6621                     total_data, STR_TERMINATE);
6622
6623         if (!link_target) {
6624                 return NT_STATUS_INVALID_PARAMETER;
6625         }
6626
6627         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6628                         new_smb_fname->base_name, link_target ));
6629
6630         if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6631                 return map_nt_error_from_unix(errno);
6632         }
6633
6634         return NT_STATUS_OK;
6635 }
6636
6637 /****************************************************************************
6638  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6639 ****************************************************************************/
6640
6641 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6642                                         struct smb_request *req,
6643                                         const char *pdata, int total_data,
6644                                         struct smb_filename *smb_fname_new)
6645 {
6646         char *oldname = NULL;
6647         struct smb_filename *smb_fname_old = NULL;
6648         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6649         TALLOC_CTX *ctx = talloc_tos();
6650         NTSTATUS status = NT_STATUS_OK;
6651
6652         /* Set a hard link. */
6653         if (total_data == 0) {
6654                 return NT_STATUS_INVALID_PARAMETER;
6655         }
6656
6657         if (req->posix_pathnames) {
6658                 srvstr_get_path_posix(ctx,
6659                         pdata,
6660                         req->flags2,
6661                         &oldname,
6662                         pdata,
6663                         total_data,
6664                         STR_TERMINATE,
6665                         &status);
6666         } else {
6667                 srvstr_get_path(ctx,
6668                         pdata,
6669                         req->flags2,
6670                         &oldname,
6671                         pdata,
6672                         total_data,
6673                         STR_TERMINATE,
6674                         &status);
6675         }
6676         if (!NT_STATUS_IS_OK(status)) {
6677                 return status;
6678         }
6679
6680         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6681                 smb_fname_str_dbg(smb_fname_new), oldname));
6682
6683         status = filename_convert(ctx,
6684                                 conn,
6685                                 oldname,
6686                                 ucf_flags,
6687                                 NULL,
6688                                 &smb_fname_old);
6689         if (!NT_STATUS_IS_OK(status)) {
6690                 return status;
6691         }
6692
6693         return hardlink_internals(ctx, conn, req, false,
6694                         smb_fname_old, smb_fname_new);
6695 }
6696
6697 /****************************************************************************
6698  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6699 ****************************************************************************/
6700
6701 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6702                                             struct smb_request *req,
6703                                             const char *pdata,
6704                                             int total_data,
6705                                             files_struct *fsp,
6706                                             struct smb_filename *smb_fname_src)
6707 {
6708         bool overwrite;
6709         uint32_t len;
6710         char *newname = NULL;
6711         struct smb_filename *smb_fname_dst = NULL;
6712         uint32_t ucf_flags = UCF_SAVE_LCOMP |
6713                 ucf_flags_from_smb_request(req);
6714         NTSTATUS status = NT_STATUS_OK;
6715         TALLOC_CTX *ctx = talloc_tos();
6716
6717         if (!fsp) {
6718                 return NT_STATUS_INVALID_HANDLE;
6719         }
6720
6721         if (total_data < 20) {
6722                 return NT_STATUS_INVALID_PARAMETER;
6723         }
6724
6725         overwrite = (CVAL(pdata,0) ? True : False);
6726         len = IVAL(pdata,16);
6727
6728         if (len > (total_data - 20) || (len == 0)) {
6729                 return NT_STATUS_INVALID_PARAMETER;
6730         }
6731
6732         if (req->posix_pathnames) {
6733                 srvstr_get_path_posix(ctx,
6734                                 pdata,
6735                                 req->flags2,
6736                                 &newname,
6737                                 &pdata[20],
6738                                 len,
6739                                 STR_TERMINATE,
6740                                 &status);
6741         } else {
6742                 srvstr_get_path(ctx,
6743                                 pdata,
6744                                 req->flags2,
6745                                 &newname,
6746                                 &pdata[20],
6747                                 len,
6748                                 STR_TERMINATE,
6749                                 &status);
6750         }
6751         if (!NT_STATUS_IS_OK(status)) {
6752                 return status;
6753         }
6754
6755         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6756                                 newname));
6757
6758         status = filename_convert(ctx,
6759                                 conn,
6760                                 newname,
6761                                 ucf_flags,
6762                                 NULL,
6763                                 &smb_fname_dst);
6764         if (!NT_STATUS_IS_OK(status)) {
6765                 return status;
6766         }
6767
6768         if (fsp->base_fsp) {
6769                 /* newname must be a stream name. */
6770                 if (newname[0] != ':') {
6771                         return NT_STATUS_NOT_SUPPORTED;
6772                 }
6773
6774                 /* Create an smb_fname to call rename_internals_fsp() with. */
6775                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6776                                         fsp->base_fsp->fsp_name->base_name,
6777                                         newname,
6778                                         NULL,
6779                                         fsp->base_fsp->fsp_name->flags);
6780                 if (smb_fname_dst == NULL) {
6781                         status = NT_STATUS_NO_MEMORY;
6782                         goto out;
6783                 }
6784
6785                 /*
6786                  * Set the original last component, since
6787                  * rename_internals_fsp() requires it.
6788                  */
6789                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6790                                                               newname);
6791                 if (smb_fname_dst->original_lcomp == NULL) {
6792                         status = NT_STATUS_NO_MEMORY;
6793                         goto out;
6794                 }
6795
6796         }
6797
6798         DEBUG(10,("smb2_file_rename_information: "
6799                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6800                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6801                   smb_fname_str_dbg(smb_fname_dst)));
6802         status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6803                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6804                                 overwrite);
6805
6806  out:
6807         TALLOC_FREE(smb_fname_dst);
6808         return status;
6809 }
6810
6811 static NTSTATUS smb_file_link_information(connection_struct *conn,
6812                                             struct smb_request *req,
6813                                             const char *pdata,
6814                                             int total_data,
6815                                             files_struct *fsp,
6816                                             struct smb_filename *smb_fname_src)
6817 {
6818         bool overwrite;
6819         uint32_t len;
6820         char *newname = NULL;
6821         struct smb_filename *smb_fname_dst = NULL;
6822         NTSTATUS status = NT_STATUS_OK;
6823         uint32_t ucf_flags = UCF_SAVE_LCOMP |
6824                 ucf_flags_from_smb_request(req);
6825         TALLOC_CTX *ctx = talloc_tos();
6826
6827         if (!fsp) {
6828                 return NT_STATUS_INVALID_HANDLE;
6829         }
6830
6831         if (total_data < 20) {
6832                 return NT_STATUS_INVALID_PARAMETER;
6833         }
6834
6835         overwrite = (CVAL(pdata,0) ? true : false);
6836         len = IVAL(pdata,16);
6837
6838         if (len > (total_data - 20) || (len == 0)) {
6839                 return NT_STATUS_INVALID_PARAMETER;
6840         }
6841
6842         if (req->posix_pathnames) {
6843                 srvstr_get_path_posix(ctx,
6844                                 pdata,
6845                                 req->flags2,
6846                                 &newname,
6847                                 &pdata[20],
6848                                 len,
6849                                 STR_TERMINATE,
6850                                 &status);
6851         } else {
6852                 srvstr_get_path(ctx,
6853                                 pdata,
6854                                 req->flags2,
6855                                 &newname,
6856                                 &pdata[20],
6857                                 len,
6858                                 STR_TERMINATE,
6859                                 &status);
6860         }
6861         if (!NT_STATUS_IS_OK(status)) {
6862                 return status;
6863         }
6864
6865         DEBUG(10,("smb_file_link_information: got name |%s|\n",
6866                                 newname));
6867
6868         status = filename_convert(ctx,
6869                                 conn,
6870                                 newname,
6871                                 ucf_flags,
6872                                 NULL,
6873                                 &smb_fname_dst);
6874         if (!NT_STATUS_IS_OK(status)) {
6875                 return status;
6876         }
6877
6878         if (fsp->base_fsp) {
6879                 /* No stream names. */
6880                 return NT_STATUS_NOT_SUPPORTED;
6881         }
6882
6883         DEBUG(10,("smb_file_link_information: "
6884                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6885                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6886                   smb_fname_str_dbg(smb_fname_dst)));
6887         status = hardlink_internals(ctx,
6888                                 conn,
6889                                 req,
6890                                 overwrite,
6891                                 fsp->fsp_name,
6892                                 smb_fname_dst);
6893
6894         TALLOC_FREE(smb_fname_dst);
6895         return status;
6896 }
6897
6898 /****************************************************************************
6899  Deal with SMB_FILE_RENAME_INFORMATION.
6900 ****************************************************************************/
6901
6902 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6903                                             struct smb_request *req,
6904                                             const char *pdata,
6905                                             int total_data,
6906                                             files_struct *fsp,
6907                                             struct smb_filename *smb_fname_src)
6908 {
6909         bool overwrite;
6910         uint32_t root_fid;
6911         uint32_t len;
6912         char *newname = NULL;
6913         struct smb_filename *smb_fname_dst = NULL;
6914         bool dest_has_wcard = False;
6915         NTSTATUS status = NT_STATUS_OK;
6916         char *p;
6917         TALLOC_CTX *ctx = talloc_tos();
6918
6919         if (total_data < 13) {
6920                 return NT_STATUS_INVALID_PARAMETER;
6921         }
6922
6923         overwrite = (CVAL(pdata,0) ? True : False);
6924         root_fid = IVAL(pdata,4);
6925         len = IVAL(pdata,8);
6926
6927         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6928                 return NT_STATUS_INVALID_PARAMETER;
6929         }
6930
6931         if (req->posix_pathnames) {
6932                 srvstr_get_path_wcard_posix(ctx,
6933                                 pdata,
6934                                 req->flags2,
6935                                 &newname,
6936                                 &pdata[12],
6937                                 len,
6938                                 0,
6939                                 &status,
6940                                 &dest_has_wcard);
6941         } else {
6942                 srvstr_get_path_wcard(ctx,
6943                                 pdata,
6944                                 req->flags2,
6945                                 &newname,
6946                                 &pdata[12],
6947                                 len,
6948                                 0,
6949                                 &status,
6950                                 &dest_has_wcard);
6951         }
6952         if (!NT_STATUS_IS_OK(status)) {
6953                 return status;
6954         }
6955
6956         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6957                                 newname));
6958
6959         if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6960                 status = resolve_dfspath_wcard(ctx, conn,
6961                                        newname,
6962                                        UCF_COND_ALLOW_WCARD_LCOMP,
6963                                        !conn->sconn->using_smb2,
6964                                        &newname,
6965                                        &dest_has_wcard);
6966                 if (!NT_STATUS_IS_OK(status)) {
6967                         return status;
6968                 }
6969         }
6970
6971         /* Check the new name has no '/' characters. */
6972         if (strchr_m(newname, '/')) {
6973                 return NT_STATUS_NOT_SUPPORTED;
6974         }
6975
6976         if (fsp && fsp->base_fsp) {
6977                 /* newname must be a stream name. */
6978                 if (newname[0] != ':') {
6979                         return NT_STATUS_NOT_SUPPORTED;
6980                 }
6981
6982                 /* Create an smb_fname to call rename_internals_fsp() with. */
6983                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6984                                         fsp->base_fsp->fsp_name->base_name,
6985                                         newname,
6986                                         NULL,
6987                                         fsp->base_fsp->fsp_name->flags);
6988                 if (smb_fname_dst == NULL) {
6989                         status = NT_STATUS_NO_MEMORY;
6990                         goto out;
6991                 }
6992
6993                 /*
6994                  * Set the original last component, since
6995                  * rename_internals_fsp() requires it.
6996                  */
6997                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6998                                                               newname);
6999                 if (smb_fname_dst->original_lcomp == NULL) {
7000                         status = NT_STATUS_NO_MEMORY;
7001                         goto out;
7002                 }
7003
7004         } else {
7005                 /*
7006                  * Build up an smb_fname_dst based on the filename passed in.
7007                  * We basically just strip off the last component, and put on
7008                  * the newname instead.
7009                  */
7010                 char *base_name = NULL;
7011                 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7012                         ucf_flags_from_smb_request(req);
7013
7014                 if (dest_has_wcard) {
7015                         ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7016                 }
7017
7018                 /* newname must *not* be a stream name. */
7019                 if (newname[0] == ':') {
7020                         return NT_STATUS_NOT_SUPPORTED;
7021                 }
7022
7023                 /*
7024                  * Strip off the last component (filename) of the path passed
7025                  * in.
7026                  */
7027                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7028                 if (!base_name) {
7029                         return NT_STATUS_NO_MEMORY;
7030                 }
7031                 p = strrchr_m(base_name, '/');
7032                 if (p) {
7033                         p[1] = '\0';
7034                 } else {
7035                         base_name = talloc_strdup(ctx, "");
7036                         if (!base_name) {
7037                                 return NT_STATUS_NO_MEMORY;
7038                         }
7039                 }
7040                 /* Append the new name. */
7041                 base_name = talloc_asprintf_append(base_name,
7042                                 "%s",
7043                                 newname);
7044                 if (!base_name) {
7045                         return NT_STATUS_NO_MEMORY;
7046                 }
7047
7048                 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7049                                         ucf_flags);
7050
7051                 /* If an error we expect this to be
7052                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7053
7054                 if (!NT_STATUS_IS_OK(status)) {
7055                         if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7056                                             status)) {
7057                                 goto out;
7058                         }
7059                         /* Create an smb_fname to call rename_internals_fsp() */
7060                         smb_fname_dst = synthetic_smb_fname(ctx,
7061                                                 base_name,
7062                                                 NULL,
7063                                                 NULL,
7064                                                 smb_fname_src->flags);
7065                         if (smb_fname_dst == NULL) {
7066                                 status = NT_STATUS_NO_MEMORY;
7067                                 goto out;
7068                         }
7069                 }
7070         }
7071
7072         if (fsp) {
7073                 DEBUG(10,("smb_file_rename_information: "
7074                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7075                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7076                           smb_fname_str_dbg(smb_fname_dst)));
7077                 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7078                                               overwrite);
7079         } else {
7080                 DEBUG(10,("smb_file_rename_information: "
7081                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7082                           smb_fname_str_dbg(smb_fname_src),
7083                           smb_fname_str_dbg(smb_fname_dst)));
7084                 status = rename_internals(ctx, conn, req, smb_fname_src,
7085                                           smb_fname_dst, 0, overwrite, false,
7086                                           dest_has_wcard,
7087                                           FILE_WRITE_ATTRIBUTES);
7088         }
7089  out:
7090         TALLOC_FREE(smb_fname_dst);
7091         return status;
7092 }
7093
7094 /****************************************************************************
7095  Deal with SMB_SET_POSIX_ACL.
7096 ****************************************************************************/
7097
7098 #if defined(HAVE_POSIX_ACLS)
7099 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7100                                 const char *pdata,
7101                                 int total_data,
7102                                 files_struct *fsp,
7103                                 const struct smb_filename *smb_fname)
7104 {
7105         uint16_t posix_acl_version;
7106         uint16_t num_file_acls;
7107         uint16_t num_def_acls;
7108         bool valid_file_acls = True;
7109         bool valid_def_acls = True;
7110         NTSTATUS status;
7111
7112         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7113                 return NT_STATUS_INVALID_PARAMETER;
7114         }
7115         posix_acl_version = SVAL(pdata,0);
7116         num_file_acls = SVAL(pdata,2);
7117         num_def_acls = SVAL(pdata,4);
7118
7119         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7120                 valid_file_acls = False;
7121                 num_file_acls = 0;
7122         }
7123
7124         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7125                 valid_def_acls = False;
7126                 num_def_acls = 0;
7127         }
7128
7129         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7130                 return NT_STATUS_INVALID_PARAMETER;
7131         }
7132
7133         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7134                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7135                 return NT_STATUS_INVALID_PARAMETER;
7136         }
7137
7138         status = refuse_symlink(conn, fsp, smb_fname);
7139         if (!NT_STATUS_IS_OK(status)) {
7140                 return status;
7141         }
7142
7143         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7144                 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7145                 (unsigned int)num_file_acls,
7146                 (unsigned int)num_def_acls));
7147
7148         if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7149                 smb_fname, num_file_acls,
7150                 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7151                 return map_nt_error_from_unix(errno);
7152         }
7153
7154         if (valid_def_acls && !set_unix_posix_default_acl(conn,
7155                 smb_fname, num_def_acls,
7156                 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7157                 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7158                 return map_nt_error_from_unix(errno);
7159         }
7160         return NT_STATUS_OK;
7161 }
7162 #endif
7163
7164 /****************************************************************************
7165  Deal with SMB_SET_POSIX_LOCK.
7166 ****************************************************************************/
7167
7168 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7169                                 struct smb_request *req,
7170                                 const char *pdata,
7171                                 int total_data,
7172                                 files_struct *fsp)
7173 {
7174         uint64_t count;
7175         uint64_t offset;
7176         uint64_t smblctx;
7177         bool blocking_lock = False;
7178         enum brl_type lock_type;
7179
7180         NTSTATUS status = NT_STATUS_OK;
7181
7182         if (fsp == NULL || fsp->fh->fd == -1) {
7183                 return NT_STATUS_INVALID_HANDLE;
7184         }
7185
7186         if (total_data != POSIX_LOCK_DATA_SIZE) {
7187                 return NT_STATUS_INVALID_PARAMETER;
7188         }
7189
7190         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7191                 case POSIX_LOCK_TYPE_READ:
7192                         lock_type = READ_LOCK;
7193                         break;
7194                 case POSIX_LOCK_TYPE_WRITE:
7195                         /* Return the right POSIX-mappable error code for files opened read-only. */
7196                         if (!fsp->can_write) {
7197                                 return NT_STATUS_INVALID_HANDLE;
7198                         }
7199                         lock_type = WRITE_LOCK;
7200                         break;
7201                 case POSIX_LOCK_TYPE_UNLOCK:
7202                         lock_type = UNLOCK_LOCK;
7203                         break;
7204                 default:
7205                         return NT_STATUS_INVALID_PARAMETER;
7206         }
7207
7208         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7209                 blocking_lock = False;
7210         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7211                 blocking_lock = True;
7212         } else {
7213                 return NT_STATUS_INVALID_PARAMETER;
7214         }
7215
7216         if (!lp_blocking_locks(SNUM(conn))) { 
7217                 blocking_lock = False;
7218         }
7219
7220         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7221         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7222                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7223         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7224                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7225
7226         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7227                         "smblctx = %llu, count = %.0f, offset = %.0f\n",
7228                 fsp_str_dbg(fsp),
7229                 (unsigned int)lock_type,
7230                 (unsigned long long)smblctx,
7231                 (double)count,
7232                 (double)offset ));
7233
7234         if (lock_type == UNLOCK_LOCK) {
7235                 status = do_unlock(req->sconn->msg_ctx,
7236                                 fsp,
7237                                 smblctx,
7238                                 count,
7239                                 offset,
7240                                 POSIX_LOCK);
7241         } else {
7242                 uint64_t block_smblctx;
7243
7244                 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7245                                                         fsp,
7246                                                         smblctx,
7247                                                         count,
7248                                                         offset,
7249                                                         lock_type,
7250                                                         POSIX_LOCK,
7251                                                         blocking_lock,
7252                                                         &status,
7253                                                         &block_smblctx);
7254
7255                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7256                         /*
7257                          * A blocking lock was requested. Package up
7258                          * this smb into a queued request and push it
7259                          * onto the blocking lock queue.
7260                          */
7261                         if(push_blocking_lock_request(br_lck,
7262                                                 req,
7263                                                 fsp,
7264                                                 -1, /* infinite timeout. */
7265                                                 0,
7266                                                 smblctx,
7267                                                 lock_type,
7268                                                 POSIX_LOCK,
7269                                                 offset,
7270                                                 count,
7271                                                 block_smblctx)) {
7272                                 TALLOC_FREE(br_lck);
7273                                 return status;
7274                         }
7275                 }
7276                 TALLOC_FREE(br_lck);
7277         }
7278
7279         return status;
7280 }
7281
7282 /****************************************************************************
7283  Deal with SMB_SET_FILE_BASIC_INFO.
7284 ****************************************************************************/
7285
7286 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7287                                         const char *pdata,
7288                                         int total_data,
7289                                         files_struct *fsp,
7290                                         const struct smb_filename *smb_fname)
7291 {
7292         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7293         struct smb_file_time ft;
7294         uint32_t dosmode = 0;
7295         NTSTATUS status = NT_STATUS_OK;
7296
7297         ZERO_STRUCT(ft);
7298
7299         if (total_data < 36) {
7300                 return NT_STATUS_INVALID_PARAMETER;
7301         }
7302
7303         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7304         if (!NT_STATUS_IS_OK(status)) {
7305                 return status;
7306         }
7307
7308         /* Set the attributes */
7309         dosmode = IVAL(pdata,32);
7310         status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7311         if (!NT_STATUS_IS_OK(status)) {
7312                 return status;
7313         }
7314
7315         /* create time */
7316         ft.create_time = interpret_long_date(pdata);
7317
7318         /* access time */
7319         ft.atime = interpret_long_date(pdata+8);
7320
7321         /* write time. */
7322         ft.mtime = interpret_long_date(pdata+16);
7323
7324         /* change time. */
7325         ft.ctime = interpret_long_date(pdata+24);
7326
7327         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7328                    smb_fname_str_dbg(smb_fname)));
7329
7330         return smb_set_file_time(conn, fsp, smb_fname, &ft,
7331                                  true);
7332 }
7333
7334 /****************************************************************************
7335  Deal with SMB_INFO_STANDARD.
7336 ****************************************************************************/
7337
7338 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7339                                         const char *pdata,
7340                                         int total_data,
7341                                         files_struct *fsp,
7342                                         const struct smb_filename *smb_fname)
7343 {
7344         NTSTATUS status;
7345         struct smb_file_time ft;
7346
7347         ZERO_STRUCT(ft);
7348
7349         if (total_data < 12) {
7350                 return NT_STATUS_INVALID_PARAMETER;
7351         }
7352
7353         /* create time */
7354         ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7355         /* access time */
7356         ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7357         /* write time */
7358         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7359
7360         DEBUG(10,("smb_set_info_standard: file %s\n",
7361                 smb_fname_str_dbg(smb_fname)));
7362
7363         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7364         if (!NT_STATUS_IS_OK(status)) {
7365                 return status;
7366         }
7367
7368         return smb_set_file_time(conn,
7369                                 fsp,
7370                                 smb_fname,
7371                                 &ft,
7372                                 true);
7373 }
7374
7375 /****************************************************************************
7376  Deal with SMB_SET_FILE_ALLOCATION_INFO.
7377 ****************************************************************************/
7378
7379 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7380                                              struct smb_request *req,
7381                                         const char *pdata,
7382                                         int total_data,
7383                                         files_struct *fsp,
7384                                         struct smb_filename *smb_fname)
7385 {
7386         uint64_t allocation_size = 0;
7387         NTSTATUS status = NT_STATUS_OK;
7388         files_struct *new_fsp = NULL;
7389
7390         if (!VALID_STAT(smb_fname->st)) {
7391                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7392         }
7393
7394         if (total_data < 8) {
7395                 return NT_STATUS_INVALID_PARAMETER;
7396         }
7397
7398         allocation_size = (uint64_t)IVAL(pdata,0);
7399         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7400         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7401                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7402                   (double)allocation_size));
7403
7404         if (allocation_size) {
7405                 allocation_size = smb_roundup(conn, allocation_size);
7406         }
7407
7408         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7409                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7410                   (double)allocation_size));
7411
7412         if (fsp && fsp->fh->fd != -1) {
7413                 /* Open file handle. */
7414                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7415                         return NT_STATUS_ACCESS_DENIED;
7416                 }
7417
7418                 /* Only change if needed. */
7419                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7420                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7421                                 return map_nt_error_from_unix(errno);
7422                         }
7423                 }
7424                 /* But always update the time. */
7425                 /*
7426                  * This is equivalent to a write. Ensure it's seen immediately
7427                  * if there are no pending writes.
7428                  */
7429                 trigger_write_time_update_immediate(fsp);
7430                 return NT_STATUS_OK;
7431         }
7432
7433         /* Pathname or stat or directory file. */
7434         status = SMB_VFS_CREATE_FILE(
7435                 conn,                                   /* conn */
7436                 req,                                    /* req */
7437                 0,                                      /* root_dir_fid */
7438                 smb_fname,                              /* fname */
7439                 FILE_WRITE_DATA,                        /* access_mask */
7440                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7441                     FILE_SHARE_DELETE),
7442                 FILE_OPEN,                              /* create_disposition*/
7443                 0,                                      /* create_options */
7444                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7445                 0,                                      /* oplock_request */
7446                 NULL,                                   /* lease */
7447                 0,                                      /* allocation_size */
7448                 0,                                      /* private_flags */
7449                 NULL,                                   /* sd */
7450                 NULL,                                   /* ea_list */
7451                 &new_fsp,                               /* result */
7452                 NULL,                                   /* pinfo */
7453                 NULL, NULL);                            /* create context */
7454
7455         if (!NT_STATUS_IS_OK(status)) {
7456                 /* NB. We check for open_was_deferred in the caller. */
7457                 return status;
7458         }
7459
7460         /* Only change if needed. */
7461         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7462                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7463                         status = map_nt_error_from_unix(errno);
7464                         close_file(req, new_fsp, NORMAL_CLOSE);
7465                         return status;
7466                 }
7467         }
7468
7469         /* Changing the allocation size should set the last mod time. */
7470         /*
7471          * This is equivalent to a write. Ensure it's seen immediately
7472          * if there are no pending writes.
7473          */
7474         trigger_write_time_update_immediate(new_fsp);
7475         close_file(req, new_fsp, NORMAL_CLOSE);
7476         return NT_STATUS_OK;
7477 }
7478
7479 /****************************************************************************
7480  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7481 ****************************************************************************/
7482
7483 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7484                                               struct smb_request *req,
7485                                         const char *pdata,
7486                                         int total_data,
7487                                         files_struct *fsp,
7488                                         const struct smb_filename *smb_fname,
7489                                         bool fail_after_createfile)
7490 {
7491         off_t size;
7492
7493         if (total_data < 8) {
7494                 return NT_STATUS_INVALID_PARAMETER;
7495         }
7496
7497         size = IVAL(pdata,0);
7498         size |= (((off_t)IVAL(pdata,4)) << 32);
7499         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7500                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7501                   (double)size));
7502
7503         return smb_set_file_size(conn, req,
7504                                 fsp,
7505                                 smb_fname,
7506                                 &smb_fname->st,
7507                                 size,
7508                                 fail_after_createfile);
7509 }
7510
7511 /****************************************************************************
7512  Allow a UNIX info mknod.
7513 ****************************************************************************/
7514
7515 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7516                                         const char *pdata,
7517                                         int total_data,
7518                                         const struct smb_filename *smb_fname)
7519 {
7520         uint32_t file_type = IVAL(pdata,56);
7521 #if defined(HAVE_MAKEDEV)
7522         uint32_t dev_major = IVAL(pdata,60);
7523         uint32_t dev_minor = IVAL(pdata,68);
7524 #endif
7525         SMB_DEV_T dev = (SMB_DEV_T)0;
7526         uint32_t raw_unixmode = IVAL(pdata,84);
7527         NTSTATUS status;
7528         mode_t unixmode;
7529
7530         if (total_data < 100) {
7531                 return NT_STATUS_INVALID_PARAMETER;
7532         }
7533
7534         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7535                                       PERM_NEW_FILE, &unixmode);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 return status;
7538         }
7539
7540 #if defined(HAVE_MAKEDEV)
7541         dev = makedev(dev_major, dev_minor);
7542 #endif
7543
7544         switch (file_type) {
7545 #if defined(S_IFIFO)
7546                 case UNIX_TYPE_FIFO:
7547                         unixmode |= S_IFIFO;
7548                         break;
7549 #endif
7550 #if defined(S_IFSOCK)
7551                 case UNIX_TYPE_SOCKET:
7552                         unixmode |= S_IFSOCK;
7553                         break;
7554 #endif
7555 #if defined(S_IFCHR)
7556                 case UNIX_TYPE_CHARDEV:
7557                         unixmode |= S_IFCHR;
7558                         break;
7559 #endif
7560 #if defined(S_IFBLK)
7561                 case UNIX_TYPE_BLKDEV:
7562                         unixmode |= S_IFBLK;
7563                         break;
7564 #endif
7565                 default:
7566                         return NT_STATUS_INVALID_PARAMETER;
7567         }
7568
7569         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7570                   "%.0f mode 0%o for file %s\n", (double)dev,
7571                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7572
7573         /* Ok - do the mknod. */
7574         if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7575                 return map_nt_error_from_unix(errno);
7576         }
7577
7578         /* If any of the other "set" calls fail we
7579          * don't want to end up with a half-constructed mknod.
7580          */
7581
7582         if (lp_inherit_permissions(SNUM(conn))) {
7583                 char *parent;
7584                 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7585                                     &parent, NULL)) {
7586                         return NT_STATUS_NO_MEMORY;
7587                 }
7588                 inherit_access_posix_acl(conn, parent, smb_fname,
7589                                          unixmode);
7590                 TALLOC_FREE(parent);
7591         }
7592
7593         return NT_STATUS_OK;
7594 }
7595
7596 /****************************************************************************
7597  Deal with SMB_SET_FILE_UNIX_BASIC.
7598 ****************************************************************************/
7599
7600 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7601                                         struct smb_request *req,
7602                                         const char *pdata,
7603                                         int total_data,
7604                                         files_struct *fsp,
7605                                         const struct smb_filename *smb_fname)
7606 {
7607         struct smb_file_time ft;
7608         uint32_t raw_unixmode;
7609         mode_t unixmode;
7610         off_t size = 0;
7611         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7612         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7613         NTSTATUS status = NT_STATUS_OK;
7614         bool delete_on_fail = False;
7615         enum perm_type ptype;
7616         files_struct *all_fsps = NULL;
7617         bool modify_mtime = true;
7618         struct file_id id;
7619         struct smb_filename *smb_fname_tmp = NULL;
7620         SMB_STRUCT_STAT sbuf;
7621
7622         ZERO_STRUCT(ft);
7623
7624         if (total_data < 100) {
7625                 return NT_STATUS_INVALID_PARAMETER;
7626         }
7627
7628         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7629            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7630                 size=IVAL(pdata,0); /* first 8 Bytes are size */
7631                 size |= (((off_t)IVAL(pdata,4)) << 32);
7632         }
7633
7634         ft.atime = interpret_long_date(pdata+24); /* access_time */
7635         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7636         set_owner = (uid_t)IVAL(pdata,40);
7637         set_grp = (gid_t)IVAL(pdata,48);
7638         raw_unixmode = IVAL(pdata,84);
7639
7640         if (VALID_STAT(smb_fname->st)) {
7641                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7642                         ptype = PERM_EXISTING_DIR;
7643                 } else {
7644                         ptype = PERM_EXISTING_FILE;
7645                 }
7646         } else {
7647                 ptype = PERM_NEW_FILE;
7648         }
7649
7650         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7651                                       ptype, &unixmode);
7652         if (!NT_STATUS_IS_OK(status)) {
7653                 return status;
7654         }
7655
7656         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7657                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7658                   smb_fname_str_dbg(smb_fname), (double)size,
7659                   (unsigned int)set_owner, (unsigned int)set_grp,
7660                   (int)raw_unixmode));
7661
7662         sbuf = smb_fname->st;
7663
7664         if (!VALID_STAT(sbuf)) {
7665                 /*
7666                  * The only valid use of this is to create character and block
7667                  * devices, and named pipes. This is deprecated (IMHO) and 
7668                  * a new info level should be used for mknod. JRA.
7669                  */
7670
7671                 status = smb_unix_mknod(conn,
7672                                         pdata,
7673                                         total_data,
7674                                         smb_fname);
7675                 if (!NT_STATUS_IS_OK(status)) {
7676                         return status;
7677                 }
7678
7679                 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7680                 if (smb_fname_tmp == NULL) {
7681                         return NT_STATUS_NO_MEMORY;
7682                 }
7683
7684                 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7685                         status = map_nt_error_from_unix(errno);
7686                         TALLOC_FREE(smb_fname_tmp);
7687                         SMB_VFS_UNLINK(conn, smb_fname);
7688                         return status;
7689                 }
7690
7691                 sbuf = smb_fname_tmp->st;
7692                 smb_fname = smb_fname_tmp;
7693
7694                 /* Ensure we don't try and change anything else. */
7695                 raw_unixmode = SMB_MODE_NO_CHANGE;
7696                 size = get_file_size_stat(&sbuf);
7697                 ft.atime = sbuf.st_ex_atime;
7698                 ft.mtime = sbuf.st_ex_mtime;
7699                 /* 
7700                  * We continue here as we might want to change the 
7701                  * owner uid/gid.
7702                  */
7703                 delete_on_fail = True;
7704         }
7705
7706 #if 1
7707         /* Horrible backwards compatibility hack as an old server bug
7708          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7709          * */
7710
7711         if (!size) {
7712                 size = get_file_size_stat(&sbuf);
7713         }
7714 #endif
7715
7716         /*
7717          * Deal with the UNIX specific mode set.
7718          */
7719
7720         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7721                 int ret;
7722
7723                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7724                           "setting mode 0%o for file %s\n",
7725                           (unsigned int)unixmode,
7726                           smb_fname_str_dbg(smb_fname)));
7727                 if (fsp && fsp->fh->fd != -1) {
7728                         ret = SMB_VFS_FCHMOD(fsp, unixmode);
7729                 } else {
7730                         ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7731                 }
7732                 if (ret != 0) {
7733                         return map_nt_error_from_unix(errno);
7734                 }
7735         }
7736
7737         /*
7738          * Deal with the UNIX specific uid set.
7739          */
7740
7741         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7742             (sbuf.st_ex_uid != set_owner)) {
7743                 int ret;
7744
7745                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7746                           "changing owner %u for path %s\n",
7747                           (unsigned int)set_owner,
7748                           smb_fname_str_dbg(smb_fname)));
7749
7750                 if (fsp && fsp->fh->fd != -1) {
7751                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7752                 } else {
7753                         /*
7754                          * UNIX extensions calls must always operate
7755                          * on symlinks.
7756                          */
7757                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
7758                                              set_owner, (gid_t)-1);
7759                 }
7760
7761                 if (ret != 0) {
7762                         status = map_nt_error_from_unix(errno);
7763                         if (delete_on_fail) {
7764                                 SMB_VFS_UNLINK(conn, smb_fname);
7765                         }
7766                         return status;
7767                 }
7768         }
7769
7770         /*
7771          * Deal with the UNIX specific gid set.
7772          */
7773
7774         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7775             (sbuf.st_ex_gid != set_grp)) {
7776                 int ret;
7777
7778                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7779                           "changing group %u for file %s\n",
7780                           (unsigned int)set_owner,
7781                           smb_fname_str_dbg(smb_fname)));
7782                 if (fsp && fsp->fh->fd != -1) {
7783                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7784                 } else {
7785                         /*
7786                          * UNIX extensions calls must always operate
7787                          * on symlinks.
7788                          */
7789                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7790                                   set_grp);
7791                 }
7792                 if (ret != 0) {
7793                         status = map_nt_error_from_unix(errno);
7794                         if (delete_on_fail) {
7795                                 SMB_VFS_UNLINK(conn, smb_fname);
7796                         }
7797                         return status;
7798                 }
7799         }
7800
7801         /* Deal with any size changes. */
7802
7803         status = smb_set_file_size(conn, req,
7804                                    fsp,
7805                                    smb_fname,
7806                                    &sbuf,
7807                                    size,
7808                                    false);
7809         if (!NT_STATUS_IS_OK(status)) {
7810                 return status;
7811         }
7812
7813         /* Deal with any time changes. */
7814         if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7815                 /* No change, don't cancel anything. */
7816                 return status;
7817         }
7818
7819         id = vfs_file_id_from_sbuf(conn, &sbuf);
7820         for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7821                         all_fsps = file_find_di_next(all_fsps)) {
7822                 /*
7823                  * We're setting the time explicitly for UNIX.
7824                  * Cancel any pending changes over all handles.
7825                  */
7826                 all_fsps->update_write_time_on_close = false;
7827                 TALLOC_FREE(all_fsps->update_write_time_event);
7828         }
7829
7830         /*
7831          * Override the "setting_write_time"
7832          * parameter here as it almost does what
7833          * we need. Just remember if we modified
7834          * mtime and send the notify ourselves.
7835          */
7836         if (null_timespec(ft.mtime)) {
7837                 modify_mtime = false;
7838         }
7839
7840         status = smb_set_file_time(conn,
7841                                 fsp,
7842                                 smb_fname,
7843                                 &ft,
7844                                 false);
7845         if (modify_mtime) {
7846                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7847                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7848         }
7849         return status;
7850 }
7851
7852 /****************************************************************************
7853  Deal with SMB_SET_FILE_UNIX_INFO2.
7854 ****************************************************************************/
7855
7856 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7857                                         struct smb_request *req,
7858                                         const char *pdata,
7859                                         int total_data,
7860                                         files_struct *fsp,
7861                                         const struct smb_filename *smb_fname)
7862 {
7863         NTSTATUS status;
7864         uint32_t smb_fflags;
7865         uint32_t smb_fmask;
7866
7867         if (total_data < 116) {
7868                 return NT_STATUS_INVALID_PARAMETER;
7869         }
7870
7871         /* Start by setting all the fields that are common between UNIX_BASIC
7872          * and UNIX_INFO2.
7873          */
7874         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7875                                          fsp, smb_fname);
7876         if (!NT_STATUS_IS_OK(status)) {
7877                 return status;
7878         }
7879
7880         smb_fflags = IVAL(pdata, 108);
7881         smb_fmask = IVAL(pdata, 112);
7882
7883         /* NB: We should only attempt to alter the file flags if the client
7884          * sends a non-zero mask.
7885          */
7886         if (smb_fmask != 0) {
7887                 int stat_fflags = 0;
7888
7889                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7890                                              smb_fmask, &stat_fflags)) {
7891                         /* Client asked to alter a flag we don't understand. */
7892                         return NT_STATUS_INVALID_PARAMETER;
7893                 }
7894
7895                 if (fsp && fsp->fh->fd != -1) {
7896                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
7897                         return NT_STATUS_NOT_SUPPORTED;
7898                 } else {
7899                         if (SMB_VFS_CHFLAGS(conn, smb_fname,
7900                                             stat_fflags) != 0) {
7901                                 return map_nt_error_from_unix(errno);
7902                         }
7903                 }
7904         }
7905
7906         /* XXX: need to add support for changing the create_time here. You
7907          * can do this for paths on Darwin with setattrlist(2). The right way
7908          * to hook this up is probably by extending the VFS utimes interface.
7909          */
7910
7911         return NT_STATUS_OK;
7912 }
7913
7914 /****************************************************************************
7915  Create a directory with POSIX semantics.
7916 ****************************************************************************/
7917
7918 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7919                                 struct smb_request *req,
7920                                 char **ppdata,
7921                                 int total_data,
7922                                 struct smb_filename *smb_fname,
7923                                 int *pdata_return_size)
7924 {
7925         NTSTATUS status = NT_STATUS_OK;
7926         uint32_t raw_unixmode = 0;
7927         uint32_t mod_unixmode = 0;
7928         mode_t unixmode = (mode_t)0;
7929         files_struct *fsp = NULL;
7930         uint16_t info_level_return = 0;
7931         int info;
7932         char *pdata = *ppdata;
7933
7934         if (total_data < 18) {
7935                 return NT_STATUS_INVALID_PARAMETER;
7936         }
7937
7938         raw_unixmode = IVAL(pdata,8);
7939         /* Next 4 bytes are not yet defined. */
7940
7941         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7942                                       PERM_NEW_DIR, &unixmode);
7943         if (!NT_STATUS_IS_OK(status)) {
7944                 return status;
7945         }
7946
7947         mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7948
7949         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7950                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7951
7952         status = SMB_VFS_CREATE_FILE(
7953                 conn,                                   /* conn */
7954                 req,                                    /* req */
7955                 0,                                      /* root_dir_fid */
7956                 smb_fname,                              /* fname */
7957                 FILE_READ_ATTRIBUTES,                   /* access_mask */
7958                 FILE_SHARE_NONE,                        /* share_access */
7959                 FILE_CREATE,                            /* create_disposition*/
7960                 FILE_DIRECTORY_FILE,                    /* create_options */
7961                 mod_unixmode,                           /* file_attributes */
7962                 0,                                      /* oplock_request */
7963                 NULL,                                   /* lease */
7964                 0,                                      /* allocation_size */
7965                 0,                                      /* private_flags */
7966                 NULL,                                   /* sd */
7967                 NULL,                                   /* ea_list */
7968                 &fsp,                                   /* result */
7969                 &info,                                  /* pinfo */
7970                 NULL, NULL);                            /* create context */
7971
7972         if (NT_STATUS_IS_OK(status)) {
7973                 close_file(req, fsp, NORMAL_CLOSE);
7974         }
7975
7976         info_level_return = SVAL(pdata,16);
7977  
7978         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7979                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7980         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7981                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7982         } else {
7983                 *pdata_return_size = 12;
7984         }
7985
7986         /* Realloc the data size */
7987         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7988         if (*ppdata == NULL) {
7989                 *pdata_return_size = 0;
7990                 return NT_STATUS_NO_MEMORY;
7991         }
7992         pdata = *ppdata;
7993
7994         SSVAL(pdata,0,NO_OPLOCK_RETURN);
7995         SSVAL(pdata,2,0); /* No fnum. */
7996         SIVAL(pdata,4,info); /* Was directory created. */
7997
7998         switch (info_level_return) {
7999                 case SMB_QUERY_FILE_UNIX_BASIC:
8000                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8001                         SSVAL(pdata,10,0); /* Padding. */
8002                         store_file_unix_basic(conn, pdata + 12, fsp,
8003                                               &smb_fname->st);
8004                         break;
8005                 case SMB_QUERY_FILE_UNIX_INFO2:
8006                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8007                         SSVAL(pdata,10,0); /* Padding. */
8008                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
8009                                                     &smb_fname->st);
8010                         break;
8011                 default:
8012                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8013                         SSVAL(pdata,10,0); /* Padding. */
8014                         break;
8015         }
8016
8017         return status;
8018 }
8019
8020 /****************************************************************************
8021  Open/Create a file with POSIX semantics.
8022 ****************************************************************************/
8023
8024 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8025 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8026
8027 static NTSTATUS smb_posix_open(connection_struct *conn,
8028                                struct smb_request *req,
8029                                 char **ppdata,
8030                                 int total_data,
8031                                 struct smb_filename *smb_fname,
8032                                 int *pdata_return_size)
8033 {
8034         bool extended_oplock_granted = False;
8035         char *pdata = *ppdata;
8036         uint32_t flags = 0;
8037         uint32_t wire_open_mode = 0;
8038         uint32_t raw_unixmode = 0;
8039         uint32_t mod_unixmode = 0;
8040         uint32_t create_disp = 0;
8041         uint32_t access_mask = 0;
8042         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8043         NTSTATUS status = NT_STATUS_OK;
8044         mode_t unixmode = (mode_t)0;
8045         files_struct *fsp = NULL;
8046         int oplock_request = 0;
8047         int info = 0;
8048         uint16_t info_level_return = 0;
8049
8050         if (total_data < 18) {
8051                 return NT_STATUS_INVALID_PARAMETER;
8052         }
8053
8054         flags = IVAL(pdata,0);
8055         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8056         if (oplock_request) {
8057                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8058         }
8059
8060         wire_open_mode = IVAL(pdata,4);
8061
8062         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8063                 return smb_posix_mkdir(conn, req,
8064                                         ppdata,
8065                                         total_data,
8066                                         smb_fname,
8067                                         pdata_return_size);
8068         }
8069
8070         switch (wire_open_mode & SMB_ACCMODE) {
8071                 case SMB_O_RDONLY:
8072                         access_mask = SMB_O_RDONLY_MAPPING;
8073                         break;
8074                 case SMB_O_WRONLY:
8075                         access_mask = SMB_O_WRONLY_MAPPING;
8076                         break;
8077                 case SMB_O_RDWR:
8078                         access_mask = (SMB_O_RDONLY_MAPPING|
8079                                         SMB_O_WRONLY_MAPPING);
8080                         break;
8081                 default:
8082                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8083                                 (unsigned int)wire_open_mode ));
8084                         return NT_STATUS_INVALID_PARAMETER;
8085         }
8086
8087         wire_open_mode &= ~SMB_ACCMODE;
8088
8089         /* First take care of O_CREAT|O_EXCL interactions. */
8090         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8091                 case (SMB_O_CREAT | SMB_O_EXCL):
8092                         /* File exists fail. File not exist create. */
8093                         create_disp = FILE_CREATE;
8094                         break;
8095                 case SMB_O_CREAT:
8096                         /* File exists open. File not exist create. */
8097                         create_disp = FILE_OPEN_IF;
8098                         break;
8099                 case SMB_O_EXCL:
8100                         /* O_EXCL on its own without O_CREAT is undefined.
8101                            We deliberately ignore it as some versions of
8102                            Linux CIFSFS can send a bare O_EXCL on the
8103                            wire which other filesystems in the kernel
8104                            ignore. See bug 9519 for details. */
8105
8106                         /* Fallthrough. */
8107
8108                 case 0:
8109                         /* File exists open. File not exist fail. */
8110                         create_disp = FILE_OPEN;
8111                         break;
8112                 default:
8113                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8114                                 (unsigned int)wire_open_mode ));
8115                         return NT_STATUS_INVALID_PARAMETER;
8116         }
8117
8118         /* Next factor in the effects of O_TRUNC. */
8119         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8120
8121         if (wire_open_mode & SMB_O_TRUNC) {
8122                 switch (create_disp) {
8123                         case FILE_CREATE:
8124                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8125                                 /* Leave create_disp alone as
8126                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8127                                 */
8128                                 /* File exists fail. File not exist create. */
8129                                 break;
8130                         case FILE_OPEN_IF:
8131                                 /* SMB_O_CREAT | SMB_O_TRUNC */
8132                                 /* File exists overwrite. File not exist create. */
8133                                 create_disp = FILE_OVERWRITE_IF;
8134                                 break;
8135                         case FILE_OPEN:
8136                                 /* SMB_O_TRUNC */
8137                                 /* File exists overwrite. File not exist fail. */
8138                                 create_disp = FILE_OVERWRITE;
8139                                 break;
8140                         default:
8141                                 /* Cannot get here. */
8142                                 smb_panic("smb_posix_open: logic error");
8143                                 return NT_STATUS_INVALID_PARAMETER;
8144                 }
8145         }
8146
8147         raw_unixmode = IVAL(pdata,8);
8148         /* Next 4 bytes are not yet defined. */
8149
8150         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8151                                       (VALID_STAT(smb_fname->st) ?
8152                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
8153                                       &unixmode);
8154
8155         if (!NT_STATUS_IS_OK(status)) {
8156                 return status;
8157         }
8158
8159         mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8160
8161         if (wire_open_mode & SMB_O_SYNC) {
8162                 create_options |= FILE_WRITE_THROUGH;
8163         }
8164         if (wire_open_mode & SMB_O_APPEND) {
8165                 access_mask |= FILE_APPEND_DATA;
8166         }
8167         if (wire_open_mode & SMB_O_DIRECT) {
8168                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8169         }
8170
8171         if ((wire_open_mode & SMB_O_DIRECTORY) ||
8172                         VALID_STAT_OF_DIR(smb_fname->st)) {
8173                 if (access_mask != SMB_O_RDONLY_MAPPING) {
8174                         return NT_STATUS_FILE_IS_A_DIRECTORY;
8175                 }
8176                 create_options &= ~FILE_NON_DIRECTORY_FILE;
8177                 create_options |= FILE_DIRECTORY_FILE;
8178         }
8179
8180         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8181                 smb_fname_str_dbg(smb_fname),
8182                 (unsigned int)wire_open_mode,
8183                 (unsigned int)unixmode ));
8184
8185         status = SMB_VFS_CREATE_FILE(
8186                 conn,                                   /* conn */
8187                 req,                                    /* req */
8188                 0,                                      /* root_dir_fid */
8189                 smb_fname,                              /* fname */
8190                 access_mask,                            /* access_mask */
8191                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
8192                     FILE_SHARE_DELETE),
8193                 create_disp,                            /* create_disposition*/
8194                 create_options,                         /* create_options */
8195                 mod_unixmode,                           /* file_attributes */
8196                 oplock_request,                         /* oplock_request */
8197                 NULL,                                   /* lease */
8198                 0,                                      /* allocation_size */
8199                 0,                                      /* private_flags */
8200                 NULL,                                   /* sd */
8201                 NULL,                                   /* ea_list */
8202                 &fsp,                                   /* result */
8203                 &info,                                  /* pinfo */
8204                 NULL, NULL);                            /* create context */
8205
8206         if (!NT_STATUS_IS_OK(status)) {
8207                 return status;
8208         }
8209
8210         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8211                 extended_oplock_granted = True;
8212         }
8213
8214         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8215                 extended_oplock_granted = True;
8216         }
8217
8218         info_level_return = SVAL(pdata,16);
8219  
8220         /* Allocate the correct return size. */
8221
8222         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8223                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8224         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
8225                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8226         } else {
8227                 *pdata_return_size = 12;
8228         }
8229
8230         /* Realloc the data size */
8231         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8232         if (*ppdata == NULL) {
8233                 close_file(req, fsp, ERROR_CLOSE);
8234                 *pdata_return_size = 0;
8235                 return NT_STATUS_NO_MEMORY;
8236         }
8237         pdata = *ppdata;
8238
8239         if (extended_oplock_granted) {
8240                 if (flags & REQUEST_BATCH_OPLOCK) {
8241                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8242                 } else {
8243                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8244                 }
8245         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8246                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8247         } else {
8248                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8249         }
8250
8251         SSVAL(pdata,2,fsp->fnum);
8252         SIVAL(pdata,4,info); /* Was file created etc. */
8253
8254         switch (info_level_return) {
8255                 case SMB_QUERY_FILE_UNIX_BASIC:
8256                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8257                         SSVAL(pdata,10,0); /* padding. */
8258                         store_file_unix_basic(conn, pdata + 12, fsp,
8259                                               &smb_fname->st);
8260                         break;
8261                 case SMB_QUERY_FILE_UNIX_INFO2:
8262                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8263                         SSVAL(pdata,10,0); /* padding. */
8264                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
8265                                                     &smb_fname->st);
8266                         break;
8267                 default:
8268                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8269                         SSVAL(pdata,10,0); /* padding. */
8270                         break;
8271         }
8272         return NT_STATUS_OK;
8273 }
8274
8275 /****************************************************************************
8276  Delete a file with POSIX semantics.
8277 ****************************************************************************/
8278
8279 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8280                                  struct smb_request *req,
8281                                 const char *pdata,
8282                                 int total_data,
8283                                 struct smb_filename *smb_fname)
8284 {
8285         NTSTATUS status = NT_STATUS_OK;
8286         files_struct *fsp = NULL;
8287         uint16_t flags = 0;
8288         char del = 1;
8289         int info = 0;
8290         int create_options = 0;
8291         int i;
8292         struct share_mode_lock *lck = NULL;
8293
8294         if (total_data < 2) {
8295                 return NT_STATUS_INVALID_PARAMETER;
8296         }
8297
8298         flags = SVAL(pdata,0);
8299
8300         if (!VALID_STAT(smb_fname->st)) {
8301                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8302         }
8303
8304         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8305                         !VALID_STAT_OF_DIR(smb_fname->st)) {
8306                 return NT_STATUS_NOT_A_DIRECTORY;
8307         }
8308
8309         DEBUG(10,("smb_posix_unlink: %s %s\n",
8310                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8311                 smb_fname_str_dbg(smb_fname)));
8312
8313         if (VALID_STAT_OF_DIR(smb_fname->st)) {
8314                 create_options |= FILE_DIRECTORY_FILE;
8315         }
8316
8317         status = SMB_VFS_CREATE_FILE(
8318                 conn,                                   /* conn */
8319                 req,                                    /* req */
8320                 0,                                      /* root_dir_fid */
8321                 smb_fname,                              /* fname */
8322                 DELETE_ACCESS,                          /* access_mask */
8323                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
8324                     FILE_SHARE_DELETE),
8325                 FILE_OPEN,                              /* create_disposition*/
8326                 create_options,                         /* create_options */
8327                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
8328                 0,                                      /* oplock_request */
8329                 NULL,                                   /* lease */
8330                 0,                                      /* allocation_size */
8331                 0,                                      /* private_flags */
8332                 NULL,                                   /* sd */
8333                 NULL,                                   /* ea_list */
8334                 &fsp,                                   /* result */
8335                 &info,                                  /* pinfo */
8336                 NULL, NULL);                            /* create context */
8337
8338         if (!NT_STATUS_IS_OK(status)) {
8339                 return status;
8340         }
8341
8342         /*
8343          * Don't lie to client. If we can't really delete due to
8344          * non-POSIX opens return SHARING_VIOLATION.
8345          */
8346
8347         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8348         if (lck == NULL) {
8349                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8350                           "lock for file %s\n", fsp_str_dbg(fsp)));
8351                 close_file(req, fsp, NORMAL_CLOSE);
8352                 return NT_STATUS_INVALID_PARAMETER;
8353         }
8354
8355         /*
8356          * See if others still have the file open. If this is the case, then
8357          * don't delete. If all opens are POSIX delete we can set the delete
8358          * on close disposition.
8359          */
8360         for (i=0; i<lck->data->num_share_modes; i++) {
8361                 struct share_mode_entry *e = &lck->data->share_modes[i];
8362                 if (is_valid_share_mode_entry(e)) {
8363                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8364                                 continue;
8365                         }
8366                         if (share_mode_stale_pid(lck->data, i)) {
8367                                 continue;
8368                         }
8369                         /* Fail with sharing violation. */
8370                         TALLOC_FREE(lck);
8371                         close_file(req, fsp, NORMAL_CLOSE);
8372                         return NT_STATUS_SHARING_VIOLATION;
8373                 }
8374         }
8375
8376         /*
8377          * Set the delete on close.
8378          */
8379         status = smb_set_file_disposition_info(conn,
8380                                                 &del,
8381                                                 1,
8382                                                 fsp,
8383                                                 smb_fname);
8384
8385         TALLOC_FREE(lck);
8386
8387         if (!NT_STATUS_IS_OK(status)) {
8388                 close_file(req, fsp, NORMAL_CLOSE);
8389                 return status;
8390         }
8391         return close_file(req, fsp, NORMAL_CLOSE);
8392 }
8393
8394 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8395                                 struct smb_request *req,
8396                                 TALLOC_CTX *mem_ctx,
8397                                 uint16_t info_level,
8398                                 files_struct *fsp,
8399                                 struct smb_filename *smb_fname,
8400                                 char **ppdata, int total_data,
8401                                 int *ret_data_size)
8402 {
8403         char *pdata = *ppdata;
8404         NTSTATUS status = NT_STATUS_OK;
8405         int data_return_size = 0;
8406
8407         *ret_data_size = 0;
8408
8409         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8410                 return NT_STATUS_INVALID_LEVEL;
8411         }
8412
8413         if (!CAN_WRITE(conn)) {
8414                 /* Allow POSIX opens. The open path will deny
8415                  * any non-readonly opens. */
8416                 if (info_level != SMB_POSIX_PATH_OPEN) {
8417                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
8418                 }
8419         }
8420
8421         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8422                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8423                  fsp_fnum_dbg(fsp),
8424                  info_level, total_data));
8425
8426         switch (info_level) {
8427
8428                 case SMB_INFO_STANDARD:
8429                 {
8430                         status = smb_set_info_standard(conn,
8431                                         pdata,
8432                                         total_data,
8433                                         fsp,
8434                                         smb_fname);
8435                         break;
8436                 }
8437
8438                 case SMB_INFO_SET_EA:
8439                 {
8440                         status = smb_info_set_ea(conn,
8441                                                 pdata,
8442                                                 total_data,
8443                                                 fsp,
8444                                                 smb_fname);
8445                         break;
8446                 }
8447
8448                 case SMB_SET_FILE_BASIC_INFO:
8449                 case SMB_FILE_BASIC_INFORMATION:
8450                 {
8451                         status = smb_set_file_basic_info(conn,
8452                                                         pdata,
8453                                                         total_data,
8454                                                         fsp,
8455                                                         smb_fname);
8456                         break;
8457                 }
8458
8459                 case SMB_FILE_ALLOCATION_INFORMATION:
8460                 case SMB_SET_FILE_ALLOCATION_INFO:
8461                 {
8462                         status = smb_set_file_allocation_info(conn, req,
8463                                                                 pdata,
8464                                                                 total_data,
8465                                                                 fsp,
8466                                                                 smb_fname);
8467                         break;
8468                 }
8469
8470                 case SMB_FILE_END_OF_FILE_INFORMATION:
8471                 case SMB_SET_FILE_END_OF_FILE_INFO:
8472                 {
8473                         /*
8474                          * XP/Win7 both fail after the createfile with
8475                          * SMB_SET_FILE_END_OF_FILE_INFO but not
8476                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8477                          * The level is known here, so pass it down
8478                          * appropriately.
8479                          */
8480                         bool should_fail =
8481                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8482
8483                         status = smb_set_file_end_of_file_info(conn, req,
8484                                                                 pdata,
8485                                                                 total_data,
8486                                                                 fsp,
8487                                                                 smb_fname,
8488                                                                 should_fail);
8489                         break;
8490                 }
8491
8492                 case SMB_FILE_DISPOSITION_INFORMATION:
8493                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8494                 {
8495 #if 0
8496                         /* JRA - We used to just ignore this on a path ? 
8497                          * Shouldn't this be invalid level on a pathname
8498                          * based call ?
8499                          */
8500                         if (tran_call != TRANSACT2_SETFILEINFO) {
8501                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8502                         }
8503 #endif
8504                         status = smb_set_file_disposition_info(conn,
8505                                                 pdata,
8506                                                 total_data,
8507                                                 fsp,
8508                                                 smb_fname);
8509                         break;
8510                 }
8511
8512                 case SMB_FILE_POSITION_INFORMATION:
8513                 {
8514                         status = smb_file_position_information(conn,
8515                                                 pdata,
8516                                                 total_data,
8517                                                 fsp);
8518                         break;
8519                 }
8520
8521                 case SMB_FILE_FULL_EA_INFORMATION:
8522                 {
8523                         status = smb_set_file_full_ea_info(conn,
8524                                                 pdata,
8525                                                 total_data,
8526                                                 fsp);
8527                         break;
8528                 }
8529
8530                 /* From tridge Samba4 : 
8531                  * MODE_INFORMATION in setfileinfo (I have no
8532                  * idea what "mode information" on a file is - it takes a value of 0,
8533                  * 2, 4 or 6. What could it be?).
8534                  */
8535
8536                 case SMB_FILE_MODE_INFORMATION:
8537                 {
8538                         status = smb_file_mode_information(conn,
8539                                                 pdata,
8540                                                 total_data);
8541                         break;
8542                 }
8543
8544                 /*
8545                  * CIFS UNIX extensions.
8546                  */
8547
8548                 case SMB_SET_FILE_UNIX_BASIC:
8549                 {
8550                         status = smb_set_file_unix_basic(conn, req,
8551                                                         pdata,
8552                                                         total_data,
8553                                                         fsp,
8554                                                         smb_fname);
8555                         break;
8556                 }
8557
8558                 case SMB_SET_FILE_UNIX_INFO2:
8559                 {
8560                         status = smb_set_file_unix_info2(conn, req,
8561                                                         pdata,
8562                                                         total_data,
8563                                                         fsp,
8564                                                         smb_fname);
8565                         break;
8566                 }
8567
8568                 case SMB_SET_FILE_UNIX_LINK:
8569                 {
8570                         if (fsp) {
8571                                 /* We must have a pathname for this. */
8572                                 return NT_STATUS_INVALID_LEVEL;
8573                         }
8574                         status = smb_set_file_unix_link(conn, req, pdata,
8575                                                         total_data, smb_fname);
8576                         break;
8577                 }
8578
8579                 case SMB_SET_FILE_UNIX_HLINK:
8580                 {
8581                         if (fsp) {
8582                                 /* We must have a pathname for this. */
8583                                 return NT_STATUS_INVALID_LEVEL;
8584                         }
8585                         status = smb_set_file_unix_hlink(conn, req,
8586                                                          pdata, total_data,
8587                                                          smb_fname);
8588                         break;
8589                 }
8590
8591                 case SMB_FILE_RENAME_INFORMATION:
8592                 {
8593                         status = smb_file_rename_information(conn, req,
8594                                                              pdata, total_data,
8595                                                              fsp, smb_fname);
8596                         break;
8597                 }
8598
8599                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8600                 {
8601                         /* SMB2 rename information. */
8602                         status = smb2_file_rename_information(conn, req,
8603                                                              pdata, total_data,
8604                                                              fsp, smb_fname);
8605                         break;
8606                 }
8607
8608                 case SMB_FILE_LINK_INFORMATION:
8609                 {
8610                         status = smb_file_link_information(conn, req,
8611                                                         pdata, total_data,
8612                                                         fsp, smb_fname);
8613                         break;
8614                 }
8615
8616 #if defined(HAVE_POSIX_ACLS)
8617                 case SMB_SET_POSIX_ACL:
8618                 {
8619                         status = smb_set_posix_acl(conn,
8620                                                 pdata,
8621                                                 total_data,
8622                                                 fsp,
8623                                                 smb_fname);
8624                         break;
8625                 }
8626 #endif
8627
8628                 case SMB_SET_POSIX_LOCK:
8629                 {
8630                         if (!fsp) {
8631                                 return NT_STATUS_INVALID_LEVEL;
8632                         }
8633                         status = smb_set_posix_lock(conn, req,
8634                                                     pdata, total_data, fsp);
8635                         break;
8636                 }
8637
8638                 case SMB_POSIX_PATH_OPEN:
8639                 {
8640                         if (fsp) {
8641                                 /* We must have a pathname for this. */
8642                                 return NT_STATUS_INVALID_LEVEL;
8643                         }
8644
8645                         status = smb_posix_open(conn, req,
8646                                                 ppdata,
8647                                                 total_data,
8648                                                 smb_fname,
8649                                                 &data_return_size);
8650                         break;
8651                 }
8652
8653                 case SMB_POSIX_PATH_UNLINK:
8654                 {
8655                         if (fsp) {
8656                                 /* We must have a pathname for this. */
8657                                 return NT_STATUS_INVALID_LEVEL;
8658                         }
8659
8660                         status = smb_posix_unlink(conn, req,
8661                                                 pdata,
8662                                                 total_data,
8663                                                 smb_fname);
8664                         break;
8665                 }
8666
8667                 default:
8668                         return NT_STATUS_INVALID_LEVEL;
8669         }
8670
8671         if (!NT_STATUS_IS_OK(status)) {
8672                 return status;
8673         }
8674
8675         *ret_data_size = data_return_size;
8676         return NT_STATUS_OK;
8677 }
8678
8679 /****************************************************************************
8680  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8681 ****************************************************************************/
8682
8683 static void call_trans2setfilepathinfo(connection_struct *conn,
8684                                        struct smb_request *req,
8685                                        unsigned int tran_call,
8686                                        char **pparams, int total_params,
8687                                        char **ppdata, int total_data,
8688                                        unsigned int max_data_bytes)
8689 {
8690         char *params = *pparams;
8691         char *pdata = *ppdata;
8692         uint16_t info_level;
8693         struct smb_filename *smb_fname = NULL;
8694         files_struct *fsp = NULL;
8695         NTSTATUS status = NT_STATUS_OK;
8696         int data_return_size = 0;
8697
8698         if (!params) {
8699                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8700                 return;
8701         }
8702
8703         if (tran_call == TRANSACT2_SETFILEINFO) {
8704                 if (total_params < 4) {
8705                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8706                         return;
8707                 }
8708
8709                 fsp = file_fsp(req, SVAL(params,0));
8710                 /* Basic check for non-null fsp. */
8711                 if (!check_fsp_open(conn, req, fsp)) {
8712                         return;
8713                 }
8714                 info_level = SVAL(params,2);
8715
8716                 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8717                 if (smb_fname == NULL) {
8718                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8719                         return;
8720                 }
8721
8722                 if(fsp->fh->fd == -1) {
8723                         /*
8724                          * This is actually a SETFILEINFO on a directory
8725                          * handle (returned from an NT SMB). NT5.0 seems
8726                          * to do this call. JRA.
8727                          */
8728                         if (INFO_LEVEL_IS_UNIX(info_level)) {
8729                                 /* Always do lstat for UNIX calls. */
8730                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8731                                         DEBUG(3,("call_trans2setfilepathinfo: "
8732                                                  "SMB_VFS_LSTAT of %s failed "
8733                                                  "(%s)\n",
8734                                                  smb_fname_str_dbg(smb_fname),
8735                                                  strerror(errno)));
8736                                         reply_nterror(req, map_nt_error_from_unix(errno));
8737                                         return;
8738                                 }
8739                         } else {
8740                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8741                                         DEBUG(3,("call_trans2setfilepathinfo: "
8742                                                  "fileinfo of %s failed (%s)\n",
8743                                                  smb_fname_str_dbg(smb_fname),
8744                                                  strerror(errno)));
8745                                         reply_nterror(req, map_nt_error_from_unix(errno));
8746                                         return;
8747                                 }
8748                         }
8749                 } else if (fsp->print_file) {
8750                         /*
8751                          * Doing a DELETE_ON_CLOSE should cancel a print job.
8752                          */
8753                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8754                                 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8755
8756                                 DEBUG(3,("call_trans2setfilepathinfo: "
8757                                          "Cancelling print job (%s)\n",
8758                                          fsp_str_dbg(fsp)));
8759
8760                                 SSVAL(params,0,0);
8761                                 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8762                                                     *ppdata, 0,
8763                                                     max_data_bytes);
8764                                 return;
8765                         } else {
8766                                 reply_nterror(req,
8767                                         NT_STATUS_OBJECT_PATH_NOT_FOUND);
8768                                 return;
8769                         }
8770                 } else {
8771                         /*
8772                          * Original code - this is an open file.
8773                          */
8774                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8775                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8776                                          "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8777                                          strerror(errno)));
8778                                 reply_nterror(req, map_nt_error_from_unix(errno));
8779                                 return;
8780                         }
8781                 }
8782         } else {
8783                 char *fname = NULL;
8784                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8785
8786                 /* set path info */
8787                 if (total_params < 7) {
8788                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8789                         return;
8790                 }
8791
8792                 info_level = SVAL(params,0);
8793                 if (req->posix_pathnames) {
8794                         srvstr_get_path_posix(req,
8795                                 params,
8796                                 req->flags2,
8797                                 &fname,
8798                                 &params[6],
8799                                 total_params - 6,
8800                                 STR_TERMINATE,
8801                                 &status);
8802                 } else {
8803                         srvstr_get_path(req,
8804                                 params,
8805                                 req->flags2,
8806                                 &fname,
8807                                 &params[6],
8808                                 total_params - 6,
8809                                 STR_TERMINATE,
8810                                 &status);
8811                 }
8812                 if (!NT_STATUS_IS_OK(status)) {
8813                         reply_nterror(req, status);
8814                         return;
8815                 }
8816
8817                 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8818                                 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8819                                 info_level == SMB_FILE_RENAME_INFORMATION ||
8820                                 info_level == SMB_POSIX_PATH_UNLINK) {
8821                         ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8822                 }
8823
8824                 status = filename_convert(req, conn,
8825                                          fname,
8826                                          ucf_flags,
8827                                          NULL,
8828                                          &smb_fname);
8829                 if (!NT_STATUS_IS_OK(status)) {
8830                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8831                                 reply_botherror(req,
8832                                                 NT_STATUS_PATH_NOT_COVERED,
8833                                                 ERRSRV, ERRbadpath);
8834                                 return;
8835                         }
8836                         reply_nterror(req, status);
8837                         return;
8838                 }
8839
8840                 if (INFO_LEVEL_IS_UNIX(info_level)) {
8841                         /*
8842                          * For CIFS UNIX extensions the target name may not exist.
8843                          */
8844
8845                         /* Always do lstat for UNIX calls. */
8846                         SMB_VFS_LSTAT(conn, smb_fname);
8847
8848                 } else if (!VALID_STAT(smb_fname->st) &&
8849                            SMB_VFS_STAT(conn, smb_fname)) {
8850                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8851                                  "%s failed (%s)\n",
8852                                  smb_fname_str_dbg(smb_fname),
8853                                  strerror(errno)));
8854                         reply_nterror(req, map_nt_error_from_unix(errno));
8855                         return;
8856                 }
8857         }
8858
8859         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8860                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8861                  fsp_fnum_dbg(fsp),
8862                  info_level,total_data));
8863
8864         /* Realloc the parameter size */
8865         *pparams = (char *)SMB_REALLOC(*pparams,2);
8866         if (*pparams == NULL) {
8867                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8868                 return;
8869         }
8870         params = *pparams;
8871
8872         SSVAL(params,0,0);
8873
8874         status = smbd_do_setfilepathinfo(conn, req, req,
8875                                          info_level,
8876                                          fsp,
8877                                          smb_fname,
8878                                          ppdata, total_data,
8879                                          &data_return_size);
8880         if (!NT_STATUS_IS_OK(status)) {
8881                 if (open_was_deferred(req->xconn, req->mid)) {
8882                         /* We have re-scheduled this call. */
8883                         return;
8884                 }
8885                 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8886                         /* We have re-scheduled this call. */
8887                         return;
8888                 }
8889                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8890                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8891                                         ERRSRV, ERRbadpath);
8892                         return;
8893                 }
8894                 if (info_level == SMB_POSIX_PATH_OPEN) {
8895                         reply_openerror(req, status);
8896                         return;
8897                 }
8898
8899                 /*
8900                  * Invalid EA name needs to return 2 param bytes,
8901                  * not a zero-length error packet.
8902                  */
8903                 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8904                         send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8905                                         max_data_bytes);
8906                 } else {
8907                         reply_nterror(req, status);
8908                 }
8909                 return;
8910         }
8911
8912         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8913                             max_data_bytes);
8914
8915         return;
8916 }
8917
8918 /****************************************************************************
8919  Reply to a TRANS2_MKDIR (make directory with extended attributes).
8920 ****************************************************************************/
8921
8922 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8923                              char **pparams, int total_params,
8924                              char **ppdata, int total_data,
8925                              unsigned int max_data_bytes)
8926 {
8927         struct smb_filename *smb_dname = NULL;
8928         char *params = *pparams;
8929         char *pdata = *ppdata;
8930         char *directory = NULL;
8931         NTSTATUS status = NT_STATUS_OK;
8932         struct ea_list *ea_list = NULL;
8933         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8934         TALLOC_CTX *ctx = talloc_tos();
8935
8936         if (!CAN_WRITE(conn)) {
8937                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8938                 return;
8939         }
8940
8941         if (total_params < 5) {
8942                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8943                 return;
8944         }
8945
8946         if (req->posix_pathnames) {
8947                 srvstr_get_path_posix(ctx,
8948                         params,
8949                         req->flags2,
8950                         &directory,
8951                         &params[4],
8952                         total_params - 4,
8953                         STR_TERMINATE,
8954                         &status);
8955         } else {
8956                 srvstr_get_path(ctx,
8957                         params,
8958                         req->flags2,
8959                         &directory,
8960                         &params[4],
8961                         total_params - 4,
8962                         STR_TERMINATE,
8963                         &status);
8964         }
8965         if (!NT_STATUS_IS_OK(status)) {
8966                 reply_nterror(req, status);
8967                 return;
8968         }
8969
8970         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8971
8972         status = filename_convert(ctx,
8973                                 conn,
8974                                 directory,
8975                                 ucf_flags,
8976                                 NULL,
8977                                 &smb_dname);
8978
8979         if (!NT_STATUS_IS_OK(status)) {
8980                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8981                         reply_botherror(req,
8982                                 NT_STATUS_PATH_NOT_COVERED,
8983                                 ERRSRV, ERRbadpath);
8984                         return;
8985                 }
8986                 reply_nterror(req, status);
8987                 return;
8988         }
8989
8990         /*
8991          * OS/2 workplace shell seems to send SET_EA requests of "null"
8992          * length (4 bytes containing IVAL 4).
8993          * They seem to have no effect. Bug #3212. JRA.
8994          */
8995
8996         if (total_data && (total_data != 4)) {
8997                 /* Any data in this call is an EA list. */
8998                 if (total_data < 10) {
8999                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9000                         goto out;
9001                 }
9002
9003                 if (IVAL(pdata,0) > total_data) {
9004                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9005                                 IVAL(pdata,0), (unsigned int)total_data));
9006                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9007                         goto out;
9008                 }
9009
9010                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9011                                        total_data - 4);
9012                 if (!ea_list) {
9013                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9014                         goto out;
9015                 }
9016
9017                 if (!lp_ea_support(SNUM(conn))) {
9018                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9019                         goto out;
9020                 }
9021         }
9022         /* If total_data == 4 Windows doesn't care what values
9023          * are placed in that field, it just ignores them.
9024          * The System i QNTC IBM SMB client puts bad values here,
9025          * so ignore them. */
9026
9027         status = create_directory(conn, req, smb_dname);
9028
9029         if (!NT_STATUS_IS_OK(status)) {
9030                 reply_nterror(req, status);
9031                 goto out;
9032         }
9033
9034         /* Try and set any given EA. */
9035         if (ea_list) {
9036                 status = set_ea(conn, NULL, smb_dname, ea_list);
9037                 if (!NT_STATUS_IS_OK(status)) {
9038                         reply_nterror(req, status);
9039                         goto out;
9040                 }
9041         }
9042
9043         /* Realloc the parameter and data sizes */
9044         *pparams = (char *)SMB_REALLOC(*pparams,2);
9045         if(*pparams == NULL) {
9046                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9047                 goto out;
9048         }
9049         params = *pparams;
9050
9051         SSVAL(params,0,0);
9052
9053         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9054
9055  out:
9056         TALLOC_FREE(smb_dname);
9057         return;
9058 }
9059
9060 /****************************************************************************
9061  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9062  We don't actually do this - we just send a null response.
9063 ****************************************************************************/
9064
9065 static void call_trans2findnotifyfirst(connection_struct *conn,
9066                                        struct smb_request *req,
9067                                        char **pparams, int total_params,
9068                                        char **ppdata, int total_data,
9069                                        unsigned int max_data_bytes)
9070 {
9071         char *params = *pparams;
9072         uint16_t info_level;
9073
9074         if (total_params < 6) {
9075                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9076                 return;
9077         }
9078
9079         info_level = SVAL(params,4);
9080         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9081
9082         switch (info_level) {
9083                 case 1:
9084                 case 2:
9085                         break;
9086                 default:
9087                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9088                         return;
9089         }
9090
9091         /* Realloc the parameter and data sizes */
9092         *pparams = (char *)SMB_REALLOC(*pparams,6);
9093         if (*pparams == NULL) {
9094                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9095                 return;
9096         }
9097         params = *pparams;
9098
9099         SSVAL(params,0,fnf_handle);
9100         SSVAL(params,2,0); /* No changes */
9101         SSVAL(params,4,0); /* No EA errors */
9102
9103         fnf_handle++;
9104
9105         if(fnf_handle == 0)
9106                 fnf_handle = 257;
9107
9108         send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9109
9110         return;
9111 }
9112
9113 /****************************************************************************
9114  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
9115  changes). Currently this does nothing.
9116 ****************************************************************************/
9117
9118 static void call_trans2findnotifynext(connection_struct *conn,
9119                                       struct smb_request *req,
9120                                       char **pparams, int total_params,
9121                                       char **ppdata, int total_data,
9122                                       unsigned int max_data_bytes)
9123 {
9124         char *params = *pparams;
9125
9126         DEBUG(3,("call_trans2findnotifynext\n"));
9127
9128         /* Realloc the parameter and data sizes */
9129         *pparams = (char *)SMB_REALLOC(*pparams,4);
9130         if (*pparams == NULL) {
9131                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9132                 return;
9133         }
9134         params = *pparams;
9135
9136         SSVAL(params,0,0); /* No changes */
9137         SSVAL(params,2,0); /* No EA errors */
9138
9139         send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9140
9141         return;
9142 }
9143
9144 /****************************************************************************
9145  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9146 ****************************************************************************/
9147
9148 static void call_trans2getdfsreferral(connection_struct *conn,
9149                                       struct smb_request *req,
9150                                       char **pparams, int total_params,
9151                                       char **ppdata, int total_data,
9152                                       unsigned int max_data_bytes)
9153 {
9154         char *params = *pparams;
9155         char *pathname = NULL;
9156         int reply_size = 0;
9157         int max_referral_level;
9158         NTSTATUS status = NT_STATUS_OK;
9159         TALLOC_CTX *ctx = talloc_tos();
9160
9161         DEBUG(10,("call_trans2getdfsreferral\n"));
9162
9163         if (total_params < 3) {
9164                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9165                 return;
9166         }
9167
9168         max_referral_level = SVAL(params,0);
9169
9170         if(!lp_host_msdfs()) {
9171                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9172                 return;
9173         }
9174
9175         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9176                     total_params - 2, STR_TERMINATE);
9177         if (!pathname) {
9178                 reply_nterror(req, NT_STATUS_NOT_FOUND);
9179                 return;
9180         }
9181         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9182                                             ppdata,&status)) < 0) {
9183                 reply_nterror(req, status);
9184                 return;
9185         }
9186
9187         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9188               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9189         send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9190
9191         return;
9192 }
9193
9194 #define LMCAT_SPL       0x53
9195 #define LMFUNC_GETJOBID 0x60
9196
9197 /****************************************************************************
9198  Reply to a TRANS2_IOCTL - used for OS/2 printing.
9199 ****************************************************************************/
9200
9201 static void call_trans2ioctl(connection_struct *conn,
9202                              struct smb_request *req,
9203                              char **pparams, int total_params,
9204                              char **ppdata, int total_data,
9205                              unsigned int max_data_bytes)
9206 {
9207         char *pdata = *ppdata;
9208         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9209         NTSTATUS status;
9210         size_t len = 0;
9211
9212         /* check for an invalid fid before proceeding */
9213
9214         if (!fsp) {
9215                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9216                 return;
9217         }
9218
9219         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9220             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9221                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9222                 if (*ppdata == NULL) {
9223                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9224                         return;
9225                 }
9226                 pdata = *ppdata;
9227
9228                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9229                         CAN ACCEPT THIS IN UNICODE. JRA. */
9230
9231                 /* Job number */
9232                 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9233
9234                 status = srvstr_push(pdata, req->flags2, pdata + 2,
9235                             lp_netbios_name(), 15,
9236                             STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9237                 if (!NT_STATUS_IS_OK(status)) {
9238                         reply_nterror(req, status);
9239                         return;
9240                 }
9241                 status = srvstr_push(pdata, req->flags2, pdata+18,
9242                             lp_servicename(talloc_tos(), SNUM(conn)), 13,
9243                             STR_ASCII|STR_TERMINATE, &len); /* Service name */
9244                 if (!NT_STATUS_IS_OK(status)) {
9245                         reply_nterror(req, status);
9246                         return;
9247                 }
9248                 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9249                                     max_data_bytes);
9250                 return;
9251         }
9252
9253         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9254         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9255 }
9256
9257 /****************************************************************************
9258  Reply to a SMBfindclose (stop trans2 directory search).
9259 ****************************************************************************/
9260
9261 void reply_findclose(struct smb_request *req)
9262 {
9263         int dptr_num;
9264         struct smbd_server_connection *sconn = req->sconn;
9265
9266         START_PROFILE(SMBfindclose);
9267
9268         if (req->wct < 1) {
9269                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9270                 END_PROFILE(SMBfindclose);
9271                 return;
9272         }
9273
9274         dptr_num = SVALS(req->vwv+0, 0);
9275
9276         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9277
9278         dptr_close(sconn, &dptr_num);
9279
9280         reply_outbuf(req, 0, 0);
9281
9282         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9283
9284         END_PROFILE(SMBfindclose);
9285         return;
9286 }
9287
9288 /****************************************************************************
9289  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9290 ****************************************************************************/
9291
9292 void reply_findnclose(struct smb_request *req)
9293 {
9294         int dptr_num;
9295
9296         START_PROFILE(SMBfindnclose);
9297
9298         if (req->wct < 1) {
9299                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9300                 END_PROFILE(SMBfindnclose);
9301                 return;
9302         }
9303
9304         dptr_num = SVAL(req->vwv+0, 0);
9305
9306         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9307
9308         /* We never give out valid handles for a 
9309            findnotifyfirst - so any dptr_num is ok here. 
9310            Just ignore it. */
9311
9312         reply_outbuf(req, 0, 0);
9313
9314         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9315
9316         END_PROFILE(SMBfindnclose);
9317         return;
9318 }
9319
9320 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9321                           struct trans_state *state)
9322 {
9323         if (get_Protocol() >= PROTOCOL_NT1) {
9324                 req->flags2 |= 0x40; /* IS_LONG_NAME */
9325                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9326         }
9327
9328         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9329                 if (state->call != TRANSACT2_QFSINFO &&
9330                     state->call != TRANSACT2_SETFSINFO) {
9331                         DEBUG(0,("handle_trans2: encryption required "
9332                                 "with call 0x%x\n",
9333                                 (unsigned int)state->call));
9334                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9335                         return;
9336                 }
9337         }
9338
9339         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9340
9341         /* Now we must call the relevant TRANS2 function */
9342         switch(state->call)  {
9343         case TRANSACT2_OPEN:
9344         {
9345                 START_PROFILE(Trans2_open);
9346                 call_trans2open(conn, req,
9347                                 &state->param, state->total_param,
9348                                 &state->data, state->total_data,
9349                                 state->max_data_return);
9350                 END_PROFILE(Trans2_open);
9351                 break;
9352         }
9353
9354         case TRANSACT2_FINDFIRST:
9355         {
9356                 START_PROFILE(Trans2_findfirst);
9357                 call_trans2findfirst(conn, req,
9358                                      &state->param, state->total_param,
9359                                      &state->data, state->total_data,
9360                                      state->max_data_return);
9361                 END_PROFILE(Trans2_findfirst);
9362                 break;
9363         }
9364
9365         case TRANSACT2_FINDNEXT:
9366         {
9367                 START_PROFILE(Trans2_findnext);
9368                 call_trans2findnext(conn, req,
9369                                     &state->param, state->total_param,
9370                                     &state->data, state->total_data,
9371                                     state->max_data_return);
9372                 END_PROFILE(Trans2_findnext);
9373                 break;
9374         }
9375
9376         case TRANSACT2_QFSINFO:
9377         {
9378                 START_PROFILE(Trans2_qfsinfo);
9379                 call_trans2qfsinfo(conn, req,
9380                                    &state->param, state->total_param,
9381                                    &state->data, state->total_data,
9382                                    state->max_data_return);
9383                 END_PROFILE(Trans2_qfsinfo);
9384             break;
9385         }
9386
9387         case TRANSACT2_SETFSINFO:
9388         {
9389                 START_PROFILE(Trans2_setfsinfo);
9390                 call_trans2setfsinfo(conn, req,
9391                                      &state->param, state->total_param,
9392                                      &state->data, state->total_data,
9393                                      state->max_data_return);
9394                 END_PROFILE(Trans2_setfsinfo);
9395                 break;
9396         }
9397
9398         case TRANSACT2_QPATHINFO:
9399         case TRANSACT2_QFILEINFO:
9400         {
9401                 START_PROFILE(Trans2_qpathinfo);
9402                 call_trans2qfilepathinfo(conn, req, state->call,
9403                                          &state->param, state->total_param,
9404                                          &state->data, state->total_data,
9405                                          state->max_data_return);
9406                 END_PROFILE(Trans2_qpathinfo);
9407                 break;
9408         }
9409
9410         case TRANSACT2_SETPATHINFO:
9411         case TRANSACT2_SETFILEINFO:
9412         {
9413                 START_PROFILE(Trans2_setpathinfo);
9414                 call_trans2setfilepathinfo(conn, req, state->call,
9415                                            &state->param, state->total_param,
9416                                            &state->data, state->total_data,
9417                                            state->max_data_return);
9418                 END_PROFILE(Trans2_setpathinfo);
9419                 break;
9420         }
9421
9422         case TRANSACT2_FINDNOTIFYFIRST:
9423         {
9424                 START_PROFILE(Trans2_findnotifyfirst);
9425                 call_trans2findnotifyfirst(conn, req,
9426                                            &state->param, state->total_param,
9427                                            &state->data, state->total_data,
9428                                            state->max_data_return);
9429                 END_PROFILE(Trans2_findnotifyfirst);
9430                 break;
9431         }
9432
9433         case TRANSACT2_FINDNOTIFYNEXT:
9434         {
9435                 START_PROFILE(Trans2_findnotifynext);
9436                 call_trans2findnotifynext(conn, req,
9437                                           &state->param, state->total_param,
9438                                           &state->data, state->total_data,
9439                                           state->max_data_return);
9440                 END_PROFILE(Trans2_findnotifynext);
9441                 break;
9442         }
9443
9444         case TRANSACT2_MKDIR:
9445         {
9446                 START_PROFILE(Trans2_mkdir);
9447                 call_trans2mkdir(conn, req,
9448                                  &state->param, state->total_param,
9449                                  &state->data, state->total_data,
9450                                  state->max_data_return);
9451                 END_PROFILE(Trans2_mkdir);
9452                 break;
9453         }
9454
9455         case TRANSACT2_GET_DFS_REFERRAL:
9456         {
9457                 START_PROFILE(Trans2_get_dfs_referral);
9458                 call_trans2getdfsreferral(conn, req,
9459                                           &state->param, state->total_param,
9460                                           &state->data, state->total_data,
9461                                           state->max_data_return);
9462                 END_PROFILE(Trans2_get_dfs_referral);
9463                 break;
9464         }
9465
9466         case TRANSACT2_IOCTL:
9467         {
9468                 START_PROFILE(Trans2_ioctl);
9469                 call_trans2ioctl(conn, req,
9470                                  &state->param, state->total_param,
9471                                  &state->data, state->total_data,
9472                                  state->max_data_return);
9473                 END_PROFILE(Trans2_ioctl);
9474                 break;
9475         }
9476
9477         default:
9478                 /* Error in request */
9479                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9480                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9481         }
9482 }
9483
9484 /****************************************************************************
9485  Reply to a SMBtrans2.
9486  ****************************************************************************/
9487
9488 void reply_trans2(struct smb_request *req)
9489 {
9490         connection_struct *conn = req->conn;
9491         unsigned int dsoff;
9492         unsigned int dscnt;
9493         unsigned int psoff;
9494         unsigned int pscnt;
9495         unsigned int tran_call;
9496         struct trans_state *state;
9497         NTSTATUS result;
9498
9499         START_PROFILE(SMBtrans2);
9500
9501         if (req->wct < 14) {
9502                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9503                 END_PROFILE(SMBtrans2);
9504                 return;
9505         }
9506
9507         dsoff = SVAL(req->vwv+12, 0);
9508         dscnt = SVAL(req->vwv+11, 0);
9509         psoff = SVAL(req->vwv+10, 0);
9510         pscnt = SVAL(req->vwv+9, 0);
9511         tran_call = SVAL(req->vwv+14, 0);
9512
9513         result = allow_new_trans(conn->pending_trans, req->mid);
9514         if (!NT_STATUS_IS_OK(result)) {
9515                 DEBUG(2, ("Got invalid trans2 request: %s\n",
9516                           nt_errstr(result)));
9517                 reply_nterror(req, result);
9518                 END_PROFILE(SMBtrans2);
9519                 return;
9520         }
9521
9522         if (IS_IPC(conn)) {
9523                 switch (tran_call) {
9524                 /* List the allowed trans2 calls on IPC$ */
9525                 case TRANSACT2_OPEN:
9526                 case TRANSACT2_GET_DFS_REFERRAL:
9527                 case TRANSACT2_QFILEINFO:
9528                 case TRANSACT2_QFSINFO:
9529                 case TRANSACT2_SETFSINFO:
9530                         break;
9531                 default:
9532                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9533                         END_PROFILE(SMBtrans2);
9534                         return;
9535                 }
9536         }
9537
9538         if ((state = talloc(conn, struct trans_state)) == NULL) {
9539                 DEBUG(0, ("talloc failed\n"));
9540                 reply_nterror(req, NT_STATUS_NO_MEMORY);
9541                 END_PROFILE(SMBtrans2);
9542                 return;
9543         }
9544
9545         state->cmd = SMBtrans2;
9546
9547         state->mid = req->mid;
9548         state->vuid = req->vuid;
9549         state->setup_count = SVAL(req->vwv+13, 0);
9550         state->setup = NULL;
9551         state->total_param = SVAL(req->vwv+0, 0);
9552         state->param = NULL;
9553         state->total_data =  SVAL(req->vwv+1, 0);
9554         state->data = NULL;
9555         state->max_param_return = SVAL(req->vwv+2, 0);
9556         state->max_data_return  = SVAL(req->vwv+3, 0);
9557         state->max_setup_return = SVAL(req->vwv+4, 0);
9558         state->close_on_completion = BITSETW(req->vwv+5, 0);
9559         state->one_way = BITSETW(req->vwv+5, 1);
9560
9561         state->call = tran_call;
9562
9563         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9564            is so as a sanity check */
9565         if (state->setup_count != 1) {
9566                 /*
9567                  * Need to have rc=0 for ioctl to get job id for OS/2.
9568                  *  Network printing will fail if function is not successful.
9569                  *  Similar function in reply.c will be used if protocol
9570                  *  is LANMAN1.0 instead of LM1.2X002.
9571                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
9572                  *  outbuf doesn't have to be set(only job id is used).
9573                  */
9574                 if ( (state->setup_count == 4)
9575                      && (tran_call == TRANSACT2_IOCTL)
9576                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9577                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9578                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9579                 } else {
9580                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9581                         DEBUG(2,("Transaction is %d\n",tran_call));
9582                         TALLOC_FREE(state);
9583                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9584                         END_PROFILE(SMBtrans2);
9585                         return;
9586                 }
9587         }
9588
9589         if ((dscnt > state->total_data) || (pscnt > state->total_param))
9590                 goto bad_param;
9591
9592         if (state->total_data) {
9593
9594                 if (trans_oob(state->total_data, 0, dscnt)
9595                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9596                         goto bad_param;
9597                 }
9598
9599                 /* Can't use talloc here, the core routines do realloc on the
9600                  * params and data. */
9601                 state->data = (char *)SMB_MALLOC(state->total_data);
9602                 if (state->data == NULL) {
9603                         DEBUG(0,("reply_trans2: data malloc fail for %u "
9604                                  "bytes !\n", (unsigned int)state->total_data));
9605                         TALLOC_FREE(state);
9606                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9607                         END_PROFILE(SMBtrans2);
9608                         return;
9609                 }
9610
9611                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9612         }
9613
9614         if (state->total_param) {
9615
9616                 if (trans_oob(state->total_param, 0, pscnt)
9617                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9618                         goto bad_param;
9619                 }
9620
9621                 /* Can't use talloc here, the core routines do realloc on the
9622                  * params and data. */
9623                 state->param = (char *)SMB_MALLOC(state->total_param);
9624                 if (state->param == NULL) {
9625                         DEBUG(0,("reply_trans: param malloc fail for %u "
9626                                  "bytes !\n", (unsigned int)state->total_param));
9627                         SAFE_FREE(state->data);
9628                         TALLOC_FREE(state);
9629                         reply_nterror(req, NT_STATUS_NO_MEMORY);
9630                         END_PROFILE(SMBtrans2);
9631                         return;
9632                 } 
9633
9634                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9635         }
9636
9637         state->received_data  = dscnt;
9638         state->received_param = pscnt;
9639
9640         if ((state->received_param == state->total_param) &&
9641             (state->received_data == state->total_data)) {
9642
9643                 handle_trans2(conn, req, state);
9644
9645                 SAFE_FREE(state->data);
9646                 SAFE_FREE(state->param);
9647                 TALLOC_FREE(state);
9648                 END_PROFILE(SMBtrans2);
9649                 return;
9650         }
9651
9652         DLIST_ADD(conn->pending_trans, state);
9653
9654         /* We need to send an interim response then receive the rest
9655            of the parameter/data bytes */
9656         reply_outbuf(req, 0, 0);
9657         show_msg((char *)req->outbuf);
9658         END_PROFILE(SMBtrans2);
9659         return;
9660
9661   bad_param:
9662
9663         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9664         SAFE_FREE(state->data);
9665         SAFE_FREE(state->param);
9666         TALLOC_FREE(state);
9667         END_PROFILE(SMBtrans2);
9668         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9669 }
9670
9671
9672 /****************************************************************************
9673  Reply to a SMBtranss2
9674  ****************************************************************************/
9675
9676 void reply_transs2(struct smb_request *req)
9677 {
9678         connection_struct *conn = req->conn;
9679         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9680         struct trans_state *state;
9681
9682         START_PROFILE(SMBtranss2);
9683
9684         show_msg((const char *)req->inbuf);
9685
9686         /* Windows clients expect all replies to
9687            a transact secondary (SMBtranss2 0x33)
9688            to have a command code of transact
9689            (SMBtrans2 0x32). See bug #8989
9690            and also [MS-CIFS] section 2.2.4.47.2
9691            for details.
9692         */
9693         req->cmd = SMBtrans2;
9694
9695         if (req->wct < 8) {
9696                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9697                 END_PROFILE(SMBtranss2);
9698                 return;
9699         }
9700
9701         for (state = conn->pending_trans; state != NULL;
9702              state = state->next) {
9703                 if (state->mid == req->mid) {
9704                         break;
9705                 }
9706         }
9707
9708         if ((state == NULL) || (state->cmd != SMBtrans2)) {
9709                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9710                 END_PROFILE(SMBtranss2);
9711                 return;
9712         }
9713
9714         /* Revise state->total_param and state->total_data in case they have
9715            changed downwards */
9716
9717         if (SVAL(req->vwv+0, 0) < state->total_param)
9718                 state->total_param = SVAL(req->vwv+0, 0);
9719         if (SVAL(req->vwv+1, 0) < state->total_data)
9720                 state->total_data = SVAL(req->vwv+1, 0);
9721
9722         pcnt = SVAL(req->vwv+2, 0);
9723         poff = SVAL(req->vwv+3, 0);
9724         pdisp = SVAL(req->vwv+4, 0);
9725
9726         dcnt = SVAL(req->vwv+5, 0);
9727         doff = SVAL(req->vwv+6, 0);
9728         ddisp = SVAL(req->vwv+7, 0);
9729
9730         state->received_param += pcnt;
9731         state->received_data += dcnt;
9732
9733         if ((state->received_data > state->total_data) ||
9734             (state->received_param > state->total_param))
9735                 goto bad_param;
9736
9737         if (pcnt) {
9738                 if (trans_oob(state->total_param, pdisp, pcnt)
9739                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9740                         goto bad_param;
9741                 }
9742                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9743         }
9744
9745         if (dcnt) {
9746                 if (trans_oob(state->total_data, ddisp, dcnt)
9747                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9748                         goto bad_param;
9749                 }
9750                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9751         }
9752
9753         if ((state->received_param < state->total_param) ||
9754             (state->received_data < state->total_data)) {
9755                 END_PROFILE(SMBtranss2);
9756                 return;
9757         }
9758
9759         handle_trans2(conn, req, state);
9760
9761         DLIST_REMOVE(conn->pending_trans, state);
9762         SAFE_FREE(state->data);
9763         SAFE_FREE(state->param);
9764         TALLOC_FREE(state);
9765
9766         END_PROFILE(SMBtranss2);
9767         return;
9768
9769   bad_param:
9770
9771         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9772         DLIST_REMOVE(conn->pending_trans, state);
9773         SAFE_FREE(state->data);
9774         SAFE_FREE(state->param);
9775         TALLOC_FREE(state);
9776         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9777         END_PROFILE(SMBtranss2);
9778         return;
9779 }