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