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