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