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