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