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