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