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