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