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