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