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