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