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