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