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