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