s3: Revert the serverid changes, they need more work
[samba.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2006-2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
42
43 static char *store_file_unix_basic(connection_struct *conn,
44                                 char *pdata,
45                                 files_struct *fsp,
46                                 const SMB_STRUCT_STAT *psbuf);
47
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49                                 char *pdata,
50                                 files_struct *fsp,
51                                 const SMB_STRUCT_STAT *psbuf);
52
53 /********************************************************************
54  The canonical "check access" based on object handle or path function.
55 ********************************************************************/
56
57 NTSTATUS check_access(connection_struct *conn,
58                                 files_struct *fsp,
59                                 const struct smb_filename *smb_fname,
60                                 uint32_t access_mask)
61 {
62         if (fsp) {
63                 if (!(fsp->access_mask & access_mask)) {
64                         return NT_STATUS_ACCESS_DENIED;
65                 }
66         } else {
67                 NTSTATUS status = smbd_check_access_rights(conn,
68                                         smb_fname,
69                                         access_mask);
70                 if (!NT_STATUS_IS_OK(status)) {
71                         return status;
72                 }
73         }
74         return NT_STATUS_OK;
75 }
76
77 /********************************************************************
78  Roundup a value to the nearest allocation roundup size boundary.
79  Only do this for Windows clients.
80 ********************************************************************/
81
82 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
83 {
84         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
85
86         /* Only roundup for Windows clients. */
87         enum remote_arch_types ra_type = get_remote_arch();
88         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
89                 val = SMB_ROUNDUP(val,rval);
90         }
91         return val;
92 }
93
94 /********************************************************************
95  Create a 64 bit FileIndex. If the file is on the same device as
96  the root of the share, just return the 64-bit inode. If it isn't,
97  mangle as we used to do.
98 ********************************************************************/
99
100 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
101 {
102         uint64_t file_index;
103         if (conn->base_share_dev == psbuf->st_ex_dev) {
104                 return (uint64_t)psbuf->st_ex_ino;
105         }
106         file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
107         file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
108         return file_index;
109 }
110
111 /****************************************************************************
112  Utility functions for dealing with extended attributes.
113 ****************************************************************************/
114
115 /****************************************************************************
116  Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
118
119 static bool samba_private_attr_name(const char *unix_ea_name)
120 {
121         static const char * const prohibited_ea_names[] = {
122                 SAMBA_POSIX_INHERITANCE_EA_NAME,
123                 SAMBA_XATTR_DOS_ATTRIB,
124                 SAMBA_XATTR_MARKER,
125                 XATTR_NTACL_NAME,
126                 NULL
127         };
128
129         int i;
130
131         for (i = 0; prohibited_ea_names[i]; i++) {
132                 if (strequal( prohibited_ea_names[i], unix_ea_name))
133                         return true;
134         }
135         if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
136                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
137                 return true;
138         }
139         return false;
140 }
141
142 /****************************************************************************
143  Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
145
146 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
147                       files_struct *fsp, const char *fname,
148                       const char *ea_name, struct ea_struct *pea)
149 {
150         /* Get the value of this xattr. Max size is 64k. */
151         size_t attr_size = 256;
152         char *val = NULL;
153         ssize_t sizeret;
154
155  again:
156
157         val = talloc_realloc(mem_ctx, val, char, attr_size);
158         if (!val) {
159                 return NT_STATUS_NO_MEMORY;
160         }
161
162         if (fsp && fsp->fh->fd != -1) {
163                 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
164         } else {
165                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
166         }
167
168         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
169                 attr_size = 65536;
170                 goto again;
171         }
172
173         if (sizeret == -1) {
174                 return map_nt_error_from_unix(errno);
175         }
176
177         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
178         dump_data(10, (uint8 *)val, sizeret);
179
180         pea->flags = 0;
181         if (strnequal(ea_name, "user.", 5)) {
182                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
183         } else {
184                 pea->name = talloc_strdup(mem_ctx, ea_name);
185         }
186         if (pea->name == NULL) {
187                 TALLOC_FREE(val);
188                 return NT_STATUS_NO_MEMORY;
189         }
190         pea->value.data = (unsigned char *)val;
191         pea->value.length = (size_t)sizeret;
192         return NT_STATUS_OK;
193 }
194
195 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
196                                 files_struct *fsp, const char *fname,
197                                 char ***pnames, size_t *pnum_names)
198 {
199         /* Get a list of all xattrs. Max namesize is 64k. */
200         size_t ea_namelist_size = 1024;
201         char *ea_namelist = NULL;
202
203         char *p;
204         char **names, **tmp;
205         size_t num_names;
206         ssize_t sizeret = -1;
207
208         if (!lp_ea_support(SNUM(conn))) {
209                 if (pnames) {
210                         *pnames = NULL;
211                 }
212                 *pnum_names = 0;
213                 return NT_STATUS_OK;
214         }
215
216         /*
217          * TALLOC the result early to get the talloc hierarchy right.
218          */
219
220         names = talloc_array(mem_ctx, char *, 1);
221         if (names == NULL) {
222                 DEBUG(0, ("talloc failed\n"));
223                 return NT_STATUS_NO_MEMORY;
224         }
225
226         while (ea_namelist_size <= 65536) {
227
228                 ea_namelist = talloc_realloc(
229                         names, ea_namelist, char, ea_namelist_size);
230                 if (ea_namelist == NULL) {
231                         DEBUG(0, ("talloc failed\n"));
232                         TALLOC_FREE(names);
233                         return NT_STATUS_NO_MEMORY;
234                 }
235
236                 if (fsp && fsp->fh->fd != -1) {
237                         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238                                                      ea_namelist_size);
239                 } else {
240                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
241                                                     ea_namelist_size);
242                 }
243
244                 if ((sizeret == -1) && (errno == ERANGE)) {
245                         ea_namelist_size *= 2;
246                 }
247                 else {
248                         break;
249                 }
250         }
251
252         if (sizeret == -1) {
253                 TALLOC_FREE(names);
254                 return map_nt_error_from_unix(errno);
255         }
256
257         DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258                    (unsigned int)sizeret));
259
260         if (sizeret == 0) {
261                 TALLOC_FREE(names);
262                 if (pnames) {
263                         *pnames = NULL;
264                 }
265                 *pnum_names = 0;
266                 return NT_STATUS_OK;
267         }
268
269         /*
270          * Ensure the result is 0-terminated
271          */
272
273         if (ea_namelist[sizeret-1] != '\0') {
274                 TALLOC_FREE(names);
275                 return NT_STATUS_INTERNAL_ERROR;
276         }
277
278         /*
279          * count the names
280          */
281         num_names = 0;
282
283         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
284                 num_names += 1;
285         }
286
287         tmp = talloc_realloc(mem_ctx, names, char *, num_names);
288         if (tmp == NULL) {
289                 DEBUG(0, ("talloc failed\n"));
290                 TALLOC_FREE(names);
291                 return NT_STATUS_NO_MEMORY;
292         }
293
294         names = tmp;
295         num_names = 0;
296
297         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298                 names[num_names++] = p;
299         }
300
301         if (pnames) {
302                 *pnames = names;
303         } else {
304                 TALLOC_FREE(names);
305         }
306         *pnum_names = num_names;
307         return NT_STATUS_OK;
308 }
309
310 /****************************************************************************
311  Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
313
314 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
315                                         const char *fname, size_t *pea_total_len)
316 {
317         /* Get a list of all xattrs. Max namesize is 64k. */
318         size_t i, num_names;
319         char **names;
320         struct ea_list *ea_list_head = NULL;
321         NTSTATUS status;
322
323         *pea_total_len = 0;
324
325         if (!lp_ea_support(SNUM(conn))) {
326                 return NULL;
327         }
328
329         status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
330                                         &names, &num_names);
331
332         if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
333                 return NULL;
334         }
335
336         for (i=0; i<num_names; i++) {
337                 struct ea_list *listp;
338                 fstring dos_ea_name;
339
340                 if (strnequal(names[i], "system.", 7)
341                     || samba_private_attr_name(names[i]))
342                         continue;
343
344                 listp = talloc(mem_ctx, struct ea_list);
345                 if (listp == NULL) {
346                         return NULL;
347                 }
348
349                 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
350                                                   fname, names[i],
351                                                   &listp->ea))) {
352                         return NULL;
353                 }
354
355                 push_ascii_fstring(dos_ea_name, listp->ea.name);
356
357                 *pea_total_len +=
358                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
359
360                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
362                           (unsigned int)listp->ea.value.length));
363
364                 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
365
366         }
367
368         /* Add on 4 for total length. */
369         if (*pea_total_len) {
370                 *pea_total_len += 4;
371         }
372
373         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374                    (unsigned int)*pea_total_len));
375
376         return ea_list_head;
377 }
378
379 /****************************************************************************
380  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
381  that was filled.
382 ****************************************************************************/
383
384 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
385         connection_struct *conn, struct ea_list *ea_list)
386 {
387         unsigned int ret_data_size = 4;
388         char *p = pdata;
389
390         SMB_ASSERT(total_data_size >= 4);
391
392         if (!lp_ea_support(SNUM(conn))) {
393                 SIVAL(pdata,4,0);
394                 return 4;
395         }
396
397         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
398                 size_t dos_namelen;
399                 fstring dos_ea_name;
400                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
401                 dos_namelen = strlen(dos_ea_name);
402                 if (dos_namelen > 255 || dos_namelen == 0) {
403                         break;
404                 }
405                 if (ea_list->ea.value.length > 65535) {
406                         break;
407                 }
408                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
409                         break;
410                 }
411
412                 /* We know we have room. */
413                 SCVAL(p,0,ea_list->ea.flags);
414                 SCVAL(p,1,dos_namelen);
415                 SSVAL(p,2,ea_list->ea.value.length);
416                 strlcpy(p+4, dos_ea_name, dos_namelen+1);
417                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
418
419                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
420                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
421         }
422
423         ret_data_size = PTR_DIFF(p, pdata);
424         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
425         SIVAL(pdata,0,ret_data_size);
426         return ret_data_size;
427 }
428
429 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
430                                        char *pdata,
431                                        unsigned int total_data_size,
432                                        unsigned int *ret_data_size,
433                                        connection_struct *conn,
434                                        struct ea_list *ea_list)
435 {
436         uint8_t *p = (uint8_t *)pdata;
437         uint8_t *last_start = NULL;
438
439         *ret_data_size = 0;
440
441         if (!lp_ea_support(SNUM(conn))) {
442                 return NT_STATUS_NO_EAS_ON_FILE;
443         }
444
445         for (; ea_list; ea_list = ea_list->next) {
446                 size_t dos_namelen;
447                 fstring dos_ea_name;
448                 size_t this_size;
449
450                 if (last_start) {
451                         SIVAL(last_start, 0, PTR_DIFF(p, last_start));
452                 }
453                 last_start = p;
454
455                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
456                 dos_namelen = strlen(dos_ea_name);
457                 if (dos_namelen > 255 || dos_namelen == 0) {
458                         return NT_STATUS_INTERNAL_ERROR;
459                 }
460                 if (ea_list->ea.value.length > 65535) {
461                         return NT_STATUS_INTERNAL_ERROR;
462                 }
463
464                 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
465
466                 if (ea_list->next) {
467                         size_t pad = 4 - (this_size % 4);
468                         this_size += pad;
469                 }
470
471                 if (this_size > total_data_size) {
472                         return NT_STATUS_INFO_LENGTH_MISMATCH;
473                 }
474
475                 /* We know we have room. */
476                 SIVAL(p, 0x00, 0); /* next offset */
477                 SCVAL(p, 0x04, ea_list->ea.flags);
478                 SCVAL(p, 0x05, dos_namelen);
479                 SSVAL(p, 0x06, ea_list->ea.value.length);
480                 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
481                 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
482
483                 total_data_size -= this_size;
484                 p += this_size;
485         }
486
487         *ret_data_size = PTR_DIFF(p, pdata);
488         DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
489         return NT_STATUS_OK;
490 }
491
492 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
493 {
494         size_t total_ea_len = 0;
495         TALLOC_CTX *mem_ctx = NULL;
496
497         if (!lp_ea_support(SNUM(conn))) {
498                 return 0;
499         }
500         mem_ctx = talloc_tos();
501         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
502         return total_ea_len;
503 }
504
505 /****************************************************************************
506  Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
508
509 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
510 {
511         size_t total_ea_len;
512         TALLOC_CTX *mem_ctx = talloc_tos();
513         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
514
515         for (; ea_list; ea_list = ea_list->next) {
516                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
517                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518                                 &unix_ea_name[5], ea_list->ea.name));
519                         strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
520                         break;
521                 }
522         }
523 }
524
525 /****************************************************************************
526  Set or delete an extended attribute.
527 ****************************************************************************/
528
529 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
530                 const struct smb_filename *smb_fname, struct ea_list *ea_list)
531 {
532         NTSTATUS status;
533         char *fname = NULL;
534
535         if (!lp_ea_support(SNUM(conn))) {
536                 return NT_STATUS_EAS_NOT_SUPPORTED;
537         }
538
539         status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
540         if (!NT_STATUS_IS_OK(status)) {
541                 return status;
542         }
543
544         /* For now setting EAs on streams isn't supported. */
545         fname = smb_fname->base_name;
546
547         for (;ea_list; ea_list = ea_list->next) {
548                 int ret;
549                 fstring unix_ea_name;
550
551                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
552                 fstrcat(unix_ea_name, ea_list->ea.name);
553
554                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
555
556                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
557
558                 if (samba_private_attr_name(unix_ea_name)) {
559                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
560                         return NT_STATUS_ACCESS_DENIED;
561                 }
562
563                 if (ea_list->ea.value.length == 0) {
564                         /* Remove the attribute. */
565                         if (fsp && (fsp->fh->fd != -1)) {
566                                 DEBUG(10,("set_ea: deleting ea name %s on "
567                                           "file %s by file descriptor.\n",
568                                           unix_ea_name, fsp_str_dbg(fsp)));
569                                 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
570                         } else {
571                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572                                         unix_ea_name, fname));
573                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
574                         }
575 #ifdef ENOATTR
576                         /* Removing a non existent attribute always succeeds. */
577                         if (ret == -1 && errno == ENOATTR) {
578                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
579                                                 unix_ea_name));
580                                 ret = 0;
581                         }
582 #endif
583                 } else {
584                         if (fsp && (fsp->fh->fd != -1)) {
585                                 DEBUG(10,("set_ea: setting ea name %s on file "
586                                           "%s by file descriptor.\n",
587                                           unix_ea_name, fsp_str_dbg(fsp)));
588                                 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
589                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
590                         } else {
591                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592                                         unix_ea_name, fname));
593                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
594                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
595                         }
596                 }
597
598                 if (ret == -1) {
599 #ifdef ENOTSUP
600                         if (errno == ENOTSUP) {
601                                 return NT_STATUS_EAS_NOT_SUPPORTED;
602                         }
603 #endif
604                         return map_nt_error_from_unix(errno);
605                 }
606
607         }
608         return NT_STATUS_OK;
609 }
610 /****************************************************************************
611  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
613
614 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
615 {
616         struct ea_list *ea_list_head = NULL;
617         size_t converted_size, offset = 0;
618
619         while (offset + 2 < data_size) {
620                 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
621                 unsigned int namelen = CVAL(pdata,offset);
622
623                 offset++; /* Go past the namelen byte. */
624
625                 /* integer wrap paranioa. */
626                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
627                                 (offset > data_size) || (namelen > data_size) ||
628                                 (offset + namelen >= data_size)) {
629                         break;
630                 }
631                 /* Ensure the name is null terminated. */
632                 if (pdata[offset + namelen] != '\0') {
633                         return NULL;
634                 }
635                 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
636                                        &converted_size)) {
637                         DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638                                  "failed: %s", strerror(errno)));
639                 }
640                 if (!eal->ea.name) {
641                         return NULL;
642                 }
643
644                 offset += (namelen + 1); /* Go past the name + terminating zero. */
645                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
646                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
647         }
648
649         return ea_list_head;
650 }
651
652 /****************************************************************************
653  Read one EA list entry from the buffer.
654 ****************************************************************************/
655
656 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
657 {
658         struct ea_list *eal = talloc_zero(ctx, struct ea_list);
659         uint16 val_len;
660         unsigned int namelen;
661         size_t converted_size;
662
663         if (!eal) {
664                 return NULL;
665         }
666
667         if (data_size < 6) {
668                 return NULL;
669         }
670
671         eal->ea.flags = CVAL(pdata,0);
672         namelen = CVAL(pdata,1);
673         val_len = SVAL(pdata,2);
674
675         if (4 + namelen + 1 + val_len > data_size) {
676                 return NULL;
677         }
678
679         /* Ensure the name is null terminated. */
680         if (pdata[namelen + 4] != '\0') {
681                 return NULL;
682         }
683         if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
684                 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
685                          strerror(errno)));
686         }
687         if (!eal->ea.name) {
688                 return NULL;
689         }
690
691         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
692         if (!eal->ea.value.data) {
693                 return NULL;
694         }
695
696         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
697
698         /* Ensure we're null terminated just in case we print the value. */
699         eal->ea.value.data[val_len] = '\0';
700         /* But don't count the null. */
701         eal->ea.value.length--;
702
703         if (pbytes_used) {
704                 *pbytes_used = 4 + namelen + 1 + val_len;
705         }
706
707         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
708         dump_data(10, eal->ea.value.data, eal->ea.value.length);
709
710         return eal;
711 }
712
713 /****************************************************************************
714  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
716
717 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
718 {
719         struct ea_list *ea_list_head = NULL;
720         size_t offset = 0;
721         size_t bytes_used = 0;
722
723         while (offset < data_size) {
724                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
725
726                 if (!eal) {
727                         return NULL;
728                 }
729
730                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
731                 offset += bytes_used;
732         }
733
734         return ea_list_head;
735 }
736
737 /****************************************************************************
738  Count the total EA size needed.
739 ****************************************************************************/
740
741 static size_t ea_list_size(struct ea_list *ealist)
742 {
743         fstring dos_ea_name;
744         struct ea_list *listp;
745         size_t ret = 0;
746
747         for (listp = ealist; listp; listp = listp->next) {
748                 push_ascii_fstring(dos_ea_name, listp->ea.name);
749                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
750         }
751         /* Add on 4 for total length. */
752         if (ret) {
753                 ret += 4;
754         }
755
756         return ret;
757 }
758
759 /****************************************************************************
760  Return a union of EA's from a file list and a list of names.
761  The TALLOC context for the two lists *MUST* be identical as we steal
762  memory from one list to add to another. JRA.
763 ****************************************************************************/
764
765 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
766 {
767         struct ea_list *nlistp, *flistp;
768
769         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
770                 for (flistp = file_list; flistp; flistp = flistp->next) {
771                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
772                                 break;
773                         }
774                 }
775
776                 if (flistp) {
777                         /* Copy the data from this entry. */
778                         nlistp->ea.flags = flistp->ea.flags;
779                         nlistp->ea.value = flistp->ea.value;
780                 } else {
781                         /* Null entry. */
782                         nlistp->ea.flags = 0;
783                         ZERO_STRUCT(nlistp->ea.value);
784                 }
785         }
786
787         *total_ea_len = ea_list_size(name_list);
788         return name_list;
789 }
790
791 /****************************************************************************
792   Send the required number of replies back.
793   We assume all fields other than the data fields are
794   set correctly for the type of call.
795   HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
797
798 void send_trans2_replies(connection_struct *conn,
799                         struct smb_request *req,
800                          const char *params,
801                          int paramsize,
802                          const char *pdata,
803                          int datasize,
804                          int max_data_bytes)
805 {
806         /* As we are using a protocol > LANMAN1 then the max_send
807          variable must have been set in the sessetupX call.
808          This takes precedence over the max_xmit field in the
809          global struct. These different max_xmit variables should
810          be merged as this is now too confusing */
811
812         int data_to_send = datasize;
813         int params_to_send = paramsize;
814         int useable_space;
815         const char *pp = params;
816         const char *pd = pdata;
817         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
818         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819         int data_alignment_offset = 0;
820         bool overflow = False;
821         struct smbd_server_connection *sconn = req->sconn;
822         int max_send = sconn->smb1.sessions.max_send;
823
824         /* Modify the data_to_send and datasize and set the error if
825            we're trying to send more than max_data_bytes. We still send
826            the part of the packet(s) that fit. Strange, but needed
827            for OS/2. */
828
829         if (max_data_bytes > 0 && datasize > max_data_bytes) {
830                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831                         max_data_bytes, datasize ));
832                 datasize = data_to_send = max_data_bytes;
833                 overflow = True;
834         }
835
836         /* If there genuinely are no parameters or data to send just send the empty packet */
837
838         if(params_to_send == 0 && data_to_send == 0) {
839                 reply_outbuf(req, 10, 0);
840                 show_msg((char *)req->outbuf);
841                 if (!srv_send_smb(sconn,
842                                 (char *)req->outbuf,
843                                 true, req->seqnum+1,
844                                 IS_CONN_ENCRYPTED(conn),
845                                 &req->pcd)) {
846                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
847                 }
848                 TALLOC_FREE(req->outbuf);
849                 return;
850         }
851
852         /* When sending params and data ensure that both are nicely aligned */
853         /* Only do this alignment when there is also data to send - else
854                 can cause NT redirector problems. */
855
856         if (((params_to_send % 4) != 0) && (data_to_send != 0))
857                 data_alignment_offset = 4 - (params_to_send % 4);
858
859         /* Space is bufsize minus Netbios over TCP header minus SMB header */
860         /* The alignment_offset is to align the param bytes on an even byte
861                 boundary. NT 4.0 Beta needs this to work correctly. */
862
863         useable_space = max_send - (smb_size
864                                     + 2 * 10 /* wct */
865                                     + alignment_offset
866                                     + data_alignment_offset);
867
868         if (useable_space < 0) {
869                 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870                           "= %d!!!", useable_space));
871                 exit_server_cleanly("send_trans2_replies: Not enough space");
872         }
873
874         while (params_to_send || data_to_send) {
875                 /* Calculate whether we will totally or partially fill this packet */
876
877                 total_sent_thistime = params_to_send + data_to_send;
878
879                 /* We can never send more than useable_space */
880                 /*
881                  * Note that 'useable_space' does not include the alignment offsets,
882                  * but we must include the alignment offsets in the calculation of
883                  * the length of the data we send over the wire, as the alignment offsets
884                  * are sent here. Fix from Marc_Jacobsen@hp.com.
885                  */
886
887                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
888
889                 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
890                              + data_alignment_offset);
891
892                 /*
893                  * We might have SMBtrans2s in req which was transferred to
894                  * the outbuf, fix that.
895                  */
896                 SCVAL(req->outbuf, smb_com, SMBtrans2);
897
898                 /* Set total params and data to be sent */
899                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
900                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
901
902                 /* Calculate how many parameters and data we can fit into
903                  * this packet. Parameters get precedence
904                  */
905
906                 params_sent_thistime = MIN(params_to_send,useable_space);
907                 data_sent_thistime = useable_space - params_sent_thistime;
908                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
909
910                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
911
912                 /* smb_proff is the offset from the start of the SMB header to the
913                         parameter bytes, however the first 4 bytes of outbuf are
914                         the Netbios over TCP header. Thus use smb_base() to subtract
915                         them from the calculation */
916
917                 SSVAL(req->outbuf,smb_proff,
918                       ((smb_buf(req->outbuf)+alignment_offset)
919                        - smb_base(req->outbuf)));
920
921                 if(params_sent_thistime == 0)
922                         SSVAL(req->outbuf,smb_prdisp,0);
923                 else
924                         /* Absolute displacement of param bytes sent in this packet */
925                         SSVAL(req->outbuf,smb_prdisp,pp - params);
926
927                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
928                 if(data_sent_thistime == 0) {
929                         SSVAL(req->outbuf,smb_droff,0);
930                         SSVAL(req->outbuf,smb_drdisp, 0);
931                 } else {
932                         /* The offset of the data bytes is the offset of the
933                                 parameter bytes plus the number of parameters being sent this time */
934                         SSVAL(req->outbuf, smb_droff,
935                               ((smb_buf(req->outbuf)+alignment_offset)
936                                - smb_base(req->outbuf))
937                               + params_sent_thistime + data_alignment_offset);
938                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
939                 }
940
941                 /* Initialize the padding for alignment */
942
943                 if (alignment_offset != 0) {
944                         memset(smb_buf(req->outbuf), 0, alignment_offset);
945                 }
946
947                 /* Copy the param bytes into the packet */
948
949                 if(params_sent_thistime) {
950                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
951                                params_sent_thistime);
952                 }
953
954                 /* Copy in the data bytes */
955                 if(data_sent_thistime) {
956                         if (data_alignment_offset != 0) {
957                                 memset((smb_buf(req->outbuf)+alignment_offset+
958                                         params_sent_thistime), 0,
959                                        data_alignment_offset);
960                         }
961                         memcpy(smb_buf(req->outbuf)+alignment_offset
962                                +params_sent_thistime+data_alignment_offset,
963                                pd,data_sent_thistime);
964                 }
965
966                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967                         params_sent_thistime, data_sent_thistime, useable_space));
968                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969                         params_to_send, data_to_send, paramsize, datasize));
970
971                 if (overflow) {
972                         error_packet_set((char *)req->outbuf,
973                                          ERRDOS,ERRbufferoverflow,
974                                          STATUS_BUFFER_OVERFLOW,
975                                          __LINE__,__FILE__);
976                 }
977
978                 /* Send the packet */
979                 show_msg((char *)req->outbuf);
980                 if (!srv_send_smb(sconn,
981                                 (char *)req->outbuf,
982                                 true, req->seqnum+1,
983                                 IS_CONN_ENCRYPTED(conn),
984                                 &req->pcd))
985                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
986
987                 TALLOC_FREE(req->outbuf);
988
989                 pp += params_sent_thistime;
990                 pd += data_sent_thistime;
991
992                 params_to_send -= params_sent_thistime;
993                 data_to_send -= data_sent_thistime;
994
995                 /* Sanity check */
996                 if(params_to_send < 0 || data_to_send < 0) {
997                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998                                 params_to_send, data_to_send));
999                         return;
1000                 }
1001         }
1002
1003         return;
1004 }
1005
1006 /****************************************************************************
1007  Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1009
1010 static void call_trans2open(connection_struct *conn,
1011                             struct smb_request *req,
1012                             char **pparams, int total_params,
1013                             char **ppdata, int total_data,
1014                             unsigned int max_data_bytes)
1015 {
1016         struct smb_filename *smb_fname = NULL;
1017         char *params = *pparams;
1018         char *pdata = *ppdata;
1019         int deny_mode;
1020         int32 open_attr;
1021         bool oplock_request;
1022 #if 0
1023         bool return_additional_info;
1024         int16 open_sattr;
1025         time_t open_time;
1026 #endif
1027         int open_ofun;
1028         uint32 open_size;
1029         char *pname;
1030         char *fname = NULL;
1031         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                         if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3430                                 flags |= SMB_WHOAMI_GUEST;
3431                         }
3432
3433                         /* NOTE: 8 bytes for UID/GID, irrespective of native
3434                          * platform size. This matches
3435                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
3436                          */
3437                         data_len = 4 /* flags */
3438                             + 4 /* flag mask */
3439                             + 8 /* uid */
3440                             + 8 /* gid */
3441                             + 4 /* ngroups */
3442                             + 4 /* num_sids */
3443                             + 4 /* SID bytes */
3444                             + 4 /* pad/reserved */
3445                             + (conn->session_info->unix_token->ngroups * 8)
3446                                 /* groups list */
3447                             + (conn->session_info->security_token->num_sids *
3448                                     SID_MAX_SIZE)
3449                                 /* SID list */;
3450
3451                         SIVAL(pdata, 0, flags);
3452                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3453                         SBIG_UINT(pdata, 8,
3454                                   (uint64_t)conn->session_info->unix_token->uid);
3455                         SBIG_UINT(pdata, 16,
3456                                   (uint64_t)conn->session_info->unix_token->gid);
3457
3458
3459                         if (data_len >= max_data_bytes) {
3460                                 /* Potential overflow, skip the GIDs and SIDs. */
3461
3462                                 SIVAL(pdata, 24, 0); /* num_groups */
3463                                 SIVAL(pdata, 28, 0); /* num_sids */
3464                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3465                                 SIVAL(pdata, 36, 0); /* reserved */
3466
3467                                 data_len = 40;
3468                                 break;
3469                         }
3470
3471                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3472                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3473
3474                         /* We walk the SID list twice, but this call is fairly
3475                          * infrequent, and I don't expect that it's performance
3476                          * sensitive -- jpeach
3477                          */
3478                         for (i = 0, sid_bytes = 0;
3479                              i < conn->session_info->security_token->num_sids; ++i) {
3480                                 sid_bytes += ndr_size_dom_sid(
3481                                         &conn->session_info->security_token->sids[i],
3482                                         0);
3483                         }
3484
3485                         /* SID list byte count */
3486                         SIVAL(pdata, 32, sid_bytes);
3487
3488                         /* 4 bytes pad/reserved - must be zero */
3489                         SIVAL(pdata, 36, 0);
3490                         data_len = 40;
3491
3492                         /* GID list */
3493                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3494                                 SBIG_UINT(pdata, data_len,
3495                                           (uint64_t)conn->session_info->unix_token->groups[i]);
3496                                 data_len += 8;
3497                         }
3498
3499                         /* SID list */
3500                         for (i = 0;
3501                             i < conn->session_info->security_token->num_sids; ++i) {
3502                                 int sid_len = ndr_size_dom_sid(
3503                                         &conn->session_info->security_token->sids[i],
3504                                         0);
3505
3506                                 sid_linearize(pdata + data_len, sid_len,
3507                                     &conn->session_info->security_token->sids[i]);
3508                                 data_len += sid_len;
3509                         }
3510
3511                         break;
3512                 }
3513
3514                 case SMB_MAC_QUERY_FS_INFO:
3515                         /*
3516                          * Thursby MAC extension... ONLY on NTFS filesystems
3517                          * once we do streams then we don't need this
3518                          */
3519                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3520                                 data_len = 88;
3521                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
3522                                 break;
3523                         }
3524                         /* drop through */
3525                 default:
3526                         return NT_STATUS_INVALID_LEVEL;
3527         }
3528
3529         *ret_data_len = data_len;
3530         return NT_STATUS_OK;
3531 }
3532
3533 /****************************************************************************
3534  Reply to a TRANS2_QFSINFO (query filesystem info).
3535 ****************************************************************************/
3536
3537 static void call_trans2qfsinfo(connection_struct *conn,
3538                                struct smb_request *req,
3539                                char **pparams, int total_params,
3540                                char **ppdata, int total_data,
3541                                unsigned int max_data_bytes)
3542 {
3543         char *params = *pparams;
3544         uint16_t info_level;
3545         int data_len = 0;
3546         NTSTATUS status;
3547
3548         if (total_params < 2) {
3549                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550                 return;
3551         }
3552
3553         info_level = SVAL(params,0);
3554
3555         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3556                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3557                         DEBUG(0,("call_trans2qfsinfo: encryption required "
3558                                 "and info level 0x%x sent.\n",
3559                                 (unsigned int)info_level));
3560                         exit_server_cleanly("encryption required "
3561                                 "on connection");
3562                         return;
3563                 }
3564         }
3565
3566         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3567
3568         status = smbd_do_qfsinfo(conn, req,
3569                                  info_level,
3570                                  req->flags2,
3571                                  max_data_bytes,
3572                                  ppdata, &data_len);
3573         if (!NT_STATUS_IS_OK(status)) {
3574                 reply_nterror(req, status);
3575                 return;
3576         }
3577
3578         send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3579                             max_data_bytes);
3580
3581         DEBUG( 4, ( "%s info_level = %d\n",
3582                     smb_fn_name(req->cmd), info_level) );
3583
3584         return;
3585 }
3586
3587 /****************************************************************************
3588  Reply to a TRANS2_SETFSINFO (set filesystem info).
3589 ****************************************************************************/
3590
3591 static void call_trans2setfsinfo(connection_struct *conn,
3592                                  struct smb_request *req,
3593                                  char **pparams, int total_params,
3594                                  char **ppdata, int total_data,
3595                                  unsigned int max_data_bytes)
3596 {
3597         struct smbd_server_connection *sconn = req->sconn;
3598         char *pdata = *ppdata;
3599         char *params = *pparams;
3600         uint16 info_level;
3601
3602         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3603
3604         /*  */
3605         if (total_params < 4) {
3606                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3607                         total_params));
3608                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3609                 return;
3610         }
3611
3612         info_level = SVAL(params,2);
3613
3614         if (IS_IPC(conn)) {
3615                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3616                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
3617                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
3618                                 "info level (0x%x) on IPC$.\n",
3619                                 (unsigned int)info_level));
3620                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3621                         return;
3622                 }
3623         }
3624
3625         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3626                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3627                         DEBUG(0,("call_trans2setfsinfo: encryption required "
3628                                 "and info level 0x%x sent.\n",
3629                                 (unsigned int)info_level));
3630                         exit_server_cleanly("encryption required "
3631                                 "on connection");
3632                         return;
3633                 }
3634         }
3635
3636         switch(info_level) {
3637                 case SMB_SET_CIFS_UNIX_INFO:
3638                         if (!lp_unix_extensions()) {
3639                                 DEBUG(2,("call_trans2setfsinfo: "
3640                                         "SMB_SET_CIFS_UNIX_INFO is invalid with "
3641                                         "unix extensions off\n"));
3642                                 reply_nterror(req,
3643                                               NT_STATUS_INVALID_LEVEL);
3644                                 return;
3645                         }
3646
3647                         /* There should be 12 bytes of capabilities set. */
3648                         if (total_data < 12) {
3649                                 reply_nterror(
3650                                         req,
3651                                         NT_STATUS_INVALID_PARAMETER);
3652                                 return;
3653                         }
3654                         sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3655                         sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3656                         sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3657                         sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3658                         /* Just print these values for now. */
3659                         DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3660                                    "major = %u, minor = %u cap_low = 0x%x, "
3661                                    "cap_high = 0x%xn",
3662                                    (unsigned int)sconn->
3663                                    smb1.unix_info.client_major,
3664                                    (unsigned int)sconn->
3665                                    smb1.unix_info.client_minor,
3666                                    (unsigned int)sconn->
3667                                    smb1.unix_info.client_cap_low,
3668                                    (unsigned int)sconn->
3669                                    smb1.unix_info.client_cap_high));
3670
3671                         /* Here is where we must switch to posix pathname processing... */
3672                         if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3673                                 lp_set_posix_pathnames();
3674                                 mangle_change_to_posix();
3675                         }
3676
3677                         if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3678                             !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3679                                 /* Client that knows how to do posix locks,
3680                                  * but not posix open/mkdir operations. Set a
3681                                  * default type for read/write checks. */
3682
3683                                 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3684
3685                         }
3686                         break;
3687
3688                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3689                         {
3690                                 NTSTATUS status;
3691                                 size_t param_len = 0;
3692                                 size_t data_len = total_data;
3693
3694                                 if (!lp_unix_extensions()) {
3695                                         reply_nterror(
3696                                                 req,
3697                                                 NT_STATUS_INVALID_LEVEL);
3698                                         return;
3699                                 }
3700
3701                                 if (lp_smb_encrypt(SNUM(conn)) == false) {
3702                                         reply_nterror(
3703                                                 req,
3704                                                 NT_STATUS_NOT_SUPPORTED);
3705                                         return;
3706                                 }
3707
3708                                 if (req->sconn->smb1.echo_handler.trusted_fde) {
3709                                         DEBUG( 2,("call_trans2setfsinfo: "
3710                                                 "request transport encryption disabled"
3711                                                 "with 'fork echo handler = yes'\n"));
3712                                         reply_nterror(
3713                                                 req,
3714                                                 NT_STATUS_NOT_SUPPORTED);
3715                                         return;
3716                                 }
3717
3718                                 DEBUG( 4,("call_trans2setfsinfo: "
3719                                         "request transport encryption.\n"));
3720
3721                                 status = srv_request_encryption_setup(conn,
3722                                                                 (unsigned char **)ppdata,
3723                                                                 &data_len,
3724                                                                 (unsigned char **)pparams,
3725                                                                 &param_len);
3726
3727                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3728                                                 !NT_STATUS_IS_OK(status)) {
3729                                         reply_nterror(req, status);
3730                                         return;
3731                                 }
3732
3733                                 send_trans2_replies(conn, req,
3734                                                 *pparams,
3735                                                 param_len,
3736                                                 *ppdata,
3737                                                 data_len,
3738                                                 max_data_bytes);
3739
3740                                 if (NT_STATUS_IS_OK(status)) {
3741                                         /* Server-side transport
3742                                          * encryption is now *on*. */
3743                                         status = srv_encryption_start(conn);
3744                                         if (!NT_STATUS_IS_OK(status)) {
3745                                                 char *reason = talloc_asprintf(talloc_tos(),
3746                                                                                "Failure in setting "
3747                                                                                "up encrypted transport: %s",
3748                                                                                nt_errstr(status));
3749                                                 exit_server_cleanly(reason);
3750                                         }
3751                                 }
3752                                 return;
3753                         }
3754
3755                 case SMB_FS_QUOTA_INFORMATION:
3756                         {
3757                                 files_struct *fsp = NULL;
3758                                 SMB_NTQUOTA_STRUCT quotas;
3759
3760                                 ZERO_STRUCT(quotas);
3761
3762                                 /* access check */
3763                                 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3764                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3765                                                  lp_servicename(SNUM(conn)),
3766                                                  conn->session_info->unix_info->unix_name));
3767                                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3768                                         return;
3769                                 }
3770
3771                                 /* note: normaly there're 48 bytes,
3772                                  * but we didn't use the last 6 bytes for now 
3773                                  * --metze 
3774                                  */
3775                                 fsp = file_fsp(req, SVAL(params,0));
3776
3777                                 if (!check_fsp_ntquota_handle(conn, req,
3778                                                               fsp)) {
3779                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3780                                         reply_nterror(
3781                                                 req, NT_STATUS_INVALID_HANDLE);
3782                                         return;
3783                                 }
3784
3785                                 if (total_data < 42) {
3786                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3787                                                 total_data));
3788                                         reply_nterror(
3789                                                 req,
3790                                                 NT_STATUS_INVALID_PARAMETER);
3791                                         return;
3792                                 }
3793
3794                                 /* unknown_1 24 NULL bytes in pdata*/
3795
3796                                 /* the soft quotas 8 bytes (uint64_t)*/
3797                                 quotas.softlim = BVAL(pdata,24);
3798
3799                                 /* the hard quotas 8 bytes (uint64_t)*/
3800                                 quotas.hardlim = BVAL(pdata,32);
3801
3802                                 /* quota_flags 2 bytes **/
3803                                 quotas.qflags = SVAL(pdata,40);
3804
3805                                 /* unknown_2 6 NULL bytes follow*/
3806
3807                                 /* now set the quotas */
3808                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3809                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3810                                         reply_nterror(req, map_nt_error_from_unix(errno));
3811                                         return;
3812                                 }
3813
3814                                 break;
3815                         }
3816                 default:
3817                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3818                                 info_level));
3819                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3820                         return;
3821                         break;
3822         }
3823
3824         /* 
3825          * sending this reply works fine, 
3826          * but I'm not sure it's the same 
3827          * like windows do...
3828          * --metze
3829          */
3830         reply_outbuf(req, 10, 0);
3831 }
3832
3833 #if defined(HAVE_POSIX_ACLS)
3834 /****************************************************************************
3835  Utility function to count the number of entries in a POSIX acl.
3836 ****************************************************************************/
3837
3838 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3839 {
3840         unsigned int ace_count = 0;
3841         int entry_id = SMB_ACL_FIRST_ENTRY;
3842         SMB_ACL_ENTRY_T entry;
3843
3844         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3845                 /* get_next... */
3846                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3847                         entry_id = SMB_ACL_NEXT_ENTRY;
3848                 }
3849                 ace_count++;
3850         }
3851         return ace_count;
3852 }
3853
3854 /****************************************************************************
3855  Utility function to marshall a POSIX acl into wire format.
3856 ****************************************************************************/
3857
3858 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3859 {
3860         int entry_id = SMB_ACL_FIRST_ENTRY;
3861         SMB_ACL_ENTRY_T entry;
3862
3863         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3864                 SMB_ACL_TAG_T tagtype;
3865                 SMB_ACL_PERMSET_T permset;
3866                 unsigned char perms = 0;
3867                 unsigned int own_grp;
3868
3869                 /* get_next... */
3870                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3871                         entry_id = SMB_ACL_NEXT_ENTRY;
3872                 }
3873
3874                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3875                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3876                         return False;
3877                 }
3878
3879                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3880                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3881                         return False;
3882                 }
3883
3884                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3885                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3886                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3887
3888                 SCVAL(pdata,1,perms);
3889
3890                 switch (tagtype) {
3891                         case SMB_ACL_USER_OBJ:
3892                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3893                                 own_grp = (unsigned int)pst->st_ex_uid;
3894                                 SIVAL(pdata,2,own_grp);
3895                                 SIVAL(pdata,6,0);
3896                                 break;
3897                         case SMB_ACL_USER:
3898                                 {
3899                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3900                                         if (!puid) {
3901                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3902                                                 return False;
3903                                         }
3904                                         own_grp = (unsigned int)*puid;
3905                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3906                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3907                                         SIVAL(pdata,2,own_grp);
3908                                         SIVAL(pdata,6,0);
3909                                         break;
3910                                 }
3911                         case SMB_ACL_GROUP_OBJ:
3912                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3913                                 own_grp = (unsigned int)pst->st_ex_gid;
3914                                 SIVAL(pdata,2,own_grp);
3915                                 SIVAL(pdata,6,0);
3916                                 break;
3917                         case SMB_ACL_GROUP:
3918                                 {
3919                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3920                                         if (!pgid) {
3921                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3922                                                 return False;
3923                                         }
3924                                         own_grp = (unsigned int)*pgid;
3925                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3926                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3927                                         SIVAL(pdata,2,own_grp);
3928                                         SIVAL(pdata,6,0);
3929                                         break;
3930                                 }
3931                         case SMB_ACL_MASK:
3932                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3933                                 SIVAL(pdata,2,0xFFFFFFFF);
3934                                 SIVAL(pdata,6,0xFFFFFFFF);
3935                                 break;
3936                         case SMB_ACL_OTHER:
3937                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3938                                 SIVAL(pdata,2,0xFFFFFFFF);
3939                                 SIVAL(pdata,6,0xFFFFFFFF);
3940                                 break;
3941                         default:
3942                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3943                                 return False;
3944                 }
3945                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3946         }
3947
3948         return True;
3949 }
3950 #endif
3951
3952 /****************************************************************************
3953  Store the FILE_UNIX_BASIC info.
3954 ****************************************************************************/
3955
3956 static char *store_file_unix_basic(connection_struct *conn,
3957                                 char *pdata,
3958                                 files_struct *fsp,
3959                                 const SMB_STRUCT_STAT *psbuf)
3960 {
3961         uint64_t file_index = get_FileIndex(conn, psbuf);
3962         dev_t devno;
3963
3964         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3965         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3966
3967         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
3968         pdata += 8;
3969
3970         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3971         pdata += 8;
3972
3973         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime);       /* Change Time 64 Bit */
3974         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime);     /* Last access time 64 Bit */
3975         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
3976         pdata += 24;
3977
3978         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
3979         SIVAL(pdata,4,0);
3980         pdata += 8;
3981
3982         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
3983         SIVAL(pdata,4,0);
3984         pdata += 8;
3985
3986         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3987         pdata += 4;
3988
3989         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3990                 devno = psbuf->st_ex_rdev;
3991         } else {
3992                 devno = psbuf->st_ex_dev;
3993         }
3994
3995         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
3996         SIVAL(pdata,4,0);
3997         pdata += 8;
3998
3999         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
4000         SIVAL(pdata,4,0);
4001         pdata += 8;
4002
4003         SINO_T_VAL(pdata,0,(SMB_INO_T)file_index);   /* inode number */
4004         pdata += 8;
4005
4006         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
4007         SIVAL(pdata,4,0);
4008         pdata += 8;
4009
4010         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
4011         SIVAL(pdata,4,0);
4012         pdata += 8;
4013
4014         return pdata;
4015 }
4016
4017 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4018  * the chflags(2) (or equivalent) flags.
4019  *
4020  * XXX: this really should be behind the VFS interface. To do this, we would
4021  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4022  * Each VFS module could then implement its own mapping as appropriate for the
4023  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4024  */
4025 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4026         info2_flags_map[] =
4027 {
4028 #ifdef UF_NODUMP
4029     { UF_NODUMP, EXT_DO_NOT_BACKUP },
4030 #endif
4031
4032 #ifdef UF_IMMUTABLE
4033     { UF_IMMUTABLE, EXT_IMMUTABLE },
4034 #endif
4035
4036 #ifdef UF_APPEND
4037     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4038 #endif
4039
4040 #ifdef UF_HIDDEN
4041     { UF_HIDDEN, EXT_HIDDEN },
4042 #endif
4043
4044     /* Do not remove. We need to guarantee that this array has at least one
4045      * entry to build on HP-UX.
4046      */
4047     { 0, 0 }
4048
4049 };
4050
4051 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4052                                 uint32 *smb_fflags, uint32 *smb_fmask)
4053 {
4054         int i;
4055
4056         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4057             *smb_fmask |= info2_flags_map[i].smb_fflag;
4058             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4059                     *smb_fflags |= info2_flags_map[i].smb_fflag;
4060             }
4061         }
4062 }
4063
4064 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4065                                 const uint32 smb_fflags,
4066                                 const uint32 smb_fmask,
4067                                 int *stat_fflags)
4068 {
4069         uint32 max_fmask = 0;
4070         int i;
4071
4072         *stat_fflags = psbuf->st_ex_flags;
4073
4074         /* For each flags requested in smb_fmask, check the state of the
4075          * corresponding flag in smb_fflags and set or clear the matching
4076          * stat flag.
4077          */
4078
4079         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4080             max_fmask |= info2_flags_map[i].smb_fflag;
4081             if (smb_fmask & info2_flags_map[i].smb_fflag) {
4082                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
4083                             *stat_fflags |= info2_flags_map[i].stat_fflag;
4084                     } else {
4085                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4086                     }
4087             }
4088         }
4089
4090         /* If smb_fmask is asking to set any bits that are not supported by
4091          * our flag mappings, we should fail.
4092          */
4093         if ((smb_fmask & max_fmask) != smb_fmask) {
4094                 return False;
4095         }
4096
4097         return True;
4098 }
4099
4100
4101 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4102  * of file flags and birth (create) time.
4103  */
4104 static char *store_file_unix_basic_info2(connection_struct *conn,
4105                                 char *pdata,
4106                                 files_struct *fsp,
4107                                 const SMB_STRUCT_STAT *psbuf)
4108 {
4109         uint32 file_flags = 0;
4110         uint32 flags_mask = 0;
4111
4112         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4113
4114         /* Create (birth) time 64 bit */
4115         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4116         pdata += 8;
4117
4118         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4119         SIVAL(pdata, 0, file_flags); /* flags */
4120         SIVAL(pdata, 4, flags_mask); /* mask */
4121         pdata += 8;
4122
4123         return pdata;
4124 }
4125
4126 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4127                                      const struct stream_struct *streams,
4128                                      char *data,
4129                                      unsigned int max_data_bytes,
4130                                      unsigned int *data_size)
4131 {
4132         unsigned int i;
4133         unsigned int ofs = 0;
4134
4135         for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4136                 unsigned int next_offset;
4137                 size_t namelen;
4138                 smb_ucs2_t *namebuf;
4139
4140                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4141                                       streams[i].name, &namelen) ||
4142                     namelen <= 2)
4143                 {
4144                         return NT_STATUS_INVALID_PARAMETER;
4145                 }
4146
4147                 /*
4148                  * name_buf is now null-terminated, we need to marshall as not
4149                  * terminated
4150                  */
4151
4152                 namelen -= 2;
4153
4154                 SIVAL(data, ofs+4, namelen);
4155                 SOFF_T(data, ofs+8, streams[i].size);
4156                 SOFF_T(data, ofs+16, streams[i].alloc_size);
4157                 memcpy(data+ofs+24, namebuf, namelen);
4158                 TALLOC_FREE(namebuf);
4159
4160                 next_offset = ofs + 24 + namelen;
4161
4162                 if (i == num_streams-1) {
4163                         SIVAL(data, ofs, 0);
4164                 }
4165                 else {
4166                         unsigned int align = ndr_align_size(next_offset, 8);
4167
4168                         memset(data+next_offset, 0, align);
4169                         next_offset += align;
4170
4171                         SIVAL(data, ofs, next_offset - ofs);
4172                         ofs = next_offset;
4173                 }
4174
4175                 ofs = next_offset;
4176         }
4177
4178         *data_size = ofs;
4179
4180         return NT_STATUS_OK;
4181 }
4182
4183 /****************************************************************************
4184  Reply to a TRANSACT2_QFILEINFO on a PIPE !
4185 ****************************************************************************/
4186
4187 static void call_trans2qpipeinfo(connection_struct *conn,
4188                                  struct smb_request *req,
4189                                  unsigned int tran_call,
4190                                  char **pparams, int total_params,
4191                                  char **ppdata, int total_data,
4192                                  unsigned int max_data_bytes)
4193 {
4194         char *params = *pparams;
4195         char *pdata = *ppdata;
4196         unsigned int data_size = 0;
4197         unsigned int param_size = 2;
4198         uint16 info_level;
4199         files_struct *fsp;
4200
4201         if (!params) {
4202                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4203                 return;
4204         }
4205
4206         if (total_params < 4) {
4207                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4208                 return;
4209         }
4210
4211         fsp = file_fsp(req, SVAL(params,0));
4212         if (!fsp_is_np(fsp)) {
4213                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4214                 return;
4215         }
4216
4217         info_level = SVAL(params,2);
4218
4219         *pparams = (char *)SMB_REALLOC(*pparams,2);
4220         if (*pparams == NULL) {
4221                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4222                 return;
4223         }
4224         params = *pparams;
4225         SSVAL(params,0,0);
4226         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4227         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4228         if (*ppdata == NULL ) {
4229                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4230                 return;
4231         }
4232         pdata = *ppdata;
4233
4234         switch (info_level) {
4235                 case SMB_FILE_STANDARD_INFORMATION:
4236                         memset(pdata,0,24);
4237                         SOFF_T(pdata,0,4096LL);
4238                         SIVAL(pdata,16,1);
4239                         SIVAL(pdata,20,1);
4240                         data_size = 24;
4241                         break;
4242
4243                 default:
4244                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4245                         return;
4246         }
4247
4248         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4249                             max_data_bytes);
4250
4251         return;
4252 }
4253
4254 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4255                                TALLOC_CTX *mem_ctx,
4256                                uint16_t info_level,
4257                                files_struct *fsp,
4258                                struct smb_filename *smb_fname,
4259                                bool delete_pending,
4260                                struct timespec write_time_ts,
4261                                struct ea_list *ea_list,
4262                                int lock_data_count,
4263                                char *lock_data,
4264                                uint16_t flags2,
4265                                unsigned int max_data_bytes,
4266                                char **ppdata,
4267                                unsigned int *pdata_size)
4268 {
4269         char *pdata = *ppdata;
4270         char *dstart, *dend;
4271         unsigned int data_size;
4272         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4273         time_t create_time, mtime, atime, c_time;
4274         SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4275         char *p;
4276         char *base_name;
4277         char *dos_fname;
4278         int mode;
4279         int nlink;
4280         NTSTATUS status;
4281         uint64_t file_size = 0;
4282         uint64_t pos = 0;
4283         uint64_t allocation_size = 0;
4284         uint64_t file_index = 0;
4285         uint32_t access_mask = 0;
4286
4287         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4288                 return NT_STATUS_INVALID_LEVEL;
4289         }
4290
4291         DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4292                  smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4293                  info_level, max_data_bytes));
4294
4295         mode = dos_mode(conn, smb_fname);
4296         nlink = psbuf->st_ex_nlink;
4297
4298         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4299                 nlink = 1;
4300         }
4301
4302         if ((nlink > 0) && delete_pending) {
4303                 nlink -= 1;
4304         }
4305
4306         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4307         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
4308         if (*ppdata == NULL) {
4309                 return NT_STATUS_NO_MEMORY;
4310         }
4311         pdata = *ppdata;
4312         dstart = pdata;
4313         dend = dstart + data_size - 1;
4314
4315         if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4316                 update_stat_ex_mtime(psbuf, write_time_ts);
4317         }
4318
4319         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4320         mtime_ts = psbuf->st_ex_mtime;
4321         atime_ts = psbuf->st_ex_atime;
4322         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4323
4324         if (lp_dos_filetime_resolution(SNUM(conn))) {
4325                 dos_filetime_timespec(&create_time_ts);
4326                 dos_filetime_timespec(&mtime_ts);
4327                 dos_filetime_timespec(&atime_ts);
4328                 dos_filetime_timespec(&ctime_ts);
4329         }
4330
4331         create_time = convert_timespec_to_time_t(create_time_ts);
4332         mtime = convert_timespec_to_time_t(mtime_ts);
4333         atime = convert_timespec_to_time_t(atime_ts);
4334         c_time = convert_timespec_to_time_t(ctime_ts);
4335
4336         p = strrchr_m(smb_fname->base_name,'/');
4337         if (!p)
4338                 base_name = smb_fname->base_name;
4339         else
4340                 base_name = p+1;
4341
4342         /* NT expects the name to be in an exact form of the *full*
4343            filename. See the trans2 torture test */
4344         if (ISDOT(base_name)) {
4345                 dos_fname = talloc_strdup(mem_ctx, "\\");
4346                 if (!dos_fname) {
4347                         return NT_STATUS_NO_MEMORY;
4348                 }
4349         } else {
4350                 dos_fname = talloc_asprintf(mem_ctx,
4351                                 "\\%s",
4352                                 smb_fname->base_name);
4353                 if (!dos_fname) {
4354                         return NT_STATUS_NO_MEMORY;
4355                 }
4356                 if (is_ntfs_stream_smb_fname(smb_fname)) {
4357                         dos_fname = talloc_asprintf(dos_fname, "%s",
4358                                                     smb_fname->stream_name);
4359                         if (!dos_fname) {
4360                                 return NT_STATUS_NO_MEMORY;
4361                         }
4362                 }
4363
4364                 string_replace(dos_fname, '/', '\\');
4365         }
4366
4367         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4368
4369         if (!fsp) {
4370                 /* Do we have this path open ? */
4371                 files_struct *fsp1;
4372                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4373                 fsp1 = file_find_di_first(conn->sconn, fileid);
4374                 if (fsp1 && fsp1->initial_allocation_size) {
4375                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4376                 }
4377         }
4378
4379         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4380                 file_size = get_file_size_stat(psbuf);
4381         }
4382
4383         if (fsp) {
4384                 pos = fsp->fh->position_information;
4385         }
4386
4387         if (fsp) {
4388                 access_mask = fsp->access_mask;
4389         } else {
4390                 /* GENERIC_EXECUTE mapping from Windows */
4391                 access_mask = 0x12019F;
4392         }
4393
4394         /* This should be an index number - looks like
4395            dev/ino to me :-)
4396
4397            I think this causes us to fail the IFSKIT
4398            BasicFileInformationTest. -tpot */
4399         file_index = get_FileIndex(conn, psbuf);
4400
4401         switch (info_level) {
4402                 case SMB_INFO_STANDARD:
4403                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4404                         data_size = 22;
4405                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4406                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4407                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4408                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
4409                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4410                         SSVAL(pdata,l1_attrFile,mode);
4411                         break;
4412
4413                 case SMB_INFO_QUERY_EA_SIZE:
4414                 {
4415                         unsigned int ea_size =
4416                             estimate_ea_size(conn, fsp,
4417                                              smb_fname->base_name);
4418                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4419                         data_size = 26;
4420                         srv_put_dos_date2(pdata,0,create_time);
4421                         srv_put_dos_date2(pdata,4,atime);
4422                         srv_put_dos_date2(pdata,8,mtime); /* write time */
4423                         SIVAL(pdata,12,(uint32)file_size);
4424                         SIVAL(pdata,16,(uint32)allocation_size);
4425                         SSVAL(pdata,20,mode);
4426                         SIVAL(pdata,22,ea_size);
4427                         break;
4428                 }
4429
4430                 case SMB_INFO_IS_NAME_VALID:
4431                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4432                         if (fsp) {
4433                                 /* os/2 needs this ? really ?*/
4434                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4435                         }
4436                         /* This is only reached for qpathinfo */
4437                         data_size = 0;
4438                         break;
4439
4440                 case SMB_INFO_QUERY_EAS_FROM_LIST:
4441                 {
4442                         size_t total_ea_len = 0;
4443                         struct ea_list *ea_file_list = NULL;
4444
4445                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4446
4447                         ea_file_list =
4448                             get_ea_list_from_file(mem_ctx, conn, fsp,
4449                                                   smb_fname->base_name,
4450                                                   &total_ea_len);
4451                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4452
4453                         if (!ea_list || (total_ea_len > data_size)) {
4454                                 data_size = 4;
4455                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4456                                 break;
4457                         }
4458
4459                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4460                         break;
4461                 }
4462
4463                 case SMB_INFO_QUERY_ALL_EAS:
4464                 {
4465                         /* We have data_size bytes to put EA's into. */
4466                         size_t total_ea_len = 0;
4467
4468                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4469
4470                         ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4471                                                         smb_fname->base_name,
4472                                                         &total_ea_len);
4473                         if (!ea_list || (total_ea_len > data_size)) {
4474                                 data_size = 4;
4475                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
4476                                 break;
4477                         }
4478
4479                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4480                         break;
4481                 }
4482
4483                 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4484                 {
4485                         /* This is FileFullEaInformation - 0xF which maps to
4486                          * 1015 (decimal) in smbd_do_setfilepathinfo. */
4487
4488                         /* We have data_size bytes to put EA's into. */
4489                         size_t total_ea_len = 0;
4490                         struct ea_list *ea_file_list = NULL;
4491
4492                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4493
4494                         /*TODO: add filtering and index handling */
4495
4496                         ea_file_list =
4497                             get_ea_list_from_file(mem_ctx, conn, fsp,
4498                                                   smb_fname->base_name,
4499                                                   &total_ea_len);
4500                         if (!ea_file_list) {
4501                                 return NT_STATUS_NO_EAS_ON_FILE;
4502                         }
4503
4504                         status = fill_ea_chained_buffer(mem_ctx,
4505                                                         pdata,
4506                                                         data_size,
4507                                                         &data_size,
4508                                                         conn, ea_file_list);
4509                         if (!NT_STATUS_IS_OK(status)) {
4510                                 return status;
4511                         }
4512                         break;
4513                 }
4514
4515                 case SMB_FILE_BASIC_INFORMATION:
4516                 case SMB_QUERY_FILE_BASIC_INFO:
4517
4518                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4519                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4520                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4521                         } else {
4522                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4523                                 data_size = 40;
4524                                 SIVAL(pdata,36,0);
4525                         }
4526                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4527                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4528                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4529                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4530                         SIVAL(pdata,32,mode);
4531
4532                         DEBUG(5,("SMB_QFBI - "));
4533                         DEBUG(5,("create: %s ", ctime(&create_time)));
4534                         DEBUG(5,("access: %s ", ctime(&atime)));
4535                         DEBUG(5,("write: %s ", ctime(&mtime)));
4536                         DEBUG(5,("change: %s ", ctime(&c_time)));
4537                         DEBUG(5,("mode: %x\n", mode));
4538                         break;
4539
4540                 case SMB_FILE_STANDARD_INFORMATION:
4541                 case SMB_QUERY_FILE_STANDARD_INFO:
4542
4543                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4544                         data_size = 24;
4545                         SOFF_T(pdata,0,allocation_size);
4546                         SOFF_T(pdata,8,file_size);
4547                         SIVAL(pdata,16,nlink);
4548                         SCVAL(pdata,20,delete_pending?1:0);
4549                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4550                         SSVAL(pdata,22,0); /* Padding. */
4551                         break;
4552
4553                 case SMB_FILE_EA_INFORMATION:
4554                 case SMB_QUERY_FILE_EA_INFO:
4555                 {
4556                         unsigned int ea_size =
4557                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4558                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4559                         data_size = 4;
4560                         SIVAL(pdata,0,ea_size);
4561                         break;
4562                 }
4563
4564                 /* Get the 8.3 name - used if NT SMB was negotiated. */
4565                 case SMB_QUERY_FILE_ALT_NAME_INFO:
4566                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4567                 {
4568                         int len;
4569                         char mangled_name[13];
4570                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4571                         if (!name_to_8_3(base_name,mangled_name,
4572                                                 True,conn->params)) {
4573                                 return NT_STATUS_NO_MEMORY;
4574                         }
4575                         len = srvstr_push(dstart, flags2,
4576                                           pdata+4, mangled_name,
4577                                           PTR_DIFF(dend, pdata+4),
4578                                           STR_UNICODE);
4579                         data_size = 4 + len;
4580                         SIVAL(pdata,0,len);
4581                         break;
4582                 }
4583
4584                 case SMB_QUERY_FILE_NAME_INFO:
4585                 {
4586                         int len;
4587                         /*
4588                           this must be *exactly* right for ACLs on mapped drives to work
4589                          */
4590                         len = srvstr_push(dstart, flags2,
4591                                           pdata+4, dos_fname,
4592                                           PTR_DIFF(dend, pdata+4),
4593                                           STR_UNICODE);
4594                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4595                         data_size = 4 + len;
4596                         SIVAL(pdata,0,len);
4597                         break;
4598                 }
4599
4600                 case SMB_FILE_ALLOCATION_INFORMATION:
4601                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4602                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4603                         data_size = 8;
4604                         SOFF_T(pdata,0,allocation_size);
4605                         break;
4606
4607                 case SMB_FILE_END_OF_FILE_INFORMATION:
4608                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4609                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4610                         data_size = 8;
4611                         SOFF_T(pdata,0,file_size);
4612                         break;
4613
4614                 case SMB_QUERY_FILE_ALL_INFO:
4615                 case SMB_FILE_ALL_INFORMATION:
4616                 {
4617                         int len;
4618                         unsigned int ea_size =
4619                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4620                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4621                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4622                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4623                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4624                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4625                         SIVAL(pdata,32,mode);
4626                         SIVAL(pdata,36,0); /* padding. */
4627                         pdata += 40;
4628                         SOFF_T(pdata,0,allocation_size);
4629                         SOFF_T(pdata,8,file_size);
4630                         SIVAL(pdata,16,nlink);
4631                         SCVAL(pdata,20,delete_pending);
4632                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4633                         SSVAL(pdata,22,0);
4634                         pdata += 24;
4635                         SIVAL(pdata,0,ea_size);
4636                         pdata += 4; /* EA info */
4637                         len = srvstr_push(dstart, flags2,
4638                                           pdata+4, dos_fname,
4639                                           PTR_DIFF(dend, pdata+4),
4640                                           STR_UNICODE);
4641                         SIVAL(pdata,0,len);
4642                         pdata += 4 + len;
4643                         data_size = PTR_DIFF(pdata,(*ppdata));
4644                         break;
4645                 }
4646
4647                 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4648                 {
4649                         int len;
4650                         unsigned int ea_size =
4651                             estimate_ea_size(conn, fsp, smb_fname->base_name);
4652                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4653                         put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4654                         put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4655                         put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4656                         put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4657                         SIVAL(pdata,    0x20, mode);
4658                         SIVAL(pdata,    0x24, 0); /* padding. */
4659                         SBVAL(pdata,    0x28, allocation_size);
4660                         SBVAL(pdata,    0x30, file_size);
4661                         SIVAL(pdata,    0x38, nlink);
4662                         SCVAL(pdata,    0x3C, delete_pending);
4663                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4664                         SSVAL(pdata,    0x3E, 0); /* padding */
4665                         SBVAL(pdata,    0x40, file_index);
4666                         SIVAL(pdata,    0x48, ea_size);
4667                         SIVAL(pdata,    0x4C, access_mask);
4668                         SBVAL(pdata,    0x50, pos);
4669                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
4670                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
4671
4672                         pdata += 0x60;
4673
4674                         len = srvstr_push(dstart, flags2,
4675                                           pdata+4, dos_fname,
4676                                           PTR_DIFF(dend, pdata+4),
4677                                           STR_UNICODE);
4678                         SIVAL(pdata,0,len);
4679                         pdata += 4 + len;
4680                         data_size = PTR_DIFF(pdata,(*ppdata));
4681                         break;
4682                 }
4683                 case SMB_FILE_INTERNAL_INFORMATION:
4684
4685                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4686                         SBVAL(pdata, 0, file_index);
4687                         data_size = 8;
4688                         break;
4689
4690                 case SMB_FILE_ACCESS_INFORMATION:
4691                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4692                         SIVAL(pdata, 0, access_mask);
4693                         data_size = 4;
4694                         break;
4695
4696                 case SMB_FILE_NAME_INFORMATION:
4697                         /* Pathname with leading '\'. */
4698                         {
4699                                 size_t byte_len;
4700                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4701                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4702                                 SIVAL(pdata,0,byte_len);
4703                                 data_size = 4 + byte_len;
4704                                 break;
4705                         }
4706
4707                 case SMB_FILE_DISPOSITION_INFORMATION:
4708                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4709                         data_size = 1;
4710                         SCVAL(pdata,0,delete_pending);
4711                         break;
4712
4713                 case SMB_FILE_POSITION_INFORMATION:
4714                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4715                         data_size = 8;
4716                         SOFF_T(pdata,0,pos);
4717                         break;
4718
4719                 case SMB_FILE_MODE_INFORMATION:
4720                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4721                         SIVAL(pdata,0,mode);
4722                         data_size = 4;
4723                         break;
4724
4725                 case SMB_FILE_ALIGNMENT_INFORMATION:
4726                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4727                         SIVAL(pdata,0,0); /* No alignment needed. */
4728                         data_size = 4;
4729                         break;
4730
4731                 /*
4732                  * NT4 server just returns "invalid query" to this - if we try
4733                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
4734                  * want this. JRA.
4735                  */
4736                 /* The first statement above is false - verified using Thursby
4737                  * client against NT4 -- gcolley.
4738                  */
4739                 case SMB_QUERY_FILE_STREAM_INFO:
4740                 case SMB_FILE_STREAM_INFORMATION: {
4741                         unsigned int num_streams = 0;
4742                         struct stream_struct *streams = NULL;
4743
4744                         DEBUG(10,("smbd_do_qfilepathinfo: "
4745                                   "SMB_FILE_STREAM_INFORMATION\n"));
4746
4747                         if (is_ntfs_stream_smb_fname(smb_fname)) {
4748                                 return NT_STATUS_INVALID_PARAMETER;
4749                         }
4750
4751                         status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4752                                                 talloc_tos(), &num_streams, &streams);
4753
4754                         if (!NT_STATUS_IS_OK(status)) {
4755                                 DEBUG(10, ("could not get stream info: %s\n",
4756                                            nt_errstr(status)));
4757                                 return status;
4758                         }
4759
4760                         status = marshall_stream_info(num_streams, streams,
4761                                                       pdata, max_data_bytes,
4762                                                       &data_size);
4763
4764                         if (!NT_STATUS_IS_OK(status)) {
4765                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
4766                                            nt_errstr(status)));
4767                                 return status;
4768                         }
4769
4770                         TALLOC_FREE(streams);
4771
4772                         break;
4773                 }
4774                 case SMB_QUERY_COMPRESSION_INFO:
4775                 case SMB_FILE_COMPRESSION_INFORMATION:
4776                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4777                         SOFF_T(pdata,0,file_size);
4778                         SIVAL(pdata,8,0); /* ??? */
4779                         SIVAL(pdata,12,0); /* ??? */
4780                         data_size = 16;
4781                         break;
4782
4783                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4784                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4785                         put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4786                         put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4787                         put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4788                         put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4789                         SOFF_T(pdata,32,allocation_size);
4790                         SOFF_T(pdata,40,file_size);
4791                         SIVAL(pdata,48,mode);
4792                         SIVAL(pdata,52,0); /* ??? */
4793                         data_size = 56;
4794                         break;
4795
4796                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4797                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4798                         SIVAL(pdata,0,mode);
4799                         SIVAL(pdata,4,0);
4800                         data_size = 8;
4801                         break;
4802
4803                 /*
4804                  * CIFS UNIX Extensions.
4805                  */
4806
4807                 case SMB_QUERY_FILE_UNIX_BASIC:
4808
4809                         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4810                         data_size = PTR_DIFF(pdata,(*ppdata));
4811
4812                         DEBUG(4,("smbd_do_qfilepathinfo: "
4813                                  "SMB_QUERY_FILE_UNIX_BASIC\n"));
4814                         dump_data(4, (uint8_t *)(*ppdata), data_size);
4815
4816                         break;
4817
4818                 case SMB_QUERY_FILE_UNIX_INFO2:
4819
4820                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4821                         data_size = PTR_DIFF(pdata,(*ppdata));
4822
4823                         {
4824                                 int i;
4825                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4826
4827                                 for (i=0; i<100; i++)
4828                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4829                                 DEBUG(4,("\n"));
4830                         }
4831
4832                         break;
4833
4834                 case SMB_QUERY_FILE_UNIX_LINK:
4835                         {
4836                                 int len;
4837                                 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4838
4839                                 if (!buffer) {
4840                                         return NT_STATUS_NO_MEMORY;
4841                                 }
4842
4843                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4844 #ifdef S_ISLNK
4845                                 if(!S_ISLNK(psbuf->st_ex_mode)) {
4846                                         return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4847                                 }
4848 #else
4849                                 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4850 #endif
4851                                 len = SMB_VFS_READLINK(conn,
4852                                                        smb_fname->base_name,
4853                                                        buffer, PATH_MAX);
4854                                 if (len == -1) {
4855                                         return map_nt_error_from_unix(errno);
4856                                 }
4857                                 buffer[len] = 0;
4858                                 len = srvstr_push(dstart, flags2,
4859                                                   pdata, buffer,
4860                                                   PTR_DIFF(dend, pdata),
4861                                                   STR_TERMINATE);
4862                                 pdata += len;
4863                                 data_size = PTR_DIFF(pdata,(*ppdata));
4864
4865                                 break;
4866                         }
4867
4868 #if defined(HAVE_POSIX_ACLS)
4869                 case SMB_QUERY_POSIX_ACL:
4870                         {
4871                                 SMB_ACL_T file_acl = NULL;
4872                                 SMB_ACL_T def_acl = NULL;
4873                                 uint16 num_file_acls = 0;
4874                                 uint16 num_def_acls = 0;
4875
4876                                 if (fsp && fsp->fh->fd != -1) {
4877                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4878                                 } else {
4879                                         file_acl =
4880                                             SMB_VFS_SYS_ACL_GET_FILE(conn,
4881                                                 smb_fname->base_name,
4882                                                 SMB_ACL_TYPE_ACCESS);
4883                                 }
4884
4885                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4886                                         DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4887                                                  "not implemented on "
4888                                                  "filesystem containing %s\n",
4889                                                  smb_fname->base_name));
4890                                         return NT_STATUS_NOT_IMPLEMENTED;
4891                                 }
4892
4893                                 if (S_ISDIR(psbuf->st_ex_mode)) {
4894                                         if (fsp && fsp->is_directory) {
4895                                                 def_acl =
4896                                                     SMB_VFS_SYS_ACL_GET_FILE(
4897                                                             conn,
4898                                                             fsp->fsp_name->base_name,
4899                                                             SMB_ACL_TYPE_DEFAULT);
4900                                         } else {
4901                                                 def_acl =
4902                                                     SMB_VFS_SYS_ACL_GET_FILE(
4903                                                             conn,
4904                                                             smb_fname->base_name,
4905                                                             SMB_ACL_TYPE_DEFAULT);
4906                                         }
4907                                         def_acl = free_empty_sys_acl(conn, def_acl);
4908                                 }
4909
4910                                 num_file_acls = count_acl_entries(conn, file_acl);
4911                                 num_def_acls = count_acl_entries(conn, def_acl);
4912
4913                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4914                                         DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4915                                                 data_size,
4916                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4917                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4918                                         if (file_acl) {
4919                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4920                                         }
4921                                         if (def_acl) {
4922                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4923                                         }
4924                                         return NT_STATUS_BUFFER_TOO_SMALL;
4925                                 }
4926
4927                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4928                                 SSVAL(pdata,2,num_file_acls);
4929                                 SSVAL(pdata,4,num_def_acls);
4930                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4931                                         if (file_acl) {
4932                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4933                                         }
4934                                         if (def_acl) {
4935                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4936                                         }
4937                                         return NT_STATUS_INTERNAL_ERROR;
4938                                 }
4939                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4940                                         if (file_acl) {
4941                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4942                                         }
4943                                         if (def_acl) {
4944                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4945                                         }
4946                                         return NT_STATUS_INTERNAL_ERROR;
4947                                 }
4948
4949                                 if (file_acl) {
4950                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4951                                 }
4952                                 if (def_acl) {
4953                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4954                                 }
4955                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4956                                 break;
4957                         }
4958 #endif
4959
4960
4961                 case SMB_QUERY_POSIX_LOCK:
4962                 {
4963                         uint64_t count;
4964                         uint64_t offset;
4965                         uint64_t smblctx;
4966                         enum brl_type lock_type;
4967
4968                         /* We need an open file with a real fd for this. */
4969                         if (!fsp || fsp->fh->fd == -1) {
4970                                 return NT_STATUS_INVALID_LEVEL;
4971                         }
4972
4973                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4974                                 return NT_STATUS_INVALID_PARAMETER;
4975                         }
4976
4977                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4978                                 case POSIX_LOCK_TYPE_READ:
4979                                         lock_type = READ_LOCK;
4980                                         break;
4981                                 case POSIX_LOCK_TYPE_WRITE:
4982                                         lock_type = WRITE_LOCK;
4983                                         break;
4984                                 case POSIX_LOCK_TYPE_UNLOCK:
4985                                 default:
4986                                         /* There's no point in asking for an unlock... */
4987                                         return NT_STATUS_INVALID_PARAMETER;
4988                         }
4989
4990                         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4991 #if defined(HAVE_LONGLONG)
4992                         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4993                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4994                         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4995                                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4996 #else /* HAVE_LONGLONG */
4997                         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4998                         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4999 #endif /* HAVE_LONGLONG */
5000
5001                         status = query_lock(fsp,
5002                                         &smblctx,
5003                                         &count,
5004                                         &offset,
5005                                         &lock_type,
5006                                         POSIX_LOCK);
5007
5008                         if (ERROR_WAS_LOCK_DENIED(status)) {
5009                                 /* Here we need to report who has it locked... */
5010                                 data_size = POSIX_LOCK_DATA_SIZE;
5011
5012                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5013                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5014                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5015 #if defined(HAVE_LONGLONG)
5016                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5017                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5018                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5019                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5020 #else /* HAVE_LONGLONG */
5021                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5022                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5023 #endif /* HAVE_LONGLONG */
5024
5025                         } else if (NT_STATUS_IS_OK(status)) {
5026                                 /* For success we just return a copy of what we sent
5027                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5028                                 data_size = POSIX_LOCK_DATA_SIZE;
5029                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5030                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5031                         } else {
5032                                 return status;
5033                         }
5034                         break;
5035                 }
5036
5037                 default:
5038                         return NT_STATUS_INVALID_LEVEL;
5039         }
5040
5041         *pdata_size = data_size;
5042         return NT_STATUS_OK;
5043 }
5044
5045 /****************************************************************************
5046  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5047  file name or file id).
5048 ****************************************************************************/
5049
5050 static void call_trans2qfilepathinfo(connection_struct *conn,
5051                                      struct smb_request *req,
5052                                      unsigned int tran_call,
5053                                      char **pparams, int total_params,
5054                                      char **ppdata, int total_data,
5055                                      unsigned int max_data_bytes)
5056 {
5057         char *params = *pparams;
5058         char *pdata = *ppdata;
5059         uint16 info_level;
5060         unsigned int data_size = 0;
5061         unsigned int param_size = 2;
5062         struct smb_filename *smb_fname = NULL;
5063         bool delete_pending = False;
5064         struct timespec write_time_ts;
5065         files_struct *fsp = NULL;
5066         struct file_id fileid;
5067         struct ea_list *ea_list = NULL;
5068         int lock_data_count = 0;
5069         char *lock_data = NULL;
5070         NTSTATUS status = NT_STATUS_OK;
5071
5072         if (!params) {
5073                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5074                 return;
5075         }
5076
5077         ZERO_STRUCT(write_time_ts);
5078
5079         if (tran_call == TRANSACT2_QFILEINFO) {
5080                 if (total_params < 4) {
5081                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5082                         return;
5083                 }
5084
5085                 if (IS_IPC(conn)) {
5086                         call_trans2qpipeinfo(conn, req, tran_call,
5087                                              pparams, total_params,
5088                                              ppdata, total_data,
5089                                              max_data_bytes);
5090                         return;
5091                 }
5092
5093                 fsp = file_fsp(req, SVAL(params,0));
5094                 info_level = SVAL(params,2);
5095
5096                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5097
5098                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5099                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5100                         return;
5101                 }
5102
5103                 /* Initial check for valid fsp ptr. */
5104                 if (!check_fsp_open(conn, req, fsp)) {
5105                         return;
5106                 }
5107
5108                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5109                                            &smb_fname);
5110                 if (!NT_STATUS_IS_OK(status)) {
5111                         reply_nterror(req, status);
5112                         return;
5113                 }
5114
5115                 if(fsp->fake_file_handle) {
5116                         /*
5117                          * This is actually for the QUOTA_FAKE_FILE --metze
5118                          */
5119
5120                         /* We know this name is ok, it's already passed the checks. */
5121
5122                 } else if(fsp->fh->fd == -1) {
5123                         /*
5124                          * This is actually a QFILEINFO on a directory
5125                          * handle (returned from an NT SMB). NT5.0 seems
5126                          * to do this call. JRA.
5127                          */
5128
5129                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5130                                 /* Always do lstat for UNIX calls. */
5131                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5132                                         DEBUG(3,("call_trans2qfilepathinfo: "
5133                                                  "SMB_VFS_LSTAT of %s failed "
5134                                                  "(%s)\n",
5135                                                  smb_fname_str_dbg(smb_fname),
5136                                                  strerror(errno)));
5137                                         reply_nterror(req,
5138                                                 map_nt_error_from_unix(errno));
5139                                         return;
5140                                 }
5141                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
5142                                 DEBUG(3,("call_trans2qfilepathinfo: "
5143                                          "SMB_VFS_STAT of %s failed (%s)\n",
5144                                          smb_fname_str_dbg(smb_fname),
5145                                          strerror(errno)));
5146                                 reply_nterror(req,
5147                                         map_nt_error_from_unix(errno));
5148                                 return;
5149                         }
5150
5151                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5152                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5153                 } else {
5154                         /*
5155                          * Original code - this is an open file.
5156                          */
5157                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5158                                 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5159                                           fsp->fnum, strerror(errno)));
5160                                 reply_nterror(req,
5161                                         map_nt_error_from_unix(errno));
5162                                 return;
5163                         }
5164                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5165                         get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5166                 }
5167
5168         } else {
5169                 uint32_t name_hash;
5170                 char *fname = NULL;
5171                 uint32_t ucf_flags = 0;
5172
5173                 /* qpathinfo */
5174                 if (total_params < 7) {
5175                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5176                         return;
5177                 }
5178
5179                 info_level = SVAL(params,0);
5180
5181                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5182
5183                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5184                         if (!lp_unix_extensions()) {
5185                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5186                                 return;
5187                         }
5188                         if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5189                                         info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5190                                         info_level == SMB_QUERY_FILE_UNIX_LINK) {
5191                                 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5192                         }
5193                 }
5194
5195                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5196                                 total_params - 6,
5197                                 STR_TERMINATE, &status);
5198                 if (!NT_STATUS_IS_OK(status)) {
5199                         reply_nterror(req, status);
5200                         return;
5201                 }
5202
5203                 status = filename_convert(req,
5204                                         conn,
5205                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
5206                                         fname,
5207                                         ucf_flags,
5208                                         NULL,
5209                                         &smb_fname);
5210                 if (!NT_STATUS_IS_OK(status)) {
5211                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5212                                 reply_botherror(req,
5213                                                 NT_STATUS_PATH_NOT_COVERED,
5214                                                 ERRSRV, ERRbadpath);
5215                                 return;
5216                         }
5217                         reply_nterror(req, status);
5218                         return;
5219                 }
5220
5221                 /* If this is a stream, check if there is a delete_pending. */
5222                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5223                     && is_ntfs_stream_smb_fname(smb_fname)) {
5224                         struct smb_filename *smb_fname_base = NULL;
5225
5226                         /* Create an smb_filename with stream_name == NULL. */
5227                         status =
5228                             create_synthetic_smb_fname(talloc_tos(),
5229                                                        smb_fname->base_name,
5230                                                        NULL, NULL,
5231                                                        &smb_fname_base);
5232                         if (!NT_STATUS_IS_OK(status)) {
5233                                 reply_nterror(req, status);
5234                                 return;
5235                         }
5236
5237                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5238                                 /* Always do lstat for UNIX calls. */
5239                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5240                                         DEBUG(3,("call_trans2qfilepathinfo: "
5241                                                  "SMB_VFS_LSTAT of %s failed "
5242                                                  "(%s)\n",
5243                                                  smb_fname_str_dbg(smb_fname_base),
5244                                                  strerror(errno)));
5245                                         TALLOC_FREE(smb_fname_base);
5246                                         reply_nterror(req,
5247                                                 map_nt_error_from_unix(errno));
5248                                         return;
5249                                 }
5250                         } else {
5251                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5252                                         DEBUG(3,("call_trans2qfilepathinfo: "
5253                                                  "fileinfo of %s failed "
5254                                                  "(%s)\n",
5255                                                  smb_fname_str_dbg(smb_fname_base),
5256                                                  strerror(errno)));
5257                                         TALLOC_FREE(smb_fname_base);
5258                                         reply_nterror(req,
5259                                                 map_nt_error_from_unix(errno));
5260                                         return;
5261                                 }
5262                         }
5263
5264                         status = file_name_hash(conn,
5265                                         smb_fname_str_dbg(smb_fname_base),
5266                                         &name_hash);
5267                         if (!NT_STATUS_IS_OK(status)) {
5268                                 TALLOC_FREE(smb_fname_base);
5269                                 reply_nterror(req, status);
5270                                 return;
5271                         }
5272
5273                         fileid = vfs_file_id_from_sbuf(conn,
5274                                                        &smb_fname_base->st);
5275                         TALLOC_FREE(smb_fname_base);
5276                         get_file_infos(fileid, name_hash, &delete_pending, NULL);
5277                         if (delete_pending) {
5278                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5279                                 return;
5280                         }
5281                 }
5282
5283                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5284                         /* Always do lstat for UNIX calls. */
5285                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
5286                                 DEBUG(3,("call_trans2qfilepathinfo: "
5287                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
5288                                          smb_fname_str_dbg(smb_fname),
5289                                          strerror(errno)));
5290                                 reply_nterror(req,
5291                                         map_nt_error_from_unix(errno));
5292                                 return;
5293                         }
5294
5295                 } else {
5296                         if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5297                                 DEBUG(3,("call_trans2qfilepathinfo: "
5298                                          "SMB_VFS_STAT of %s failed (%s)\n",
5299                                          smb_fname_str_dbg(smb_fname),
5300                                          strerror(errno)));
5301                                 reply_nterror(req,
5302                                         map_nt_error_from_unix(errno));
5303                                 return;
5304                         }
5305                 }
5306
5307                 status = file_name_hash(conn,
5308                                 smb_fname_str_dbg(smb_fname),
5309                                 &name_hash);
5310                 if (!NT_STATUS_IS_OK(status)) {
5311                         reply_nterror(req, status);
5312                         return;
5313                 }
5314
5315                 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5316                 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5317                 if (delete_pending) {
5318                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
5319                         return;
5320                 }
5321         }
5322
5323         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5324                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5325                  fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5326
5327         /* Pull out any data sent here before we realloc. */
5328         switch (info_level) {
5329                 case SMB_INFO_QUERY_EAS_FROM_LIST:
5330                 {
5331                         /* Pull any EA list from the data portion. */
5332                         uint32 ea_size;
5333
5334                         if (total_data < 4) {
5335                                 reply_nterror(
5336                                         req, NT_STATUS_INVALID_PARAMETER);
5337                                 return;
5338                         }
5339                         ea_size = IVAL(pdata,0);
5340
5341                         if (total_data > 0 && ea_size != total_data) {
5342                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5343 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5344                                 reply_nterror(
5345                                         req, NT_STATUS_INVALID_PARAMETER);
5346                                 return;
5347                         }
5348
5349                         if (!lp_ea_support(SNUM(conn))) {
5350                                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5351                                 return;
5352                         }
5353
5354                         /* Pull out the list of names. */
5355                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5356                         if (!ea_list) {
5357                                 reply_nterror(
5358                                         req, NT_STATUS_INVALID_PARAMETER);
5359                                 return;
5360                         }
5361                         break;
5362                 }
5363
5364                 case SMB_QUERY_POSIX_LOCK:
5365                 {
5366                         if (fsp == NULL || fsp->fh->fd == -1) {
5367                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5368                                 return;
5369                         }
5370
5371                         if (total_data != POSIX_LOCK_DATA_SIZE) {
5372                                 reply_nterror(
5373                                         req, NT_STATUS_INVALID_PARAMETER);
5374                                 return;
5375                         }
5376
5377                         /* Copy the lock range data. */
5378                         lock_data = (char *)talloc_memdup(
5379                                 req, pdata, total_data);
5380                         if (!lock_data) {
5381                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5382                                 return;
5383                         }
5384                         lock_data_count = total_data;
5385                 }
5386                 default:
5387                         break;
5388         }
5389
5390         *pparams = (char *)SMB_REALLOC(*pparams,2);
5391         if (*pparams == NULL) {
5392                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5393                 return;
5394         }
5395         params = *pparams;
5396         SSVAL(params,0,0);
5397
5398         /*
5399          * draft-leach-cifs-v1-spec-02.txt
5400          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5401          * says:
5402          *
5403          *  The requested information is placed in the Data portion of the
5404          *  transaction response. For the information levels greater than 0x100,
5405          *  the transaction response has 1 parameter word which should be
5406          *  ignored by the client.
5407          *
5408          * However Windows only follows this rule for the IS_NAME_VALID call.
5409          */
5410         switch (info_level) {
5411         case SMB_INFO_IS_NAME_VALID:
5412                 param_size = 0;
5413                 break;
5414         }
5415
5416         if ((info_level & 0xFF00) == 0xFF00) {
5417                 /*
5418                  * We use levels that start with 0xFF00
5419                  * internally to represent SMB2 specific levels
5420                  */
5421                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5422                 return;
5423         }
5424
5425         status = smbd_do_qfilepathinfo(conn, req, info_level,
5426                                        fsp, smb_fname,
5427                                        delete_pending, write_time_ts,
5428                                        ea_list,
5429                                        lock_data_count, lock_data,
5430                                        req->flags2, max_data_bytes,
5431                                        ppdata, &data_size);
5432         if (!NT_STATUS_IS_OK(status)) {
5433                 reply_nterror(req, status);
5434                 return;
5435         }
5436
5437         send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5438                             max_data_bytes);
5439
5440         return;
5441 }
5442
5443 /****************************************************************************
5444  Set a hard link (called by UNIX extensions and by NT rename with HARD link
5445  code.
5446 ****************************************************************************/
5447
5448 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5449                 connection_struct *conn,
5450                 struct smb_request *req,
5451                 bool overwrite_if_exists,
5452                 const struct smb_filename *smb_fname_old,
5453                 struct smb_filename *smb_fname_new)
5454 {
5455         NTSTATUS status = NT_STATUS_OK;
5456
5457         /* source must already exist. */
5458         if (!VALID_STAT(smb_fname_old->st)) {
5459                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5460         }
5461
5462         if (VALID_STAT(smb_fname_new->st)) {
5463                 if (overwrite_if_exists) {
5464                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5465                                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5466                         }
5467                         status = unlink_internals(conn,
5468                                                 req,
5469                                                 FILE_ATTRIBUTE_NORMAL,
5470                                                 smb_fname_new,
5471                                                 false);
5472                         if (!NT_STATUS_IS_OK(status)) {
5473                                 return status;
5474                         }
5475                 } else {
5476                         /* Disallow if newname already exists. */
5477                         return NT_STATUS_OBJECT_NAME_COLLISION;
5478                 }
5479         }
5480
5481         /* No links from a directory. */
5482         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5483                 return NT_STATUS_FILE_IS_A_DIRECTORY;
5484         }
5485
5486         /* Setting a hardlink to/from a stream isn't currently supported. */
5487         if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5488             is_ntfs_stream_smb_fname(smb_fname_new)) {
5489                 return NT_STATUS_INVALID_PARAMETER;
5490         }
5491
5492         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5493                   smb_fname_old->base_name, smb_fname_new->base_name));
5494
5495         if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5496                          smb_fname_new->base_name) != 0) {
5497                 status = map_nt_error_from_unix(errno);
5498                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5499                          nt_errstr(status), smb_fname_old->base_name,
5500                          smb_fname_new->base_name));
5501         }
5502         return status;
5503 }
5504
5505 /****************************************************************************
5506  Deal with setting the time from any of the setfilepathinfo functions.
5507  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5508  calling this function.
5509 ****************************************************************************/
5510
5511 NTSTATUS smb_set_file_time(connection_struct *conn,
5512                            files_struct *fsp,
5513                            const struct smb_filename *smb_fname,
5514                            struct smb_file_time *ft,
5515                            bool setting_write_time)
5516 {
5517         struct smb_filename smb_fname_base;
5518         uint32 action =
5519                 FILE_NOTIFY_CHANGE_LAST_ACCESS
5520                 |FILE_NOTIFY_CHANGE_LAST_WRITE
5521                 |FILE_NOTIFY_CHANGE_CREATION;
5522
5523         if (!VALID_STAT(smb_fname->st)) {
5524                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5525         }
5526
5527         /* get some defaults (no modifications) if any info is zero or -1. */
5528         if (null_timespec(ft->create_time)) {
5529                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5530         }
5531
5532         if (null_timespec(ft->atime)) {
5533                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5534         }
5535
5536         if (null_timespec(ft->mtime)) {
5537                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5538         }
5539
5540         if (!setting_write_time) {
5541                 /* ft->mtime comes from change time, not write time. */
5542                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5543         }
5544
5545         /* Ensure the resolution is the correct for
5546          * what we can store on this filesystem. */
5547
5548         round_timespec(conn->ts_res, &ft->create_time);
5549         round_timespec(conn->ts_res, &ft->ctime);
5550         round_timespec(conn->ts_res, &ft->atime);
5551         round_timespec(conn->ts_res, &ft->mtime);
5552
5553         DEBUG(5,("smb_set_filetime: actime: %s\n ",
5554                 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5555         DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5556                 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5557         DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5558                 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5559         DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5560                 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5561
5562         if (setting_write_time) {
5563                 /*
5564                  * This was a Windows setfileinfo on an open file.
5565                  * NT does this a lot. We also need to 
5566                  * set the time here, as it can be read by 
5567                  * FindFirst/FindNext and with the patch for bug #2045
5568                  * in smbd/fileio.c it ensures that this timestamp is
5569                  * kept sticky even after a write. We save the request
5570                  * away and will set it on file close and after a write. JRA.
5571                  */
5572
5573                 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5574                           time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5575
5576                 if (fsp != NULL) {
5577                         if (fsp->base_fsp) {
5578                                 set_sticky_write_time_fsp(fsp->base_fsp,
5579                                                           ft->mtime);
5580                         } else {
5581                                 set_sticky_write_time_fsp(fsp, ft->mtime);
5582                         }
5583                 } else {
5584                         set_sticky_write_time_path(
5585                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5586                                 ft->mtime);
5587                 }
5588         }
5589
5590         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5591
5592         /* Always call ntimes on the base, even if a stream was passed in. */
5593         smb_fname_base = *smb_fname;
5594         smb_fname_base.stream_name = NULL;
5595
5596         if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5597                 return map_nt_error_from_unix(errno);
5598         }
5599
5600         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5601                      smb_fname->base_name);
5602         return NT_STATUS_OK;
5603 }
5604
5605 /****************************************************************************
5606  Deal with setting the dosmode from any of the setfilepathinfo functions.
5607  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5608  done before calling this function.
5609 ****************************************************************************/
5610
5611 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5612                                      const struct smb_filename *smb_fname,
5613                                      uint32 dosmode)
5614 {
5615         struct smb_filename *smb_fname_base = NULL;
5616         NTSTATUS status;
5617
5618         if (!VALID_STAT(smb_fname->st)) {
5619                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5620         }
5621
5622         /* Always operate on the base_name, even if a stream was passed in. */
5623         status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5624                                             NULL, &smb_fname->st,
5625                                             &smb_fname_base);
5626         if (!NT_STATUS_IS_OK(status)) {
5627                 return status;
5628         }
5629
5630         if (dosmode) {
5631                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5632                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5633                 } else {
5634                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5635                 }
5636         }
5637
5638         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5639
5640         /* check the mode isn't different, before changing it */
5641         if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5642                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5643                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5644                           (unsigned int)dosmode));
5645
5646                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5647                                     false)) {
5648                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5649                                  "%s failed (%s)\n",
5650                                  smb_fname_str_dbg(smb_fname_base),
5651                                  strerror(errno)));
5652                         status = map_nt_error_from_unix(errno);
5653                         goto out;
5654                 }
5655         }
5656         status = NT_STATUS_OK;
5657  out:
5658         TALLOC_FREE(smb_fname_base);
5659         return status;
5660 }
5661
5662 /****************************************************************************
5663  Deal with setting the size from any of the setfilepathinfo functions.
5664 ****************************************************************************/
5665
5666 static NTSTATUS smb_set_file_size(connection_struct *conn,
5667                                   struct smb_request *req,
5668                                   files_struct *fsp,
5669                                   const struct smb_filename *smb_fname,
5670                                   const SMB_STRUCT_STAT *psbuf,
5671                                   off_t size,
5672                                   bool fail_after_createfile)
5673 {
5674         NTSTATUS status = NT_STATUS_OK;
5675         struct smb_filename *smb_fname_tmp = NULL;
5676         files_struct *new_fsp = NULL;
5677
5678         if (!VALID_STAT(*psbuf)) {
5679                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5680         }
5681
5682         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5683
5684         if (size == get_file_size_stat(psbuf)) {
5685                 return NT_STATUS_OK;
5686         }
5687
5688         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5689                   smb_fname_str_dbg(smb_fname), (double)size));
5690
5691         if (fsp && fsp->fh->fd != -1) {
5692                 /* Handle based call. */
5693                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5694                         return NT_STATUS_ACCESS_DENIED;
5695                 }
5696
5697                 if (vfs_set_filelen(fsp, size) == -1) {
5698                         return map_nt_error_from_unix(errno);
5699                 }
5700                 trigger_write_time_update_immediate(fsp);
5701                 return NT_STATUS_OK;
5702         }
5703
5704         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5705         if (!NT_STATUS_IS_OK(status)) {
5706                 return status;
5707         }
5708
5709         smb_fname_tmp->st = *psbuf;
5710
5711         status = SMB_VFS_CREATE_FILE(
5712                 conn,                                   /* conn */
5713                 req,                                    /* req */
5714                 0,                                      /* root_dir_fid */
5715                 smb_fname_tmp,                          /* fname */
5716                 FILE_WRITE_DATA,                        /* access_mask */
5717                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5718                     FILE_SHARE_DELETE),
5719                 FILE_OPEN,                              /* create_disposition*/
5720                 0,                                      /* create_options */
5721                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5722                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
5723                 0,                                      /* allocation_size */
5724                 0,                                      /* private_flags */
5725                 NULL,                                   /* sd */
5726                 NULL,                                   /* ea_list */
5727                 &new_fsp,                               /* result */
5728                 NULL);                                  /* pinfo */
5729
5730         TALLOC_FREE(smb_fname_tmp);
5731
5732         if (!NT_STATUS_IS_OK(status)) {
5733                 /* NB. We check for open_was_deferred in the caller. */
5734                 return status;
5735         }
5736
5737         /* See RAW-SFILEINFO-END-OF-FILE */
5738         if (fail_after_createfile) {
5739                 close_file(req, new_fsp,NORMAL_CLOSE);
5740                 return NT_STATUS_INVALID_LEVEL;
5741         }
5742
5743         if (vfs_set_filelen(new_fsp, size) == -1) {
5744                 status = map_nt_error_from_unix(errno);
5745                 close_file(req, new_fsp,NORMAL_CLOSE);
5746                 return status;
5747         }
5748
5749         trigger_write_time_update_immediate(new_fsp);
5750         close_file(req, new_fsp,NORMAL_CLOSE);
5751         return NT_STATUS_OK;
5752 }
5753
5754 /****************************************************************************
5755  Deal with SMB_INFO_SET_EA.
5756 ****************************************************************************/
5757
5758 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5759                                 const char *pdata,
5760                                 int total_data,
5761                                 files_struct *fsp,
5762                                 const struct smb_filename *smb_fname)
5763 {
5764         struct ea_list *ea_list = NULL;
5765         TALLOC_CTX *ctx = NULL;
5766         NTSTATUS status = NT_STATUS_OK;
5767
5768         if (total_data < 10) {
5769
5770                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5771                    length. They seem to have no effect. Bug #3212. JRA */
5772
5773                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5774                         /* We're done. We only get EA info in this call. */
5775                         return NT_STATUS_OK;
5776                 }
5777
5778                 return NT_STATUS_INVALID_PARAMETER;
5779         }
5780
5781         if (IVAL(pdata,0) > total_data) {
5782                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5783                         IVAL(pdata,0), (unsigned int)total_data));
5784                 return NT_STATUS_INVALID_PARAMETER;
5785         }
5786
5787         ctx = talloc_tos();
5788         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5789         if (!ea_list) {
5790                 return NT_STATUS_INVALID_PARAMETER;
5791         }
5792
5793         status = set_ea(conn, fsp, smb_fname, ea_list);
5794
5795         return status;
5796 }
5797
5798 /****************************************************************************
5799  Deal with SMB_FILE_FULL_EA_INFORMATION set.
5800 ****************************************************************************/
5801
5802 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5803                                 const char *pdata,
5804                                 int total_data,
5805                                 files_struct *fsp)
5806 {
5807         struct ea_list *ea_list = NULL;
5808         NTSTATUS status;
5809
5810         if (!fsp) {
5811                 return NT_STATUS_INVALID_HANDLE;
5812         }
5813
5814         if (!lp_ea_support(SNUM(conn))) {
5815                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5816                         "EA's not supported.\n",
5817                         (unsigned int)total_data));
5818                 return NT_STATUS_EAS_NOT_SUPPORTED;
5819         }
5820
5821         if (total_data < 10) {
5822                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5823                         "too small.\n",
5824                         (unsigned int)total_data));
5825                 return NT_STATUS_INVALID_PARAMETER;
5826         }
5827
5828         ea_list = read_nttrans_ea_list(talloc_tos(),
5829                                 pdata,
5830                                 total_data);
5831
5832         if (!ea_list) {
5833                 return NT_STATUS_INVALID_PARAMETER;
5834         }
5835
5836         status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5837
5838         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5839                 smb_fname_str_dbg(fsp->fsp_name),
5840                 nt_errstr(status) ));
5841
5842         return status;
5843 }
5844
5845
5846 /****************************************************************************
5847  Deal with SMB_SET_FILE_DISPOSITION_INFO.
5848 ****************************************************************************/
5849
5850 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5851                                 const char *pdata,
5852                                 int total_data,
5853                                 files_struct *fsp,
5854                                 struct smb_filename *smb_fname)
5855 {
5856         NTSTATUS status = NT_STATUS_OK;
5857         bool delete_on_close;
5858         uint32 dosmode = 0;
5859
5860         if (total_data < 1) {
5861                 return NT_STATUS_INVALID_PARAMETER;
5862         }
5863
5864         if (fsp == NULL) {
5865                 return NT_STATUS_INVALID_HANDLE;
5866         }
5867
5868         delete_on_close = (CVAL(pdata,0) ? True : False);
5869         dosmode = dos_mode(conn, smb_fname);
5870
5871         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5872                 "delete_on_close = %u\n",
5873                 smb_fname_str_dbg(smb_fname),
5874                 (unsigned int)dosmode,
5875                 (unsigned int)delete_on_close ));
5876
5877         if (delete_on_close) {
5878                 status = can_set_delete_on_close(fsp, dosmode);
5879                 if (!NT_STATUS_IS_OK(status)) {
5880                         return status;
5881                 }
5882         }
5883
5884         /* The set is across all open files on this dev/inode pair. */
5885         if (!set_delete_on_close(fsp, delete_on_close,
5886                                  conn->session_info->security_token,
5887                                  conn->session_info->unix_token)) {
5888                 return NT_STATUS_ACCESS_DENIED;
5889         }
5890         return NT_STATUS_OK;
5891 }
5892
5893 /****************************************************************************
5894  Deal with SMB_FILE_POSITION_INFORMATION.
5895 ****************************************************************************/
5896
5897 static NTSTATUS smb_file_position_information(connection_struct *conn,
5898                                 const char *pdata,
5899                                 int total_data,
5900                                 files_struct *fsp)
5901 {
5902         uint64_t position_information;
5903
5904         if (total_data < 8) {
5905                 return NT_STATUS_INVALID_PARAMETER;
5906         }
5907
5908         if (fsp == NULL) {
5909                 /* Ignore on pathname based set. */
5910                 return NT_STATUS_OK;
5911         }
5912
5913         position_information = (uint64_t)IVAL(pdata,0);
5914         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5915
5916         DEBUG(10,("smb_file_position_information: Set file position "
5917                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5918                   (double)position_information));
5919         fsp->fh->position_information = position_information;
5920         return NT_STATUS_OK;
5921 }
5922
5923 /****************************************************************************
5924  Deal with SMB_FILE_MODE_INFORMATION.
5925 ****************************************************************************/
5926
5927 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5928                                 const char *pdata,
5929                                 int total_data)
5930 {
5931         uint32 mode;
5932
5933         if (total_data < 4) {
5934                 return NT_STATUS_INVALID_PARAMETER;
5935         }
5936         mode = IVAL(pdata,0);
5937         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5938                 return NT_STATUS_INVALID_PARAMETER;
5939         }
5940         return NT_STATUS_OK;
5941 }
5942
5943 /****************************************************************************
5944  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5945 ****************************************************************************/
5946
5947 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5948                                        struct smb_request *req,
5949                                        const char *pdata,
5950                                        int total_data,
5951                                        const struct smb_filename *smb_fname)
5952 {
5953         char *link_target = NULL;
5954         const char *newname = smb_fname->base_name;
5955         TALLOC_CTX *ctx = talloc_tos();
5956
5957         /* Set a symbolic link. */
5958         /* Don't allow this if follow links is false. */
5959
5960         if (total_data == 0) {
5961                 return NT_STATUS_INVALID_PARAMETER;
5962         }
5963
5964         if (!lp_symlinks(SNUM(conn))) {
5965                 return NT_STATUS_ACCESS_DENIED;
5966         }
5967
5968         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5969                     total_data, STR_TERMINATE);
5970
5971         if (!link_target) {
5972                 return NT_STATUS_INVALID_PARAMETER;
5973         }
5974
5975         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5976                         newname, link_target ));
5977
5978         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5979                 return map_nt_error_from_unix(errno);
5980         }
5981
5982         return NT_STATUS_OK;
5983 }
5984
5985 /****************************************************************************
5986  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5987 ****************************************************************************/
5988
5989 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5990                                         struct smb_request *req,
5991                                         const char *pdata, int total_data,
5992                                         struct smb_filename *smb_fname_new)
5993 {
5994         char *oldname = NULL;
5995         struct smb_filename *smb_fname_old = NULL;
5996         TALLOC_CTX *ctx = talloc_tos();
5997         NTSTATUS status = NT_STATUS_OK;
5998
5999         /* Set a hard link. */
6000         if (total_data == 0) {
6001                 return NT_STATUS_INVALID_PARAMETER;
6002         }
6003
6004         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6005                         total_data, STR_TERMINATE, &status);
6006         if (!NT_STATUS_IS_OK(status)) {
6007                 return status;
6008         }
6009
6010         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6011                 smb_fname_str_dbg(smb_fname_new), oldname));
6012
6013         status = filename_convert(ctx,
6014                                 conn,
6015                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
6016                                 oldname,
6017                                 0,
6018                                 NULL,
6019                                 &smb_fname_old);
6020         if (!NT_STATUS_IS_OK(status)) {
6021                 return status;
6022         }
6023
6024         return hardlink_internals(ctx, conn, req, false,
6025                         smb_fname_old, smb_fname_new);
6026 }
6027
6028 /****************************************************************************
6029  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6030 ****************************************************************************/
6031
6032 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6033                                             struct smb_request *req,
6034                                             const char *pdata,
6035                                             int total_data,
6036                                             files_struct *fsp,
6037                                             struct smb_filename *smb_fname_src)
6038 {
6039         bool overwrite;
6040         uint32_t len;
6041         char *newname = NULL;
6042         struct smb_filename *smb_fname_dst = NULL;
6043         NTSTATUS status = NT_STATUS_OK;
6044         TALLOC_CTX *ctx = talloc_tos();
6045
6046         if (!fsp) {
6047                 return NT_STATUS_INVALID_HANDLE;
6048         }
6049
6050         if (total_data < 20) {
6051                 return NT_STATUS_INVALID_PARAMETER;
6052         }
6053
6054         overwrite = (CVAL(pdata,0) ? True : False);
6055         len = IVAL(pdata,16);
6056
6057         if (len > (total_data - 20) || (len == 0)) {
6058                 return NT_STATUS_INVALID_PARAMETER;
6059         }
6060
6061         srvstr_get_path(ctx, pdata, req->flags2, &newname,
6062                                 &pdata[20], len, STR_TERMINATE,
6063                                 &status);
6064         if (!NT_STATUS_IS_OK(status)) {
6065                 return status;
6066         }
6067
6068         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6069                                 newname));
6070
6071         status = filename_convert(ctx,
6072                                 conn,
6073                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
6074                                 newname,
6075                                 UCF_SAVE_LCOMP,
6076                                 NULL,
6077                                 &smb_fname_dst);
6078         if (!NT_STATUS_IS_OK(status)) {
6079                 return status;
6080         }
6081
6082         if (fsp->base_fsp) {
6083                 /* newname must be a stream name. */
6084                 if (newname[0] != ':') {
6085                         return NT_STATUS_NOT_SUPPORTED;
6086                 }
6087
6088                 /* Create an smb_fname to call rename_internals_fsp() with. */
6089                 status = create_synthetic_smb_fname(talloc_tos(),
6090                     fsp->base_fsp->fsp_name->base_name, newname, NULL,
6091                     &smb_fname_dst);
6092                 if (!NT_STATUS_IS_OK(status)) {
6093                         goto out;
6094                 }
6095
6096                 /*
6097                  * Set the original last component, since
6098                  * rename_internals_fsp() requires it.
6099                  */
6100                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6101                                                               newname);
6102                 if (smb_fname_dst->original_lcomp == NULL) {
6103                         status = NT_STATUS_NO_MEMORY;
6104                         goto out;
6105                 }
6106
6107         }
6108
6109         DEBUG(10,("smb2_file_rename_information: "
6110                   "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6111                   fsp->fnum, fsp_str_dbg(fsp),
6112                   smb_fname_str_dbg(smb_fname_dst)));
6113         status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6114                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6115                                 overwrite);
6116
6117  out:
6118         TALLOC_FREE(smb_fname_dst);
6119         return status;
6120 }
6121
6122 static NTSTATUS smb_file_link_information(connection_struct *conn,
6123                                             struct smb_request *req,
6124                                             const char *pdata,
6125                                             int total_data,
6126                                             files_struct *fsp,
6127                                             struct smb_filename *smb_fname_src)
6128 {
6129         bool overwrite;
6130         uint32_t len;
6131         char *newname = NULL;
6132         struct smb_filename *smb_fname_dst = NULL;
6133         NTSTATUS status = NT_STATUS_OK;
6134         TALLOC_CTX *ctx = talloc_tos();
6135
6136         if (!fsp) {
6137                 return NT_STATUS_INVALID_HANDLE;
6138         }
6139
6140         if (total_data < 20) {
6141                 return NT_STATUS_INVALID_PARAMETER;
6142         }
6143
6144         overwrite = (CVAL(pdata,0) ? true : false);
6145         len = IVAL(pdata,16);
6146
6147         if (len > (total_data - 20) || (len == 0)) {
6148                 return NT_STATUS_INVALID_PARAMETER;
6149         }
6150
6151         srvstr_get_path(ctx, pdata, req->flags2, &newname,
6152                                 &pdata[20], len, STR_TERMINATE,
6153                                 &status);
6154         if (!NT_STATUS_IS_OK(status)) {
6155                 return status;
6156         }
6157
6158         DEBUG(10,("smb_file_link_information: got name |%s|\n",
6159                                 newname));
6160
6161         status = filename_convert(ctx,
6162                                 conn,
6163                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
6164                                 newname,
6165                                 UCF_SAVE_LCOMP,
6166                                 NULL,
6167                                 &smb_fname_dst);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 return status;
6170         }
6171
6172         if (fsp->base_fsp) {
6173                 /* No stream names. */
6174                 return NT_STATUS_NOT_SUPPORTED;
6175         }
6176
6177         DEBUG(10,("smb_file_link_information: "
6178                   "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6179                   fsp->fnum, fsp_str_dbg(fsp),
6180                   smb_fname_str_dbg(smb_fname_dst)));
6181         status = hardlink_internals(ctx,
6182                                 conn,
6183                                 req,
6184                                 overwrite,
6185                                 fsp->fsp_name,
6186                                 smb_fname_dst);
6187
6188         TALLOC_FREE(smb_fname_dst);
6189         return status;
6190 }
6191
6192 /****************************************************************************
6193  Deal with SMB_FILE_RENAME_INFORMATION.
6194 ****************************************************************************/
6195
6196 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6197                                             struct smb_request *req,
6198                                             const char *pdata,
6199                                             int total_data,
6200                                             files_struct *fsp,
6201                                             struct smb_filename *smb_fname_src)
6202 {
6203         bool overwrite;
6204         uint32 root_fid;
6205         uint32 len;
6206         char *newname = NULL;
6207         struct smb_filename *smb_fname_dst = NULL;
6208         bool dest_has_wcard = False;
6209         NTSTATUS status = NT_STATUS_OK;
6210         char *p;
6211         TALLOC_CTX *ctx = talloc_tos();
6212
6213         if (total_data < 13) {
6214                 return NT_STATUS_INVALID_PARAMETER;
6215         }
6216
6217         overwrite = (CVAL(pdata,0) ? True : False);
6218         root_fid = IVAL(pdata,4);
6219         len = IVAL(pdata,8);
6220
6221         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6222                 return NT_STATUS_INVALID_PARAMETER;
6223         }
6224
6225         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6226                               len, 0, &status,
6227                               &dest_has_wcard);
6228         if (!NT_STATUS_IS_OK(status)) {
6229                 return status;
6230         }
6231
6232         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6233                                 newname));
6234
6235         status = resolve_dfspath_wcard(ctx, conn,
6236                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6237                                        newname,
6238                                        true,
6239                                        &newname,
6240                                        &dest_has_wcard);
6241         if (!NT_STATUS_IS_OK(status)) {
6242                 return status;
6243         }
6244
6245         /* Check the new name has no '/' characters. */
6246         if (strchr_m(newname, '/')) {
6247                 return NT_STATUS_NOT_SUPPORTED;
6248         }
6249
6250         if (fsp && fsp->base_fsp) {
6251                 /* newname must be a stream name. */
6252                 if (newname[0] != ':') {
6253                         return NT_STATUS_NOT_SUPPORTED;
6254                 }
6255
6256                 /* Create an smb_fname to call rename_internals_fsp() with. */
6257                 status = create_synthetic_smb_fname(talloc_tos(),
6258                     fsp->base_fsp->fsp_name->base_name, newname, NULL,
6259                     &smb_fname_dst);
6260                 if (!NT_STATUS_IS_OK(status)) {
6261                         goto out;
6262                 }
6263
6264                 /*
6265                  * Set the original last component, since
6266                  * rename_internals_fsp() requires it.
6267                  */
6268                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6269                                                               newname);
6270                 if (smb_fname_dst->original_lcomp == NULL) {
6271                         status = NT_STATUS_NO_MEMORY;
6272                         goto out;
6273                 }
6274
6275         } else {
6276                 /*
6277                  * Build up an smb_fname_dst based on the filename passed in.
6278                  * We basically just strip off the last component, and put on
6279                  * the newname instead.
6280                  */
6281                 char *base_name = NULL;
6282
6283                 /* newname must *not* be a stream name. */
6284                 if (newname[0] == ':') {
6285                         return NT_STATUS_NOT_SUPPORTED;
6286                 }
6287
6288                 /*
6289                  * Strip off the last component (filename) of the path passed
6290                  * in.
6291                  */
6292                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6293                 if (!base_name) {
6294                         return NT_STATUS_NO_MEMORY;
6295                 }
6296                 p = strrchr_m(base_name, '/');
6297                 if (p) {
6298                         p[1] = '\0';
6299                 } else {
6300                         base_name = talloc_strdup(ctx, "");
6301                         if (!base_name) {
6302                                 return NT_STATUS_NO_MEMORY;
6303                         }
6304                 }
6305                 /* Append the new name. */
6306                 base_name = talloc_asprintf_append(base_name,
6307                                 "%s",
6308                                 newname);
6309                 if (!base_name) {
6310                         return NT_STATUS_NO_MEMORY;
6311                 }
6312
6313                 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6314                                       (UCF_SAVE_LCOMP |
6315                                           (dest_has_wcard ?
6316                                               UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6317                                               0)));
6318
6319                 /* If an error we expect this to be
6320                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6321
6322                 if (!NT_STATUS_IS_OK(status)) {
6323                         if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6324                                             status)) {
6325                                 goto out;
6326                         }
6327                         /* Create an smb_fname to call rename_internals_fsp() */
6328                         status = create_synthetic_smb_fname(ctx,
6329                                                             base_name, NULL,
6330                                                             NULL,
6331                                                             &smb_fname_dst);
6332                         if (!NT_STATUS_IS_OK(status)) {
6333                                 goto out;
6334                         }
6335                 }
6336         }
6337
6338         if (fsp) {
6339                 DEBUG(10,("smb_file_rename_information: "
6340                           "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6341                           fsp->fnum, fsp_str_dbg(fsp),
6342                           smb_fname_str_dbg(smb_fname_dst)));
6343                 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6344                                               overwrite);
6345         } else {
6346                 DEBUG(10,("smb_file_rename_information: "
6347                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6348                           smb_fname_str_dbg(smb_fname_src),
6349                           smb_fname_str_dbg(smb_fname_dst)));
6350                 status = rename_internals(ctx, conn, req, smb_fname_src,
6351                                           smb_fname_dst, 0, overwrite, false,
6352                                           dest_has_wcard,
6353                                           FILE_WRITE_ATTRIBUTES);
6354         }
6355  out:
6356         TALLOC_FREE(smb_fname_dst);
6357         return status;
6358 }
6359
6360 /****************************************************************************
6361  Deal with SMB_SET_POSIX_ACL.
6362 ****************************************************************************/
6363
6364 #if defined(HAVE_POSIX_ACLS)
6365 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6366                                 const char *pdata,
6367                                 int total_data,
6368                                 files_struct *fsp,
6369                                 const struct smb_filename *smb_fname)
6370 {
6371         uint16 posix_acl_version;
6372         uint16 num_file_acls;
6373         uint16 num_def_acls;
6374         bool valid_file_acls = True;
6375         bool valid_def_acls = True;
6376
6377         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6378                 return NT_STATUS_INVALID_PARAMETER;
6379         }
6380         posix_acl_version = SVAL(pdata,0);
6381         num_file_acls = SVAL(pdata,2);
6382         num_def_acls = SVAL(pdata,4);
6383
6384         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6385                 valid_file_acls = False;
6386                 num_file_acls = 0;
6387         }
6388
6389         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6390                 valid_def_acls = False;
6391                 num_def_acls = 0;
6392         }
6393
6394         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6395                 return NT_STATUS_INVALID_PARAMETER;
6396         }
6397
6398         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6399                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6400                 return NT_STATUS_INVALID_PARAMETER;
6401         }
6402
6403         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6404                 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6405                 (unsigned int)num_file_acls,
6406                 (unsigned int)num_def_acls));
6407
6408         if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6409                 smb_fname->base_name, num_file_acls,
6410                 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6411                 return map_nt_error_from_unix(errno);
6412         }
6413
6414         if (valid_def_acls && !set_unix_posix_default_acl(conn,
6415                 smb_fname->base_name, &smb_fname->st, num_def_acls,
6416                 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6417                 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6418                 return map_nt_error_from_unix(errno);
6419         }
6420         return NT_STATUS_OK;
6421 }
6422 #endif
6423
6424 /****************************************************************************
6425  Deal with SMB_SET_POSIX_LOCK.
6426 ****************************************************************************/
6427
6428 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6429                                 struct smb_request *req,
6430                                 const char *pdata,
6431                                 int total_data,
6432                                 files_struct *fsp)
6433 {
6434         uint64_t count;
6435         uint64_t offset;
6436         uint64_t smblctx;
6437         bool blocking_lock = False;
6438         enum brl_type lock_type;
6439
6440         NTSTATUS status = NT_STATUS_OK;
6441
6442         if (fsp == NULL || fsp->fh->fd == -1) {
6443                 return NT_STATUS_INVALID_HANDLE;
6444         }
6445
6446         if (total_data != POSIX_LOCK_DATA_SIZE) {
6447                 return NT_STATUS_INVALID_PARAMETER;
6448         }
6449
6450         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6451                 case POSIX_LOCK_TYPE_READ:
6452                         lock_type = READ_LOCK;
6453                         break;
6454                 case POSIX_LOCK_TYPE_WRITE:
6455                         /* Return the right POSIX-mappable error code for files opened read-only. */
6456                         if (!fsp->can_write) {
6457                                 return NT_STATUS_INVALID_HANDLE;
6458                         }
6459                         lock_type = WRITE_LOCK;
6460                         break;
6461                 case POSIX_LOCK_TYPE_UNLOCK:
6462                         lock_type = UNLOCK_LOCK;
6463                         break;
6464                 default:
6465                         return NT_STATUS_INVALID_PARAMETER;
6466         }
6467
6468         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6469                 blocking_lock = False;
6470         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6471                 blocking_lock = True;
6472         } else {
6473                 return NT_STATUS_INVALID_PARAMETER;
6474         }
6475
6476         if (!lp_blocking_locks(SNUM(conn))) { 
6477                 blocking_lock = False;
6478         }
6479
6480         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6481 #if defined(HAVE_LONGLONG)
6482         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6483                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6484         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6485                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6486 #else /* HAVE_LONGLONG */
6487         offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6488         count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6489 #endif /* HAVE_LONGLONG */
6490
6491         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6492                         "smblctx = %llu, count = %.0f, offset = %.0f\n",
6493                 fsp_str_dbg(fsp),
6494                 (unsigned int)lock_type,
6495                 (unsigned long long)smblctx,
6496                 (double)count,
6497                 (double)offset ));
6498
6499         if (lock_type == UNLOCK_LOCK) {
6500                 status = do_unlock(req->sconn->msg_ctx,
6501                                 fsp,
6502                                 smblctx,
6503                                 count,
6504                                 offset,
6505                                 POSIX_LOCK);
6506         } else {
6507                 uint64_t block_smblctx;
6508
6509                 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6510                                                         fsp,
6511                                                         smblctx,
6512                                                         count,
6513                                                         offset,
6514                                                         lock_type,
6515                                                         POSIX_LOCK,
6516                                                         blocking_lock,
6517                                                         &status,
6518                                                         &block_smblctx,
6519                                                         NULL);
6520
6521                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6522                         /*
6523                          * A blocking lock was requested. Package up
6524                          * this smb into a queued request and push it
6525                          * onto the blocking lock queue.
6526                          */
6527                         if(push_blocking_lock_request(br_lck,
6528                                                 req,
6529                                                 fsp,
6530                                                 -1, /* infinite timeout. */
6531                                                 0,
6532                                                 smblctx,
6533                                                 lock_type,
6534                                                 POSIX_LOCK,
6535                                                 offset,
6536                                                 count,
6537                                                 block_smblctx)) {
6538                                 TALLOC_FREE(br_lck);
6539                                 return status;
6540                         }
6541                 }
6542                 TALLOC_FREE(br_lck);
6543         }
6544
6545         return status;
6546 }
6547
6548 /****************************************************************************
6549  Deal with SMB_SET_FILE_BASIC_INFO.
6550 ****************************************************************************/
6551
6552 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6553                                         const char *pdata,
6554                                         int total_data,
6555                                         files_struct *fsp,
6556                                         const struct smb_filename *smb_fname)
6557 {
6558         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6559         struct smb_file_time ft;
6560         uint32 dosmode = 0;
6561         NTSTATUS status = NT_STATUS_OK;
6562
6563         ZERO_STRUCT(ft);
6564
6565         if (total_data < 36) {
6566                 return NT_STATUS_INVALID_PARAMETER;
6567         }
6568
6569         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6570         if (!NT_STATUS_IS_OK(status)) {
6571                 return status;
6572         }
6573
6574         /* Set the attributes */
6575         dosmode = IVAL(pdata,32);
6576         status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6577         if (!NT_STATUS_IS_OK(status)) {
6578                 return status;
6579         }
6580
6581         /* create time */
6582         ft.create_time = interpret_long_date(pdata);
6583
6584         /* access time */
6585         ft.atime = interpret_long_date(pdata+8);
6586
6587         /* write time. */
6588         ft.mtime = interpret_long_date(pdata+16);
6589
6590         /* change time. */
6591         ft.ctime = interpret_long_date(pdata+24);
6592
6593         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6594                    smb_fname_str_dbg(smb_fname)));
6595
6596         return smb_set_file_time(conn, fsp, smb_fname, &ft,
6597                                  true);
6598 }
6599
6600 /****************************************************************************
6601  Deal with SMB_INFO_STANDARD.
6602 ****************************************************************************/
6603
6604 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6605                                         const char *pdata,
6606                                         int total_data,
6607                                         files_struct *fsp,
6608                                         const struct smb_filename *smb_fname)
6609 {
6610         NTSTATUS status;
6611         struct smb_file_time ft;
6612
6613         ZERO_STRUCT(ft);
6614
6615         if (total_data < 12) {
6616                 return NT_STATUS_INVALID_PARAMETER;
6617         }
6618
6619         /* create time */
6620         ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6621         /* access time */
6622         ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6623         /* write time */
6624         ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6625
6626         DEBUG(10,("smb_set_info_standard: file %s\n",
6627                 smb_fname_str_dbg(smb_fname)));
6628
6629         status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6630         if (!NT_STATUS_IS_OK(status)) {
6631                 return status;
6632         }
6633
6634         return smb_set_file_time(conn,
6635                                 fsp,
6636                                 smb_fname,
6637                                 &ft,
6638                                 true);
6639 }
6640
6641 /****************************************************************************
6642  Deal with SMB_SET_FILE_ALLOCATION_INFO.
6643 ****************************************************************************/
6644
6645 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6646                                              struct smb_request *req,
6647                                         const char *pdata,
6648                                         int total_data,
6649                                         files_struct *fsp,
6650                                         struct smb_filename *smb_fname)
6651 {
6652         uint64_t allocation_size = 0;
6653         NTSTATUS status = NT_STATUS_OK;
6654         files_struct *new_fsp = NULL;
6655
6656         if (!VALID_STAT(smb_fname->st)) {
6657                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6658         }
6659
6660         if (total_data < 8) {
6661                 return NT_STATUS_INVALID_PARAMETER;
6662         }
6663
6664         allocation_size = (uint64_t)IVAL(pdata,0);
6665         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6666         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6667                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6668                   (double)allocation_size));
6669
6670         if (allocation_size) {
6671                 allocation_size = smb_roundup(conn, allocation_size);
6672         }
6673
6674         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6675                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6676                   (double)allocation_size));
6677
6678         if (fsp && fsp->fh->fd != -1) {
6679                 /* Open file handle. */
6680                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6681                         return NT_STATUS_ACCESS_DENIED;
6682                 }
6683
6684                 /* Only change if needed. */
6685                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6686                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6687                                 return map_nt_error_from_unix(errno);
6688                         }
6689                 }
6690                 /* But always update the time. */
6691                 /*
6692                  * This is equivalent to a write. Ensure it's seen immediately
6693                  * if there are no pending writes.
6694                  */
6695                 trigger_write_time_update_immediate(fsp);
6696                 return NT_STATUS_OK;
6697         }
6698
6699         /* Pathname or stat or directory file. */
6700         status = SMB_VFS_CREATE_FILE(
6701                 conn,                                   /* conn */
6702                 req,                                    /* req */
6703                 0,                                      /* root_dir_fid */
6704                 smb_fname,                              /* fname */
6705                 FILE_WRITE_DATA,                        /* access_mask */
6706                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6707                     FILE_SHARE_DELETE),
6708                 FILE_OPEN,                              /* create_disposition*/
6709                 0,                                      /* create_options */
6710                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6711                 FORCE_OPLOCK_BREAK_TO_NONE,             /* oplock_request */
6712                 0,                                      /* allocation_size */
6713                 0,                                      /* private_flags */
6714                 NULL,                                   /* sd */
6715                 NULL,                                   /* ea_list */
6716                 &new_fsp,                               /* result */
6717                 NULL);                                  /* pinfo */
6718
6719         if (!NT_STATUS_IS_OK(status)) {
6720                 /* NB. We check for open_was_deferred in the caller. */
6721                 return status;
6722         }
6723
6724         /* Only change if needed. */
6725         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6726                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6727                         status = map_nt_error_from_unix(errno);
6728                         close_file(req, new_fsp, NORMAL_CLOSE);
6729                         return status;
6730                 }
6731         }
6732
6733         /* Changing the allocation size should set the last mod time. */
6734         /*
6735          * This is equivalent to a write. Ensure it's seen immediately
6736          * if there are no pending writes.
6737          */
6738         trigger_write_time_update_immediate(new_fsp);
6739
6740         close_file(req, new_fsp, NORMAL_CLOSE);
6741         return NT_STATUS_OK;
6742 }
6743
6744 /****************************************************************************
6745  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6746 ****************************************************************************/
6747
6748 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6749                                               struct smb_request *req,
6750                                         const char *pdata,
6751                                         int total_data,
6752                                         files_struct *fsp,
6753                                         const struct smb_filename *smb_fname,
6754                                         bool fail_after_createfile)
6755 {
6756         off_t size;
6757
6758         if (total_data < 8) {
6759                 return NT_STATUS_INVALID_PARAMETER;
6760         }
6761
6762         size = IVAL(pdata,0);
6763         size |= (((off_t)IVAL(pdata,4)) << 32);
6764         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6765                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6766                   (double)size));
6767
6768         return smb_set_file_size(conn, req,
6769                                 fsp,
6770                                 smb_fname,
6771                                 &smb_fname->st,
6772                                 size,
6773                                 fail_after_createfile);
6774 }
6775
6776 /****************************************************************************
6777  Allow a UNIX info mknod.
6778 ****************************************************************************/
6779
6780 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6781                                         const char *pdata,
6782                                         int total_data,
6783                                         const struct smb_filename *smb_fname)
6784 {
6785         uint32 file_type = IVAL(pdata,56);
6786 #if defined(HAVE_MAKEDEV)
6787         uint32 dev_major = IVAL(pdata,60);
6788         uint32 dev_minor = IVAL(pdata,68);
6789 #endif
6790         SMB_DEV_T dev = (SMB_DEV_T)0;
6791         uint32 raw_unixmode = IVAL(pdata,84);
6792         NTSTATUS status;
6793         mode_t unixmode;
6794
6795         if (total_data < 100) {
6796                 return NT_STATUS_INVALID_PARAMETER;
6797         }
6798
6799         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6800                                       PERM_NEW_FILE, &unixmode);
6801         if (!NT_STATUS_IS_OK(status)) {
6802                 return status;
6803         }
6804
6805 #if defined(HAVE_MAKEDEV)
6806         dev = makedev(dev_major, dev_minor);
6807 #endif
6808
6809         switch (file_type) {
6810 #if defined(S_IFIFO)
6811                 case UNIX_TYPE_FIFO:
6812                         unixmode |= S_IFIFO;
6813                         break;
6814 #endif
6815 #if defined(S_IFSOCK)
6816                 case UNIX_TYPE_SOCKET:
6817                         unixmode |= S_IFSOCK;
6818                         break;
6819 #endif
6820 #if defined(S_IFCHR)
6821                 case UNIX_TYPE_CHARDEV:
6822                         unixmode |= S_IFCHR;
6823                         break;
6824 #endif
6825 #if defined(S_IFBLK)
6826                 case UNIX_TYPE_BLKDEV:
6827                         unixmode |= S_IFBLK;
6828                         break;
6829 #endif
6830                 default:
6831                         return NT_STATUS_INVALID_PARAMETER;
6832         }
6833
6834         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6835                   "%.0f mode 0%o for file %s\n", (double)dev,
6836                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6837
6838         /* Ok - do the mknod. */
6839         if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6840                 return map_nt_error_from_unix(errno);
6841         }
6842
6843         /* If any of the other "set" calls fail we
6844          * don't want to end up with a half-constructed mknod.
6845          */
6846
6847         if (lp_inherit_perms(SNUM(conn))) {
6848                 char *parent;
6849                 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6850                                     &parent, NULL)) {
6851                         return NT_STATUS_NO_MEMORY;
6852                 }
6853                 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6854                                          unixmode);
6855                 TALLOC_FREE(parent);
6856         }
6857
6858         return NT_STATUS_OK;
6859 }
6860
6861 /****************************************************************************
6862  Deal with SMB_SET_FILE_UNIX_BASIC.
6863 ****************************************************************************/
6864
6865 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6866                                         struct smb_request *req,
6867                                         const char *pdata,
6868                                         int total_data,
6869                                         files_struct *fsp,
6870                                         const struct smb_filename *smb_fname)
6871 {
6872         struct smb_file_time ft;
6873         uint32 raw_unixmode;
6874         mode_t unixmode;
6875         off_t size = 0;
6876         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6877         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6878         NTSTATUS status = NT_STATUS_OK;
6879         bool delete_on_fail = False;
6880         enum perm_type ptype;
6881         files_struct *all_fsps = NULL;
6882         bool modify_mtime = true;
6883         struct file_id id;
6884         struct smb_filename *smb_fname_tmp = NULL;
6885         SMB_STRUCT_STAT sbuf;
6886
6887         ZERO_STRUCT(ft);
6888
6889         if (total_data < 100) {
6890                 return NT_STATUS_INVALID_PARAMETER;
6891         }
6892
6893         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6894            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6895                 size=IVAL(pdata,0); /* first 8 Bytes are size */
6896                 size |= (((off_t)IVAL(pdata,4)) << 32);
6897         }
6898
6899         ft.atime = interpret_long_date(pdata+24); /* access_time */
6900         ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6901         set_owner = (uid_t)IVAL(pdata,40);
6902         set_grp = (gid_t)IVAL(pdata,48);
6903         raw_unixmode = IVAL(pdata,84);
6904
6905         if (VALID_STAT(smb_fname->st)) {
6906                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6907                         ptype = PERM_EXISTING_DIR;
6908                 } else {
6909                         ptype = PERM_EXISTING_FILE;
6910                 }
6911         } else {
6912                 ptype = PERM_NEW_FILE;
6913         }
6914
6915         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6916                                       ptype, &unixmode);
6917         if (!NT_STATUS_IS_OK(status)) {
6918                 return status;
6919         }
6920
6921         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6922                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6923                   smb_fname_str_dbg(smb_fname), (double)size,
6924                   (unsigned int)set_owner, (unsigned int)set_grp,
6925                   (int)raw_unixmode));
6926
6927         sbuf = smb_fname->st;
6928
6929         if (!VALID_STAT(sbuf)) {
6930                 /*
6931                  * The only valid use of this is to create character and block
6932                  * devices, and named pipes. This is deprecated (IMHO) and 
6933                  * a new info level should be used for mknod. JRA.
6934                  */
6935
6936                 status = smb_unix_mknod(conn,
6937                                         pdata,
6938                                         total_data,
6939                                         smb_fname);
6940                 if (!NT_STATUS_IS_OK(status)) {
6941                         return status;
6942                 }
6943
6944                 status = copy_smb_filename(talloc_tos(), smb_fname,
6945                                            &smb_fname_tmp);
6946                 if (!NT_STATUS_IS_OK(status)) {
6947                         return status;
6948                 }
6949
6950                 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6951                         status = map_nt_error_from_unix(errno);
6952                         TALLOC_FREE(smb_fname_tmp);
6953                         SMB_VFS_UNLINK(conn, smb_fname);
6954                         return status;
6955                 }
6956
6957                 sbuf = smb_fname_tmp->st;
6958                 smb_fname = smb_fname_tmp;
6959
6960                 /* Ensure we don't try and change anything else. */
6961                 raw_unixmode = SMB_MODE_NO_CHANGE;
6962                 size = get_file_size_stat(&sbuf);
6963                 ft.atime = sbuf.st_ex_atime;
6964                 ft.mtime = sbuf.st_ex_mtime;
6965                 /* 
6966                  * We continue here as we might want to change the 
6967                  * owner uid/gid.
6968                  */
6969                 delete_on_fail = True;
6970         }
6971
6972 #if 1
6973         /* Horrible backwards compatibility hack as an old server bug
6974          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6975          * */
6976
6977         if (!size) {
6978                 size = get_file_size_stat(&sbuf);
6979         }
6980 #endif
6981
6982         /*
6983          * Deal with the UNIX specific mode set.
6984          */
6985
6986         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6987                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6988                           "setting mode 0%o for file %s\n",
6989                           (unsigned int)unixmode,
6990                           smb_fname_str_dbg(smb_fname)));
6991                 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6992                         return map_nt_error_from_unix(errno);
6993                 }
6994         }
6995
6996         /*
6997          * Deal with the UNIX specific uid set.
6998          */
6999
7000         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7001             (sbuf.st_ex_uid != set_owner)) {
7002                 int ret;
7003
7004                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7005                           "changing owner %u for path %s\n",
7006                           (unsigned int)set_owner,
7007                           smb_fname_str_dbg(smb_fname)));
7008
7009                 if (S_ISLNK(sbuf.st_ex_mode)) {
7010                         ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7011                                              set_owner, (gid_t)-1);
7012                 } else {
7013                         ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7014                                             set_owner, (gid_t)-1);
7015                 }
7016
7017                 if (ret != 0) {
7018                         status = map_nt_error_from_unix(errno);
7019                         if (delete_on_fail) {
7020                                 SMB_VFS_UNLINK(conn, smb_fname);
7021                         }
7022                         return status;
7023                 }
7024         }
7025
7026         /*
7027          * Deal with the UNIX specific gid set.
7028          */
7029
7030         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7031             (sbuf.st_ex_gid != set_grp)) {
7032                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7033                           "changing group %u for file %s\n",
7034                           (unsigned int)set_owner,
7035                           smb_fname_str_dbg(smb_fname)));
7036                 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7037                                   set_grp) != 0) {
7038                         status = map_nt_error_from_unix(errno);
7039                         if (delete_on_fail) {
7040                                 SMB_VFS_UNLINK(conn, smb_fname);
7041                         }
7042                         return status;
7043                 }
7044         }
7045
7046         /* Deal with any size changes. */
7047
7048         status = smb_set_file_size(conn, req,
7049                                    fsp,
7050                                    smb_fname,
7051                                    &sbuf,
7052                                    size,
7053                                    false);
7054         if (!NT_STATUS_IS_OK(status)) {
7055                 return status;
7056         }
7057
7058         /* Deal with any time changes. */
7059         if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7060                 /* No change, don't cancel anything. */
7061                 return status;
7062         }
7063
7064         id = vfs_file_id_from_sbuf(conn, &sbuf);
7065         for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7066                         all_fsps = file_find_di_next(all_fsps)) {
7067                 /*
7068                  * We're setting the time explicitly for UNIX.
7069                  * Cancel any pending changes over all handles.
7070                  */
7071                 all_fsps->update_write_time_on_close = false;
7072                 TALLOC_FREE(all_fsps->update_write_time_event);
7073         }
7074
7075         /*
7076          * Override the "setting_write_time"
7077          * parameter here as it almost does what
7078          * we need. Just remember if we modified
7079          * mtime and send the notify ourselves.
7080          */
7081         if (null_timespec(ft.mtime)) {
7082                 modify_mtime = false;
7083         }
7084
7085         status = smb_set_file_time(conn,
7086                                 fsp,
7087                                 smb_fname,
7088                                 &ft,
7089                                 false);
7090         if (modify_mtime) {
7091                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7092                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7093         }
7094         return status;
7095 }
7096
7097 /****************************************************************************
7098  Deal with SMB_SET_FILE_UNIX_INFO2.
7099 ****************************************************************************/
7100
7101 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7102                                         struct smb_request *req,
7103                                         const char *pdata,
7104                                         int total_data,
7105                                         files_struct *fsp,
7106                                         const struct smb_filename *smb_fname)
7107 {
7108         NTSTATUS status;
7109         uint32 smb_fflags;
7110         uint32 smb_fmask;
7111
7112         if (total_data < 116) {
7113                 return NT_STATUS_INVALID_PARAMETER;
7114         }
7115
7116         /* Start by setting all the fields that are common between UNIX_BASIC
7117          * and UNIX_INFO2.
7118          */
7119         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7120                                          fsp, smb_fname);
7121         if (!NT_STATUS_IS_OK(status)) {
7122                 return status;
7123         }
7124
7125         smb_fflags = IVAL(pdata, 108);
7126         smb_fmask = IVAL(pdata, 112);
7127
7128         /* NB: We should only attempt to alter the file flags if the client
7129          * sends a non-zero mask.
7130          */
7131         if (smb_fmask != 0) {
7132                 int stat_fflags = 0;
7133
7134                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7135                                              smb_fmask, &stat_fflags)) {
7136                         /* Client asked to alter a flag we don't understand. */
7137                         return NT_STATUS_INVALID_PARAMETER;
7138                 }
7139
7140                 if (fsp && fsp->fh->fd != -1) {
7141                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
7142                         return NT_STATUS_NOT_SUPPORTED;
7143                 } else {
7144                         if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7145                                             stat_fflags) != 0) {
7146                                 return map_nt_error_from_unix(errno);
7147                         }
7148                 }
7149         }
7150
7151         /* XXX: need to add support for changing the create_time here. You
7152          * can do this for paths on Darwin with setattrlist(2). The right way
7153          * to hook this up is probably by extending the VFS utimes interface.
7154          */
7155
7156         return NT_STATUS_OK;
7157 }
7158
7159 /****************************************************************************
7160  Create a directory with POSIX semantics.
7161 ****************************************************************************/
7162
7163 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7164                                 struct smb_request *req,
7165                                 char **ppdata,
7166                                 int total_data,
7167                                 struct smb_filename *smb_fname,
7168                                 int *pdata_return_size)
7169 {
7170         NTSTATUS status = NT_STATUS_OK;
7171         uint32 raw_unixmode = 0;
7172         uint32 mod_unixmode = 0;
7173         mode_t unixmode = (mode_t)0;
7174         files_struct *fsp = NULL;
7175         uint16 info_level_return = 0;
7176         int info;
7177         char *pdata = *ppdata;
7178
7179         if (total_data < 18) {
7180                 return NT_STATUS_INVALID_PARAMETER;
7181         }
7182
7183         raw_unixmode = IVAL(pdata,8);
7184         /* Next 4 bytes are not yet defined. */
7185
7186         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7187                                       PERM_NEW_DIR, &unixmode);
7188         if (!NT_STATUS_IS_OK(status)) {
7189                 return status;
7190         }
7191
7192         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7193
7194         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7195                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7196
7197         status = SMB_VFS_CREATE_FILE(
7198                 conn,                                   /* conn */
7199                 req,                                    /* req */
7200                 0,                                      /* root_dir_fid */
7201                 smb_fname,                              /* fname */
7202                 FILE_READ_ATTRIBUTES,                   /* access_mask */
7203                 FILE_SHARE_NONE,                        /* share_access */
7204                 FILE_CREATE,                            /* create_disposition*/
7205                 FILE_DIRECTORY_FILE,                    /* create_options */
7206                 mod_unixmode,                           /* file_attributes */
7207                 0,                                      /* oplock_request */
7208                 0,                                      /* allocation_size */
7209                 0,                                      /* private_flags */
7210                 NULL,                                   /* sd */
7211                 NULL,                                   /* ea_list */
7212                 &fsp,                                   /* result */
7213                 &info);                                 /* pinfo */
7214
7215         if (NT_STATUS_IS_OK(status)) {
7216                 close_file(req, fsp, NORMAL_CLOSE);
7217         }
7218
7219         info_level_return = SVAL(pdata,16);
7220  
7221         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7222                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7223         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7224                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7225         } else {
7226                 *pdata_return_size = 12;
7227         }
7228
7229         /* Realloc the data size */
7230         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7231         if (*ppdata == NULL) {
7232                 *pdata_return_size = 0;
7233                 return NT_STATUS_NO_MEMORY;
7234         }
7235         pdata = *ppdata;
7236
7237         SSVAL(pdata,0,NO_OPLOCK_RETURN);
7238         SSVAL(pdata,2,0); /* No fnum. */
7239         SIVAL(pdata,4,info); /* Was directory created. */
7240
7241         switch (info_level_return) {
7242                 case SMB_QUERY_FILE_UNIX_BASIC:
7243                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7244                         SSVAL(pdata,10,0); /* Padding. */
7245                         store_file_unix_basic(conn, pdata + 12, fsp,
7246                                               &smb_fname->st);
7247                         break;
7248                 case SMB_QUERY_FILE_UNIX_INFO2:
7249                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7250                         SSVAL(pdata,10,0); /* Padding. */
7251                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7252                                                     &smb_fname->st);
7253                         break;
7254                 default:
7255                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7256                         SSVAL(pdata,10,0); /* Padding. */
7257                         break;
7258         }
7259
7260         return status;
7261 }
7262
7263 /****************************************************************************
7264  Open/Create a file with POSIX semantics.
7265 ****************************************************************************/
7266
7267 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7268 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7269
7270 static NTSTATUS smb_posix_open(connection_struct *conn,
7271                                struct smb_request *req,
7272                                 char **ppdata,
7273                                 int total_data,
7274                                 struct smb_filename *smb_fname,
7275                                 int *pdata_return_size)
7276 {
7277         bool extended_oplock_granted = False;
7278         char *pdata = *ppdata;
7279         uint32 flags = 0;
7280         uint32 wire_open_mode = 0;
7281         uint32 raw_unixmode = 0;
7282         uint32 mod_unixmode = 0;
7283         uint32 create_disp = 0;
7284         uint32 access_mask = 0;
7285         uint32 create_options = FILE_NON_DIRECTORY_FILE;
7286         NTSTATUS status = NT_STATUS_OK;
7287         mode_t unixmode = (mode_t)0;
7288         files_struct *fsp = NULL;
7289         int oplock_request = 0;
7290         int info = 0;
7291         uint16 info_level_return = 0;
7292
7293         if (total_data < 18) {
7294                 return NT_STATUS_INVALID_PARAMETER;
7295         }
7296
7297         flags = IVAL(pdata,0);
7298         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7299         if (oplock_request) {
7300                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7301         }
7302
7303         wire_open_mode = IVAL(pdata,4);
7304
7305         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7306                 return smb_posix_mkdir(conn, req,
7307                                         ppdata,
7308                                         total_data,
7309                                         smb_fname,
7310                                         pdata_return_size);
7311         }
7312
7313         switch (wire_open_mode & SMB_ACCMODE) {
7314                 case SMB_O_RDONLY:
7315                         access_mask = SMB_O_RDONLY_MAPPING;
7316                         break;
7317                 case SMB_O_WRONLY:
7318                         access_mask = SMB_O_WRONLY_MAPPING;
7319                         break;
7320                 case SMB_O_RDWR:
7321                         access_mask = (SMB_O_RDONLY_MAPPING|
7322                                         SMB_O_WRONLY_MAPPING);
7323                         break;
7324                 default:
7325                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7326                                 (unsigned int)wire_open_mode ));
7327                         return NT_STATUS_INVALID_PARAMETER;
7328         }
7329
7330         wire_open_mode &= ~SMB_ACCMODE;
7331
7332         /* First take care of O_CREAT|O_EXCL interactions. */
7333         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7334                 case (SMB_O_CREAT | SMB_O_EXCL):
7335                         /* File exists fail. File not exist create. */
7336                         create_disp = FILE_CREATE;
7337                         break;
7338                 case SMB_O_CREAT:
7339                         /* File exists open. File not exist create. */
7340                         create_disp = FILE_OPEN_IF;
7341                         break;
7342                 case 0:
7343                         /* File exists open. File not exist fail. */
7344                         create_disp = FILE_OPEN;
7345                         break;
7346                 case SMB_O_EXCL:
7347                         /* O_EXCL on its own without O_CREAT is undefined. */
7348                 default:
7349                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7350                                 (unsigned int)wire_open_mode ));
7351                         return NT_STATUS_INVALID_PARAMETER;
7352         }
7353
7354         /* Next factor in the effects of O_TRUNC. */
7355         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7356
7357         if (wire_open_mode & SMB_O_TRUNC) {
7358                 switch (create_disp) {
7359                         case FILE_CREATE:
7360                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7361                                 /* Leave create_disp alone as
7362                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7363                                 */
7364                                 /* File exists fail. File not exist create. */
7365                                 break;
7366                         case FILE_OPEN_IF:
7367                                 /* SMB_O_CREAT | SMB_O_TRUNC */
7368                                 /* File exists overwrite. File not exist create. */
7369                                 create_disp = FILE_OVERWRITE_IF;
7370                                 break;
7371                         case FILE_OPEN:
7372                                 /* SMB_O_TRUNC */
7373                                 /* File exists overwrite. File not exist fail. */
7374                                 create_disp = FILE_OVERWRITE;
7375                                 break;
7376                         default:
7377                                 /* Cannot get here. */
7378                                 smb_panic("smb_posix_open: logic error");
7379                                 return NT_STATUS_INVALID_PARAMETER;
7380                 }
7381         }
7382
7383         raw_unixmode = IVAL(pdata,8);
7384         /* Next 4 bytes are not yet defined. */
7385
7386         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7387                                       (VALID_STAT(smb_fname->st) ?
7388                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
7389                                       &unixmode);
7390
7391         if (!NT_STATUS_IS_OK(status)) {
7392                 return status;
7393         }
7394
7395         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7396
7397         if (wire_open_mode & SMB_O_SYNC) {
7398                 create_options |= FILE_WRITE_THROUGH;
7399         }
7400         if (wire_open_mode & SMB_O_APPEND) {
7401                 access_mask |= FILE_APPEND_DATA;
7402         }
7403         if (wire_open_mode & SMB_O_DIRECT) {
7404                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7405         }
7406
7407         if ((wire_open_mode & SMB_O_DIRECTORY) ||
7408                         VALID_STAT_OF_DIR(smb_fname->st)) {
7409                 if (access_mask != SMB_O_RDONLY_MAPPING) {
7410                         return NT_STATUS_FILE_IS_A_DIRECTORY;
7411                 }
7412                 create_options &= ~FILE_NON_DIRECTORY_FILE;
7413                 create_options |= FILE_DIRECTORY_FILE;
7414         }
7415
7416         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7417                 smb_fname_str_dbg(smb_fname),
7418                 (unsigned int)wire_open_mode,
7419                 (unsigned int)unixmode ));
7420
7421         status = SMB_VFS_CREATE_FILE(
7422                 conn,                                   /* conn */
7423                 req,                                    /* req */
7424                 0,                                      /* root_dir_fid */
7425                 smb_fname,                              /* fname */
7426                 access_mask,                            /* access_mask */
7427                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7428                     FILE_SHARE_DELETE),
7429                 create_disp,                            /* create_disposition*/
7430                 create_options,                         /* create_options */
7431                 mod_unixmode,                           /* file_attributes */
7432                 oplock_request,                         /* oplock_request */
7433                 0,                                      /* allocation_size */
7434                 0,                                      /* private_flags */
7435                 NULL,                                   /* sd */
7436                 NULL,                                   /* ea_list */
7437                 &fsp,                                   /* result */
7438                 &info);                                 /* pinfo */
7439
7440         if (!NT_STATUS_IS_OK(status)) {
7441                 return status;
7442         }
7443
7444         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7445                 extended_oplock_granted = True;
7446         }
7447
7448         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7449                 extended_oplock_granted = True;
7450         }
7451
7452         info_level_return = SVAL(pdata,16);
7453  
7454         /* Allocate the correct return size. */
7455
7456         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7457                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7458         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
7459                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7460         } else {
7461                 *pdata_return_size = 12;
7462         }
7463
7464         /* Realloc the data size */
7465         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7466         if (*ppdata == NULL) {
7467                 close_file(req, fsp, ERROR_CLOSE);
7468                 *pdata_return_size = 0;
7469                 return NT_STATUS_NO_MEMORY;
7470         }
7471         pdata = *ppdata;
7472
7473         if (extended_oplock_granted) {
7474                 if (flags & REQUEST_BATCH_OPLOCK) {
7475                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7476                 } else {
7477                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7478                 }
7479         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7480                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7481         } else {
7482                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7483         }
7484
7485         SSVAL(pdata,2,fsp->fnum);
7486         SIVAL(pdata,4,info); /* Was file created etc. */
7487
7488         switch (info_level_return) {
7489                 case SMB_QUERY_FILE_UNIX_BASIC:
7490                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7491                         SSVAL(pdata,10,0); /* padding. */
7492                         store_file_unix_basic(conn, pdata + 12, fsp,
7493                                               &smb_fname->st);
7494                         break;
7495                 case SMB_QUERY_FILE_UNIX_INFO2:
7496                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7497                         SSVAL(pdata,10,0); /* padding. */
7498                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
7499                                                     &smb_fname->st);
7500                         break;
7501                 default:
7502                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7503                         SSVAL(pdata,10,0); /* padding. */
7504                         break;
7505         }
7506         return NT_STATUS_OK;
7507 }
7508
7509 /****************************************************************************
7510  Delete a file with POSIX semantics.
7511 ****************************************************************************/
7512
7513 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7514                                  struct smb_request *req,
7515                                 const char *pdata,
7516                                 int total_data,
7517                                 struct smb_filename *smb_fname)
7518 {
7519         NTSTATUS status = NT_STATUS_OK;
7520         files_struct *fsp = NULL;
7521         uint16 flags = 0;
7522         char del = 1;
7523         int info = 0;
7524         int create_options = 0;
7525         int i;
7526         struct share_mode_lock *lck = NULL;
7527
7528         if (total_data < 2) {
7529                 return NT_STATUS_INVALID_PARAMETER;
7530         }
7531
7532         flags = SVAL(pdata,0);
7533
7534         if (!VALID_STAT(smb_fname->st)) {
7535                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7536         }
7537
7538         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7539                         !VALID_STAT_OF_DIR(smb_fname->st)) {
7540                 return NT_STATUS_NOT_A_DIRECTORY;
7541         }
7542
7543         DEBUG(10,("smb_posix_unlink: %s %s\n",
7544                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7545                 smb_fname_str_dbg(smb_fname)));
7546
7547         if (VALID_STAT_OF_DIR(smb_fname->st)) {
7548                 create_options |= FILE_DIRECTORY_FILE;
7549         }
7550
7551         status = SMB_VFS_CREATE_FILE(
7552                 conn,                                   /* conn */
7553                 req,                                    /* req */
7554                 0,                                      /* root_dir_fid */
7555                 smb_fname,                              /* fname */
7556                 DELETE_ACCESS,                          /* access_mask */
7557                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
7558                     FILE_SHARE_DELETE),
7559                 FILE_OPEN,                              /* create_disposition*/
7560                 create_options,                         /* create_options */
7561                 FILE_FLAG_POSIX_SEMANTICS|0777,         /* file_attributes */
7562                 0,                                      /* oplock_request */
7563                 0,                                      /* allocation_size */
7564                 0,                                      /* private_flags */
7565                 NULL,                                   /* sd */
7566                 NULL,                                   /* ea_list */
7567                 &fsp,                                   /* result */
7568                 &info);                                 /* pinfo */
7569
7570         if (!NT_STATUS_IS_OK(status)) {
7571                 return status;
7572         }
7573
7574         /*
7575          * Don't lie to client. If we can't really delete due to
7576          * non-POSIX opens return SHARING_VIOLATION.
7577          */
7578
7579         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7580         if (lck == NULL) {
7581                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7582                           "lock for file %s\n", fsp_str_dbg(fsp)));
7583                 close_file(req, fsp, NORMAL_CLOSE);
7584                 return NT_STATUS_INVALID_PARAMETER;
7585         }
7586
7587         /*
7588          * See if others still have the file open. If this is the case, then
7589          * don't delete. If all opens are POSIX delete we can set the delete
7590          * on close disposition.
7591          */
7592         for (i=0; i<lck->data->num_share_modes; i++) {
7593                 struct share_mode_entry *e = &lck->data->share_modes[i];
7594                 if (is_valid_share_mode_entry(e)) {
7595                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7596                                 continue;
7597                         }
7598                         /* Fail with sharing violation. */
7599                         close_file(req, fsp, NORMAL_CLOSE);
7600                         TALLOC_FREE(lck);
7601                         return NT_STATUS_SHARING_VIOLATION;
7602                 }
7603         }
7604
7605         /*
7606          * Set the delete on close.
7607          */
7608         status = smb_set_file_disposition_info(conn,
7609                                                 &del,
7610                                                 1,
7611                                                 fsp,
7612                                                 smb_fname);
7613
7614         if (!NT_STATUS_IS_OK(status)) {
7615                 close_file(req, fsp, NORMAL_CLOSE);
7616                 TALLOC_FREE(lck);
7617                 return status;
7618         }
7619         TALLOC_FREE(lck);
7620         return close_file(req, fsp, NORMAL_CLOSE);
7621 }
7622
7623 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7624                                 struct smb_request *req,
7625                                 TALLOC_CTX *mem_ctx,
7626                                 uint16_t info_level,
7627                                 files_struct *fsp,
7628                                 struct smb_filename *smb_fname,
7629                                 char **ppdata, int total_data,
7630                                 int *ret_data_size)
7631 {
7632         char *pdata = *ppdata;
7633         NTSTATUS status = NT_STATUS_OK;
7634         int data_return_size = 0;
7635
7636         *ret_data_size = 0;
7637
7638         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7639                 return NT_STATUS_INVALID_LEVEL;
7640         }
7641
7642         if (!CAN_WRITE(conn)) {
7643                 /* Allow POSIX opens. The open path will deny
7644                  * any non-readonly opens. */
7645                 if (info_level != SMB_POSIX_PATH_OPEN) {
7646                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
7647                 }
7648         }
7649
7650         DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7651                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7652                  fsp ? fsp->fnum : -1, info_level, total_data));
7653
7654         switch (info_level) {
7655
7656                 case SMB_INFO_STANDARD:
7657                 {
7658                         status = smb_set_info_standard(conn,
7659                                         pdata,
7660                                         total_data,
7661                                         fsp,
7662                                         smb_fname);
7663                         break;
7664                 }
7665
7666                 case SMB_INFO_SET_EA:
7667                 {
7668                         status = smb_info_set_ea(conn,
7669                                                 pdata,
7670                                                 total_data,
7671                                                 fsp,
7672                                                 smb_fname);
7673                         break;
7674                 }
7675
7676                 case SMB_SET_FILE_BASIC_INFO:
7677                 case SMB_FILE_BASIC_INFORMATION:
7678                 {
7679                         status = smb_set_file_basic_info(conn,
7680                                                         pdata,
7681                                                         total_data,
7682                                                         fsp,
7683                                                         smb_fname);
7684                         break;
7685                 }
7686
7687                 case SMB_FILE_ALLOCATION_INFORMATION:
7688                 case SMB_SET_FILE_ALLOCATION_INFO:
7689                 {
7690                         status = smb_set_file_allocation_info(conn, req,
7691                                                                 pdata,
7692                                                                 total_data,
7693                                                                 fsp,
7694                                                                 smb_fname);
7695                         break;
7696                 }
7697
7698                 case SMB_FILE_END_OF_FILE_INFORMATION:
7699                 case SMB_SET_FILE_END_OF_FILE_INFO:
7700                 {
7701                         /*
7702                          * XP/Win7 both fail after the createfile with
7703                          * SMB_SET_FILE_END_OF_FILE_INFO but not
7704                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7705                          * The level is known here, so pass it down
7706                          * appropriately.
7707                          */
7708                         bool should_fail =
7709                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7710
7711                         status = smb_set_file_end_of_file_info(conn, req,
7712                                                                 pdata,
7713                                                                 total_data,
7714                                                                 fsp,
7715                                                                 smb_fname,
7716                                                                 should_fail);
7717                         break;
7718                 }
7719
7720                 case SMB_FILE_DISPOSITION_INFORMATION:
7721                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7722                 {
7723 #if 0
7724                         /* JRA - We used to just ignore this on a path ? 
7725                          * Shouldn't this be invalid level on a pathname
7726                          * based call ?
7727                          */
7728                         if (tran_call != TRANSACT2_SETFILEINFO) {
7729                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7730                         }
7731 #endif
7732                         status = smb_set_file_disposition_info(conn,
7733                                                 pdata,
7734                                                 total_data,
7735                                                 fsp,
7736                                                 smb_fname);
7737                         break;
7738                 }
7739
7740                 case SMB_FILE_POSITION_INFORMATION:
7741                 {
7742                         status = smb_file_position_information(conn,
7743                                                 pdata,
7744                                                 total_data,
7745                                                 fsp);
7746                         break;
7747                 }
7748
7749                 case SMB_FILE_FULL_EA_INFORMATION:
7750                 {
7751                         status = smb_set_file_full_ea_info(conn,
7752                                                 pdata,
7753                                                 total_data,
7754                                                 fsp);
7755                         break;
7756                 }
7757
7758                 /* From tridge Samba4 : 
7759                  * MODE_INFORMATION in setfileinfo (I have no
7760                  * idea what "mode information" on a file is - it takes a value of 0,
7761                  * 2, 4 or 6. What could it be?).
7762                  */
7763
7764                 case SMB_FILE_MODE_INFORMATION:
7765                 {
7766                         status = smb_file_mode_information(conn,
7767                                                 pdata,
7768                                                 total_data);
7769                         break;
7770                 }
7771
7772                 /*
7773                  * CIFS UNIX extensions.
7774                  */
7775
7776                 case SMB_SET_FILE_UNIX_BASIC:
7777                 {
7778                         status = smb_set_file_unix_basic(conn, req,
7779                                                         pdata,
7780                                                         total_data,
7781                                                         fsp,
7782                                                         smb_fname);
7783                         break;
7784                 }
7785
7786                 case SMB_SET_FILE_UNIX_INFO2:
7787                 {
7788                         status = smb_set_file_unix_info2(conn, req,
7789                                                         pdata,
7790                                                         total_data,
7791                                                         fsp,
7792                                                         smb_fname);
7793                         break;
7794                 }
7795
7796                 case SMB_SET_FILE_UNIX_LINK:
7797                 {
7798                         if (fsp) {
7799                                 /* We must have a pathname for this. */
7800                                 return NT_STATUS_INVALID_LEVEL;
7801                         }
7802                         status = smb_set_file_unix_link(conn, req, pdata,
7803                                                         total_data, smb_fname);
7804                         break;
7805                 }
7806
7807                 case SMB_SET_FILE_UNIX_HLINK:
7808                 {
7809                         if (fsp) {
7810                                 /* We must have a pathname for this. */
7811                                 return NT_STATUS_INVALID_LEVEL;
7812                         }
7813                         status = smb_set_file_unix_hlink(conn, req,
7814                                                          pdata, total_data,
7815                                                          smb_fname);
7816                         break;
7817                 }
7818
7819                 case SMB_FILE_RENAME_INFORMATION:
7820                 {
7821                         status = smb_file_rename_information(conn, req,
7822                                                              pdata, total_data,
7823                                                              fsp, smb_fname);
7824                         break;
7825                 }
7826
7827                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7828                 {
7829                         /* SMB2 rename information. */
7830                         status = smb2_file_rename_information(conn, req,
7831                                                              pdata, total_data,
7832                                                              fsp, smb_fname);
7833                         break;
7834                 }
7835
7836                 case SMB_FILE_LINK_INFORMATION:
7837                 {
7838                         status = smb_file_link_information(conn, req,
7839                                                         pdata, total_data,
7840                                                         fsp, smb_fname);
7841                         break;
7842                 }
7843
7844 #if defined(HAVE_POSIX_ACLS)
7845                 case SMB_SET_POSIX_ACL:
7846                 {
7847                         status = smb_set_posix_acl(conn,
7848                                                 pdata,
7849                                                 total_data,
7850                                                 fsp,
7851                                                 smb_fname);
7852                         break;
7853                 }
7854 #endif
7855
7856                 case SMB_SET_POSIX_LOCK:
7857                 {
7858                         if (!fsp) {
7859                                 return NT_STATUS_INVALID_LEVEL;
7860                         }
7861                         status = smb_set_posix_lock(conn, req,
7862                                                     pdata, total_data, fsp);
7863                         break;
7864                 }
7865
7866                 case SMB_POSIX_PATH_OPEN:
7867                 {
7868                         if (fsp) {
7869                                 /* We must have a pathname for this. */
7870                                 return NT_STATUS_INVALID_LEVEL;
7871                         }
7872
7873                         status = smb_posix_open(conn, req,
7874                                                 ppdata,
7875                                                 total_data,
7876                                                 smb_fname,
7877                                                 &data_return_size);
7878                         break;
7879                 }
7880
7881                 case SMB_POSIX_PATH_UNLINK:
7882                 {
7883                         if (fsp) {
7884                                 /* We must have a pathname for this. */
7885                                 return NT_STATUS_INVALID_LEVEL;
7886                         }
7887
7888                         status = smb_posix_unlink(conn, req,
7889                                                 pdata,
7890                                                 total_data,
7891                                                 smb_fname);
7892                         break;
7893                 }
7894
7895                 default:
7896                         return NT_STATUS_INVALID_LEVEL;
7897         }
7898
7899         if (!NT_STATUS_IS_OK(status)) {
7900                 return status;
7901         }
7902
7903         *ret_data_size = data_return_size;
7904         return NT_STATUS_OK;
7905 }
7906
7907 /****************************************************************************
7908  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7909 ****************************************************************************/
7910
7911 static void call_trans2setfilepathinfo(connection_struct *conn,
7912                                        struct smb_request *req,
7913                                        unsigned int tran_call,
7914                                        char **pparams, int total_params,
7915                                        char **ppdata, int total_data,
7916                                        unsigned int max_data_bytes)
7917 {
7918         char *params = *pparams;
7919         char *pdata = *ppdata;
7920         uint16 info_level;
7921         struct smb_filename *smb_fname = NULL;
7922         files_struct *fsp = NULL;
7923         NTSTATUS status = NT_STATUS_OK;
7924         int data_return_size = 0;
7925
7926         if (!params) {
7927                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7928                 return;
7929         }
7930
7931         if (tran_call == TRANSACT2_SETFILEINFO) {
7932                 if (total_params < 4) {
7933                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7934                         return;
7935                 }
7936
7937                 fsp = file_fsp(req, SVAL(params,0));
7938                 /* Basic check for non-null fsp. */
7939                 if (!check_fsp_open(conn, req, fsp)) {
7940                         return;
7941                 }
7942                 info_level = SVAL(params,2);
7943
7944                 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7945                                            &smb_fname);
7946                 if (!NT_STATUS_IS_OK(status)) {
7947                         reply_nterror(req, status);
7948                         return;
7949                 }
7950
7951                 if(fsp->fh->fd == -1) {
7952                         /*
7953                          * This is actually a SETFILEINFO on a directory
7954                          * handle (returned from an NT SMB). NT5.0 seems
7955                          * to do this call. JRA.
7956                          */
7957                         if (INFO_LEVEL_IS_UNIX(info_level)) {
7958                                 /* Always do lstat for UNIX calls. */
7959                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7960                                         DEBUG(3,("call_trans2setfilepathinfo: "
7961                                                  "SMB_VFS_LSTAT of %s failed "
7962                                                  "(%s)\n",
7963                                                  smb_fname_str_dbg(smb_fname),
7964                                                  strerror(errno)));
7965                                         reply_nterror(req, map_nt_error_from_unix(errno));
7966                                         return;
7967                                 }
7968                         } else {
7969                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7970                                         DEBUG(3,("call_trans2setfilepathinfo: "
7971                                                  "fileinfo of %s failed (%s)\n",
7972                                                  smb_fname_str_dbg(smb_fname),
7973                                                  strerror(errno)));
7974                                         reply_nterror(req, map_nt_error_from_unix(errno));
7975                                         return;
7976                                 }
7977                         }
7978                 } else if (fsp->print_file) {
7979                         /*
7980                          * Doing a DELETE_ON_CLOSE should cancel a print job.
7981                          */
7982                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7983                                 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7984
7985                                 DEBUG(3,("call_trans2setfilepathinfo: "
7986                                          "Cancelling print job (%s)\n",
7987                                          fsp_str_dbg(fsp)));
7988
7989                                 SSVAL(params,0,0);
7990                                 send_trans2_replies(conn, req, params, 2,
7991                                                     *ppdata, 0,
7992                                                     max_data_bytes);
7993                                 return;
7994                         } else {
7995                                 reply_nterror(req,
7996                                         NT_STATUS_OBJECT_PATH_NOT_FOUND);
7997                                 return;
7998                         }
7999                 } else {
8000                         /*
8001                          * Original code - this is an open file.
8002                          */
8003                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8004                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8005                                          "of fnum %d failed (%s)\n", fsp->fnum,
8006                                          strerror(errno)));
8007                                 reply_nterror(req, map_nt_error_from_unix(errno));
8008                                 return;
8009                         }
8010                 }
8011         } else {
8012                 char *fname = NULL;
8013                 uint32_t ucf_flags = 0;
8014
8015                 /* set path info */
8016                 if (total_params < 7) {
8017                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8018                         return;
8019                 }
8020
8021                 info_level = SVAL(params,0);
8022                 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8023                                 total_params - 6, STR_TERMINATE,
8024                                 &status);
8025                 if (!NT_STATUS_IS_OK(status)) {
8026                         reply_nterror(req, status);
8027                         return;
8028                 }
8029
8030                 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8031                                 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8032                                 info_level == SMB_FILE_RENAME_INFORMATION ||
8033                                 info_level == SMB_POSIX_PATH_UNLINK) {
8034                         ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8035                 }
8036
8037                 status = filename_convert(req, conn,
8038                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
8039                                          fname,
8040                                          ucf_flags,
8041                                          NULL,
8042                                          &smb_fname);
8043                 if (!NT_STATUS_IS_OK(status)) {
8044                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8045                                 reply_botherror(req,
8046                                                 NT_STATUS_PATH_NOT_COVERED,
8047                                                 ERRSRV, ERRbadpath);
8048                                 return;
8049                         }
8050                         reply_nterror(req, status);
8051                         return;
8052                 }
8053
8054                 if (INFO_LEVEL_IS_UNIX(info_level)) {
8055                         /*
8056                          * For CIFS UNIX extensions the target name may not exist.
8057                          */
8058
8059                         /* Always do lstat for UNIX calls. */
8060                         SMB_VFS_LSTAT(conn, smb_fname);
8061
8062                 } else if (!VALID_STAT(smb_fname->st) &&
8063                            SMB_VFS_STAT(conn, smb_fname)) {
8064                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8065                                  "%s failed (%s)\n",
8066                                  smb_fname_str_dbg(smb_fname),
8067                                  strerror(errno)));
8068                         reply_nterror(req, map_nt_error_from_unix(errno));
8069                         return;
8070                 }
8071         }
8072
8073         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8074                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8075                  fsp ? fsp->fnum : -1, info_level,total_data));
8076
8077         /* Realloc the parameter size */
8078         *pparams = (char *)SMB_REALLOC(*pparams,2);
8079         if (*pparams == NULL) {
8080                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8081                 return;
8082         }
8083         params = *pparams;
8084
8085         SSVAL(params,0,0);
8086
8087         status = smbd_do_setfilepathinfo(conn, req, req,
8088                                          info_level,
8089                                          fsp,
8090                                          smb_fname,
8091                                          ppdata, total_data,
8092                                          &data_return_size);
8093         if (!NT_STATUS_IS_OK(status)) {
8094                 if (open_was_deferred(req->sconn, req->mid)) {
8095                         /* We have re-scheduled this call. */
8096                         return;
8097                 }
8098                 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8099                         /* We have re-scheduled this call. */
8100                         return;
8101                 }
8102                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8103                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8104                                         ERRSRV, ERRbadpath);
8105                         return;
8106                 }
8107                 if (info_level == SMB_POSIX_PATH_OPEN) {
8108                         reply_openerror(req, status);
8109                         return;
8110                 }
8111
8112                 reply_nterror(req, status);
8113                 return;
8114         }
8115
8116         send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8117                             max_data_bytes);
8118
8119         return;
8120 }
8121
8122 /****************************************************************************
8123  Reply to a TRANS2_MKDIR (make directory with extended attributes).
8124 ****************************************************************************/
8125
8126 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8127                              char **pparams, int total_params,
8128                              char **ppdata, int total_data,
8129                              unsigned int max_data_bytes)
8130 {
8131         struct smb_filename *smb_dname = NULL;
8132         char *params = *pparams;
8133         char *pdata = *ppdata;
8134         char *directory = NULL;
8135         NTSTATUS status = NT_STATUS_OK;
8136         struct ea_list *ea_list = NULL;
8137         TALLOC_CTX *ctx = talloc_tos();
8138
8139         if (!CAN_WRITE(conn)) {
8140                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8141                 return;
8142         }
8143
8144         if (total_params < 5) {
8145                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8146                 return;
8147         }
8148
8149         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8150                         total_params - 4, STR_TERMINATE,
8151                         &status);
8152         if (!NT_STATUS_IS_OK(status)) {
8153                 reply_nterror(req, status);
8154                 return;
8155         }
8156
8157         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8158
8159         status = filename_convert(ctx,
8160                                 conn,
8161                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
8162                                 directory,
8163                                 0,
8164                                 NULL,
8165                                 &smb_dname);
8166
8167         if (!NT_STATUS_IS_OK(status)) {
8168                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8169                         reply_botherror(req,
8170                                 NT_STATUS_PATH_NOT_COVERED,
8171                                 ERRSRV, ERRbadpath);
8172                         return;
8173                 }
8174                 reply_nterror(req, status);
8175                 return;
8176         }
8177
8178         /*
8179          * OS/2 workplace shell seems to send SET_EA requests of "null"
8180          * length (4 bytes containing IVAL 4).
8181          * They seem to have no effect. Bug #3212. JRA.
8182          */
8183
8184         if (total_data && (total_data != 4)) {
8185                 /* Any data in this call is an EA list. */
8186                 if (total_data < 10) {
8187                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8188                         goto out;
8189                 }
8190
8191                 if (IVAL(pdata,0) > total_data) {
8192                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8193                                 IVAL(pdata,0), (unsigned int)total_data));
8194                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8195                         goto out;
8196                 }
8197
8198                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8199                                        total_data - 4);
8200                 if (!ea_list) {
8201                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8202                         goto out;
8203                 }
8204
8205                 if (!lp_ea_support(SNUM(conn))) {
8206                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8207                         goto out;
8208                 }
8209         }
8210         /* If total_data == 4 Windows doesn't care what values
8211          * are placed in that field, it just ignores them.
8212          * The System i QNTC IBM SMB client puts bad values here,
8213          * so ignore them. */
8214
8215         status = create_directory(conn, req, smb_dname);
8216
8217         if (!NT_STATUS_IS_OK(status)) {
8218                 reply_nterror(req, status);
8219                 goto out;
8220         }
8221
8222         /* Try and set any given EA. */
8223         if (ea_list) {
8224                 status = set_ea(conn, NULL, smb_dname, ea_list);
8225                 if (!NT_STATUS_IS_OK(status)) {
8226                         reply_nterror(req, status);
8227                         goto out;
8228                 }
8229         }
8230
8231         /* Realloc the parameter and data sizes */
8232         *pparams = (char *)SMB_REALLOC(*pparams,2);
8233         if(*pparams == NULL) {
8234                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8235                 goto out;
8236         }
8237         params = *pparams;
8238
8239         SSVAL(params,0,0);
8240
8241         send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8242
8243  out:
8244         TALLOC_FREE(smb_dname);
8245         return;
8246 }
8247
8248 /****************************************************************************
8249  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8250  We don't actually do this - we just send a null response.
8251 ****************************************************************************/
8252
8253 static void call_trans2findnotifyfirst(connection_struct *conn,
8254                                        struct smb_request *req,
8255                                        char **pparams, int total_params,
8256                                        char **ppdata, int total_data,
8257                                        unsigned int max_data_bytes)
8258 {
8259         char *params = *pparams;
8260         uint16 info_level;
8261
8262         if (total_params < 6) {
8263                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8264                 return;
8265         }
8266
8267         info_level = SVAL(params,4);
8268         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8269
8270         switch (info_level) {
8271                 case 1:
8272                 case 2:
8273                         break;
8274                 default:
8275                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8276                         return;
8277         }
8278
8279         /* Realloc the parameter and data sizes */
8280         *pparams = (char *)SMB_REALLOC(*pparams,6);
8281         if (*pparams == NULL) {
8282                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8283                 return;
8284         }
8285         params = *pparams;
8286
8287         SSVAL(params,0,fnf_handle);
8288         SSVAL(params,2,0); /* No changes */
8289         SSVAL(params,4,0); /* No EA errors */
8290
8291         fnf_handle++;
8292
8293         if(fnf_handle == 0)
8294                 fnf_handle = 257;
8295
8296         send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8297
8298         return;
8299 }
8300
8301 /****************************************************************************
8302  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
8303  changes). Currently this does nothing.
8304 ****************************************************************************/
8305
8306 static void call_trans2findnotifynext(connection_struct *conn,
8307                                       struct smb_request *req,
8308                                       char **pparams, int total_params,
8309                                       char **ppdata, int total_data,
8310                                       unsigned int max_data_bytes)
8311 {
8312         char *params = *pparams;
8313
8314         DEBUG(3,("call_trans2findnotifynext\n"));
8315
8316         /* Realloc the parameter and data sizes */
8317         *pparams = (char *)SMB_REALLOC(*pparams,4);
8318         if (*pparams == NULL) {
8319                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8320                 return;
8321         }
8322         params = *pparams;
8323
8324         SSVAL(params,0,0); /* No changes */
8325         SSVAL(params,2,0); /* No EA errors */
8326
8327         send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8328
8329         return;
8330 }
8331
8332 /****************************************************************************
8333  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8334 ****************************************************************************/
8335
8336 static void call_trans2getdfsreferral(connection_struct *conn,
8337                                       struct smb_request *req,
8338                                       char **pparams, int total_params,
8339                                       char **ppdata, int total_data,
8340                                       unsigned int max_data_bytes)
8341 {
8342         char *params = *pparams;
8343         char *pathname = NULL;
8344         int reply_size = 0;
8345         int max_referral_level;
8346         NTSTATUS status = NT_STATUS_OK;
8347         TALLOC_CTX *ctx = talloc_tos();
8348
8349         DEBUG(10,("call_trans2getdfsreferral\n"));
8350
8351         if (total_params < 3) {
8352                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8353                 return;
8354         }
8355
8356         max_referral_level = SVAL(params,0);
8357
8358         if(!lp_host_msdfs()) {
8359                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8360                 return;
8361         }
8362
8363         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8364                     total_params - 2, STR_TERMINATE);
8365         if (!pathname) {
8366                 reply_nterror(req, NT_STATUS_NOT_FOUND);
8367                 return;
8368         }
8369         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8370                                             ppdata,&status)) < 0) {
8371                 reply_nterror(req, status);
8372                 return;
8373         }
8374
8375         SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8376               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8377         send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8378
8379         return;
8380 }
8381
8382 #define LMCAT_SPL       0x53
8383 #define LMFUNC_GETJOBID 0x60
8384
8385 /****************************************************************************
8386  Reply to a TRANS2_IOCTL - used for OS/2 printing.
8387 ****************************************************************************/
8388
8389 static void call_trans2ioctl(connection_struct *conn,
8390                              struct smb_request *req,
8391                              char **pparams, int total_params,
8392                              char **ppdata, int total_data,
8393                              unsigned int max_data_bytes)
8394 {
8395         char *pdata = *ppdata;
8396         files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8397
8398         /* check for an invalid fid before proceeding */
8399
8400         if (!fsp) {
8401                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8402                 return;
8403         }
8404
8405         if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8406             && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8407                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8408                 if (*ppdata == NULL) {
8409                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8410                         return;
8411                 }
8412                 pdata = *ppdata;
8413
8414                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8415                         CAN ACCEPT THIS IN UNICODE. JRA. */
8416
8417                 /* Job number */
8418                 if (fsp->print_file) {
8419                         SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8420                 } else {
8421                         SSVAL(pdata, 0, 0);
8422                 }
8423                 srvstr_push(pdata, req->flags2, pdata + 2,
8424                             lp_netbios_name(), 15,
8425                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8426                 srvstr_push(pdata, req->flags2, pdata+18,
8427                             lp_servicename(SNUM(conn)), 13,
8428                             STR_ASCII|STR_TERMINATE); /* Service name */
8429                 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8430                                     max_data_bytes);
8431                 return;
8432         }
8433
8434         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8435         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8436 }
8437
8438 /****************************************************************************
8439  Reply to a SMBfindclose (stop trans2 directory search).
8440 ****************************************************************************/
8441
8442 void reply_findclose(struct smb_request *req)
8443 {
8444         int dptr_num;
8445         struct smbd_server_connection *sconn = req->sconn;
8446
8447         START_PROFILE(SMBfindclose);
8448
8449         if (req->wct < 1) {
8450                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8451                 END_PROFILE(SMBfindclose);
8452                 return;
8453         }
8454
8455         dptr_num = SVALS(req->vwv+0, 0);
8456
8457         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8458
8459         dptr_close(sconn, &dptr_num);
8460
8461         reply_outbuf(req, 0, 0);
8462
8463         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8464
8465         END_PROFILE(SMBfindclose);
8466         return;
8467 }
8468
8469 /****************************************************************************
8470  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8471 ****************************************************************************/
8472
8473 void reply_findnclose(struct smb_request *req)
8474 {
8475         int dptr_num;
8476
8477         START_PROFILE(SMBfindnclose);
8478
8479         if (req->wct < 1) {
8480                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8481                 END_PROFILE(SMBfindnclose);
8482                 return;
8483         }
8484
8485         dptr_num = SVAL(req->vwv+0, 0);
8486
8487         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8488
8489         /* We never give out valid handles for a 
8490            findnotifyfirst - so any dptr_num is ok here. 
8491            Just ignore it. */
8492
8493         reply_outbuf(req, 0, 0);
8494
8495         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8496
8497         END_PROFILE(SMBfindnclose);
8498         return;
8499 }
8500
8501 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8502                           struct trans_state *state)
8503 {
8504         if (get_Protocol() >= PROTOCOL_NT1) {
8505                 req->flags2 |= 0x40; /* IS_LONG_NAME */
8506                 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8507         }
8508
8509         if (conn->encrypt_level == Required && !req->encrypted) {
8510                 if (state->call != TRANSACT2_QFSINFO &&
8511                                 state->call != TRANSACT2_SETFSINFO) {
8512                         DEBUG(0,("handle_trans2: encryption required "
8513                                 "with call 0x%x\n",
8514                                 (unsigned int)state->call));
8515                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8516                         return;
8517                 }
8518         }
8519
8520         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8521
8522         /* Now we must call the relevant TRANS2 function */
8523         switch(state->call)  {
8524         case TRANSACT2_OPEN:
8525         {
8526                 START_PROFILE(Trans2_open);
8527                 call_trans2open(conn, req,
8528                                 &state->param, state->total_param,
8529                                 &state->data, state->total_data,
8530                                 state->max_data_return);
8531                 END_PROFILE(Trans2_open);
8532                 break;
8533         }
8534
8535         case TRANSACT2_FINDFIRST:
8536         {
8537                 START_PROFILE(Trans2_findfirst);
8538                 call_trans2findfirst(conn, req,
8539                                      &state->param, state->total_param,
8540                                      &state->data, state->total_data,
8541                                      state->max_data_return);
8542                 END_PROFILE(Trans2_findfirst);
8543                 break;
8544         }
8545
8546         case TRANSACT2_FINDNEXT:
8547         {
8548                 START_PROFILE(Trans2_findnext);
8549                 call_trans2findnext(conn, req,
8550                                     &state->param, state->total_param,
8551                                     &state->data, state->total_data,
8552                                     state->max_data_return);
8553                 END_PROFILE(Trans2_findnext);
8554                 break;
8555         }
8556
8557         case TRANSACT2_QFSINFO:
8558         {
8559                 START_PROFILE(Trans2_qfsinfo);
8560                 call_trans2qfsinfo(conn, req,
8561                                    &state->param, state->total_param,
8562                                    &state->data, state->total_data,
8563                                    state->max_data_return);
8564                 END_PROFILE(Trans2_qfsinfo);
8565             break;
8566         }
8567
8568         case TRANSACT2_SETFSINFO:
8569         {
8570                 START_PROFILE(Trans2_setfsinfo);
8571                 call_trans2setfsinfo(conn, req,
8572                                      &state->param, state->total_param,
8573                                      &state->data, state->total_data,
8574                                      state->max_data_return);
8575                 END_PROFILE(Trans2_setfsinfo);
8576                 break;
8577         }
8578
8579         case TRANSACT2_QPATHINFO:
8580         case TRANSACT2_QFILEINFO:
8581         {
8582                 START_PROFILE(Trans2_qpathinfo);
8583                 call_trans2qfilepathinfo(conn, req, state->call,
8584                                          &state->param, state->total_param,
8585                                          &state->data, state->total_data,
8586                                          state->max_data_return);
8587                 END_PROFILE(Trans2_qpathinfo);
8588                 break;
8589         }
8590
8591         case TRANSACT2_SETPATHINFO:
8592         case TRANSACT2_SETFILEINFO:
8593         {
8594                 START_PROFILE(Trans2_setpathinfo);
8595                 call_trans2setfilepathinfo(conn, req, state->call,
8596                                            &state->param, state->total_param,
8597                                            &state->data, state->total_data,
8598                                            state->max_data_return);
8599                 END_PROFILE(Trans2_setpathinfo);
8600                 break;
8601         }
8602
8603         case TRANSACT2_FINDNOTIFYFIRST:
8604         {
8605                 START_PROFILE(Trans2_findnotifyfirst);
8606                 call_trans2findnotifyfirst(conn, req,
8607                                            &state->param, state->total_param,
8608                                            &state->data, state->total_data,
8609                                            state->max_data_return);
8610                 END_PROFILE(Trans2_findnotifyfirst);
8611                 break;
8612         }
8613
8614         case TRANSACT2_FINDNOTIFYNEXT:
8615         {
8616                 START_PROFILE(Trans2_findnotifynext);
8617                 call_trans2findnotifynext(conn, req,
8618                                           &state->param, state->total_param,
8619                                           &state->data, state->total_data,
8620                                           state->max_data_return);
8621                 END_PROFILE(Trans2_findnotifynext);
8622                 break;
8623         }
8624
8625         case TRANSACT2_MKDIR:
8626         {
8627                 START_PROFILE(Trans2_mkdir);
8628                 call_trans2mkdir(conn, req,
8629                                  &state->param, state->total_param,
8630                                  &state->data, state->total_data,
8631                                  state->max_data_return);
8632                 END_PROFILE(Trans2_mkdir);
8633                 break;
8634         }
8635
8636         case TRANSACT2_GET_DFS_REFERRAL:
8637         {
8638                 START_PROFILE(Trans2_get_dfs_referral);
8639                 call_trans2getdfsreferral(conn, req,
8640                                           &state->param, state->total_param,
8641                                           &state->data, state->total_data,
8642                                           state->max_data_return);
8643                 END_PROFILE(Trans2_get_dfs_referral);
8644                 break;
8645         }
8646
8647         case TRANSACT2_IOCTL:
8648         {
8649                 START_PROFILE(Trans2_ioctl);
8650                 call_trans2ioctl(conn, req,
8651                                  &state->param, state->total_param,
8652                                  &state->data, state->total_data,
8653                                  state->max_data_return);
8654                 END_PROFILE(Trans2_ioctl);
8655                 break;
8656         }
8657
8658         default:
8659                 /* Error in request */
8660                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8661                 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8662         }
8663 }
8664
8665 /****************************************************************************
8666  Reply to a SMBtrans2.
8667  ****************************************************************************/
8668
8669 void reply_trans2(struct smb_request *req)
8670 {
8671         connection_struct *conn = req->conn;
8672         unsigned int dsoff;
8673         unsigned int dscnt;
8674         unsigned int psoff;
8675         unsigned int pscnt;
8676         unsigned int tran_call;
8677         struct trans_state *state;
8678         NTSTATUS result;
8679
8680         START_PROFILE(SMBtrans2);
8681
8682         if (req->wct < 14) {
8683                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8684                 END_PROFILE(SMBtrans2);
8685                 return;
8686         }
8687
8688         dsoff = SVAL(req->vwv+12, 0);
8689         dscnt = SVAL(req->vwv+11, 0);
8690         psoff = SVAL(req->vwv+10, 0);
8691         pscnt = SVAL(req->vwv+9, 0);
8692         tran_call = SVAL(req->vwv+14, 0);
8693
8694         result = allow_new_trans(conn->pending_trans, req->mid);
8695         if (!NT_STATUS_IS_OK(result)) {
8696                 DEBUG(2, ("Got invalid trans2 request: %s\n",
8697                           nt_errstr(result)));
8698                 reply_nterror(req, result);
8699                 END_PROFILE(SMBtrans2);
8700                 return;
8701         }
8702
8703         if (IS_IPC(conn)) {
8704                 switch (tran_call) {
8705                 /* List the allowed trans2 calls on IPC$ */
8706                 case TRANSACT2_OPEN:
8707                 case TRANSACT2_GET_DFS_REFERRAL:
8708                 case TRANSACT2_QFILEINFO:
8709                 case TRANSACT2_QFSINFO:
8710                 case TRANSACT2_SETFSINFO:
8711                         break;
8712                 default:
8713                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8714                         END_PROFILE(SMBtrans2);
8715                         return;
8716                 }
8717         }
8718
8719         if ((state = talloc(conn, struct trans_state)) == NULL) {
8720                 DEBUG(0, ("talloc failed\n"));
8721                 reply_nterror(req, NT_STATUS_NO_MEMORY);
8722                 END_PROFILE(SMBtrans2);
8723                 return;
8724         }
8725
8726         state->cmd = SMBtrans2;
8727
8728         state->mid = req->mid;
8729         state->vuid = req->vuid;
8730         state->setup_count = SVAL(req->vwv+13, 0);
8731         state->setup = NULL;
8732         state->total_param = SVAL(req->vwv+0, 0);
8733         state->param = NULL;
8734         state->total_data =  SVAL(req->vwv+1, 0);
8735         state->data = NULL;
8736         state->max_param_return = SVAL(req->vwv+2, 0);
8737         state->max_data_return  = SVAL(req->vwv+3, 0);
8738         state->max_setup_return = SVAL(req->vwv+4, 0);
8739         state->close_on_completion = BITSETW(req->vwv+5, 0);
8740         state->one_way = BITSETW(req->vwv+5, 1);
8741
8742         state->call = tran_call;
8743
8744         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8745            is so as a sanity check */
8746         if (state->setup_count != 1) {
8747                 /*
8748                  * Need to have rc=0 for ioctl to get job id for OS/2.
8749                  *  Network printing will fail if function is not successful.
8750                  *  Similar function in reply.c will be used if protocol
8751                  *  is LANMAN1.0 instead of LM1.2X002.
8752                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
8753                  *  outbuf doesn't have to be set(only job id is used).
8754                  */
8755                 if ( (state->setup_count == 4)
8756                      && (tran_call == TRANSACT2_IOCTL)
8757                      && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8758                      && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8759                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8760                 } else {
8761                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8762                         DEBUG(2,("Transaction is %d\n",tran_call));
8763                         TALLOC_FREE(state);
8764                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8765                         END_PROFILE(SMBtrans2);
8766                         return;
8767                 }
8768         }
8769
8770         if ((dscnt > state->total_data) || (pscnt > state->total_param))
8771                 goto bad_param;
8772
8773         if (state->total_data) {
8774
8775                 if (trans_oob(state->total_data, 0, dscnt)
8776                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8777                         goto bad_param;
8778                 }
8779
8780                 /* Can't use talloc here, the core routines do realloc on the
8781                  * params and data. */
8782                 state->data = (char *)SMB_MALLOC(state->total_data);
8783                 if (state->data == NULL) {
8784                         DEBUG(0,("reply_trans2: data malloc fail for %u "
8785                                  "bytes !\n", (unsigned int)state->total_data));
8786                         TALLOC_FREE(state);
8787                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8788                         END_PROFILE(SMBtrans2);
8789                         return;
8790                 }
8791
8792                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8793         }
8794
8795         if (state->total_param) {
8796
8797                 if (trans_oob(state->total_param, 0, pscnt)
8798                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8799                         goto bad_param;
8800                 }
8801
8802                 /* Can't use talloc here, the core routines do realloc on the
8803                  * params and data. */
8804                 state->param = (char *)SMB_MALLOC(state->total_param);
8805                 if (state->param == NULL) {
8806                         DEBUG(0,("reply_trans: param malloc fail for %u "
8807                                  "bytes !\n", (unsigned int)state->total_param));
8808                         SAFE_FREE(state->data);
8809                         TALLOC_FREE(state);
8810                         reply_nterror(req, NT_STATUS_NO_MEMORY);
8811                         END_PROFILE(SMBtrans2);
8812                         return;
8813                 } 
8814
8815                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8816         }
8817
8818         state->received_data  = dscnt;
8819         state->received_param = pscnt;
8820
8821         if ((state->received_param == state->total_param) &&
8822             (state->received_data == state->total_data)) {
8823
8824                 handle_trans2(conn, req, state);
8825
8826                 SAFE_FREE(state->data);
8827                 SAFE_FREE(state->param);
8828                 TALLOC_FREE(state);
8829                 END_PROFILE(SMBtrans2);
8830                 return;
8831         }
8832
8833         DLIST_ADD(conn->pending_trans, state);
8834
8835         /* We need to send an interim response then receive the rest
8836            of the parameter/data bytes */
8837         reply_outbuf(req, 0, 0);
8838         show_msg((char *)req->outbuf);
8839         END_PROFILE(SMBtrans2);
8840         return;
8841
8842   bad_param:
8843
8844         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8845         SAFE_FREE(state->data);
8846         SAFE_FREE(state->param);
8847         TALLOC_FREE(state);
8848         END_PROFILE(SMBtrans2);
8849         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8850 }
8851
8852
8853 /****************************************************************************
8854  Reply to a SMBtranss2
8855  ****************************************************************************/
8856
8857 void reply_transs2(struct smb_request *req)
8858 {
8859         connection_struct *conn = req->conn;
8860         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8861         struct trans_state *state;
8862
8863         START_PROFILE(SMBtranss2);
8864
8865         show_msg((const char *)req->inbuf);
8866
8867         if (req->wct < 8) {
8868                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8869                 END_PROFILE(SMBtranss2);
8870                 return;
8871         }
8872
8873         for (state = conn->pending_trans; state != NULL;
8874              state = state->next) {
8875                 if (state->mid == req->mid) {
8876                         break;
8877                 }
8878         }
8879
8880         if ((state == NULL) || (state->cmd != SMBtrans2)) {
8881                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8882                 END_PROFILE(SMBtranss2);
8883                 return;
8884         }
8885
8886         /* Revise state->total_param and state->total_data in case they have
8887            changed downwards */
8888
8889         if (SVAL(req->vwv+0, 0) < state->total_param)
8890                 state->total_param = SVAL(req->vwv+0, 0);
8891         if (SVAL(req->vwv+1, 0) < state->total_data)
8892                 state->total_data = SVAL(req->vwv+1, 0);
8893
8894         pcnt = SVAL(req->vwv+2, 0);
8895         poff = SVAL(req->vwv+3, 0);
8896         pdisp = SVAL(req->vwv+4, 0);
8897
8898         dcnt = SVAL(req->vwv+5, 0);
8899         doff = SVAL(req->vwv+6, 0);
8900         ddisp = SVAL(req->vwv+7, 0);
8901
8902         state->received_param += pcnt;
8903         state->received_data += dcnt;
8904
8905         if ((state->received_data > state->total_data) ||
8906             (state->received_param > state->total_param))
8907                 goto bad_param;
8908
8909         if (pcnt) {
8910                 if (trans_oob(state->total_param, pdisp, pcnt)
8911                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8912                         goto bad_param;
8913                 }
8914                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8915         }
8916
8917         if (dcnt) {
8918                 if (trans_oob(state->total_data, ddisp, dcnt)
8919                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8920                         goto bad_param;
8921                 }
8922                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8923         }
8924
8925         if ((state->received_param < state->total_param) ||
8926             (state->received_data < state->total_data)) {
8927                 END_PROFILE(SMBtranss2);
8928                 return;
8929         }
8930
8931         handle_trans2(conn, req, state);
8932
8933         DLIST_REMOVE(conn->pending_trans, state);
8934         SAFE_FREE(state->data);
8935         SAFE_FREE(state->param);
8936         TALLOC_FREE(state);
8937
8938         END_PROFILE(SMBtranss2);
8939         return;
8940
8941   bad_param:
8942
8943         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8944         DLIST_REMOVE(conn->pending_trans, state);
8945         SAFE_FREE(state->data);
8946         SAFE_FREE(state->param);
8947         TALLOC_FREE(state);
8948         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8949         END_PROFILE(SMBtranss2);
8950         return;
8951 }