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