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