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