4417cb27e72256eff7ff3cfabd9f7f6f15710103
[mat/samba.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40
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         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6974         if (!NT_STATUS_IS_OK(status)) {
6975                 return status;
6976         }
6977
6978         /*
6979          * Deal with the UNIX specific mode set.
6980          */
6981
6982         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6983                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6984                           "setting mode 0%o for file %s\n",
6985                           (unsigned int)unixmode,
6986                           smb_fname_str_dbg(smb_fname)));
6987                 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6988                         return map_nt_error_from_unix(errno);
6989                 }
6990         }
6991
6992         /*
6993          * Deal with the UNIX specific uid set.
6994          */
6995
6996         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6997             (sbuf.st_ex_uid != set_owner)) {
6998                 int ret;
6999
7000                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7001                           "changing owner %u for path %s\n",
7002                           (unsigned int)set_owner,
7003                           smb_fname_str_dbg(smb_fname)));
7004
7005                 if (S_ISLNK(sbuf.st_ex_mode)) {
7006                         ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7007                                              set_owner, (gid_t)-1);
7008                 } else {
7009                         ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7010                                             set_owner, (gid_t)-1);
7011                 }
7012
7013                 if (ret != 0) {
7014                         status = map_nt_error_from_unix(errno);
7015                         if (delete_on_fail) {
7016                                 SMB_VFS_UNLINK(conn, smb_fname);
7017                         }
7018                         return status;
7019                 }
7020         }
7021
7022         /*
7023          * Deal with the UNIX specific gid set.
7024          */
7025
7026         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7027             (sbuf.st_ex_gid != set_grp)) {
7028                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7029                           "changing group %u for file %s\n",
7030                           (unsigned int)set_owner,
7031                           smb_fname_str_dbg(smb_fname)));
7032                 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7033                                   set_grp) != 0) {
7034                         status = map_nt_error_from_unix(errno);
7035                         if (delete_on_fail) {
7036                                 SMB_VFS_UNLINK(conn, smb_fname);
7037                         }
7038                         return status;
7039                 }
7040         }
7041
7042         /* Deal with any size changes. */
7043
7044         status = smb_set_file_size(conn, req,
7045                                    fsp,
7046                                    smb_fname,
7047                                    &sbuf,
7048                                    size,
7049                                    false);
7050         if (!NT_STATUS_IS_OK(status)) {
7051                 return status;
7052         }
7053
7054         /* Deal with any time changes. */
7055         if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7056                 /* No change, don't cancel anything. */
7057                 return status;
7058         }
7059
7060         id = vfs_file_id_from_sbuf(conn, &sbuf);
7061         for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7062                         all_fsps = file_find_di_next(all_fsps)) {
7063                 /*
7064                  * We're setting the time explicitly for UNIX.
7065                  * Cancel any pending changes over all handles.
7066                  */
7067                 all_fsps->update_write_time_on_close = false;
7068                 TALLOC_FREE(all_fsps->update_write_time_event);
7069         }
7070
7071         /*
7072          * Override the "setting_write_time"
7073          * parameter here as it almost does what
7074          * we need. Just remember if we modified
7075          * mtime and send the notify ourselves.
7076          */
7077         if (null_timespec(ft.mtime)) {
7078                 modify_mtime = false;
7079         }
7080
7081         status = smb_set_file_time(conn,
7082                                 fsp,
7083                                 smb_fname,
7084                                 &ft,
7085                                 false);
7086         if (modify_mtime) {
7087                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7088                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7089         }
7090         return status;
7091 }
7092
7093 /****************************************************************************
7094  Deal with SMB_SET_FILE_UNIX_INFO2.
7095 ****************************************************************************/
7096
7097 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7098                                         struct smb_request *req,
7099                                         const char *pdata,
7100                                         int total_data,
7101                                         files_struct *fsp,
7102                                         const struct smb_filename *smb_fname)
7103 {
7104         NTSTATUS status;
7105         uint32 smb_fflags;
7106         uint32 smb_fmask;
7107
7108         if (total_data < 116) {
7109                 return NT_STATUS_INVALID_PARAMETER;
7110         }
7111
7112         /* Start by setting all the fields that are common between UNIX_BASIC
7113          * and UNIX_INFO2.
7114          */
7115         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7116                                          fsp, smb_fname);
7117         if (!NT_STATUS_IS_OK(status)) {
7118                 return status;
7119         }
7120
7121         smb_fflags = IVAL(pdata, 108);
7122         smb_fmask = IVAL(pdata, 112);
7123
7124         /* NB: We should only attempt to alter the file flags if the client
7125          * sends a non-zero mask.
7126          */
7127         if (smb_fmask != 0) {
7128                 int stat_fflags = 0;
7129
7130                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7131                                              smb_fmask, &stat_fflags)) {
7132                         /* Client asked to alter a flag we don't understand. */
7133                         return NT_STATUS_INVALID_PARAMETER;
7134                 }
7135
7136                 if (fsp && fsp->fh->fd != -1) {
7137                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
7138                         return NT_STATUS_NOT_SUPPORTED;
7139                 } else {
7140                         if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7141                                             stat_fflags) != 0) {
7142                                 return map_nt_error_from_unix(errno);
7143                         }
7144                 }
7145         }
7146
7147         /* XXX: need to add support for changing the create_time here. You
7148          * can do this for paths on Darwin with setattrlist(2). The right way
7149          * to hook this up is probably by extending the VFS utimes interface.
7150          */
7151
7152         return NT_STATUS_OK;
7153 }
7154
7155 /****************************************************************************
7156  Create a directory with POSIX semantics.
7157 ****************************************************************************/
7158
7159 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7160                                 struct smb_request *req,
7161                                 char **ppdata,
7162                                 int total_data,
7163                                 struct smb_filename *smb_fname,
7164                                 int *pdata_return_size)
7165 {
7166         NTSTATUS status = NT_STATUS_OK;
7167         uint32 raw_unixmode = 0;
7168         uint32 mod_unixmode = 0;
7169         mode_t unixmode = (mode_t)0;
7170         files_struct *fsp = NULL;
7171         uint16 info_level_return = 0;
7172         int info;
7173         char *pdata = *ppdata;
7174
7175         if (total_data < 18) {
7176                 return NT_STATUS_INVALID_PARAMETER;
7177         }
7178
7179         raw_unixmode = IVAL(pdata,8);
7180         /* Next 4 bytes are not yet defined. */
7181
7182         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7183                                       PERM_NEW_DIR, &unixmode);
7184         if (!NT_STATUS_IS_OK(status)) {
7185                 return status;
7186         }
7187
7188         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7189
7190         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7191                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7192
7193         status = SMB_VFS_CREATE_FILE(
7194                 conn,                                   /* conn */
7195                 req,                                    /* req */
7196                 0,                                      /* root_dir_fid */
7197                 smb_fname,                              /* fname */
7198                 FILE_READ_ATTRIBUTES,                   /* access_mask */
7199                 FILE_SHARE_NONE,                        /* share_access */
7200                 FILE_CREATE,                            /* create_disposition*/
7201                 FILE_DIRECTORY_FILE,                    /* create_options */
7202                 mod_unixmode,                           /* file_attributes */
7203                 0,                                      /* oplock_request */
7204                 0,                                      /* allocation_size */
7205                 0,                                      /* private_flags */
7206                 NULL,                                   /* sd */
7207                 NULL,                                   /* ea_list */
7208                 &fsp,                                   /* result */
7209                 &info);                                 /* pinfo */
7210
7211         if (NT_STATUS_IS_OK(status)) {
7212                 close_file(req, fsp, NORMAL_CLOSE);
7213         }
7214
7215         info_level_return = SVAL(pdata,16);
7216  
7217         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7218                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7219         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7220                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7221         } else {
7222                 *pdata_return_size = 12;
7223         }
7224
7225         /* Realloc the data size */
7226         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7227         if (*ppdata == NULL) {
7228                 *pdata_return_size = 0;
7229                 return NT_STATUS_NO_MEMORY;
7230         }
7231         pdata = *ppdata;
7232
7233         SSVAL(pdata,0,NO_OPLOCK_RETURN);
7234         SSVAL(pdata,2,0); /* No fnum. */
7235         SIVAL(pdata,4,info); /* Was directory created. */
7236
7237         switch (info_level_return) {
7238                 case SMB_QUERY_FILE_UNIX_BASIC:
7239                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7240                         SSVAL(pdata,10,0); /* Padding. */
7241                         store_file_unix_basic(conn, pdata + 12, fsp,
7242                                               &smb_fname->st);
7243                         break;
7244                 case SMB_QUERY_FILE_UNIX_INFO2:
7245                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7246                         SSVAL(pdata,10,0); /* Padding. */
7247                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7248                                                     &smb_fname->st);
7249                         break;
7250                 default:
7251                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7252                         SSVAL(pdata,10,0); /* Padding. */
7253                         break;
7254         }
7255
7256         return status;
7257 }
7258
7259 /****************************************************************************
7260  Open/Create a file with POSIX semantics.
7261 ****************************************************************************/
7262
7263 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7264 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7265
7266 static NTSTATUS smb_posix_open(connection_struct *conn,
7267                                struct smb_request *req,
7268                                 char **ppdata,
7269                                 int total_data,
7270                                 struct smb_filename *smb_fname,
7271                                 int *pdata_return_size)
7272 {
7273         bool extended_oplock_granted = False;
7274         char *pdata = *ppdata;
7275         uint32 flags = 0;
7276         uint32 wire_open_mode = 0;
7277         uint32 raw_unixmode = 0;
7278         uint32 mod_unixmode = 0;
7279         uint32 create_disp = 0;
7280         uint32 access_mask = 0;
7281         uint32 create_options = FILE_NON_DIRECTORY_FILE;
7282         NTSTATUS status = NT_STATUS_OK;
7283         mode_t unixmode = (mode_t)0;
7284         files_struct *fsp = NULL;
7285         int oplock_request = 0;
7286         int info = 0;
7287         uint16 info_level_return = 0;
7288
7289         if (total_data < 18) {
7290                 return NT_STATUS_INVALID_PARAMETER;
7291         }
7292
7293         flags = IVAL(pdata,0);
7294         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7295         if (oplock_request) {
7296                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7297         }
7298
7299         wire_open_mode = IVAL(pdata,4);
7300
7301         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7302                 return smb_posix_mkdir(conn, req,
7303                                         ppdata,
7304                                         total_data,
7305                                         smb_fname,
7306                                         pdata_return_size);
7307         }
7308
7309         switch (wire_open_mode & SMB_ACCMODE) {
7310                 case SMB_O_RDONLY:
7311                         access_mask = SMB_O_RDONLY_MAPPING;
7312                         break;
7313                 case SMB_O_WRONLY:
7314                         access_mask = SMB_O_WRONLY_MAPPING;
7315                         break;
7316                 case SMB_O_RDWR:
7317                         access_mask = (SMB_O_RDONLY_MAPPING|
7318                                         SMB_O_WRONLY_MAPPING);
7319                         break;
7320                 default:
7321                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7322                                 (unsigned int)wire_open_mode ));
7323                         return NT_STATUS_INVALID_PARAMETER;
7324         }
7325
7326         wire_open_mode &= ~SMB_ACCMODE;
7327
7328         /* First take care of O_CREAT|O_EXCL interactions. */
7329         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7330                 case (SMB_O_CREAT | SMB_O_EXCL):
7331                         /* File exists fail. File not exist create. */
7332                         create_disp = FILE_CREATE;
7333                         break;
7334                 case SMB_O_CREAT:
7335                         /* File exists open. File not exist create. */
7336                         create_disp = FILE_OPEN_IF;
7337                         break;
7338                 case 0:
7339                         /* File exists open. File not exist fail. */
7340                         create_disp = FILE_OPEN;
7341                         break;
7342                 case SMB_O_EXCL:
7343                         /* O_EXCL on its own without O_CREAT is undefined. */
7344                 default:
7345                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7346                                 (unsigned int)wire_open_mode ));
7347                         return NT_STATUS_INVALID_PARAMETER;
7348         }
7349
7350         /* Next factor in the effects of O_TRUNC. */
7351         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7352
7353         if (wire_open_mode & SMB_O_TRUNC) {
7354                 switch (create_disp) {
7355                         case FILE_CREATE:
7356                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7357                                 /* Leave create_disp alone as
7358                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7359                                 */
7360                                 /* File exists fail. File not exist create. */
7361                                 break;
7362                         case FILE_OPEN_IF:
7363                                 /* SMB_O_CREAT | SMB_O_TRUNC */
7364                                 /* File exists overwrite. File not exist create. */
7365                                 create_disp = FILE_OVERWRITE_IF;
7366                                 break;
7367                         case FILE_OPEN:
7368                                 /* SMB_O_TRUNC */
7369                                 /* File exists overwrite. File not exist fail. */
7370                                 create_disp = FILE_OVERWRITE;
7371                                 break;
7372                         default:
7373                                 /* Cannot get here. */
7374                                 smb_panic("smb_posix_open: logic error");
7375                                 return NT_STATUS_INVALID_PARAMETER;
7376                 }
7377         }
7378
7379         raw_unixmode = IVAL(pdata,8);
7380         /* Next 4 bytes are not yet defined. */
7381
7382         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7383                                       (VALID_STAT(smb_fname->st) ?
7384                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
7385                                       &unixmode);
7386
7387         if (!NT_STATUS_IS_OK(status)) {
7388                 return status;
7389         }
7390
7391         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7392
7393         if (wire_open_mode & SMB_O_SYNC) {
7394                 create_options |= FILE_WRITE_THROUGH;
7395         }
7396         if (wire_open_mode & SMB_O_APPEND) {
7397                 access_mask |= FILE_APPEND_DATA;
7398         }
7399         if (wire_open_mode & SMB_O_DIRECT) {
7400                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7401         }
7402
7403         if ((wire_open_mode & SMB_O_DIRECTORY) ||
7404                         VALID_STAT_OF_DIR(smb_fname->st)) {
7405                 if (access_mask != SMB_O_RDONLY_MAPPING) {
7406                         return NT_STATUS_FILE_IS_A_DIRECTORY;
7407                 }
7408                 create_options &= ~FILE_NON_DIRECTORY_FILE;
7409                 create_options |= FILE_DIRECTORY_FILE;
7410         }
7411
7412         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7413                 smb_fname_str_dbg(smb_fname),
7414                 (unsigned int)wire_open_mode,
7415                 (unsigned int)unixmode ));
7416
7417         status = SMB_VFS_CREATE_FILE(
7418                 conn,                                   /* conn */
7419                 req,                                    /* req */
7420                 0,                                      /* root_dir_fid */
7421                 smb_fname,                              /* fname */
7422                 access_mask,                            /* access_mask */
7423                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7424                     FILE_SHARE_DELETE),
7425                 create_disp,                            /* create_disposition*/
7426                 create_options,                         /* create_options */
7427                 mod_unixmode,                           /* file_attributes */
7428                 oplock_request,                         /* oplock_request */
7429                 0,                                      /* allocation_size */
7430                 0,                                      /* private_flags */
7431                 NULL,                                   /* sd */
7432                 NULL,                                   /* ea_list */
7433                 &fsp,                                   /* result */
7434                 &info);                                 /* pinfo */
7435
7436         if (!NT_STATUS_IS_OK(status)) {
7437                 return status;
7438         }
7439
7440         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7441                 extended_oplock_granted = True;
7442         }
7443
7444         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7445                 extended_oplock_granted = True;
7446         }
7447
7448         info_level_return = SVAL(pdata,16);
7449  
7450         /* Allocate the correct return size. */
7451
7452         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7453                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7454         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7455                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7456         } else {
7457                 *pdata_return_size = 12;
7458         }
7459
7460         /* Realloc the data size */
7461         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7462         if (*ppdata == NULL) {
7463                 close_file(req, fsp, ERROR_CLOSE);
7464                 *pdata_return_size = 0;
7465                 return NT_STATUS_NO_MEMORY;
7466         }
7467         pdata = *ppdata;
7468
7469         if (extended_oplock_granted) {
7470                 if (flags & REQUEST_BATCH_OPLOCK) {
7471                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7472                 } else {
7473                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7474                 }
7475         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7476                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7477         } else {
7478                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7479         }
7480
7481         SSVAL(pdata,2,fsp->fnum);
7482         SIVAL(pdata,4,info); /* Was file created etc. */
7483
7484         switch (info_level_return) {
7485                 case SMB_QUERY_FILE_UNIX_BASIC:
7486                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7487                         SSVAL(pdata,10,0); /* padding. */
7488                         store_file_unix_basic(conn, pdata + 12, fsp,
7489                                               &smb_fname->st);
7490                         break;
7491                 case SMB_QUERY_FILE_UNIX_INFO2:
7492                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7493                         SSVAL(pdata,10,0); /* padding. */
7494                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7495                                                     &smb_fname->st);
7496                         break;
7497                 default:
7498                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7499                         SSVAL(pdata,10,0); /* padding. */
7500                         break;
7501         }
7502         return NT_STATUS_OK;
7503 }
7504
7505 /****************************************************************************
7506  Delete a file with POSIX semantics.
7507 ****************************************************************************/
7508
7509 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7510                                  struct smb_request *req,
7511                                 const char *pdata,
7512                                 int total_data,
7513                                 struct smb_filename *smb_fname)
7514 {
7515         NTSTATUS status = NT_STATUS_OK;
7516         files_struct *fsp = NULL;
7517         uint16 flags = 0;
7518         char del = 1;
7519         int info = 0;
7520         int create_options = 0;
7521         int i;
7522         struct share_mode_lock *lck = NULL;
7523
7524         if (total_data < 2) {
7525                 return NT_STATUS_INVALID_PARAMETER;
7526         }
7527
7528         flags = SVAL(pdata,0);
7529
7530         if (!VALID_STAT(smb_fname->st)) {
7531                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7532         }
7533
7534         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7535                         !VALID_STAT_OF_DIR(smb_fname->st)) {
7536                 return NT_STATUS_NOT_A_DIRECTORY;
7537         }
7538
7539         DEBUG(10,("smb_posix_unlink: %s %s\n",
7540                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7541                 smb_fname_str_dbg(smb_fname)));
7542
7543         if (VALID_STAT_OF_DIR(smb_fname->st)) {
7544                 create_options |= FILE_DIRECTORY_FILE;
7545         }
7546
7547         status = SMB_VFS_CREATE_FILE(
7548                 conn,                                   /* conn */
7549                 req,                                    /* req */
7550                 0,                                      /* root_dir_fid */
7551                 smb_fname,                              /* fname */
7552                 DELETE_ACCESS,                          /* access_mask */
7553                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7554                     FILE_SHARE_DELETE),
7555                 FILE_OPEN,                              /* create_disposition*/
7556                 create_options,                         /* create_options */
7557                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
7558                 0,                                      /* oplock_request */
7559                 0,                                      /* allocation_size */
7560                 0,                                      /* private_flags */
7561                 NULL,                                   /* sd */
7562                 NULL,                                   /* ea_list */
7563                 &fsp,                                   /* result */
7564                 &info);                                 /* pinfo */
7565
7566         if (!NT_STATUS_IS_OK(status)) {
7567                 return status;
7568         }
7569
7570         /*
7571          * Don't lie to client. If we can't really delete due to
7572          * non-POSIX opens return SHARING_VIOLATION.
7573          */
7574
7575         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7576                                   NULL);
7577         if (lck == NULL) {
7578                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7579                           "lock for file %s\n", fsp_str_dbg(fsp)));
7580                 close_file(req, fsp, NORMAL_CLOSE);
7581                 return NT_STATUS_INVALID_PARAMETER;
7582         }
7583
7584         /*
7585          * See if others still have the file open. If this is the case, then
7586          * don't delete. If all opens are POSIX delete we can set the delete
7587          * on close disposition.
7588          */
7589         for (i=0; i<lck->num_share_modes; i++) {
7590                 struct share_mode_entry *e = &lck->share_modes[i];
7591                 if (is_valid_share_mode_entry(e)) {
7592                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7593                                 continue;
7594                         }
7595                         /* Fail with sharing violation. */
7596                         close_file(req, fsp, NORMAL_CLOSE);
7597                         TALLOC_FREE(lck);
7598                         return NT_STATUS_SHARING_VIOLATION;
7599                 }
7600         }
7601
7602         /*
7603          * Set the delete on close.
7604          */
7605         status = smb_set_file_disposition_info(conn,
7606                                                 &del,
7607                                                 1,
7608                                                 fsp,
7609                                                 smb_fname);
7610
7611         if (!NT_STATUS_IS_OK(status)) {
7612                 close_file(req, fsp, NORMAL_CLOSE);
7613                 TALLOC_FREE(lck);
7614                 return status;
7615         }
7616         TALLOC_FREE(lck);
7617         return close_file(req, fsp, NORMAL_CLOSE);
7618 }
7619
7620 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7621                                 struct smb_request *req,
7622                                 TALLOC_CTX *mem_ctx,
7623                                 uint16_t info_level,
7624                                 files_struct *fsp,
7625                                 struct smb_filename *smb_fname,
7626                                 char **ppdata, int total_data,
7627                                 int *ret_data_size)
7628 {
7629         char *pdata = *ppdata;
7630         NTSTATUS status = NT_STATUS_OK;
7631         int data_return_size = 0;
7632
7633         *ret_data_size = 0;
7634
7635         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7636                 return NT_STATUS_INVALID_LEVEL;
7637         }
7638
7639         if (!CAN_WRITE(conn)) {
7640                 /* Allow POSIX opens. The open path will deny
7641                  * any non-readonly opens. */
7642                 if (info_level != SMB_POSIX_PATH_OPEN) {
7643                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
7644                 }
7645         }
7646
7647         DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7648                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7649                  fsp ? fsp->fnum : -1, info_level, total_data));
7650
7651         switch (info_level) {
7652
7653                 case SMB_INFO_STANDARD:
7654                 {
7655                         status = smb_set_info_standard(conn,
7656                                         pdata,
7657                                         total_data,
7658                                         fsp,
7659                                         smb_fname);
7660                         break;
7661                 }
7662
7663                 case SMB_INFO_SET_EA:
7664                 {
7665                         status = smb_info_set_ea(conn,
7666                                                 pdata,
7667                                                 total_data,
7668                                                 fsp,
7669                                                 smb_fname);
7670                         break;
7671                 }
7672
7673                 case SMB_SET_FILE_BASIC_INFO:
7674                 case SMB_FILE_BASIC_INFORMATION:
7675                 {
7676                         status = smb_set_file_basic_info(conn,
7677                                                         pdata,
7678                                                         total_data,
7679                                                         fsp,
7680                                                         smb_fname);
7681                         break;
7682                 }
7683
7684                 case SMB_FILE_ALLOCATION_INFORMATION:
7685                 case SMB_SET_FILE_ALLOCATION_INFO:
7686                 {
7687                         status = smb_set_file_allocation_info(conn, req,
7688                                                                 pdata,
7689                                                                 total_data,
7690                                                                 fsp,
7691                                                                 smb_fname);
7692                         break;
7693                 }
7694
7695                 case SMB_FILE_END_OF_FILE_INFORMATION:
7696                 case SMB_SET_FILE_END_OF_FILE_INFO:
7697                 {
7698                         /*
7699                          * XP/Win7 both fail after the createfile with
7700                          * SMB_SET_FILE_END_OF_FILE_INFO but not
7701                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7702                          * The level is known here, so pass it down
7703                          * appropriately.
7704                          */
7705                         bool should_fail =
7706                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7707
7708                         status = smb_set_file_end_of_file_info(conn, req,
7709                                                                 pdata,
7710                                                                 total_data,
7711                                                                 fsp,
7712                                                                 smb_fname,
7713                                                                 should_fail);
7714                         break;
7715                 }
7716
7717                 case SMB_FILE_DISPOSITION_INFORMATION:
7718                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7719                 {
7720 #if 0
7721                         /* JRA - We used to just ignore this on a path ? 
7722                          * Shouldn't this be invalid level on a pathname
7723                          * based call ?
7724                          */
7725                         if (tran_call != TRANSACT2_SETFILEINFO) {
7726                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7727                         }
7728 #endif
7729                         status = smb_set_file_disposition_info(conn,
7730                                                 pdata,
7731                                                 total_data,
7732                                                 fsp,
7733                                                 smb_fname);
7734                         break;
7735                 }
7736
7737                 case SMB_FILE_POSITION_INFORMATION:
7738                 {
7739                         status = smb_file_position_information(conn,
7740                                                 pdata,
7741                                                 total_data,
7742                                                 fsp);
7743                         break;
7744                 }
7745
7746                 case SMB_FILE_FULL_EA_INFORMATION:
7747                 {
7748                         status = smb_set_file_full_ea_info(conn,
7749                                                 pdata,
7750                                                 total_data,
7751                                                 fsp);
7752                         break;
7753                 }
7754
7755                 /* From tridge Samba4 : 
7756                  * MODE_INFORMATION in setfileinfo (I have no
7757                  * idea what "mode information" on a file is - it takes a value of 0,
7758                  * 2, 4 or 6. What could it be?).
7759                  */
7760
7761                 case SMB_FILE_MODE_INFORMATION:
7762                 {
7763                         status = smb_file_mode_information(conn,
7764                                                 pdata,
7765                                                 total_data);
7766                         break;
7767                 }
7768
7769                 /*
7770                  * CIFS UNIX extensions.
7771                  */
7772
7773                 case SMB_SET_FILE_UNIX_BASIC:
7774                 {
7775                         status = smb_set_file_unix_basic(conn, req,
7776                                                         pdata,
7777                                                         total_data,
7778                                                         fsp,
7779                                                         smb_fname);
7780                         break;
7781                 }
7782
7783                 case SMB_SET_FILE_UNIX_INFO2:
7784                 {
7785                         status = smb_set_file_unix_info2(conn, req,
7786                                                         pdata,
7787                                                         total_data,
7788                                                         fsp,
7789                                                         smb_fname);
7790                         break;
7791                 }
7792
7793                 case SMB_SET_FILE_UNIX_LINK:
7794                 {
7795                         if (fsp) {
7796                                 /* We must have a pathname for this. */
7797                                 return NT_STATUS_INVALID_LEVEL;
7798                         }
7799                         status = smb_set_file_unix_link(conn, req, pdata,
7800                                                         total_data, smb_fname);
7801                         break;
7802                 }
7803
7804                 case SMB_SET_FILE_UNIX_HLINK:
7805                 {
7806                         if (fsp) {
7807                                 /* We must have a pathname for this. */
7808                                 return NT_STATUS_INVALID_LEVEL;
7809                         }
7810                         status = smb_set_file_unix_hlink(conn, req,
7811                                                          pdata, total_data,
7812                                                          smb_fname);
7813                         break;
7814                 }
7815
7816                 case SMB_FILE_RENAME_INFORMATION:
7817                 {
7818                         status = smb_file_rename_information(conn, req,
7819                                                              pdata, total_data,
7820                                                              fsp, smb_fname);
7821                         break;
7822                 }
7823
7824                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7825                 {
7826                         /* SMB2 rename information. */
7827                         status = smb2_file_rename_information(conn, req,
7828                                                              pdata, total_data,
7829                                                              fsp, smb_fname);
7830                         break;
7831                 }
7832
7833                 case SMB_FILE_LINK_INFORMATION:
7834                 {
7835                         status = smb_file_link_information(conn, req,
7836                                                         pdata, total_data,
7837                                                         fsp, smb_fname);
7838                         break;
7839                 }
7840
7841 #if defined(HAVE_POSIX_ACLS)
7842                 case SMB_SET_POSIX_ACL:
7843                 {
7844                         status = smb_set_posix_acl(conn,
7845                                                 pdata,
7846                                                 total_data,
7847                                                 fsp,
7848                                                 smb_fname);
7849                         break;
7850                 }
7851 #endif
7852
7853                 case SMB_SET_POSIX_LOCK:
7854                 {
7855                         if (!fsp) {
7856                                 return NT_STATUS_INVALID_LEVEL;
7857                         }
7858                         status = smb_set_posix_lock(conn, req,
7859                                                     pdata, total_data, fsp);
7860                         break;
7861                 }
7862
7863                 case SMB_POSIX_PATH_OPEN:
7864                 {
7865                         if (fsp) {
7866                                 /* We must have a pathname for this. */
7867                                 return NT_STATUS_INVALID_LEVEL;
7868                         }
7869
7870                         status = smb_posix_open(conn, req,
7871                                                 ppdata,
7872                                                 total_data,
7873                                                 smb_fname,
7874                                                 &data_return_size);
7875                         break;
7876                 }
7877
7878                 case SMB_POSIX_PATH_UNLINK:
7879                 {
7880                         if (fsp) {
7881                                 /* We must have a pathname for this. */
7882                                 return NT_STATUS_INVALID_LEVEL;
7883                         }
7884
7885                         status = smb_posix_unlink(conn, req,
7886                                                 pdata,
7887                                                 total_data,
7888                                                 smb_fname);
7889                         break;
7890                 }
7891
7892                 default:
7893                         return NT_STATUS_INVALID_LEVEL;
7894         }
7895
7896         if (!NT_STATUS_IS_OK(status)) {
7897                 return status;
7898         }
7899
7900         *ret_data_size = data_return_size;
7901         return NT_STATUS_OK;
7902 }
7903
7904 /****************************************************************************
7905  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7906 ****************************************************************************/
7907
7908 static void call_trans2setfilepathinfo(connection_struct *conn,
7909                                        struct smb_request *req,
7910                                        unsigned int tran_call,
7911                                        char **pparams, int total_params,
7912                                        char **ppdata, int total_data,
7913                                        unsigned int max_data_bytes)
7914 {
7915         char *params = *pparams;
7916         char *pdata = *ppdata;
7917         uint16 info_level;
7918         struct smb_filename *smb_fname = NULL;
7919         files_struct *fsp = NULL;
7920         NTSTATUS status = NT_STATUS_OK;
7921         int data_return_size = 0;
7922
7923         if (!params) {
7924                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7925                 return;
7926         }
7927
7928         if (tran_call == TRANSACT2_SETFILEINFO) {
7929                 if (total_params < 4) {
7930                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7931                         return;
7932                 }
7933
7934                 fsp = file_fsp(req, SVAL(params,0));
7935                 /* Basic check for non-null fsp. */
7936                 if (!check_fsp_open(conn, req, fsp)) {
7937                         return;
7938                 }
7939                 info_level = SVAL(params,2);
7940
7941                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7942                                            &smb_fname);
7943                 if (!NT_STATUS_IS_OK(status)) {
7944                         reply_nterror(req, status);
7945                         return;
7946                 }
7947
7948                 if(fsp->fh->fd == -1) {
7949                         /*
7950                          * This is actually a SETFILEINFO on a directory
7951                          * handle (returned from an NT SMB). NT5.0 seems
7952                          * to do this call. JRA.
7953                          */
7954                         if (INFO_LEVEL_IS_UNIX(info_level)) {
7955                                 /* Always do lstat for UNIX calls. */
7956                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7957                                         DEBUG(3,("call_trans2setfilepathinfo: "
7958                                                  "SMB_VFS_LSTAT of %s failed "
7959                                                  "(%s)\n",
7960                                                  smb_fname_str_dbg(smb_fname),
7961                                                  strerror(errno)));
7962                                         reply_nterror(req, map_nt_error_from_unix(errno));
7963                                         return;
7964                                 }
7965                         } else {
7966                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7967                                         DEBUG(3,("call_trans2setfilepathinfo: "
7968                                                  "fileinfo of %s failed (%s)\n",
7969                                                  smb_fname_str_dbg(smb_fname),
7970                                                  strerror(errno)));
7971                                         reply_nterror(req, map_nt_error_from_unix(errno));
7972                                         return;
7973                                 }
7974                         }
7975                 } else if (fsp->print_file) {
7976                         /*
7977                          * Doing a DELETE_ON_CLOSE should cancel a print job.
7978                          */
7979                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7980                                 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7981
7982                                 DEBUG(3,("call_trans2setfilepathinfo: "
7983                                          "Cancelling print job (%s)\n",
7984                                          fsp_str_dbg(fsp)));
7985
7986                                 SSVAL(params,0,0);
7987                                 send_trans2_replies(conn, req, params, 2,
7988                                                     *ppdata, 0,
7989                                                     max_data_bytes);
7990                                 return;
7991                         } else {
7992                                 reply_nterror(req,
7993                                         NT_STATUS_OBJECT_PATH_NOT_FOUND);
7994                                 return;
7995                         }
7996                 } else {
7997                         /*
7998                          * Original code - this is an open file.
7999                          */
8000                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8001                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8002                                          "of fnum %d failed (%s)\n", fsp->fnum,
8003                                          strerror(errno)));
8004                                 reply_nterror(req, map_nt_error_from_unix(errno));
8005                                 return;
8006                         }
8007                 }
8008         } else {
8009                 char *fname = NULL;
8010                 uint32_t ucf_flags = 0;
8011
8012                 /* set path info */
8013                 if (total_params < 7) {
8014                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8015                         return;
8016                 }
8017
8018                 info_level = SVAL(params,0);
8019                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8020                                 total_params - 6, STR_TERMINATE,
8021                                 &status);
8022                 if (!NT_STATUS_IS_OK(status)) {
8023                         reply_nterror(req, status);
8024                         return;
8025                 }
8026
8027                 if (INFO_LEVEL_IS_UNIX(info_level)) {
8028                         ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8029                 }
8030
8031                 status = filename_convert(req, conn,
8032                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
8033                                          fname,
8034                                          ucf_flags,
8035                                          NULL,
8036                                          &smb_fname);
8037                 if (!NT_STATUS_IS_OK(status)) {
8038                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8039                                 reply_botherror(req,
8040                                                 NT_STATUS_PATH_NOT_COVERED,
8041                                                 ERRSRV, ERRbadpath);
8042                                 return;
8043                         }
8044                         reply_nterror(req, status);
8045                         return;
8046                 }
8047
8048                 if (INFO_LEVEL_IS_UNIX(info_level)) {
8049                         /*
8050                          * For CIFS UNIX extensions the target name may not exist.
8051                          */
8052
8053                         /* Always do lstat for UNIX calls. */
8054                         SMB_VFS_LSTAT(conn, smb_fname);
8055
8056                 } else if (!VALID_STAT(smb_fname->st) &&
8057                            SMB_VFS_STAT(conn, smb_fname)) {
8058                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8059                                  "%s failed (%s)\n",
8060                                  smb_fname_str_dbg(smb_fname),
8061                                  strerror(errno)));
8062                         reply_nterror(req, map_nt_error_from_unix(errno));
8063                         return;
8064                 }
8065         }
8066
8067         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8068                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8069                  fsp ? fsp->fnum : -1, info_level,total_data));
8070
8071         /* Realloc the parameter size */
8072         *pparams = (char *)SMB_REALLOC(*pparams,2);
8073         if (*pparams == NULL) {
8074                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8075                 return;
8076         }
8077         params = *pparams;
8078
8079         SSVAL(params,0,0);
8080
8081         status = smbd_do_setfilepathinfo(conn, req, req,
8082                                          info_level,
8083                                          fsp,
8084                                          smb_fname,
8085                                          ppdata, total_data,
8086                                          &data_return_size);
8087         if (!NT_STATUS_IS_OK(status)) {
8088                 if (open_was_deferred(req->sconn, req->mid)) {
8089                         /* We have re-scheduled this call. */
8090                         return;
8091                 }
8092                 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8093                         /* We have re-scheduled this call. */
8094                         return;
8095                 }
8096                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8097                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8098                                         ERRSRV, ERRbadpath);
8099                         return;
8100                 }
8101                 if (info_level == SMB_POSIX_PATH_OPEN) {
8102                         reply_openerror(req, status);
8103                         return;
8104                 }
8105
8106                 reply_nterror(req, status);
8107                 return;
8108         }
8109
8110         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8111                             max_data_bytes);
8112
8113         return;
8114 }
8115
8116 /****************************************************************************
8117  Reply to a TRANS2_MKDIR (make directory with extended attributes).
8118 ****************************************************************************/
8119
8120 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8121                              char **pparams, int total_params,
8122                              char **ppdata, int total_data,
8123                              unsigned int max_data_bytes)
8124 {
8125         struct smb_filename *smb_dname = NULL;
8126         char *params = *pparams;
8127         char *pdata = *ppdata;
8128         char *directory = NULL;
8129         NTSTATUS status = NT_STATUS_OK;
8130         struct ea_list *ea_list = NULL;
8131         TALLOC_CTX *ctx = talloc_tos();
8132
8133         if (!CAN_WRITE(conn)) {
8134                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8135                 return;
8136         }
8137
8138         if (total_params < 5) {
8139                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8140                 return;
8141         }
8142
8143         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8144                         total_params - 4, STR_TERMINATE,
8145                         &status);
8146         if (!NT_STATUS_IS_OK(status)) {
8147                 reply_nterror(req, status);
8148                 return;
8149         }
8150
8151         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8152
8153         status = filename_convert(ctx,
8154                                 conn,
8155                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
8156                                 directory,
8157                                 0,
8158                                 NULL,
8159                                 &smb_dname);
8160
8161         if (!NT_STATUS_IS_OK(status)) {
8162                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8163                         reply_botherror(req,
8164                                 NT_STATUS_PATH_NOT_COVERED,
8165                                 ERRSRV, ERRbadpath);
8166                         return;
8167                 }
8168                 reply_nterror(req, status);
8169                 return;
8170         }
8171
8172         /*
8173          * OS/2 workplace shell seems to send SET_EA requests of "null"
8174          * length (4 bytes containing IVAL 4).
8175          * They seem to have no effect. Bug #3212. JRA.
8176          */
8177
8178         if (total_data && (total_data != 4)) {
8179                 /* Any data in this call is an EA list. */
8180                 if (total_data < 10) {
8181                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8182                         goto out;
8183                 }
8184
8185                 if (IVAL(pdata,0) > total_data) {
8186                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8187                                 IVAL(pdata,0), (unsigned int)total_data));
8188                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8189                         goto out;
8190                 }
8191
8192                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8193                                        total_data - 4);
8194                 if (!ea_list) {
8195                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8196                         goto out;
8197                 }
8198
8199                 if (!lp_ea_support(SNUM(conn))) {
8200                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8201                         goto out;
8202                 }
8203         }
8204         /* If total_data == 4 Windows doesn't care what values
8205          * are placed in that field, it just ignores them.
8206          * The System i QNTC IBM SMB client puts bad values here,
8207          * so ignore them. */
8208
8209         status = create_directory(conn, req, smb_dname);
8210
8211         if (!NT_STATUS_IS_OK(status)) {
8212                 reply_nterror(req, status);
8213                 goto out;
8214         }
8215
8216         /* Try and set any given EA. */
8217         if (ea_list) {
8218                 status = set_ea(conn, NULL, smb_dname, ea_list);
8219                 if (!NT_STATUS_IS_OK(status)) {
8220                         reply_nterror(req, status);
8221                         goto out;
8222                 }
8223         }
8224
8225         /* Realloc the parameter and data sizes */
8226         *pparams = (char *)SMB_REALLOC(*pparams,2);
8227         if(*pparams == NULL) {
8228                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8229                 goto out;
8230         }
8231         params = *pparams;
8232
8233         SSVAL(params,0,0);
8234
8235         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8236
8237  out:
8238         TALLOC_FREE(smb_dname);
8239         return;
8240 }
8241
8242 /****************************************************************************
8243  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8244  We don't actually do this - we just send a null response.
8245 ****************************************************************************/
8246
8247 static void call_trans2findnotifyfirst(connection_struct *conn,
8248                                        struct smb_request *req,
8249                                        char **pparams, int total_params,
8250                                        char **ppdata, int total_data,
8251                                        unsigned int max_data_bytes)
8252 {
8253         char *params = *pparams;
8254         uint16 info_level;
8255
8256         if (total_params < 6) {
8257                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8258                 return;
8259         }
8260
8261         info_level = SVAL(params,4);
8262         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8263
8264         switch (info_level) {
8265                 case 1:
8266                 case 2:
8267                         break;
8268                 default:
8269                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8270                         return;
8271         }
8272
8273         /* Realloc the parameter and data sizes */
8274         *pparams = (char *)SMB_REALLOC(*pparams,6);
8275         if (*pparams == NULL) {
8276                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8277                 return;
8278         }
8279         params = *pparams;
8280
8281         SSVAL(params,0,fnf_handle);
8282         SSVAL(params,2,0); /* No changes */
8283         SSVAL(params,4,0); /* No EA errors */
8284
8285         fnf_handle++;
8286
8287         if(fnf_handle == 0)
8288                 fnf_handle = 257;
8289
8290         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8291
8292         return;
8293 }
8294
8295 /****************************************************************************
8296  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
8297  changes). Currently this does nothing.
8298 ****************************************************************************/
8299
8300 static void call_trans2findnotifynext(connection_struct *conn,
8301                                       struct smb_request *req,
8302                                       char **pparams, int total_params,
8303                                       char **ppdata, int total_data,
8304                                       unsigned int max_data_bytes)
8305 {
8306         char *params = *pparams;
8307
8308         DEBUG(3,("call_trans2findnotifynext\n"));
8309
8310         /* Realloc the parameter and data sizes */
8311         *pparams = (char *)SMB_REALLOC(*pparams,4);
8312         if (*pparams == NULL) {
8313                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8314                 return;
8315         }
8316         params = *pparams;
8317
8318         SSVAL(params,0,0); /* No changes */
8319         SSVAL(params,2,0); /* No EA errors */
8320
8321         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8322
8323         return;
8324 }
8325
8326 /****************************************************************************
8327  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8328 ****************************************************************************/
8329
8330 static void call_trans2getdfsreferral(connection_struct *conn,
8331                                       struct smb_request *req,
8332                                       char **pparams, int total_params,
8333                                       char **ppdata, int total_data,
8334                                       unsigned int max_data_bytes)
8335 {
8336         char *params = *pparams;
8337         char *pathname = NULL;
8338         int reply_size = 0;
8339         int max_referral_level;
8340         NTSTATUS status = NT_STATUS_OK;
8341         TALLOC_CTX *ctx = talloc_tos();
8342
8343         DEBUG(10,("call_trans2getdfsreferral\n"));
8344
8345         if (total_params < 3) {
8346                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8347                 return;
8348         }
8349
8350         max_referral_level = SVAL(params,0);
8351
8352         if(!lp_host_msdfs()) {
8353                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8354                 return;
8355         }
8356
8357         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8358                     total_params - 2, STR_TERMINATE);
8359         if (!pathname) {
8360                 reply_nterror(req, NT_STATUS_NOT_FOUND);
8361                 return;
8362         }
8363         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8364                                             ppdata,&status)) < 0) {
8365                 reply_nterror(req, status);
8366                 return;
8367         }
8368
8369         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8370               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8371         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8372
8373         return;
8374 }
8375
8376 #define LMCAT_SPL       0x53
8377 #define LMFUNC_GETJOBID 0x60
8378
8379 /****************************************************************************
8380  Reply to a TRANS2_IOCTL - used for OS/2 printing.
8381 ****************************************************************************/
8382
8383 static void call_trans2ioctl(connection_struct *conn,
8384                              struct smb_request *req,
8385                              char **pparams, int total_params,
8386                              char **ppdata, int total_data,
8387                              unsigned int max_data_bytes)
8388 {
8389         char *pdata = *ppdata;
8390         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8391
8392         /* check for an invalid fid before proceeding */
8393
8394         if (!fsp) {
8395                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8396                 return;
8397         }
8398
8399         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8400             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8401                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8402                 if (*ppdata == NULL) {
8403                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8404                         return;
8405                 }
8406                 pdata = *ppdata;
8407
8408                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8409                         CAN ACCEPT THIS IN UNICODE. JRA. */
8410
8411                 /* Job number */
8412                 if (fsp->print_file) {
8413                         SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8414                 } else {
8415                         SSVAL(pdata, 0, 0);
8416                 }
8417                 srvstr_push(pdata, req->flags2, pdata + 2,
8418                             lp_netbios_name(), 15,
8419                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8420                 srvstr_push(pdata, req->flags2, pdata+18,
8421                             lp_servicename(SNUM(conn)), 13,
8422                             STR_ASCII|STR_TERMINATE); /* Service name */
8423                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8424                                     max_data_bytes);
8425                 return;
8426         }
8427
8428         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8429         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8430 }
8431
8432 /****************************************************************************
8433  Reply to a SMBfindclose (stop trans2 directory search).
8434 ****************************************************************************/
8435
8436 void reply_findclose(struct smb_request *req)
8437 {
8438         int dptr_num;
8439         struct smbd_server_connection *sconn = req->sconn;
8440
8441         START_PROFILE(SMBfindclose);
8442
8443         if (req->wct < 1) {
8444                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445                 END_PROFILE(SMBfindclose);
8446                 return;
8447         }
8448
8449         dptr_num = SVALS(req->vwv+0, 0);
8450
8451         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8452
8453         dptr_close(sconn, &dptr_num);
8454
8455         reply_outbuf(req, 0, 0);
8456
8457         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8458
8459         END_PROFILE(SMBfindclose);
8460         return;
8461 }
8462
8463 /****************************************************************************
8464  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8465 ****************************************************************************/
8466
8467 void reply_findnclose(struct smb_request *req)
8468 {
8469         int dptr_num;
8470
8471         START_PROFILE(SMBfindnclose);
8472
8473         if (req->wct < 1) {
8474                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8475                 END_PROFILE(SMBfindnclose);
8476                 return;
8477         }
8478
8479         dptr_num = SVAL(req->vwv+0, 0);
8480
8481         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8482
8483         /* We never give out valid handles for a 
8484            findnotifyfirst - so any dptr_num is ok here. 
8485            Just ignore it. */
8486
8487         reply_outbuf(req, 0, 0);
8488
8489         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8490
8491         END_PROFILE(SMBfindnclose);
8492         return;
8493 }
8494
8495 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8496                           struct trans_state *state)
8497 {
8498         if (get_Protocol() >= PROTOCOL_NT1) {
8499                 req->flags2 |= 0x40; /* IS_LONG_NAME */
8500                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8501         }
8502
8503         if (conn->encrypt_level == Required && !req->encrypted) {
8504                 if (state->call != TRANSACT2_QFSINFO &&
8505                                 state->call != TRANSACT2_SETFSINFO) {
8506                         DEBUG(0,("handle_trans2: encryption required "
8507                                 "with call 0x%x\n",
8508                                 (unsigned int)state->call));
8509                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8510                         return;
8511                 }
8512         }
8513
8514         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8515
8516         /* Now we must call the relevant TRANS2 function */
8517         switch(state->call)  {
8518         case TRANSACT2_OPEN:
8519         {
8520                 START_PROFILE(Trans2_open);
8521                 call_trans2open(conn, req,
8522                                 &state->param, state->total_param,
8523                                 &state->data, state->total_data,
8524                                 state->max_data_return);
8525                 END_PROFILE(Trans2_open);
8526                 break;
8527         }
8528
8529         case TRANSACT2_FINDFIRST:
8530         {
8531                 START_PROFILE(Trans2_findfirst);
8532                 call_trans2findfirst(conn, req,
8533                                      &state->param, state->total_param,
8534                                      &state->data, state->total_data,
8535                                      state->max_data_return);
8536                 END_PROFILE(Trans2_findfirst);
8537                 break;
8538         }
8539
8540         case TRANSACT2_FINDNEXT:
8541         {
8542                 START_PROFILE(Trans2_findnext);
8543                 call_trans2findnext(conn, req,
8544                                     &state->param, state->total_param,
8545                                     &state->data, state->total_data,
8546                                     state->max_data_return);
8547                 END_PROFILE(Trans2_findnext);
8548                 break;
8549         }
8550
8551         case TRANSACT2_QFSINFO:
8552         {
8553                 START_PROFILE(Trans2_qfsinfo);
8554                 call_trans2qfsinfo(conn, req,
8555                                    &state->param, state->total_param,
8556                                    &state->data, state->total_data,
8557                                    state->max_data_return);
8558                 END_PROFILE(Trans2_qfsinfo);
8559             break;
8560         }
8561
8562         case TRANSACT2_SETFSINFO:
8563         {
8564                 START_PROFILE(Trans2_setfsinfo);
8565                 call_trans2setfsinfo(conn, req,
8566                                      &state->param, state->total_param,
8567                                      &state->data, state->total_data,
8568                                      state->max_data_return);
8569                 END_PROFILE(Trans2_setfsinfo);
8570                 break;
8571         }
8572
8573         case TRANSACT2_QPATHINFO:
8574         case TRANSACT2_QFILEINFO:
8575         {
8576                 START_PROFILE(Trans2_qpathinfo);
8577                 call_trans2qfilepathinfo(conn, req, state->call,
8578                                          &state->param, state->total_param,
8579                                          &state->data, state->total_data,
8580                                          state->max_data_return);
8581                 END_PROFILE(Trans2_qpathinfo);
8582                 break;
8583         }
8584
8585         case TRANSACT2_SETPATHINFO:
8586         case TRANSACT2_SETFILEINFO:
8587         {
8588                 START_PROFILE(Trans2_setpathinfo);
8589                 call_trans2setfilepathinfo(conn, req, state->call,
8590                                            &state->param, state->total_param,
8591                                            &state->data, state->total_data,
8592                                            state->max_data_return);
8593                 END_PROFILE(Trans2_setpathinfo);
8594                 break;
8595         }
8596
8597         case TRANSACT2_FINDNOTIFYFIRST:
8598         {
8599                 START_PROFILE(Trans2_findnotifyfirst);
8600                 call_trans2findnotifyfirst(conn, req,
8601                                            &state->param, state->total_param,
8602                                            &state->data, state->total_data,
8603                                            state->max_data_return);
8604                 END_PROFILE(Trans2_findnotifyfirst);
8605                 break;
8606         }
8607
8608         case TRANSACT2_FINDNOTIFYNEXT:
8609         {
8610                 START_PROFILE(Trans2_findnotifynext);
8611                 call_trans2findnotifynext(conn, req,
8612                                           &state->param, state->total_param,
8613                                           &state->data, state->total_data,
8614                                           state->max_data_return);
8615                 END_PROFILE(Trans2_findnotifynext);
8616                 break;
8617         }
8618
8619         case TRANSACT2_MKDIR:
8620         {
8621                 START_PROFILE(Trans2_mkdir);
8622                 call_trans2mkdir(conn, req,
8623                                  &state->param, state->total_param,
8624                                  &state->data, state->total_data,
8625                                  state->max_data_return);
8626                 END_PROFILE(Trans2_mkdir);
8627                 break;
8628         }
8629
8630         case TRANSACT2_GET_DFS_REFERRAL:
8631         {
8632                 START_PROFILE(Trans2_get_dfs_referral);
8633                 call_trans2getdfsreferral(conn, req,
8634                                           &state->param, state->total_param,
8635                                           &state->data, state->total_data,
8636                                           state->max_data_return);
8637                 END_PROFILE(Trans2_get_dfs_referral);
8638                 break;
8639         }
8640
8641         case TRANSACT2_IOCTL:
8642         {
8643                 START_PROFILE(Trans2_ioctl);
8644                 call_trans2ioctl(conn, req,
8645                                  &state->param, state->total_param,
8646                                  &state->data, state->total_data,
8647                                  state->max_data_return);
8648                 END_PROFILE(Trans2_ioctl);
8649                 break;
8650         }
8651
8652         default:
8653                 /* Error in request */
8654                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8655                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8656         }
8657 }
8658
8659 /****************************************************************************
8660  Reply to a SMBtrans2.
8661  ****************************************************************************/
8662
8663 void reply_trans2(struct smb_request *req)
8664 {
8665         connection_struct *conn = req->conn;
8666         unsigned int dsoff;
8667         unsigned int dscnt;
8668         unsigned int psoff;
8669         unsigned int pscnt;
8670         unsigned int tran_call;
8671         struct trans_state *state;
8672         NTSTATUS result;
8673
8674         START_PROFILE(SMBtrans2);
8675
8676         if (req->wct < 14) {
8677                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8678                 END_PROFILE(SMBtrans2);
8679                 return;
8680         }
8681
8682         dsoff = SVAL(req->vwv+12, 0);
8683         dscnt = SVAL(req->vwv+11, 0);
8684         psoff = SVAL(req->vwv+10, 0);
8685         pscnt = SVAL(req->vwv+9, 0);
8686         tran_call = SVAL(req->vwv+14, 0);
8687
8688         result = allow_new_trans(conn->pending_trans, req->mid);
8689         if (!NT_STATUS_IS_OK(result)) {
8690                 DEBUG(2, ("Got invalid trans2 request: %s\n",
8691                           nt_errstr(result)));
8692                 reply_nterror(req, result);
8693                 END_PROFILE(SMBtrans2);
8694                 return;
8695         }
8696
8697         if (IS_IPC(conn)) {
8698                 switch (tran_call) {
8699                 /* List the allowed trans2 calls on IPC$ */
8700                 case TRANSACT2_OPEN:
8701                 case TRANSACT2_GET_DFS_REFERRAL:
8702                 case TRANSACT2_QFILEINFO:
8703                 case TRANSACT2_QFSINFO:
8704                 case TRANSACT2_SETFSINFO:
8705                         break;
8706                 default:
8707                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8708                         END_PROFILE(SMBtrans2);
8709                         return;
8710                 }
8711         }
8712
8713         if ((state = talloc(conn, struct trans_state)) == NULL) {
8714                 DEBUG(0, ("talloc failed\n"));
8715                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8716                 END_PROFILE(SMBtrans2);
8717                 return;
8718         }
8719
8720         state->cmd = SMBtrans2;
8721
8722         state->mid = req->mid;
8723         state->vuid = req->vuid;
8724         state->setup_count = SVAL(req->vwv+13, 0);
8725         state->setup = NULL;
8726         state->total_param = SVAL(req->vwv+0, 0);
8727         state->param = NULL;
8728         state->total_data =  SVAL(req->vwv+1, 0);
8729         state->data = NULL;
8730         state->max_param_return = SVAL(req->vwv+2, 0);
8731         state->max_data_return  = SVAL(req->vwv+3, 0);
8732         state->max_setup_return = SVAL(req->vwv+4, 0);
8733         state->close_on_completion = BITSETW(req->vwv+5, 0);
8734         state->one_way = BITSETW(req->vwv+5, 1);
8735
8736         state->call = tran_call;
8737
8738         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8739            is so as a sanity check */
8740         if (state->setup_count != 1) {
8741                 /*
8742                  * Need to have rc=0 for ioctl to get job id for OS/2.
8743                  *  Network printing will fail if function is not successful.
8744                  *  Similar function in reply.c will be used if protocol
8745                  *  is LANMAN1.0 instead of LM1.2X002.
8746                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
8747                  *  outbuf doesn't have to be set(only job id is used).
8748                  */
8749                 if ( (state->setup_count == 4)
8750                      && (tran_call == TRANSACT2_IOCTL)
8751                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8752                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8753                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8754                 } else {
8755                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8756                         DEBUG(2,("Transaction is %d\n",tran_call));
8757                         TALLOC_FREE(state);
8758                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8759                         END_PROFILE(SMBtrans2);
8760                         return;
8761                 }
8762         }
8763
8764         if ((dscnt > state->total_data) || (pscnt > state->total_param))
8765                 goto bad_param;
8766
8767         if (state->total_data) {
8768
8769                 if (trans_oob(state->total_data, 0, dscnt)
8770                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8771                         goto bad_param;
8772                 }
8773
8774                 /* Can't use talloc here, the core routines do realloc on the
8775                  * params and data. */
8776                 state->data = (char *)SMB_MALLOC(state->total_data);
8777                 if (state->data == NULL) {
8778                         DEBUG(0,("reply_trans2: data malloc fail for %u "
8779                                  "bytes !\n", (unsigned int)state->total_data));
8780                         TALLOC_FREE(state);
8781                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8782                         END_PROFILE(SMBtrans2);
8783                         return;
8784                 }
8785
8786                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8787         }
8788
8789         if (state->total_param) {
8790
8791                 if (trans_oob(state->total_param, 0, pscnt)
8792                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8793                         goto bad_param;
8794                 }
8795
8796                 /* Can't use talloc here, the core routines do realloc on the
8797                  * params and data. */
8798                 state->param = (char *)SMB_MALLOC(state->total_param);
8799                 if (state->param == NULL) {
8800                         DEBUG(0,("reply_trans: param malloc fail for %u "
8801                                  "bytes !\n", (unsigned int)state->total_param));
8802                         SAFE_FREE(state->data);
8803                         TALLOC_FREE(state);
8804                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8805                         END_PROFILE(SMBtrans2);
8806                         return;
8807                 } 
8808
8809                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8810         }
8811
8812         state->received_data  = dscnt;
8813         state->received_param = pscnt;
8814
8815         if ((state->received_param == state->total_param) &&
8816             (state->received_data == state->total_data)) {
8817
8818                 handle_trans2(conn, req, state);
8819
8820                 SAFE_FREE(state->data);
8821                 SAFE_FREE(state->param);
8822                 TALLOC_FREE(state);
8823                 END_PROFILE(SMBtrans2);
8824                 return;
8825         }
8826
8827         DLIST_ADD(conn->pending_trans, state);
8828
8829         /* We need to send an interim response then receive the rest
8830            of the parameter/data bytes */
8831         reply_outbuf(req, 0, 0);
8832         show_msg((char *)req->outbuf);
8833         END_PROFILE(SMBtrans2);
8834         return;
8835
8836   bad_param:
8837
8838         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8839         SAFE_FREE(state->data);
8840         SAFE_FREE(state->param);
8841         TALLOC_FREE(state);
8842         END_PROFILE(SMBtrans2);
8843         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8844 }
8845
8846
8847 /****************************************************************************
8848  Reply to a SMBtranss2
8849  ****************************************************************************/
8850
8851 void reply_transs2(struct smb_request *req)
8852 {
8853         connection_struct *conn = req->conn;
8854         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8855         struct trans_state *state;
8856
8857         START_PROFILE(SMBtranss2);
8858
8859         show_msg((const char *)req->inbuf);
8860
8861         if (req->wct < 8) {
8862                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8863                 END_PROFILE(SMBtranss2);
8864                 return;
8865         }
8866
8867         for (state = conn->pending_trans; state != NULL;
8868              state = state->next) {
8869                 if (state->mid == req->mid) {
8870                         break;
8871                 }
8872         }
8873
8874         if ((state == NULL) || (state->cmd != SMBtrans2)) {
8875                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8876                 END_PROFILE(SMBtranss2);
8877                 return;
8878         }
8879
8880         /* Revise state->total_param and state->total_data in case they have
8881            changed downwards */
8882
8883         if (SVAL(req->vwv+0, 0) < state->total_param)
8884                 state->total_param = SVAL(req->vwv+0, 0);
8885         if (SVAL(req->vwv+1, 0) < state->total_data)
8886                 state->total_data = SVAL(req->vwv+1, 0);
8887
8888         pcnt = SVAL(req->vwv+2, 0);
8889         poff = SVAL(req->vwv+3, 0);
8890         pdisp = SVAL(req->vwv+4, 0);
8891
8892         dcnt = SVAL(req->vwv+5, 0);
8893         doff = SVAL(req->vwv+6, 0);
8894         ddisp = SVAL(req->vwv+7, 0);
8895
8896         state->received_param += pcnt;
8897         state->received_data += dcnt;
8898
8899         if ((state->received_data > state->total_data) ||
8900             (state->received_param > state->total_param))
8901                 goto bad_param;
8902
8903         if (pcnt) {
8904                 if (trans_oob(state->total_param, pdisp, pcnt)
8905                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8906                         goto bad_param;
8907                 }
8908                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8909         }
8910
8911         if (dcnt) {
8912                 if (trans_oob(state->total_data, ddisp, dcnt)
8913                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8914                         goto bad_param;
8915                 }
8916                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8917         }
8918
8919         if ((state->received_param < state->total_param) ||
8920             (state->received_data < state->total_data)) {
8921                 END_PROFILE(SMBtranss2);
8922                 return;
8923         }
8924
8925         handle_trans2(conn, req, state);
8926
8927         DLIST_REMOVE(conn->pending_trans, state);
8928         SAFE_FREE(state->data);
8929         SAFE_FREE(state->param);
8930         TALLOC_FREE(state);
8931
8932         END_PROFILE(SMBtranss2);
8933         return;
8934
8935   bad_param:
8936
8937         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8938         DLIST_REMOVE(conn->pending_trans, state);
8939         SAFE_FREE(state->data);
8940         SAFE_FREE(state->param);
8941         TALLOC_FREE(state);
8942         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8943         END_PROFILE(SMBtranss2);
8944         return;
8945 }