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 "../librpc/gen_ndr/ndr_smb3posix.h"
37 : #include "libcli/security/security.h"
38 : #include "trans2.h"
39 : #include "auth.h"
40 : #include "smbprofile.h"
41 : #include "rpc_server/srv_pipe_hnd.h"
42 : #include "printing.h"
43 : #include "lib/util_ea.h"
44 : #include "lib/readdir_attr.h"
45 : #include "messages.h"
46 : #include "libcli/smb/smb2_posix.h"
47 : #include "lib/util/string_wrappers.h"
48 : #include "source3/lib/substitute.h"
49 : #include "source3/lib/adouble.h"
50 :
51 : #define DIR_ENTRY_SAFETY_MARGIN 4096
52 :
53 : static uint32_t generate_volume_serial_number(
54 : const struct loadparm_substitution *lp_sub,
55 : int snum);
56 :
57 : /****************************************************************************
58 : Check if an open file handle is a symlink.
59 : ****************************************************************************/
60 :
61 795889 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
62 : {
63 :
64 795889 : if (!VALID_STAT(fsp->fsp_name->st)) {
65 0 : return NT_STATUS_ACCESS_DENIED;
66 : }
67 795889 : if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
68 56 : return NT_STATUS_ACCESS_DENIED;
69 : }
70 795833 : if (fsp_get_pathref_fd(fsp) == -1) {
71 2 : return NT_STATUS_ACCESS_DENIED;
72 : }
73 795831 : return NT_STATUS_OK;
74 : }
75 :
76 6647 : NTSTATUS check_access_fsp(struct files_struct *fsp,
77 : uint32_t access_mask)
78 : {
79 6647 : if (!fsp->fsp_flags.is_fsa) {
80 138 : return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
81 : fsp,
82 : false,
83 : access_mask);
84 : }
85 6509 : if (!(fsp->access_mask & access_mask)) {
86 40 : return NT_STATUS_ACCESS_DENIED;
87 : }
88 6469 : return NT_STATUS_OK;
89 : }
90 :
91 : /********************************************************************
92 : Roundup a value to the nearest allocation roundup size boundary.
93 : Only do this for Windows clients.
94 : ********************************************************************/
95 :
96 1729658 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
97 : {
98 1729658 : uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
99 :
100 : /* Only roundup for Windows clients. */
101 1729658 : enum remote_arch_types ra_type = get_remote_arch();
102 1729658 : if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
103 0 : val = SMB_ROUNDUP(val,rval);
104 : }
105 1729658 : return val;
106 : }
107 :
108 : /****************************************************************************
109 : Utility functions for dealing with extended attributes.
110 : ****************************************************************************/
111 :
112 : /****************************************************************************
113 : Refuse to allow clients to overwrite our private xattrs.
114 : ****************************************************************************/
115 :
116 723745 : bool samba_private_attr_name(const char *unix_ea_name)
117 : {
118 723745 : bool prohibited = false;
119 :
120 723745 : prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
121 723745 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
122 723745 : prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
123 723745 : prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
124 723745 : prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
125 :
126 723745 : if (prohibited) {
127 710530 : return true;
128 : }
129 :
130 12259 : if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
131 : strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
132 106 : return true;
133 : }
134 11085 : return false;
135 : }
136 :
137 : /****************************************************************************
138 : Get one EA value. Fill in a struct ea_struct.
139 : ****************************************************************************/
140 :
141 15174 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
142 : files_struct *fsp,
143 : const char *ea_name,
144 : struct ea_struct *pea)
145 : {
146 : /* Get the value of this xattr. Max size is 64k. */
147 15174 : size_t attr_size = 256;
148 15174 : char *val = NULL;
149 575 : ssize_t sizeret;
150 15174 : size_t max_xattr_size = 0;
151 575 : NTSTATUS status;
152 :
153 15174 : if (fsp == NULL) {
154 0 : return NT_STATUS_INVALID_HANDLE;
155 : }
156 15174 : status = refuse_symlink_fsp(fsp);
157 15174 : if (!NT_STATUS_IS_OK(status)) {
158 0 : return status;
159 : }
160 :
161 15174 : max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
162 :
163 15288 : again:
164 :
165 15288 : val = talloc_realloc(mem_ctx, val, char, attr_size);
166 15288 : if (!val) {
167 0 : return NT_STATUS_NO_MEMORY;
168 : }
169 :
170 15288 : sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
171 15288 : if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
172 114 : attr_size = max_xattr_size;
173 114 : goto again;
174 : }
175 :
176 15174 : if (sizeret == -1) {
177 2608 : return map_nt_error_from_unix(errno);
178 : }
179 :
180 12566 : DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
181 12566 : dump_data(10, (uint8_t *)val, sizeret);
182 :
183 12566 : pea->flags = 0;
184 12566 : if (strnequal(ea_name, "user.", 5)) {
185 12566 : pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
186 : } else {
187 0 : pea->name = talloc_strdup(mem_ctx, ea_name);
188 : }
189 12566 : if (pea->name == NULL) {
190 0 : TALLOC_FREE(val);
191 0 : return NT_STATUS_NO_MEMORY;
192 : }
193 12566 : pea->value.data = (unsigned char *)val;
194 12566 : pea->value.length = (size_t)sizeret;
195 12566 : return NT_STATUS_OK;
196 : }
197 :
198 749518 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
199 : files_struct *fsp,
200 : char ***pnames,
201 : size_t *pnum_names)
202 : {
203 1071 : char smallbuf[1024];
204 : /* Get a list of all xattrs. Max namesize is 64k. */
205 749518 : size_t ea_namelist_size = 1024;
206 749518 : char *ea_namelist = smallbuf;
207 749518 : char *to_free = NULL;
208 :
209 1071 : char *p;
210 1071 : char **names;
211 1071 : size_t num_names;
212 749518 : ssize_t sizeret = -1;
213 1071 : NTSTATUS status;
214 :
215 749518 : if (pnames) {
216 748237 : *pnames = NULL;
217 : }
218 749518 : *pnum_names = 0;
219 :
220 749518 : if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
221 : /*
222 : * Callers may pass fsp == NULL when passing smb_fname->fsp of a
223 : * symlink. This is ok, handle it here, by just return no EA's
224 : * on a symlink.
225 : */
226 46 : return NT_STATUS_OK;
227 : }
228 :
229 749472 : sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
230 : ea_namelist_size);
231 :
232 749472 : if ((sizeret == -1) && (errno == ERANGE)) {
233 0 : ea_namelist_size = 65536;
234 0 : ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
235 0 : if (ea_namelist == NULL) {
236 0 : return NT_STATUS_NO_MEMORY;
237 : }
238 0 : to_free = ea_namelist;
239 :
240 0 : sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
241 : ea_namelist_size);
242 : }
243 :
244 749472 : if (sizeret == -1) {
245 0 : status = map_nt_error_from_unix(errno);
246 0 : TALLOC_FREE(to_free);
247 0 : return status;
248 : }
249 :
250 749472 : DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
251 :
252 749472 : if (sizeret == 0) {
253 40752 : TALLOC_FREE(to_free);
254 40752 : return NT_STATUS_OK;
255 : }
256 :
257 : /*
258 : * Ensure the result is 0-terminated
259 : */
260 :
261 708720 : if (ea_namelist[sizeret-1] != '\0') {
262 0 : TALLOC_FREE(to_free);
263 0 : return NT_STATUS_INTERNAL_ERROR;
264 : }
265 :
266 : /*
267 : * count the names
268 : */
269 707690 : num_names = 0;
270 :
271 4162238 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
272 3453518 : num_names += 1;
273 : }
274 :
275 708720 : *pnum_names = num_names;
276 :
277 708720 : if (pnames == NULL) {
278 1272 : TALLOC_FREE(to_free);
279 1272 : return NT_STATUS_OK;
280 : }
281 :
282 707448 : names = talloc_array(mem_ctx, char *, num_names);
283 707448 : if (names == NULL) {
284 0 : DEBUG(0, ("talloc failed\n"));
285 0 : TALLOC_FREE(to_free);
286 0 : return NT_STATUS_NO_MEMORY;
287 : }
288 :
289 707448 : if (ea_namelist == smallbuf) {
290 707448 : ea_namelist = talloc_memdup(names, smallbuf, sizeret);
291 707448 : if (ea_namelist == NULL) {
292 0 : TALLOC_FREE(names);
293 0 : return NT_STATUS_NO_MEMORY;
294 : }
295 : } else {
296 0 : talloc_steal(names, ea_namelist);
297 :
298 0 : ea_namelist = talloc_realloc(names, ea_namelist, char,
299 : sizeret);
300 0 : if (ea_namelist == NULL) {
301 0 : TALLOC_FREE(names);
302 0 : return NT_STATUS_NO_MEMORY;
303 : }
304 : }
305 :
306 707448 : num_names = 0;
307 :
308 4154262 : for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
309 3446814 : names[num_names++] = p;
310 : }
311 :
312 707448 : *pnames = names;
313 :
314 707448 : return NT_STATUS_OK;
315 : }
316 :
317 : /****************************************************************************
318 : Return a linked list of the total EA's. Plus the total size
319 : ****************************************************************************/
320 :
321 742244 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
322 : files_struct *fsp,
323 : size_t *pea_total_len,
324 : struct ea_list **ea_list)
325 : {
326 : /* Get a list of all xattrs. Max namesize is 64k. */
327 994 : size_t i, num_names;
328 994 : char **names;
329 742244 : struct ea_list *ea_list_head = NULL;
330 742244 : bool posix_pathnames = false;
331 994 : NTSTATUS status;
332 :
333 742244 : *pea_total_len = 0;
334 742244 : *ea_list = NULL;
335 :
336 : /* symlink */
337 742244 : if (fsp == NULL) {
338 0 : return NT_STATUS_OK;
339 : }
340 :
341 742244 : if (!lp_ea_support(SNUM(fsp->conn))) {
342 0 : return NT_STATUS_OK;
343 : }
344 :
345 742244 : if (fsp_is_alternate_stream(fsp)) {
346 8 : return NT_STATUS_INVALID_PARAMETER;
347 : }
348 :
349 742236 : posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
350 :
351 742236 : status = get_ea_names_from_fsp(talloc_tos(),
352 : fsp,
353 : &names,
354 : &num_names);
355 :
356 742236 : if (!NT_STATUS_IS_OK(status)) {
357 0 : return status;
358 : }
359 :
360 742236 : if (num_names == 0) {
361 40775 : return NT_STATUS_OK;
362 : }
363 :
364 4133590 : for (i=0; i<num_names; i++) {
365 5395 : struct ea_list *listp;
366 5395 : fstring dos_ea_name;
367 :
368 : /*
369 : * POSIX EA names are divided into several namespaces by
370 : * means of string prefixes. Usually, the system controls
371 : * semantics for each namespace, but the 'user' namespace is
372 : * available for arbitrary use, which comes closest to
373 : * Windows EA semantics. Hence, we map POSIX EAs from the
374 : * 'user' namespace to Windows EAs, and just ignore all the
375 : * other namespaces. Also, a few specific names in the 'user'
376 : * namespace are used by Samba internally. Filter them out as
377 : * well, and only present the EAs that are available for
378 : * arbitrary use.
379 : */
380 3432129 : if (!strnequal(names[i], "user.", 5)
381 706175 : || samba_private_attr_name(names[i]))
382 3425983 : continue;
383 :
384 : /*
385 : * Filter out any underlying POSIX EA names
386 : * that a Windows client can't handle.
387 : */
388 12288 : if (!posix_pathnames &&
389 6142 : is_invalid_windows_ea_name(names[i])) {
390 0 : continue;
391 : }
392 :
393 6146 : listp = talloc(mem_ctx, struct ea_list);
394 6146 : if (listp == NULL) {
395 0 : return NT_STATUS_NO_MEMORY;
396 : }
397 :
398 6721 : status = get_ea_value_fsp(listp,
399 : fsp,
400 6146 : names[i],
401 : &listp->ea);
402 :
403 6146 : if (!NT_STATUS_IS_OK(status)) {
404 0 : TALLOC_FREE(listp);
405 0 : return status;
406 : }
407 :
408 6146 : if (listp->ea.value.length == 0) {
409 : /*
410 : * We can never return a zero length EA.
411 : * Windows reports the EA's as corrupted.
412 : */
413 0 : TALLOC_FREE(listp);
414 0 : continue;
415 6146 : } else if (listp->ea.value.length > 65536) {
416 : /*
417 : * SMB clients may report error with file
418 : * if large EA is presented to them.
419 : */
420 0 : DBG_ERR("EA [%s] on file [%s] exceeds "
421 : "maximum permitted EA size of 64KiB: %zu\n.",
422 : listp->ea.name, fsp_str_dbg(fsp),
423 : listp->ea.value.length);
424 0 : TALLOC_FREE(listp);
425 0 : continue;
426 : }
427 :
428 6146 : push_ascii_fstring(dos_ea_name, listp->ea.name);
429 :
430 6146 : *pea_total_len +=
431 6146 : 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
432 :
433 6146 : DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
434 : "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
435 : (unsigned int)listp->ea.value.length));
436 :
437 6146 : DLIST_ADD_END(ea_list_head, listp);
438 :
439 : }
440 :
441 : /* Add on 4 for total length. */
442 701461 : if (*pea_total_len) {
443 3922 : *pea_total_len += 4;
444 : }
445 :
446 701461 : DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
447 : (unsigned int)*pea_total_len));
448 :
449 701461 : *ea_list = ea_list_head;
450 701461 : return NT_STATUS_OK;
451 : }
452 :
453 : /****************************************************************************
454 : Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
455 : that was filled.
456 : ****************************************************************************/
457 :
458 170 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
459 : connection_struct *conn, struct ea_list *ea_list)
460 : {
461 170 : unsigned int ret_data_size = 4;
462 170 : char *p = pdata;
463 :
464 170 : SMB_ASSERT(total_data_size >= 4);
465 :
466 170 : if (!lp_ea_support(SNUM(conn))) {
467 0 : SIVAL(pdata,4,0);
468 0 : return 4;
469 : }
470 :
471 358 : for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
472 28 : size_t dos_namelen;
473 28 : fstring dos_ea_name;
474 188 : push_ascii_fstring(dos_ea_name, ea_list->ea.name);
475 188 : dos_namelen = strlen(dos_ea_name);
476 188 : if (dos_namelen > 255 || dos_namelen == 0) {
477 : break;
478 : }
479 188 : if (ea_list->ea.value.length > 65535) {
480 0 : break;
481 : }
482 188 : if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
483 0 : break;
484 : }
485 :
486 : /* We know we have room. */
487 188 : SCVAL(p,0,ea_list->ea.flags);
488 188 : SCVAL(p,1,dos_namelen);
489 188 : SSVAL(p,2,ea_list->ea.value.length);
490 188 : strlcpy(p+4, dos_ea_name, dos_namelen+1);
491 188 : if (ea_list->ea.value.length > 0) {
492 139 : memcpy(p + 4 + dos_namelen + 1,
493 111 : ea_list->ea.value.data,
494 : ea_list->ea.value.length);
495 : }
496 :
497 188 : total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
498 188 : p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
499 : }
500 :
501 170 : ret_data_size = PTR_DIFF(p, pdata);
502 170 : DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
503 170 : SIVAL(pdata,0,ret_data_size);
504 170 : return ret_data_size;
505 : }
506 :
507 554453 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
508 : char *pdata,
509 : unsigned int total_data_size,
510 : unsigned int *ret_data_size,
511 : connection_struct *conn,
512 : struct ea_list *ea_list)
513 : {
514 554453 : uint8_t *p = (uint8_t *)pdata;
515 554453 : uint8_t *last_start = NULL;
516 554453 : bool do_store_data = (pdata != NULL);
517 :
518 554453 : *ret_data_size = 0;
519 :
520 554453 : if (!lp_ea_support(SNUM(conn))) {
521 0 : return NT_STATUS_NO_EAS_ON_FILE;
522 : }
523 :
524 556597 : for (; ea_list; ea_list = ea_list->next) {
525 0 : size_t dos_namelen;
526 0 : fstring dos_ea_name;
527 0 : size_t this_size;
528 2144 : size_t pad = 0;
529 :
530 2144 : if (last_start != NULL && do_store_data) {
531 8 : SIVAL(last_start, 0, PTR_DIFF(p, last_start));
532 : }
533 2144 : last_start = p;
534 :
535 2144 : push_ascii_fstring(dos_ea_name, ea_list->ea.name);
536 2144 : dos_namelen = strlen(dos_ea_name);
537 2144 : if (dos_namelen > 255 || dos_namelen == 0) {
538 0 : return NT_STATUS_INTERNAL_ERROR;
539 : }
540 2144 : if (ea_list->ea.value.length > 65535) {
541 0 : return NT_STATUS_INTERNAL_ERROR;
542 : }
543 :
544 2144 : this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
545 :
546 2144 : if (ea_list->next) {
547 1071 : pad = (4 - (this_size % 4)) % 4;
548 1071 : this_size += pad;
549 : }
550 :
551 2144 : if (do_store_data) {
552 18 : if (this_size > total_data_size) {
553 0 : return NT_STATUS_INFO_LENGTH_MISMATCH;
554 : }
555 :
556 : /* We know we have room. */
557 18 : SIVAL(p, 0x00, 0); /* next offset */
558 18 : SCVAL(p, 0x04, ea_list->ea.flags);
559 18 : SCVAL(p, 0x05, dos_namelen);
560 18 : SSVAL(p, 0x06, ea_list->ea.value.length);
561 18 : strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
562 18 : memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
563 18 : if (pad) {
564 0 : memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
565 : '\0',
566 : pad);
567 : }
568 18 : total_data_size -= this_size;
569 : }
570 :
571 2144 : p += this_size;
572 : }
573 :
574 554453 : *ret_data_size = PTR_DIFF(p, pdata);
575 554453 : DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
576 554453 : return NT_STATUS_OK;
577 : }
578 :
579 738233 : unsigned int estimate_ea_size(files_struct *fsp)
580 : {
581 738233 : size_t total_ea_len = 0;
582 473 : TALLOC_CTX *mem_ctx;
583 738233 : struct ea_list *ea_list = NULL;
584 473 : NTSTATUS status;
585 :
586 : /* symlink */
587 738233 : if (fsp == NULL) {
588 52 : return 0;
589 : }
590 :
591 738181 : if (!lp_ea_support(SNUM(fsp->conn))) {
592 0 : return 0;
593 : }
594 :
595 738181 : mem_ctx = talloc_stackframe();
596 :
597 : /* If this is a stream fsp, then we need to instead find the
598 : * estimated ea len from the main file, not the stream
599 : * (streams cannot have EAs), but the estimate isn't just 0 in
600 : * this case! */
601 738181 : fsp = metadata_fsp(fsp);
602 738181 : (void)get_ea_list_from_fsp(mem_ctx,
603 : fsp,
604 : &total_ea_len,
605 : &ea_list);
606 :
607 738181 : if(fsp->conn->sconn->using_smb2) {
608 0 : unsigned int ret_data_size;
609 : /*
610 : * We're going to be using fill_ea_chained_buffer() to
611 : * marshall EA's - this size is significantly larger
612 : * than the SMB1 buffer. Re-calculate the size without
613 : * marshalling.
614 : */
615 554443 : status = fill_ea_chained_buffer(mem_ctx,
616 : NULL,
617 : 0,
618 : &ret_data_size,
619 554443 : fsp->conn,
620 : ea_list);
621 554443 : if (!NT_STATUS_IS_OK(status)) {
622 0 : ret_data_size = 0;
623 : }
624 554443 : total_ea_len = ret_data_size;
625 : }
626 738181 : TALLOC_FREE(mem_ctx);
627 738181 : return total_ea_len;
628 : }
629 :
630 : /****************************************************************************
631 : Ensure the EA name is case insensitive by matching any existing EA name.
632 : ****************************************************************************/
633 :
634 3851 : static void canonicalize_ea_name(files_struct *fsp,
635 : fstring unix_ea_name)
636 : {
637 493 : size_t total_ea_len;
638 3851 : TALLOC_CTX *mem_ctx = talloc_tos();
639 493 : struct ea_list *ea_list;
640 3851 : NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
641 : fsp,
642 : &total_ea_len,
643 : &ea_list);
644 3851 : if (!NT_STATUS_IS_OK(status)) {
645 0 : return;
646 : }
647 :
648 4862 : for (; ea_list; ea_list = ea_list->next) {
649 2124 : if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
650 1113 : DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
651 : &unix_ea_name[5], ea_list->ea.name));
652 1113 : strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
653 1113 : break;
654 : }
655 : }
656 : }
657 :
658 : /****************************************************************************
659 : Set or delete an extended attribute.
660 : ****************************************************************************/
661 :
662 3213 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
663 : struct ea_list *ea_list)
664 : {
665 500 : NTSTATUS status;
666 3213 : bool posix_pathnames = false;
667 :
668 3213 : if (!lp_ea_support(SNUM(conn))) {
669 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
670 : }
671 :
672 3213 : if (fsp == NULL) {
673 0 : return NT_STATUS_INVALID_HANDLE;
674 : }
675 :
676 3213 : posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
677 :
678 3213 : status = refuse_symlink_fsp(fsp);
679 3213 : if (!NT_STATUS_IS_OK(status)) {
680 12 : return status;
681 : }
682 :
683 3201 : status = check_access_fsp(fsp, FILE_WRITE_EA);
684 3201 : if (!NT_STATUS_IS_OK(status)) {
685 0 : return status;
686 : }
687 :
688 : /* Setting EAs on streams isn't supported. */
689 3201 : if (fsp_is_alternate_stream(fsp)) {
690 4 : return NT_STATUS_INVALID_PARAMETER;
691 : }
692 :
693 : /*
694 : * Filter out invalid Windows EA names - before
695 : * we set *any* of them.
696 : */
697 :
698 3197 : if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
699 235 : return STATUS_INVALID_EA_NAME;
700 : }
701 :
702 6811 : for (;ea_list; ea_list = ea_list->next) {
703 493 : int ret;
704 493 : fstring unix_ea_name;
705 :
706 : /*
707 : * Complementing the forward mapping from POSIX EAs to
708 : * Windows EAs in get_ea_list_from_fsp(), here we map in the
709 : * opposite direction from Windows EAs to the 'user' namespace
710 : * of POSIX EAs. Hence, all POSIX EA names the we set here must
711 : * start with a 'user.' prefix.
712 : */
713 3851 : fstrcpy(unix_ea_name, "user.");
714 3851 : fstrcat(unix_ea_name, ea_list->ea.name);
715 :
716 3851 : canonicalize_ea_name(fsp, unix_ea_name);
717 :
718 3851 : DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
719 :
720 3851 : if (samba_private_attr_name(unix_ea_name)) {
721 0 : DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
722 0 : return NT_STATUS_ACCESS_DENIED;
723 : }
724 :
725 3851 : if (ea_list->ea.value.length == 0) {
726 : /* Remove the attribute. */
727 1060 : DBG_DEBUG("deleting ea name %s on "
728 : "file %s by file descriptor.\n",
729 : unix_ea_name, fsp_str_dbg(fsp));
730 1060 : ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
731 : #ifdef ENOATTR
732 : /* Removing a non existent attribute always succeeds. */
733 1060 : if (ret == -1 && errno == ENOATTR) {
734 5 : DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
735 : unix_ea_name));
736 4 : ret = 0;
737 : }
738 : #endif
739 : } else {
740 2791 : DEBUG(10,("set_ea: setting ea name %s on file "
741 : "%s by file descriptor.\n",
742 : unix_ea_name, fsp_str_dbg(fsp)));
743 2791 : ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
744 : ea_list->ea.value.data, ea_list->ea.value.length, 0);
745 : }
746 :
747 3850 : if (ret == -1) {
748 : #ifdef ENOTSUP
749 2 : if (errno == ENOTSUP) {
750 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
751 : }
752 : #endif
753 2 : return map_nt_error_from_unix(errno);
754 : }
755 :
756 : }
757 2960 : return NT_STATUS_OK;
758 : }
759 :
760 : /****************************************************************************
761 : Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
762 : ****************************************************************************/
763 :
764 3032 : struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
765 : {
766 3032 : struct ea_list *ea_list_head = NULL;
767 3032 : size_t offset = 0;
768 3032 : size_t bytes_used = 0;
769 :
770 6818 : while (offset < data_size) {
771 3794 : struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
772 :
773 3794 : if (!eal) {
774 8 : return NULL;
775 : }
776 :
777 3786 : DLIST_ADD_END(ea_list_head, eal);
778 3786 : offset += bytes_used;
779 : }
780 :
781 2516 : return ea_list_head;
782 : }
783 :
784 : /****************************************************************************
785 : Count the total EA size needed.
786 : ****************************************************************************/
787 :
788 166 : static size_t ea_list_size(struct ea_list *ealist)
789 : {
790 28 : fstring dos_ea_name;
791 28 : struct ea_list *listp;
792 166 : size_t ret = 0;
793 :
794 350 : for (listp = ealist; listp; listp = listp->next) {
795 184 : push_ascii_fstring(dos_ea_name, listp->ea.name);
796 184 : ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
797 : }
798 : /* Add on 4 for total length. */
799 166 : if (ret) {
800 166 : ret += 4;
801 : }
802 :
803 166 : return ret;
804 : }
805 :
806 : /****************************************************************************
807 : Return a union of EA's from a file list and a list of names.
808 : The TALLOC context for the two lists *MUST* be identical as we steal
809 : memory from one list to add to another. JRA.
810 : ****************************************************************************/
811 :
812 166 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
813 : {
814 28 : struct ea_list *nlistp, *flistp;
815 :
816 350 : for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
817 340 : for (flistp = file_list; flistp; flistp = flistp->next) {
818 263 : if (strequal(nlistp->ea.name, flistp->ea.name)) {
819 88 : break;
820 : }
821 : }
822 :
823 184 : if (flistp) {
824 : /* Copy the data from this entry. */
825 107 : nlistp->ea.flags = flistp->ea.flags;
826 107 : nlistp->ea.value = flistp->ea.value;
827 : } else {
828 : /* Null entry. */
829 77 : nlistp->ea.flags = 0;
830 77 : ZERO_STRUCT(nlistp->ea.value);
831 : }
832 : }
833 :
834 166 : *total_ea_len = ea_list_size(name_list);
835 166 : return name_list;
836 : }
837 :
838 : /****************************************************************************
839 : Return the filetype for UNIX extensions.
840 : ****************************************************************************/
841 :
842 576 : static uint32_t unix_filetype(mode_t mode)
843 : {
844 576 : if(S_ISREG(mode))
845 280 : return UNIX_TYPE_FILE;
846 296 : else if(S_ISDIR(mode))
847 80 : return UNIX_TYPE_DIR;
848 : #ifdef S_ISLNK
849 216 : else if(S_ISLNK(mode))
850 208 : return UNIX_TYPE_SYMLINK;
851 : #endif
852 : #ifdef S_ISCHR
853 8 : else if(S_ISCHR(mode))
854 0 : return UNIX_TYPE_CHARDEV;
855 : #endif
856 : #ifdef S_ISBLK
857 8 : else if(S_ISBLK(mode))
858 0 : return UNIX_TYPE_BLKDEV;
859 : #endif
860 : #ifdef S_ISFIFO
861 8 : else if(S_ISFIFO(mode))
862 4 : return UNIX_TYPE_FIFO;
863 : #endif
864 : #ifdef S_ISSOCK
865 4 : else if(S_ISSOCK(mode))
866 4 : return UNIX_TYPE_SOCKET;
867 : #endif
868 :
869 0 : DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
870 0 : return UNIX_TYPE_UNKNOWN;
871 : }
872 :
873 : /****************************************************************************
874 : Map wire perms onto standard UNIX permissions. Obey share restrictions.
875 : ****************************************************************************/
876 :
877 3084 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
878 : const SMB_STRUCT_STAT *psbuf,
879 : uint32_t perms,
880 : enum perm_type ptype,
881 : mode_t *ret_perms)
882 : {
883 3084 : mode_t ret = 0;
884 :
885 3084 : if (perms == SMB_MODE_NO_CHANGE) {
886 132 : if (!VALID_STAT(*psbuf)) {
887 0 : return NT_STATUS_INVALID_PARAMETER;
888 : } else {
889 132 : *ret_perms = psbuf->st_ex_mode;
890 132 : return NT_STATUS_OK;
891 : }
892 : }
893 :
894 2952 : ret = wire_perms_to_unix(perms);
895 :
896 2952 : if (ptype == PERM_NEW_FILE) {
897 : /*
898 : * "create mask"/"force create mode" are
899 : * only applied to new files, not existing ones.
900 : */
901 2171 : ret &= lp_create_mask(SNUM(conn));
902 : /* Add in force bits */
903 2171 : ret |= lp_force_create_mode(SNUM(conn));
904 781 : } else if (ptype == PERM_NEW_DIR) {
905 : /*
906 : * "directory mask"/"force directory mode" are
907 : * only applied to new directories, not existing ones.
908 : */
909 701 : ret &= lp_directory_mask(SNUM(conn));
910 : /* Add in force bits */
911 701 : ret |= lp_force_directory_mode(SNUM(conn));
912 : }
913 :
914 2952 : *ret_perms = ret;
915 2952 : return NT_STATUS_OK;
916 : }
917 :
918 : /****************************************************************************
919 : Get a level dependent lanman2 dir entry.
920 : ****************************************************************************/
921 :
922 : struct smbd_dirptr_lanman2_state {
923 : connection_struct *conn;
924 : uint32_t info_level;
925 : bool check_mangled_names;
926 : bool case_sensitive;
927 : };
928 :
929 907924 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
930 : void *private_data,
931 : const char *dname,
932 : const char *mask,
933 : char **_fname)
934 : {
935 907924 : struct smbd_dirptr_lanman2_state *state =
936 : (struct smbd_dirptr_lanman2_state *)private_data;
937 315 : bool ok;
938 315 : char mangled_name[13]; /* mangled 8.3 name. */
939 315 : bool got_match;
940 315 : const char *fname;
941 :
942 : /* Mangle fname if it's an illegal name. */
943 907924 : if (mangle_must_mangle(dname, state->conn->params)) {
944 : /*
945 : * Slow path - ensure we can push the original name as UCS2. If
946 : * not, then just don't return this name.
947 : */
948 0 : NTSTATUS status;
949 114 : size_t ret_len = 0;
950 114 : size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
951 114 : uint8_t *tmp = talloc_array(talloc_tos(),
952 : uint8_t,
953 : len);
954 :
955 114 : status = srvstr_push(NULL,
956 : FLAGS2_UNICODE_STRINGS,
957 : tmp,
958 : dname,
959 : len,
960 : STR_TERMINATE,
961 : &ret_len);
962 :
963 114 : TALLOC_FREE(tmp);
964 :
965 114 : if (!NT_STATUS_IS_OK(status)) {
966 40 : return false;
967 : }
968 :
969 74 : ok = name_to_8_3(dname, mangled_name,
970 74 : true, state->conn->params);
971 74 : if (!ok) {
972 0 : return false;
973 : }
974 74 : fname = mangled_name;
975 : } else {
976 907495 : fname = dname;
977 : }
978 :
979 908199 : got_match = mask_match(fname, mask,
980 907884 : state->case_sensitive);
981 :
982 907884 : if(!got_match && state->check_mangled_names &&
983 5725 : !mangle_is_8_3(fname, false, state->conn->params)) {
984 : /*
985 : * It turns out that NT matches wildcards against
986 : * both long *and* short names. This may explain some
987 : * of the wildcard weirdness from old DOS clients
988 : * that some people have been seeing.... JRA.
989 : */
990 : /* Force the mangling into 8.3. */
991 3334 : ok = name_to_8_3(fname, mangled_name,
992 3334 : false, state->conn->params);
993 3334 : if (!ok) {
994 0 : return false;
995 : }
996 :
997 3334 : got_match = mask_match(mangled_name, mask,
998 3334 : state->case_sensitive);
999 : }
1000 :
1001 907884 : if (!got_match) {
1002 5721 : return false;
1003 : }
1004 :
1005 902163 : *_fname = talloc_strdup(ctx, fname);
1006 902163 : if (*_fname == NULL) {
1007 0 : return false;
1008 : }
1009 :
1010 901848 : return true;
1011 : }
1012 :
1013 866108 : static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1014 : void *private_data,
1015 : struct files_struct *dirfsp,
1016 : struct smb_filename *smb_fname,
1017 : bool get_dosmode,
1018 : uint32_t *_mode)
1019 : {
1020 866108 : if (get_dosmode) {
1021 846012 : SMB_ASSERT(smb_fname != NULL);
1022 846012 : *_mode = fdos_mode(smb_fname->fsp);
1023 846012 : if (smb_fname->fsp != NULL) {
1024 846012 : smb_fname->st = smb_fname->fsp->fsp_name->st;
1025 : }
1026 : }
1027 866108 : return true;
1028 : }
1029 :
1030 624837 : static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1031 : {
1032 624837 : if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1033 624467 : unsigned ea_size = estimate_ea_size(fsp);
1034 624467 : return ea_size;
1035 : }
1036 370 : return IO_REPARSE_TAG_DFS;
1037 : }
1038 :
1039 893594 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1040 : connection_struct *conn,
1041 : uint16_t flags2,
1042 : uint32_t info_level,
1043 : struct ea_list *name_list,
1044 : bool check_mangled_names,
1045 : bool requires_resume_key,
1046 : uint32_t mode,
1047 : const char *fname,
1048 : const struct smb_filename *smb_fname,
1049 : int space_remaining,
1050 : uint8_t align,
1051 : bool do_pad,
1052 : char *base_data,
1053 : char **ppdata,
1054 : char *end_data,
1055 : uint64_t *last_entry_off)
1056 : {
1057 893594 : char *p, *q, *pdata = *ppdata;
1058 893594 : uint32_t reskey=0;
1059 893594 : uint64_t file_size = 0;
1060 893594 : uint64_t allocation_size = 0;
1061 893594 : uint64_t file_id = 0;
1062 893594 : size_t len = 0;
1063 893594 : struct timespec mdate_ts = {0};
1064 893594 : struct timespec adate_ts = {0};
1065 893594 : struct timespec cdate_ts = {0};
1066 893594 : struct timespec create_date_ts = {0};
1067 893594 : time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1068 227 : char *nameptr;
1069 227 : char *last_entry_ptr;
1070 227 : bool was_8_3;
1071 227 : int off;
1072 893594 : int pad = 0;
1073 227 : NTSTATUS status;
1074 893594 : struct readdir_attr_data *readdir_attr_data = NULL;
1075 227 : uint32_t ea_size;
1076 :
1077 893594 : if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1078 833293 : file_size = get_file_size_stat(&smb_fname->st);
1079 : }
1080 893594 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1081 :
1082 : /*
1083 : * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1084 : * a DFS symlink.
1085 : */
1086 893594 : if (smb_fname->fsp != NULL &&
1087 892945 : !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1088 893172 : status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1089 : ctx,
1090 : &readdir_attr_data);
1091 893172 : if (!NT_STATUS_IS_OK(status)) {
1092 892868 : if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1093 : status)) {
1094 0 : return status;
1095 : }
1096 : }
1097 : }
1098 :
1099 893594 : file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1100 :
1101 893594 : mdate_ts = smb_fname->st.st_ex_mtime;
1102 893594 : adate_ts = smb_fname->st.st_ex_atime;
1103 893594 : create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1104 893594 : cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1105 :
1106 893594 : if (lp_dos_filetime_resolution(SNUM(conn))) {
1107 0 : dos_filetime_timespec(&create_date_ts);
1108 0 : dos_filetime_timespec(&mdate_ts);
1109 0 : dos_filetime_timespec(&adate_ts);
1110 0 : dos_filetime_timespec(&cdate_ts);
1111 : }
1112 :
1113 893594 : create_date = convert_timespec_to_time_t(create_date_ts);
1114 893594 : mdate = convert_timespec_to_time_t(mdate_ts);
1115 893594 : adate = convert_timespec_to_time_t(adate_ts);
1116 :
1117 : /* align the record */
1118 893594 : SMB_ASSERT(align >= 1);
1119 :
1120 893594 : off = (int)PTR_DIFF(pdata, base_data);
1121 893594 : pad = (off + (align-1)) & ~(align-1);
1122 893594 : pad -= off;
1123 :
1124 893594 : if (pad && pad > space_remaining) {
1125 0 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1126 : "for padding (wanted %u, had %d)\n",
1127 : (unsigned int)pad,
1128 : space_remaining ));
1129 0 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1130 : }
1131 :
1132 893594 : off += pad;
1133 : /* initialize padding to 0 */
1134 893594 : if (pad) {
1135 642860 : memset(pdata, 0, pad);
1136 : }
1137 893594 : space_remaining -= pad;
1138 :
1139 893594 : DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1140 : space_remaining ));
1141 :
1142 893594 : pdata += pad;
1143 893594 : p = pdata;
1144 893594 : last_entry_ptr = p;
1145 :
1146 893594 : pad = 0;
1147 893594 : off = 0;
1148 :
1149 893594 : switch (info_level) {
1150 8406 : case SMB_FIND_INFO_STANDARD:
1151 8406 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1152 8406 : if(requires_resume_key) {
1153 0 : SIVAL(p,0,reskey);
1154 0 : p += 4;
1155 : }
1156 8406 : srv_put_dos_date2(p,0,create_date);
1157 8406 : srv_put_dos_date2(p,4,adate);
1158 8406 : srv_put_dos_date2(p,8,mdate);
1159 8406 : SIVAL(p,12,(uint32_t)file_size);
1160 8406 : SIVAL(p,16,(uint32_t)allocation_size);
1161 8406 : SSVAL(p,20,mode);
1162 8406 : p += 23;
1163 8406 : nameptr = p;
1164 8406 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1165 8406 : p += ucs2_align(base_data, p, 0);
1166 : }
1167 8406 : status = srvstr_push(base_data, flags2, p,
1168 : fname, PTR_DIFF(end_data, p),
1169 : STR_TERMINATE, &len);
1170 8406 : if (!NT_STATUS_IS_OK(status)) {
1171 40 : return status;
1172 : }
1173 8406 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1174 8406 : if (len > 2) {
1175 8406 : SCVAL(nameptr, -1, len - 2);
1176 : } else {
1177 0 : SCVAL(nameptr, -1, 0);
1178 : }
1179 : } else {
1180 0 : if (len > 1) {
1181 0 : SCVAL(nameptr, -1, len - 1);
1182 : } else {
1183 0 : SCVAL(nameptr, -1, 0);
1184 : }
1185 : }
1186 8406 : p += len;
1187 8406 : break;
1188 :
1189 106206 : case SMB_FIND_EA_SIZE:
1190 106206 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1191 106206 : if (requires_resume_key) {
1192 97800 : SIVAL(p,0,reskey);
1193 97800 : p += 4;
1194 : }
1195 106206 : srv_put_dos_date2(p,0,create_date);
1196 106206 : srv_put_dos_date2(p,4,adate);
1197 106206 : srv_put_dos_date2(p,8,mdate);
1198 106206 : SIVAL(p,12,(uint32_t)file_size);
1199 106206 : SIVAL(p,16,(uint32_t)allocation_size);
1200 106206 : SSVAL(p,20,mode);
1201 : {
1202 106206 : ea_size = estimate_ea_size(smb_fname->fsp);
1203 106206 : SIVAL(p,22,ea_size); /* Extended attributes */
1204 : }
1205 106206 : p += 27;
1206 106206 : nameptr = p - 1;
1207 106206 : status = srvstr_push(base_data, flags2,
1208 : p, fname, PTR_DIFF(end_data, p),
1209 : STR_TERMINATE | STR_NOALIGN, &len);
1210 106206 : if (!NT_STATUS_IS_OK(status)) {
1211 0 : return status;
1212 : }
1213 106206 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1214 106206 : if (len > 2) {
1215 106206 : len -= 2;
1216 : } else {
1217 0 : len = 0;
1218 : }
1219 : } else {
1220 0 : if (len > 1) {
1221 0 : len -= 1;
1222 : } else {
1223 0 : len = 0;
1224 : }
1225 : }
1226 106206 : SCVAL(nameptr,0,len);
1227 106206 : p += len;
1228 106206 : SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1229 106206 : break;
1230 :
1231 18 : case SMB_FIND_EA_LIST:
1232 : {
1233 18 : struct ea_list *file_list = NULL;
1234 18 : size_t ea_len = 0;
1235 :
1236 18 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1237 18 : if (!name_list) {
1238 0 : return NT_STATUS_INVALID_PARAMETER;
1239 : }
1240 18 : if (requires_resume_key) {
1241 18 : SIVAL(p,0,reskey);
1242 18 : p += 4;
1243 : }
1244 18 : srv_put_dos_date2(p,0,create_date);
1245 18 : srv_put_dos_date2(p,4,adate);
1246 18 : srv_put_dos_date2(p,8,mdate);
1247 18 : SIVAL(p,12,(uint32_t)file_size);
1248 18 : SIVAL(p,16,(uint32_t)allocation_size);
1249 18 : SSVAL(p,20,mode);
1250 18 : p += 22; /* p now points to the EA area. */
1251 :
1252 18 : status = get_ea_list_from_fsp(ctx,
1253 18 : smb_fname->fsp,
1254 : &ea_len, &file_list);
1255 18 : if (!NT_STATUS_IS_OK(status)) {
1256 0 : file_list = NULL;
1257 : }
1258 18 : name_list = ea_list_union(name_list, file_list, &ea_len);
1259 :
1260 : /* We need to determine if this entry will fit in the space available. */
1261 : /* Max string size is 255 bytes. */
1262 18 : if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1263 0 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1264 : "(wanted %u, had %d)\n",
1265 : (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1266 : space_remaining ));
1267 0 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1268 : }
1269 :
1270 : /* Push the ea_data followed by the name. */
1271 18 : p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1272 18 : nameptr = p;
1273 18 : status = srvstr_push(base_data, flags2,
1274 : p + 1, fname, PTR_DIFF(end_data, p+1),
1275 : STR_TERMINATE | STR_NOALIGN, &len);
1276 18 : if (!NT_STATUS_IS_OK(status)) {
1277 0 : return status;
1278 : }
1279 18 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
1280 18 : if (len > 2) {
1281 18 : len -= 2;
1282 : } else {
1283 0 : len = 0;
1284 : }
1285 : } else {
1286 0 : if (len > 1) {
1287 0 : len -= 1;
1288 : } else {
1289 0 : len = 0;
1290 : }
1291 : }
1292 18 : SCVAL(nameptr,0,len);
1293 18 : p += len + 1;
1294 18 : SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1295 18 : break;
1296 : }
1297 :
1298 113671 : case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1299 113671 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1300 113671 : was_8_3 = mangle_is_8_3(fname, True, conn->params);
1301 113671 : p += 4;
1302 113671 : SIVAL(p,0,reskey); p += 4;
1303 113671 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1304 113671 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1305 113671 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1306 113671 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1307 113671 : SOFF_T(p,0,file_size); p += 8;
1308 113671 : SOFF_T(p,0,allocation_size); p += 8;
1309 113671 : SIVAL(p,0,mode); p += 4;
1310 113671 : q = p; p += 4; /* q is placeholder for name length. */
1311 113671 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1312 113671 : SIVAL(p, 0, ea_size);
1313 113671 : p += 4;
1314 : /* Clear the short name buffer. This is
1315 : * IMPORTANT as not doing so will trigger
1316 : * a Win2k client bug. JRA.
1317 : */
1318 113671 : if (!was_8_3 && check_mangled_names) {
1319 25 : char mangled_name[13]; /* mangled 8.3 name. */
1320 20051 : if (!name_to_8_3(fname,mangled_name,True,
1321 20051 : conn->params)) {
1322 : /* Error - mangle failed ! */
1323 0 : memset(mangled_name,'\0',12);
1324 : }
1325 20051 : mangled_name[12] = 0;
1326 20051 : status = srvstr_push(base_data, flags2,
1327 : p+2, mangled_name, 24,
1328 : STR_UPPER|STR_UNICODE, &len);
1329 20051 : if (!NT_STATUS_IS_OK(status)) {
1330 0 : return status;
1331 : }
1332 20051 : if (len < 24) {
1333 10862 : memset(p + 2 + len,'\0',24 - len);
1334 : }
1335 20051 : SSVAL(p, 0, len);
1336 : } else {
1337 93620 : memset(p,'\0',26);
1338 : }
1339 113671 : p += 2 + 24;
1340 113671 : status = srvstr_push(base_data, flags2, p,
1341 : fname, PTR_DIFF(end_data, p),
1342 : STR_TERMINATE_ASCII, &len);
1343 113671 : if (!NT_STATUS_IS_OK(status)) {
1344 12 : return status;
1345 : }
1346 113659 : SIVAL(q,0,len);
1347 113659 : p += len;
1348 :
1349 113659 : len = PTR_DIFF(p, pdata);
1350 113659 : pad = (len + (align-1)) & ~(align-1);
1351 : /*
1352 : * offset to the next entry, the caller
1353 : * will overwrite it for the last entry
1354 : * that's why we always include the padding
1355 : */
1356 113659 : SIVAL(pdata,0,pad);
1357 : /*
1358 : * set padding to zero
1359 : */
1360 113659 : if (do_pad) {
1361 50071 : memset(p, 0, pad - len);
1362 50071 : p = pdata + pad;
1363 : } else {
1364 63588 : p = pdata + len;
1365 : }
1366 113525 : break;
1367 :
1368 20686 : case SMB_FIND_FILE_DIRECTORY_INFO:
1369 20686 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1370 20686 : p += 4;
1371 20686 : SIVAL(p,0,reskey); p += 4;
1372 20686 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1373 20686 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1374 20686 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1375 20686 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1376 20686 : SOFF_T(p,0,file_size); p += 8;
1377 20686 : SOFF_T(p,0,allocation_size); p += 8;
1378 20686 : SIVAL(p,0,mode); p += 4;
1379 20686 : status = srvstr_push(base_data, flags2,
1380 : p + 4, fname, PTR_DIFF(end_data, p+4),
1381 : STR_TERMINATE_ASCII, &len);
1382 20686 : if (!NT_STATUS_IS_OK(status)) {
1383 0 : return status;
1384 : }
1385 20686 : SIVAL(p,0,len);
1386 20686 : p += 4 + len;
1387 :
1388 20686 : len = PTR_DIFF(p, pdata);
1389 20686 : pad = (len + (align-1)) & ~(align-1);
1390 : /*
1391 : * offset to the next entry, the caller
1392 : * will overwrite it for the last entry
1393 : * that's why we always include the padding
1394 : */
1395 20686 : SIVAL(pdata,0,pad);
1396 : /*
1397 : * set padding to zero
1398 : */
1399 20686 : if (do_pad) {
1400 8406 : memset(p, 0, pad - len);
1401 8406 : p = pdata + pad;
1402 : } else {
1403 12280 : p = pdata + len;
1404 : }
1405 20686 : break;
1406 :
1407 420921 : case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1408 420921 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1409 420921 : p += 4;
1410 420921 : SIVAL(p,0,reskey); p += 4;
1411 420921 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1412 420921 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1413 420921 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1414 420921 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1415 420921 : SOFF_T(p,0,file_size); p += 8;
1416 420921 : SOFF_T(p,0,allocation_size); p += 8;
1417 420921 : SIVAL(p,0,mode); p += 4;
1418 420921 : q = p; p += 4; /* q is placeholder for name length. */
1419 420921 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1420 420921 : SIVAL(p, 0, ea_size);
1421 420921 : p +=4;
1422 420921 : status = srvstr_push(base_data, flags2, p,
1423 : fname, PTR_DIFF(end_data, p),
1424 : STR_TERMINATE_ASCII, &len);
1425 420921 : if (!NT_STATUS_IS_OK(status)) {
1426 0 : return status;
1427 : }
1428 420921 : SIVAL(q, 0, len);
1429 420921 : p += len;
1430 :
1431 420921 : len = PTR_DIFF(p, pdata);
1432 420921 : pad = (len + (align-1)) & ~(align-1);
1433 : /*
1434 : * offset to the next entry, the caller
1435 : * will overwrite it for the last entry
1436 : * that's why we always include the padding
1437 : */
1438 420921 : SIVAL(pdata,0,pad);
1439 : /*
1440 : * set padding to zero
1441 : */
1442 420921 : if (do_pad) {
1443 8841 : memset(p, 0, pad - len);
1444 8841 : p = pdata + pad;
1445 : } else {
1446 412080 : p = pdata + len;
1447 : }
1448 420834 : break;
1449 :
1450 131905 : case SMB_FIND_FILE_NAMES_INFO:
1451 131905 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1452 131905 : p += 4;
1453 131905 : SIVAL(p,0,reskey); p += 4;
1454 131905 : p += 4;
1455 : /* this must *not* be null terminated or w2k gets in a loop trying to set an
1456 : acl on a dir (tridge) */
1457 131905 : status = srvstr_push(base_data, flags2, p,
1458 : fname, PTR_DIFF(end_data, p),
1459 : STR_TERMINATE_ASCII, &len);
1460 131905 : if (!NT_STATUS_IS_OK(status)) {
1461 0 : return status;
1462 : }
1463 131905 : SIVAL(p, -4, len);
1464 131905 : p += len;
1465 :
1466 131905 : len = PTR_DIFF(p, pdata);
1467 131905 : pad = (len + (align-1)) & ~(align-1);
1468 : /*
1469 : * offset to the next entry, the caller
1470 : * will overwrite it for the last entry
1471 : * that's why we always include the padding
1472 : */
1473 131905 : SIVAL(pdata,0,pad);
1474 : /*
1475 : * set padding to zero
1476 : */
1477 131905 : if (do_pad) {
1478 6 : memset(p, 0, pad - len);
1479 6 : p = pdata + pad;
1480 : } else {
1481 131899 : p = pdata + len;
1482 : }
1483 131899 : break;
1484 :
1485 19638 : case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1486 19638 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1487 19638 : p += 4;
1488 19638 : SIVAL(p,0,reskey); p += 4;
1489 19638 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1490 19638 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1491 19638 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1492 19638 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1493 19638 : SOFF_T(p,0,file_size); p += 8;
1494 19638 : SOFF_T(p,0,allocation_size); p += 8;
1495 19638 : SIVAL(p,0,mode); p += 4;
1496 19638 : q = p; p += 4; /* q is placeholder for name length. */
1497 19638 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1498 19638 : SIVAL(p, 0, ea_size);
1499 19638 : p += 4;
1500 19638 : SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1501 19638 : SBVAL(p,0,file_id); p += 8;
1502 19638 : status = srvstr_push(base_data, flags2, p,
1503 : fname, PTR_DIFF(end_data, p),
1504 : STR_TERMINATE_ASCII, &len);
1505 19638 : if (!NT_STATUS_IS_OK(status)) {
1506 0 : return status;
1507 : }
1508 19638 : SIVAL(q, 0, len);
1509 19638 : p += len;
1510 :
1511 19638 : len = PTR_DIFF(p, pdata);
1512 19638 : pad = (len + (align-1)) & ~(align-1);
1513 : /*
1514 : * offset to the next entry, the caller
1515 : * will overwrite it for the last entry
1516 : * that's why we always include the padding
1517 : */
1518 19638 : SIVAL(pdata,0,pad);
1519 : /*
1520 : * set padding to zero
1521 : */
1522 19638 : if (do_pad) {
1523 8406 : memset(p, 0, pad - len);
1524 8406 : p = pdata + pad;
1525 : } else {
1526 11232 : p = pdata + len;
1527 : }
1528 19638 : break;
1529 :
1530 70705 : case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1531 70705 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1532 70705 : was_8_3 = mangle_is_8_3(fname, True, conn->params);
1533 70705 : p += 4;
1534 70705 : SIVAL(p,0,reskey); p += 4;
1535 70705 : put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1536 70705 : put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1537 70705 : put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1538 70705 : put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1539 70705 : SOFF_T(p,0,file_size); p += 8;
1540 70705 : SOFF_T(p,0,allocation_size); p += 8;
1541 70705 : SIVAL(p,0,mode); p += 4;
1542 70705 : q = p; p += 4; /* q is placeholder for name length */
1543 70705 : if (readdir_attr_data &&
1544 98 : readdir_attr_data->type == RDATTR_AAPL) {
1545 : /*
1546 : * OS X specific SMB2 extension negotiated via
1547 : * AAPL create context: return max_access in
1548 : * ea_size field.
1549 : */
1550 98 : ea_size = readdir_attr_data->attr_data.aapl.max_access;
1551 : } else {
1552 70607 : ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1553 : }
1554 70705 : SIVAL(p,0,ea_size); /* Extended attributes */
1555 70705 : p += 4;
1556 :
1557 70705 : if (readdir_attr_data &&
1558 98 : readdir_attr_data->type == RDATTR_AAPL) {
1559 : /*
1560 : * OS X specific SMB2 extension negotiated via
1561 : * AAPL create context: return resource fork
1562 : * length and compressed FinderInfo in
1563 : * shortname field.
1564 : *
1565 : * According to documentation short_name_len
1566 : * should be 0, but on the wire behaviour
1567 : * shows its set to 24 by clients.
1568 : */
1569 98 : SSVAL(p, 0, 24);
1570 :
1571 : /* Resourefork length */
1572 98 : SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1573 :
1574 : /* Compressed FinderInfo */
1575 98 : memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1576 70607 : } else if (!was_8_3 && check_mangled_names) {
1577 0 : char mangled_name[13]; /* mangled 8.3 name. */
1578 22021 : if (!name_to_8_3(fname,mangled_name,True,
1579 22021 : conn->params)) {
1580 : /* Error - mangle failed ! */
1581 0 : memset(mangled_name,'\0',12);
1582 : }
1583 22021 : mangled_name[12] = 0;
1584 22021 : status = srvstr_push(base_data, flags2,
1585 : p+2, mangled_name, 24,
1586 : STR_UPPER|STR_UNICODE, &len);
1587 22021 : if (!NT_STATUS_IS_OK(status)) {
1588 0 : return status;
1589 : }
1590 22021 : SSVAL(p, 0, len);
1591 22021 : if (len < 24) {
1592 20385 : memset(p + 2 + len,'\0',24 - len);
1593 : }
1594 22021 : SSVAL(p, 0, len);
1595 : } else {
1596 : /* Clear the short name buffer. This is
1597 : * IMPORTANT as not doing so will trigger
1598 : * a Win2k client bug. JRA.
1599 : */
1600 48586 : memset(p,'\0',26);
1601 : }
1602 70705 : p += 26;
1603 :
1604 : /* Reserved ? */
1605 70705 : if (readdir_attr_data &&
1606 98 : readdir_attr_data->type == RDATTR_AAPL) {
1607 : /*
1608 : * OS X specific SMB2 extension negotiated via
1609 : * AAPL create context: return UNIX mode in
1610 : * reserved field.
1611 : */
1612 98 : uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1613 98 : SSVAL(p, 0, aapl_mode);
1614 : } else {
1615 70607 : SSVAL(p, 0, 0);
1616 : }
1617 70705 : p += 2;
1618 :
1619 70705 : SBVAL(p,0,file_id); p += 8;
1620 70705 : status = srvstr_push(base_data, flags2, p,
1621 : fname, PTR_DIFF(end_data, p),
1622 : STR_TERMINATE_ASCII, &len);
1623 70705 : if (!NT_STATUS_IS_OK(status)) {
1624 28 : return status;
1625 : }
1626 70677 : SIVAL(q,0,len);
1627 70677 : p += len;
1628 :
1629 70677 : len = PTR_DIFF(p, pdata);
1630 70677 : pad = (len + (align-1)) & ~(align-1);
1631 : /*
1632 : * offset to the next entry, the caller
1633 : * will overwrite it for the last entry
1634 : * that's why we always include the padding
1635 : */
1636 70677 : SIVAL(pdata,0,pad);
1637 : /*
1638 : * set padding to zero
1639 : */
1640 70677 : if (do_pad) {
1641 8406 : memset(p, 0, pad - len);
1642 8406 : p = pdata + pad;
1643 : } else {
1644 62271 : p = pdata + len;
1645 : }
1646 70677 : break;
1647 :
1648 : /* CIFS UNIX Extension. */
1649 :
1650 10 : case SMB_FIND_FILE_UNIX:
1651 : case SMB_FIND_FILE_UNIX_INFO2:
1652 10 : p+= 4;
1653 10 : SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1654 :
1655 : /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1656 :
1657 10 : if (info_level == SMB_FIND_FILE_UNIX) {
1658 6 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1659 6 : p = store_file_unix_basic(conn, p,
1660 : NULL, &smb_fname->st);
1661 6 : status = srvstr_push(base_data, flags2, p,
1662 : fname, PTR_DIFF(end_data, p),
1663 : STR_TERMINATE, &len);
1664 6 : if (!NT_STATUS_IS_OK(status)) {
1665 0 : return status;
1666 : }
1667 : } else {
1668 4 : DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1669 4 : p = store_file_unix_basic_info2(conn, p,
1670 : NULL, &smb_fname->st);
1671 4 : nameptr = p;
1672 4 : p += 4;
1673 4 : status = srvstr_push(base_data, flags2, p, fname,
1674 : PTR_DIFF(end_data, p), 0, &len);
1675 4 : if (!NT_STATUS_IS_OK(status)) {
1676 0 : return status;
1677 : }
1678 4 : SIVAL(nameptr, 0, len);
1679 : }
1680 :
1681 10 : p += len;
1682 :
1683 10 : len = PTR_DIFF(p, pdata);
1684 10 : pad = (len + (align-1)) & ~(align-1);
1685 : /*
1686 : * offset to the next entry, the caller
1687 : * will overwrite it for the last entry
1688 : * that's why we always include the padding
1689 : */
1690 10 : SIVAL(pdata,0,pad);
1691 : /*
1692 : * set padding to zero
1693 : */
1694 10 : if (do_pad) {
1695 10 : memset(p, 0, pad - len);
1696 10 : p = pdata + pad;
1697 : } else {
1698 0 : p = pdata + len;
1699 : }
1700 : /* End of SMB_QUERY_FILE_UNIX_BASIC */
1701 :
1702 10 : break;
1703 :
1704 : /* SMB2 UNIX Extension. */
1705 :
1706 1428 : case SMB2_FILE_POSIX_INFORMATION:
1707 : {
1708 1428 : struct smb3_file_posix_information info = {};
1709 0 : uint8_t buf[sizeof(info)];
1710 1428 : struct ndr_push ndr = {
1711 : .data = buf,
1712 : .alloc_size = sizeof(buf),
1713 : .fixed_buf_size = true,
1714 : };
1715 0 : enum ndr_err_code ndr_err;
1716 :
1717 1428 : p+= 4;
1718 1428 : SIVAL(p,0,reskey); p+= 4;
1719 :
1720 1428 : DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1721 :
1722 1428 : if (!(conn->sconn->using_smb2)) {
1723 0 : return NT_STATUS_INVALID_LEVEL;
1724 : }
1725 :
1726 1428 : smb3_file_posix_information_init(
1727 1428 : conn, &smb_fname->st, 0, mode, &info);
1728 :
1729 1428 : ndr_err = ndr_push_smb3_file_posix_information(
1730 : &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1731 1428 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1732 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1733 : }
1734 :
1735 1428 : memcpy(p, buf, ndr.offset);
1736 1428 : p += ndr.offset;
1737 :
1738 1428 : nameptr = p;
1739 1428 : p += 4;
1740 1428 : status = srvstr_push(base_data, flags2, p, fname,
1741 : PTR_DIFF(end_data, p), 0, &len);
1742 1428 : if (!NT_STATUS_IS_OK(status)) {
1743 0 : return status;
1744 : }
1745 1428 : SIVAL(nameptr, 0, len);
1746 :
1747 1428 : p += len;
1748 :
1749 1428 : len = PTR_DIFF(p, pdata);
1750 1428 : pad = (len + (align-1)) & ~(align-1);
1751 : /*
1752 : * offset to the next entry, the caller
1753 : * will overwrite it for the last entry
1754 : * that's why we always include the padding
1755 : */
1756 1428 : SIVAL(pdata,0,pad);
1757 1428 : break;
1758 : }
1759 :
1760 0 : default:
1761 0 : return NT_STATUS_INVALID_LEVEL;
1762 : }
1763 :
1764 893554 : if (PTR_DIFF(p,pdata) > space_remaining) {
1765 668 : DEBUG(9,("smbd_marshall_dir_entry: out of space "
1766 : "(wanted %u, had %d)\n",
1767 : (unsigned int)PTR_DIFF(p,pdata),
1768 : space_remaining ));
1769 668 : return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1770 : }
1771 :
1772 : /* Setup the last entry pointer, as an offset from base_data */
1773 892886 : *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1774 : /* Advance the data pointer to the next slot */
1775 892886 : *ppdata = p;
1776 :
1777 892886 : return NT_STATUS_OK;
1778 : }
1779 :
1780 920832 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1781 : connection_struct *conn,
1782 : struct dptr_struct *dirptr,
1783 : uint16_t flags2,
1784 : const char *path_mask,
1785 : uint32_t dirtype,
1786 : int info_level,
1787 : int requires_resume_key,
1788 : bool dont_descend,
1789 : bool ask_sharemode,
1790 : bool get_dosmode,
1791 : uint8_t align,
1792 : bool do_pad,
1793 : char **ppdata,
1794 : char *base_data,
1795 : char *end_data,
1796 : int space_remaining,
1797 : struct smb_filename **_smb_fname,
1798 : int *_last_entry_off,
1799 : struct ea_list *name_list,
1800 : struct file_id *file_id)
1801 : {
1802 316 : const char *p;
1803 920832 : const char *mask = NULL;
1804 920832 : uint32_t mode = 0;
1805 920832 : char *fname = NULL;
1806 920832 : struct smb_filename *smb_fname = NULL;
1807 316 : struct smbd_dirptr_lanman2_state state;
1808 316 : bool ok;
1809 920832 : uint64_t last_entry_off = 0;
1810 316 : NTSTATUS status;
1811 316 : enum mangled_names_options mangled_names;
1812 316 : bool marshall_with_83_names;
1813 :
1814 920832 : mangled_names = lp_mangled_names(conn->params);
1815 :
1816 920832 : ZERO_STRUCT(state);
1817 920832 : state.conn = conn;
1818 920832 : state.info_level = info_level;
1819 920832 : if (mangled_names != MANGLED_NAMES_NO) {
1820 919240 : state.check_mangled_names = true;
1821 : }
1822 920832 : state.case_sensitive = dptr_case_sensitive(dirptr);
1823 :
1824 920832 : p = strrchr_m(path_mask,'/');
1825 920832 : if(p != NULL) {
1826 0 : if(p[1] == '\0') {
1827 0 : mask = "*.*";
1828 : } else {
1829 0 : mask = p+1;
1830 : }
1831 : } else {
1832 920516 : mask = path_mask;
1833 : }
1834 :
1835 920832 : ok = smbd_dirptr_get_entry(ctx,
1836 : dirptr,
1837 : mask,
1838 : dirtype,
1839 : dont_descend,
1840 : ask_sharemode,
1841 : get_dosmode,
1842 : smbd_dirptr_lanman2_match_fn,
1843 : smbd_dirptr_lanman2_mode_fn,
1844 : &state,
1845 : &fname,
1846 : &smb_fname,
1847 : &mode);
1848 920832 : if (!ok) {
1849 27238 : return NT_STATUS_END_OF_FILE;
1850 : }
1851 :
1852 893594 : marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1853 :
1854 893594 : status = smbd_marshall_dir_entry(ctx,
1855 : conn,
1856 : flags2,
1857 : info_level,
1858 : name_list,
1859 : marshall_with_83_names,
1860 : requires_resume_key,
1861 : mode,
1862 : fname,
1863 : smb_fname,
1864 : space_remaining,
1865 : align,
1866 : do_pad,
1867 : base_data,
1868 : ppdata,
1869 : end_data,
1870 : &last_entry_off);
1871 893594 : if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1872 40 : DEBUG(1,("Conversion error: illegal character: %s\n",
1873 : smb_fname_str_dbg(smb_fname)));
1874 : }
1875 :
1876 893594 : if (file_id != NULL) {
1877 694806 : *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1878 : }
1879 :
1880 893594 : if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1881 668 : smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1882 : }
1883 :
1884 893594 : if (!NT_STATUS_IS_OK(status)) {
1885 708 : TALLOC_FREE(smb_fname);
1886 708 : TALLOC_FREE(fname);
1887 708 : return status;
1888 : }
1889 :
1890 892886 : smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1891 :
1892 892886 : if (_smb_fname != NULL) {
1893 : /*
1894 : * smb_fname is already talloc'ed off ctx.
1895 : * We just need to make sure we don't return
1896 : * any stream_name, and replace base_name
1897 : * with fname in case base_name got mangled.
1898 : * This allows us to preserve any smb_fname->fsp
1899 : * for asynchronous handle lookups.
1900 : */
1901 694110 : TALLOC_FREE(smb_fname->stream_name);
1902 :
1903 : /*
1904 : * smbd_dirptr_set_last_name_sent() above consumed
1905 : * base_name
1906 : */
1907 694110 : smb_fname->base_name = talloc_strdup(smb_fname, fname);
1908 :
1909 694110 : if (smb_fname->base_name == NULL) {
1910 0 : TALLOC_FREE(smb_fname);
1911 0 : TALLOC_FREE(fname);
1912 0 : return NT_STATUS_NO_MEMORY;
1913 : }
1914 694110 : *_smb_fname = smb_fname;
1915 : } else {
1916 198776 : TALLOC_FREE(smb_fname);
1917 : }
1918 892886 : TALLOC_FREE(fname);
1919 :
1920 892886 : *_last_entry_off = last_entry_off;
1921 892886 : return NT_STATUS_OK;
1922 : }
1923 :
1924 112 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1925 : {
1926 0 : const struct loadparm_substitution *lp_sub =
1927 112 : loadparm_s3_global_substitution();
1928 :
1929 112 : E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1930 112 : return objid;
1931 : }
1932 :
1933 40 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
1934 : {
1935 40 : SMB_ASSERT(extended_info != NULL);
1936 :
1937 40 : extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1938 40 : extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1939 : | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1940 : | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1941 : #ifdef SAMBA_VERSION_REVISION
1942 : extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1943 : #endif
1944 40 : extended_info->samba_subversion = 0;
1945 : #ifdef SAMBA_VERSION_RC_RELEASE
1946 : extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1947 : #else
1948 : #ifdef SAMBA_VERSION_PRE_RELEASE
1949 40 : extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1950 : #endif
1951 : #endif
1952 : #ifdef SAMBA_VERSION_VENDOR_PATCH
1953 : extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1954 : #endif
1955 40 : extended_info->samba_gitcommitdate = 0;
1956 : #ifdef SAMBA_VERSION_COMMIT_TIME
1957 : unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1958 : #endif
1959 :
1960 40 : memset(extended_info->samba_version_string, 0,
1961 : sizeof(extended_info->samba_version_string));
1962 :
1963 40 : snprintf (extended_info->samba_version_string,
1964 : sizeof(extended_info->samba_version_string),
1965 : "%s", samba_version_string());
1966 40 : }
1967 :
1968 0 : static bool fsinfo_unix_valid_level(connection_struct *conn,
1969 : uint16_t info_level)
1970 : {
1971 0 : if (conn->sconn->using_smb2 &&
1972 : info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
1973 0 : return true;
1974 : }
1975 : #if defined(SMB1SERVER)
1976 : if (lp_smb1_unix_extensions() &&
1977 : info_level == SMB_QUERY_POSIX_FS_INFO) {
1978 : return true;
1979 : }
1980 : #endif
1981 0 : return false;
1982 : }
1983 :
1984 3418 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1985 : connection_struct *conn,
1986 : TALLOC_CTX *mem_ctx,
1987 : uint16_t info_level,
1988 : uint16_t flags2,
1989 : unsigned int max_data_bytes,
1990 : size_t *fixed_portion,
1991 : struct smb_filename *fname,
1992 : char **ppdata,
1993 : int *ret_data_len)
1994 : {
1995 0 : const struct loadparm_substitution *lp_sub =
1996 3418 : loadparm_s3_global_substitution();
1997 0 : char *pdata, *end_data;
1998 3418 : int data_len = 0;
1999 3418 : size_t len = 0;
2000 3418 : const char *vname = volume_label(talloc_tos(), SNUM(conn));
2001 3418 : int snum = SNUM(conn);
2002 3418 : const char *fstype = lp_fstype(SNUM(conn));
2003 3418 : const char *filename = NULL;
2004 3418 : const uint64_t bytes_per_sector = 512;
2005 3418 : uint32_t additional_flags = 0;
2006 0 : struct smb_filename smb_fname;
2007 0 : SMB_STRUCT_STAT st;
2008 3418 : NTSTATUS status = NT_STATUS_OK;
2009 0 : uint64_t df_ret;
2010 0 : uint32_t serial;
2011 :
2012 3418 : if (fname == NULL || fname->base_name == NULL) {
2013 1369 : filename = ".";
2014 : } else {
2015 2049 : filename = fname->base_name;
2016 : }
2017 :
2018 3418 : if (IS_IPC(conn)) {
2019 240 : if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2020 0 : DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2021 : "info level (0x%x) on IPC$.\n",
2022 : (unsigned int)info_level));
2023 0 : return NT_STATUS_ACCESS_DENIED;
2024 : }
2025 : }
2026 :
2027 3418 : DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2028 :
2029 3418 : smb_fname = (struct smb_filename) {
2030 : .base_name = discard_const_p(char, filename),
2031 3418 : .flags = fname ? fname->flags : 0,
2032 3418 : .twrp = fname ? fname->twrp : 0,
2033 : };
2034 :
2035 3418 : if(info_level != SMB_FS_QUOTA_INFORMATION
2036 3414 : && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2037 0 : DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2038 0 : return map_nt_error_from_unix(errno);
2039 : }
2040 :
2041 3418 : st = smb_fname.st;
2042 :
2043 3418 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2044 0 : return NT_STATUS_INVALID_PARAMETER;
2045 : }
2046 :
2047 3418 : *ppdata = (char *)SMB_REALLOC(
2048 : *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2049 3418 : if (*ppdata == NULL) {
2050 0 : return NT_STATUS_NO_MEMORY;
2051 : }
2052 :
2053 3418 : pdata = *ppdata;
2054 3418 : memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2055 3418 : end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2056 :
2057 3418 : *fixed_portion = 0;
2058 :
2059 3418 : switch (info_level) {
2060 0 : case SMB_INFO_ALLOCATION:
2061 : {
2062 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2063 0 : data_len = 18;
2064 0 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2065 : &dfree, &dsize);
2066 0 : if (df_ret == (uint64_t)-1) {
2067 0 : return map_nt_error_from_unix(errno);
2068 : }
2069 :
2070 0 : block_size = lp_block_size(snum);
2071 0 : if (bsize < block_size) {
2072 0 : uint64_t factor = block_size/bsize;
2073 0 : bsize = block_size;
2074 0 : dsize /= factor;
2075 0 : dfree /= factor;
2076 : }
2077 0 : if (bsize > block_size) {
2078 0 : uint64_t factor = bsize/block_size;
2079 0 : bsize = block_size;
2080 0 : dsize *= factor;
2081 0 : dfree *= factor;
2082 : }
2083 0 : sectors_per_unit = bsize/bytes_per_sector;
2084 :
2085 0 : DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2086 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2087 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2088 :
2089 : /*
2090 : * For large drives, return max values and not modulo.
2091 : */
2092 0 : dsize = MIN(dsize, UINT32_MAX);
2093 0 : dfree = MIN(dfree, UINT32_MAX);
2094 :
2095 0 : SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2096 0 : SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2097 0 : SIVAL(pdata,l1_cUnit,dsize);
2098 0 : SIVAL(pdata,l1_cUnitAvail,dfree);
2099 0 : SSVAL(pdata,l1_cbSector,bytes_per_sector);
2100 0 : break;
2101 : }
2102 :
2103 0 : case SMB_INFO_VOLUME:
2104 : /* Return volume name */
2105 : /*
2106 : * Add volume serial number - hash of a combination of
2107 : * the called hostname and the service name.
2108 : */
2109 0 : serial = generate_volume_serial_number(lp_sub, snum);
2110 0 : SIVAL(pdata,0,serial);
2111 : /*
2112 : * Win2k3 and previous mess this up by sending a name length
2113 : * one byte short. I believe only older clients (OS/2 Win9x) use
2114 : * this call so try fixing this by adding a terminating null to
2115 : * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2116 : */
2117 0 : status = srvstr_push(
2118 : pdata, flags2,
2119 : pdata+l2_vol_szVolLabel, vname,
2120 : PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2121 : STR_NOALIGN|STR_TERMINATE, &len);
2122 0 : if (!NT_STATUS_IS_OK(status)) {
2123 0 : return status;
2124 : }
2125 0 : SCVAL(pdata,l2_vol_cch,len);
2126 0 : data_len = l2_vol_szVolLabel + len;
2127 0 : DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2128 : "name = %s serial = 0x%04"PRIx32"\n",
2129 : (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2130 : (unsigned)len, vname, serial));
2131 0 : break;
2132 :
2133 548 : case SMB_QUERY_FS_ATTRIBUTE_INFO:
2134 : case SMB_FS_ATTRIBUTE_INFORMATION:
2135 :
2136 548 : additional_flags = 0;
2137 : #if defined(HAVE_SYS_QUOTAS)
2138 548 : additional_flags |= FILE_VOLUME_QUOTAS;
2139 : #endif
2140 :
2141 548 : if(lp_nt_acl_support(SNUM(conn))) {
2142 548 : additional_flags |= FILE_PERSISTENT_ACLS;
2143 : }
2144 :
2145 : /* Capabilities are filled in at connection time through STATVFS call */
2146 548 : additional_flags |= conn->fs_capabilities;
2147 548 : additional_flags |= lp_parm_int(conn->params->service,
2148 : "share", "fake_fscaps",
2149 : 0);
2150 :
2151 548 : SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2152 : FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2153 : additional_flags); /* FS ATTRIBUTES */
2154 :
2155 548 : SIVAL(pdata,4,255); /* Max filename component length */
2156 : /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2157 : and will think we can't do long filenames */
2158 548 : status = srvstr_push(pdata, flags2, pdata+12, fstype,
2159 : PTR_DIFF(end_data, pdata+12),
2160 : STR_UNICODE, &len);
2161 548 : if (!NT_STATUS_IS_OK(status)) {
2162 0 : return status;
2163 : }
2164 548 : SIVAL(pdata,8,len);
2165 548 : data_len = 12 + len;
2166 548 : if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2167 : /* the client only requested a portion of the
2168 : file system name */
2169 16 : data_len = max_data_bytes;
2170 16 : status = STATUS_BUFFER_OVERFLOW;
2171 : }
2172 548 : *fixed_portion = 16;
2173 548 : break;
2174 :
2175 0 : case SMB_QUERY_FS_LABEL_INFO:
2176 : case SMB_FS_LABEL_INFORMATION:
2177 0 : status = srvstr_push(pdata, flags2, pdata+4, vname,
2178 : PTR_DIFF(end_data, pdata+4), 0, &len);
2179 0 : if (!NT_STATUS_IS_OK(status)) {
2180 0 : return status;
2181 : }
2182 0 : data_len = 4 + len;
2183 0 : SIVAL(pdata,0,len);
2184 0 : break;
2185 :
2186 130 : case SMB_QUERY_FS_VOLUME_INFO:
2187 : case SMB_FS_VOLUME_INFORMATION:
2188 130 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2189 : pdata, &st.st_ex_btime);
2190 : /*
2191 : * Add volume serial number - hash of a combination of
2192 : * the called hostname and the service name.
2193 : */
2194 130 : serial = generate_volume_serial_number(lp_sub, snum);
2195 130 : SIVAL(pdata,8,serial);
2196 :
2197 : /* Max label len is 32 characters. */
2198 130 : status = srvstr_push(pdata, flags2, pdata+18, vname,
2199 : PTR_DIFF(end_data, pdata+18),
2200 : STR_UNICODE, &len);
2201 130 : if (!NT_STATUS_IS_OK(status)) {
2202 0 : return status;
2203 : }
2204 130 : SIVAL(pdata,12,len);
2205 130 : data_len = 18+len;
2206 :
2207 130 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2208 : "namelen = %d, vol=%s serv=%s "
2209 : "serial=0x%04"PRIx32"\n",
2210 : (int)strlen(vname),vname,
2211 : lp_servicename(talloc_tos(), lp_sub, snum),
2212 : serial));
2213 130 : if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2214 : /* the client only requested a portion of the
2215 : volume label */
2216 0 : data_len = max_data_bytes;
2217 0 : status = STATUS_BUFFER_OVERFLOW;
2218 : }
2219 130 : *fixed_portion = 24;
2220 130 : break;
2221 :
2222 1212 : case SMB_QUERY_FS_SIZE_INFO:
2223 : case SMB_FS_SIZE_INFORMATION:
2224 : {
2225 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2226 1212 : data_len = 24;
2227 1212 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2228 : &dfree, &dsize);
2229 1212 : if (df_ret == (uint64_t)-1) {
2230 0 : return map_nt_error_from_unix(errno);
2231 : }
2232 1212 : block_size = lp_block_size(snum);
2233 1212 : if (bsize < block_size) {
2234 1166 : uint64_t factor = block_size/bsize;
2235 1166 : bsize = block_size;
2236 1166 : dsize /= factor;
2237 1166 : dfree /= factor;
2238 : }
2239 1212 : if (bsize > block_size) {
2240 42 : uint64_t factor = bsize/block_size;
2241 42 : bsize = block_size;
2242 42 : dsize *= factor;
2243 42 : dfree *= factor;
2244 : }
2245 1212 : sectors_per_unit = bsize/bytes_per_sector;
2246 1212 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2247 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2248 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2249 1212 : SBIG_UINT(pdata,0,dsize);
2250 1212 : SBIG_UINT(pdata,8,dfree);
2251 1212 : SIVAL(pdata,16,sectors_per_unit);
2252 1212 : SIVAL(pdata,20,bytes_per_sector);
2253 1212 : *fixed_portion = 24;
2254 1212 : break;
2255 : }
2256 :
2257 428 : case SMB_FS_FULL_SIZE_INFORMATION:
2258 : {
2259 0 : uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2260 428 : data_len = 32;
2261 428 : df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2262 : &dfree, &dsize);
2263 428 : if (df_ret == (uint64_t)-1) {
2264 0 : return map_nt_error_from_unix(errno);
2265 : }
2266 428 : block_size = lp_block_size(snum);
2267 428 : if (bsize < block_size) {
2268 424 : uint64_t factor = block_size/bsize;
2269 424 : bsize = block_size;
2270 424 : dsize /= factor;
2271 424 : dfree /= factor;
2272 : }
2273 428 : if (bsize > block_size) {
2274 4 : uint64_t factor = bsize/block_size;
2275 4 : bsize = block_size;
2276 4 : dsize *= factor;
2277 4 : dfree *= factor;
2278 : }
2279 428 : sectors_per_unit = bsize/bytes_per_sector;
2280 428 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2281 : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2282 : (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2283 428 : SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2284 428 : SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2285 428 : SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2286 428 : SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2287 428 : SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2288 428 : *fixed_portion = 32;
2289 428 : break;
2290 : }
2291 :
2292 44 : case SMB_QUERY_FS_DEVICE_INFO:
2293 : case SMB_FS_DEVICE_INFORMATION:
2294 : {
2295 44 : uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2296 :
2297 44 : if (!CAN_WRITE(conn)) {
2298 0 : characteristics |= FILE_READ_ONLY_DEVICE;
2299 : }
2300 44 : data_len = 8;
2301 44 : SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2302 44 : SIVAL(pdata,4,characteristics);
2303 44 : *fixed_portion = 8;
2304 44 : break;
2305 : }
2306 :
2307 : #ifdef HAVE_SYS_QUOTAS
2308 4 : case SMB_FS_QUOTA_INFORMATION:
2309 : /*
2310 : * what we have to send --metze:
2311 : *
2312 : * Unknown1: 24 NULL bytes
2313 : * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2314 : * Hard Quota Limit: 8 bytes seems like uint64_t or so
2315 : * Quota Flags: 2 byte :
2316 : * Unknown3: 6 NULL bytes
2317 : *
2318 : * 48 bytes total
2319 : *
2320 : * details for Quota Flags:
2321 : *
2322 : * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2323 : * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2324 : * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2325 : * 0x0001 Enable Quotas: enable quota for this fs
2326 : *
2327 : */
2328 : {
2329 : /* we need to fake up a fsp here,
2330 : * because its not send in this call
2331 : */
2332 0 : files_struct fsp;
2333 0 : SMB_NTQUOTA_STRUCT quotas;
2334 :
2335 4 : ZERO_STRUCT(fsp);
2336 4 : ZERO_STRUCT(quotas);
2337 :
2338 4 : fsp.conn = conn;
2339 4 : fsp.fnum = FNUM_FIELD_INVALID;
2340 :
2341 : /* access check */
2342 4 : if (get_current_uid(conn) != 0) {
2343 4 : DEBUG(0,("get_user_quota: access_denied "
2344 : "service [%s] user [%s]\n",
2345 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2346 : conn->session_info->unix_info->unix_name));
2347 4 : return NT_STATUS_ACCESS_DENIED;
2348 : }
2349 :
2350 0 : status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2351 : NULL, "as);
2352 0 : if (!NT_STATUS_IS_OK(status)) {
2353 0 : DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2354 0 : return status;
2355 : }
2356 :
2357 0 : data_len = 48;
2358 :
2359 0 : DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2360 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2361 :
2362 : /* Unknown1 24 NULL bytes*/
2363 0 : SBIG_UINT(pdata,0,(uint64_t)0);
2364 0 : SBIG_UINT(pdata,8,(uint64_t)0);
2365 0 : SBIG_UINT(pdata,16,(uint64_t)0);
2366 :
2367 : /* Default Soft Quota 8 bytes */
2368 0 : SBIG_UINT(pdata,24,quotas.softlim);
2369 :
2370 : /* Default Hard Quota 8 bytes */
2371 0 : SBIG_UINT(pdata,32,quotas.hardlim);
2372 :
2373 : /* Quota flag 2 bytes */
2374 0 : SSVAL(pdata,40,quotas.qflags);
2375 :
2376 : /* Unknown3 6 NULL bytes */
2377 0 : SSVAL(pdata,42,0);
2378 0 : SIVAL(pdata,44,0);
2379 :
2380 0 : break;
2381 : }
2382 : #endif /* HAVE_SYS_QUOTAS */
2383 40 : case SMB_FS_OBJECTID_INFORMATION:
2384 : {
2385 0 : unsigned char objid[16];
2386 0 : struct smb_extended_info extended_info;
2387 40 : memcpy(pdata,create_volume_objectid(conn, objid),16);
2388 40 : samba_extended_info_version (&extended_info);
2389 40 : SIVAL(pdata,16,extended_info.samba_magic);
2390 40 : SIVAL(pdata,20,extended_info.samba_version);
2391 40 : SIVAL(pdata,24,extended_info.samba_subversion);
2392 40 : SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2393 40 : memcpy(pdata+36,extended_info.samba_version_string,28);
2394 40 : data_len = 64;
2395 40 : break;
2396 : }
2397 :
2398 8 : case SMB_FS_SECTOR_SIZE_INFORMATION:
2399 : {
2400 8 : data_len = 28;
2401 : /*
2402 : * These values match a physical Windows Server 2012
2403 : * share backed by NTFS atop spinning rust.
2404 : */
2405 8 : DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2406 : /* logical_bytes_per_sector */
2407 8 : SIVAL(pdata, 0, bytes_per_sector);
2408 : /* phys_bytes_per_sector_atomic */
2409 8 : SIVAL(pdata, 4, bytes_per_sector);
2410 : /* phys_bytes_per_sector_perf */
2411 8 : SIVAL(pdata, 8, bytes_per_sector);
2412 : /* fs_effective_phys_bytes_per_sector_atomic */
2413 8 : SIVAL(pdata, 12, bytes_per_sector);
2414 : /* flags */
2415 8 : SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2416 : | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2417 : /* byte_off_sector_align */
2418 8 : SIVAL(pdata, 20, 0);
2419 : /* byte_off_partition_align */
2420 8 : SIVAL(pdata, 24, 0);
2421 8 : *fixed_portion = 28;
2422 8 : break;
2423 : }
2424 :
2425 :
2426 : #if defined(WITH_SMB1SERVER)
2427 : /*
2428 : * Query the version and capabilities of the CIFS UNIX extensions
2429 : * in use.
2430 : */
2431 :
2432 962 : case SMB_QUERY_CIFS_UNIX_INFO:
2433 : {
2434 962 : bool large_write = lp_min_receive_file_size() &&
2435 0 : !smb1_srv_is_signing_active(xconn);
2436 962 : bool large_read = !smb1_srv_is_signing_active(xconn);
2437 962 : int encrypt_caps = 0;
2438 :
2439 962 : if (!lp_smb1_unix_extensions()) {
2440 0 : return NT_STATUS_INVALID_LEVEL;
2441 : }
2442 :
2443 962 : switch (conn->encrypt_level) {
2444 0 : case SMB_SIGNING_OFF:
2445 0 : encrypt_caps = 0;
2446 0 : break;
2447 797 : case SMB_SIGNING_DESIRED:
2448 : case SMB_SIGNING_IF_REQUIRED:
2449 : case SMB_SIGNING_DEFAULT:
2450 797 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2451 797 : break;
2452 165 : case SMB_SIGNING_REQUIRED:
2453 165 : encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2454 : CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2455 165 : large_write = false;
2456 165 : large_read = false;
2457 165 : break;
2458 : }
2459 :
2460 962 : data_len = 12;
2461 962 : SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2462 962 : SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2463 :
2464 : /* We have POSIX ACLs, pathname, encryption,
2465 : * large read/write, and locking capability. */
2466 :
2467 962 : SBIG_UINT(pdata,4,((uint64_t)(
2468 : CIFS_UNIX_POSIX_ACLS_CAP|
2469 : CIFS_UNIX_POSIX_PATHNAMES_CAP|
2470 : CIFS_UNIX_FCNTL_LOCKS_CAP|
2471 : CIFS_UNIX_EXTATTR_CAP|
2472 : CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2473 : encrypt_caps|
2474 : (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2475 : (large_write ?
2476 : CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2477 962 : break;
2478 : }
2479 : #endif
2480 :
2481 0 : case SMB_QUERY_POSIX_FS_INFO:
2482 : case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2483 : {
2484 0 : int rc;
2485 0 : struct vfs_statvfs_struct svfs;
2486 :
2487 0 : if (!fsinfo_unix_valid_level(conn, info_level)) {
2488 0 : return NT_STATUS_INVALID_LEVEL;
2489 : }
2490 :
2491 0 : rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2492 :
2493 0 : if (!rc) {
2494 0 : data_len = 56;
2495 0 : SIVAL(pdata,0,svfs.OptimalTransferSize);
2496 0 : SIVAL(pdata,4,svfs.BlockSize);
2497 0 : SBIG_UINT(pdata,8,svfs.TotalBlocks);
2498 0 : SBIG_UINT(pdata,16,svfs.BlocksAvail);
2499 0 : SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2500 0 : SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2501 0 : SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2502 0 : SBIG_UINT(pdata,48,svfs.FsIdentifier);
2503 0 : DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2504 : #ifdef EOPNOTSUPP
2505 0 : } else if (rc == EOPNOTSUPP) {
2506 0 : return NT_STATUS_INVALID_LEVEL;
2507 : #endif /* EOPNOTSUPP */
2508 : } else {
2509 0 : DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2510 0 : return NT_STATUS_DOS(ERRSRV, ERRerror);
2511 : }
2512 0 : break;
2513 : }
2514 :
2515 42 : case SMB_QUERY_POSIX_WHOAMI:
2516 : {
2517 42 : uint32_t flags = 0;
2518 0 : uint32_t sid_bytes;
2519 0 : uint32_t i;
2520 :
2521 42 : if (!lp_smb1_unix_extensions()) {
2522 0 : return NT_STATUS_INVALID_LEVEL;
2523 : }
2524 :
2525 42 : if (max_data_bytes < 40) {
2526 0 : return NT_STATUS_BUFFER_TOO_SMALL;
2527 : }
2528 :
2529 42 : if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2530 6 : flags |= SMB_WHOAMI_GUEST;
2531 : }
2532 :
2533 : /* NOTE: 8 bytes for UID/GID, irrespective of native
2534 : * platform size. This matches
2535 : * SMB_QUERY_FILE_UNIX_BASIC and friends.
2536 : */
2537 42 : data_len = 4 /* flags */
2538 : + 4 /* flag mask */
2539 : + 8 /* uid */
2540 : + 8 /* gid */
2541 : + 4 /* ngroups */
2542 : + 4 /* num_sids */
2543 : + 4 /* SID bytes */
2544 : + 4 /* pad/reserved */
2545 42 : + (conn->session_info->unix_token->ngroups * 8)
2546 : /* groups list */
2547 42 : + (conn->session_info->security_token->num_sids *
2548 : SID_MAX_SIZE)
2549 : /* SID list */;
2550 :
2551 42 : SIVAL(pdata, 0, flags);
2552 42 : SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2553 42 : SBIG_UINT(pdata, 8,
2554 : (uint64_t)conn->session_info->unix_token->uid);
2555 42 : SBIG_UINT(pdata, 16,
2556 : (uint64_t)conn->session_info->unix_token->gid);
2557 :
2558 :
2559 42 : if (data_len >= max_data_bytes) {
2560 : /* Potential overflow, skip the GIDs and SIDs. */
2561 :
2562 14 : SIVAL(pdata, 24, 0); /* num_groups */
2563 14 : SIVAL(pdata, 28, 0); /* num_sids */
2564 14 : SIVAL(pdata, 32, 0); /* num_sid_bytes */
2565 14 : SIVAL(pdata, 36, 0); /* reserved */
2566 :
2567 14 : data_len = 40;
2568 14 : break;
2569 : }
2570 :
2571 28 : SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2572 28 : SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2573 :
2574 : /* We walk the SID list twice, but this call is fairly
2575 : * infrequent, and I don't expect that it's performance
2576 : * sensitive -- jpeach
2577 : */
2578 28 : for (i = 0, sid_bytes = 0;
2579 341 : i < conn->session_info->security_token->num_sids; ++i) {
2580 313 : sid_bytes += ndr_size_dom_sid(
2581 313 : &conn->session_info->security_token->sids[i],
2582 : 0);
2583 : }
2584 :
2585 : /* SID list byte count */
2586 28 : SIVAL(pdata, 32, sid_bytes);
2587 :
2588 : /* 4 bytes pad/reserved - must be zero */
2589 28 : SIVAL(pdata, 36, 0);
2590 28 : data_len = 40;
2591 :
2592 : /* GID list */
2593 256 : for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2594 228 : SBIG_UINT(pdata, data_len,
2595 : (uint64_t)conn->session_info->unix_token->groups[i]);
2596 228 : data_len += 8;
2597 : }
2598 :
2599 : /* SID list */
2600 28 : for (i = 0;
2601 341 : i < conn->session_info->security_token->num_sids; ++i) {
2602 626 : int sid_len = ndr_size_dom_sid(
2603 313 : &conn->session_info->security_token->sids[i],
2604 : 0);
2605 :
2606 313 : sid_linearize((uint8_t *)(pdata + data_len),
2607 : sid_len,
2608 313 : &conn->session_info->security_token->sids[i]);
2609 313 : data_len += sid_len;
2610 : }
2611 :
2612 28 : break;
2613 : }
2614 :
2615 0 : case SMB_MAC_QUERY_FS_INFO:
2616 : /*
2617 : * Thursby MAC extension... ONLY on NTFS filesystems
2618 : * once we do streams then we don't need this
2619 : */
2620 0 : if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2621 0 : data_len = 88;
2622 0 : SIVAL(pdata,84,0x100); /* Don't support mac... */
2623 0 : break;
2624 : }
2625 :
2626 0 : FALL_THROUGH;
2627 : default:
2628 0 : return NT_STATUS_INVALID_LEVEL;
2629 : }
2630 :
2631 3414 : *ret_data_len = data_len;
2632 3414 : return status;
2633 : }
2634 :
2635 0 : NTSTATUS smb_set_fsquota(connection_struct *conn,
2636 : struct smb_request *req,
2637 : files_struct *fsp,
2638 : const DATA_BLOB *qdata)
2639 : {
2640 0 : const struct loadparm_substitution *lp_sub =
2641 0 : loadparm_s3_global_substitution();
2642 0 : NTSTATUS status;
2643 0 : SMB_NTQUOTA_STRUCT quotas;
2644 :
2645 0 : ZERO_STRUCT(quotas);
2646 :
2647 : /* access check */
2648 0 : if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2649 0 : DBG_NOTICE("access_denied service [%s] user [%s]\n",
2650 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2651 : conn->session_info->unix_info->unix_name);
2652 0 : return NT_STATUS_ACCESS_DENIED;
2653 : }
2654 :
2655 0 : if (!check_fsp_ntquota_handle(conn, req,
2656 : fsp)) {
2657 0 : DBG_WARNING("no valid QUOTA HANDLE\n");
2658 0 : return NT_STATUS_INVALID_HANDLE;
2659 : }
2660 :
2661 : /* note: normally there're 48 bytes,
2662 : * but we didn't use the last 6 bytes for now
2663 : * --metze
2664 : */
2665 0 : if (qdata->length < 42) {
2666 0 : DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2667 : qdata->length);
2668 0 : return NT_STATUS_INVALID_PARAMETER;
2669 : }
2670 :
2671 : /* unknown_1 24 NULL bytes in pdata*/
2672 :
2673 : /* the soft quotas 8 bytes (uint64_t)*/
2674 0 : quotas.softlim = BVAL(qdata->data,24);
2675 :
2676 : /* the hard quotas 8 bytes (uint64_t)*/
2677 0 : quotas.hardlim = BVAL(qdata->data,32);
2678 :
2679 : /* quota_flags 2 bytes **/
2680 0 : quotas.qflags = SVAL(qdata->data,40);
2681 :
2682 : /* unknown_2 6 NULL bytes follow*/
2683 :
2684 : /* now set the quotas */
2685 0 : if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2686 0 : DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2687 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2688 0 : status = map_nt_error_from_unix(errno);
2689 : } else {
2690 0 : status = NT_STATUS_OK;
2691 : }
2692 0 : return status;
2693 : }
2694 :
2695 0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2696 : struct smb_request *req,
2697 : TALLOC_CTX *mem_ctx,
2698 : uint16_t info_level,
2699 : files_struct *fsp,
2700 : const DATA_BLOB *pdata)
2701 : {
2702 0 : switch (info_level) {
2703 0 : case SMB_FS_QUOTA_INFORMATION:
2704 : {
2705 0 : return smb_set_fsquota(conn,
2706 : req,
2707 : fsp,
2708 : pdata);
2709 : }
2710 :
2711 0 : default:
2712 0 : break;
2713 : }
2714 0 : return NT_STATUS_INVALID_LEVEL;
2715 : }
2716 :
2717 : /****************************************************************************
2718 : Store the FILE_UNIX_BASIC info.
2719 : ****************************************************************************/
2720 :
2721 144 : char *store_file_unix_basic(connection_struct *conn,
2722 : char *pdata,
2723 : files_struct *fsp,
2724 : const SMB_STRUCT_STAT *psbuf)
2725 : {
2726 0 : dev_t devno;
2727 :
2728 144 : DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2729 144 : DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2730 :
2731 144 : SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2732 144 : pdata += 8;
2733 :
2734 144 : SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2735 144 : pdata += 8;
2736 :
2737 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2738 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2739 144 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2740 144 : pdata += 24;
2741 :
2742 144 : SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2743 144 : SIVAL(pdata,4,0);
2744 144 : pdata += 8;
2745 :
2746 144 : SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2747 144 : SIVAL(pdata,4,0);
2748 144 : pdata += 8;
2749 :
2750 144 : SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2751 144 : pdata += 4;
2752 :
2753 144 : if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2754 0 : devno = psbuf->st_ex_rdev;
2755 : } else {
2756 144 : devno = psbuf->st_ex_dev;
2757 : }
2758 :
2759 144 : SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2760 144 : SIVAL(pdata,4,0);
2761 144 : pdata += 8;
2762 :
2763 144 : SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2764 144 : SIVAL(pdata,4,0);
2765 144 : pdata += 8;
2766 :
2767 144 : SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2768 144 : pdata += 8;
2769 :
2770 144 : SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2771 144 : SIVAL(pdata,4,0);
2772 144 : pdata += 8;
2773 :
2774 144 : SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2775 144 : SIVAL(pdata,4,0);
2776 144 : pdata += 8;
2777 :
2778 144 : return pdata;
2779 : }
2780 :
2781 : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2782 : * the chflags(2) (or equivalent) flags.
2783 : *
2784 : * XXX: this really should be behind the VFS interface. To do this, we would
2785 : * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2786 : * Each VFS module could then implement its own mapping as appropriate for the
2787 : * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2788 : */
2789 : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2790 : info2_flags_map[] =
2791 : {
2792 : #ifdef UF_NODUMP
2793 : { UF_NODUMP, EXT_DO_NOT_BACKUP },
2794 : #endif
2795 :
2796 : #ifdef UF_IMMUTABLE
2797 : { UF_IMMUTABLE, EXT_IMMUTABLE },
2798 : #endif
2799 :
2800 : #ifdef UF_APPEND
2801 : { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2802 : #endif
2803 :
2804 : #ifdef UF_HIDDEN
2805 : { UF_HIDDEN, EXT_HIDDEN },
2806 : #endif
2807 :
2808 : /* Do not remove. We need to guarantee that this array has at least one
2809 : * entry to build on HP-UX.
2810 : */
2811 : { 0, 0 }
2812 :
2813 : };
2814 :
2815 24 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2816 : uint32_t *smb_fflags, uint32_t *smb_fmask)
2817 : {
2818 : size_t i;
2819 :
2820 48 : for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2821 24 : *smb_fmask |= info2_flags_map[i].smb_fflag;
2822 24 : if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2823 0 : *smb_fflags |= info2_flags_map[i].smb_fflag;
2824 : }
2825 : }
2826 24 : }
2827 :
2828 128 : bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2829 : const uint32_t smb_fflags,
2830 : const uint32_t smb_fmask,
2831 : int *stat_fflags)
2832 : {
2833 128 : uint32_t max_fmask = 0;
2834 0 : size_t i;
2835 :
2836 128 : *stat_fflags = psbuf->st_ex_flags;
2837 :
2838 : /* For each flags requested in smb_fmask, check the state of the
2839 : * corresponding flag in smb_fflags and set or clear the matching
2840 : * stat flag.
2841 : */
2842 :
2843 256 : for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2844 128 : max_fmask |= info2_flags_map[i].smb_fflag;
2845 128 : if (smb_fmask & info2_flags_map[i].smb_fflag) {
2846 0 : if (smb_fflags & info2_flags_map[i].smb_fflag) {
2847 0 : *stat_fflags |= info2_flags_map[i].stat_fflag;
2848 : } else {
2849 0 : *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2850 : }
2851 : }
2852 : }
2853 :
2854 : /* If smb_fmask is asking to set any bits that are not supported by
2855 : * our flag mappings, we should fail.
2856 : */
2857 128 : if ((smb_fmask & max_fmask) != smb_fmask) {
2858 128 : return False;
2859 : }
2860 :
2861 0 : return True;
2862 : }
2863 :
2864 :
2865 : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2866 : * of file flags and birth (create) time.
2867 : */
2868 24 : char *store_file_unix_basic_info2(connection_struct *conn,
2869 : char *pdata,
2870 : files_struct *fsp,
2871 : const SMB_STRUCT_STAT *psbuf)
2872 : {
2873 24 : uint32_t file_flags = 0;
2874 24 : uint32_t flags_mask = 0;
2875 :
2876 24 : pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2877 :
2878 : /* Create (birth) time 64 bit */
2879 24 : put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2880 24 : pdata += 8;
2881 :
2882 24 : map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2883 24 : SIVAL(pdata, 0, file_flags); /* flags */
2884 24 : SIVAL(pdata, 4, flags_mask); /* mask */
2885 24 : pdata += 8;
2886 :
2887 24 : return pdata;
2888 : }
2889 :
2890 3598 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
2891 : const struct stream_struct *streams,
2892 : char *data,
2893 : unsigned int max_data_bytes,
2894 : unsigned int *data_size)
2895 : {
2896 0 : unsigned int i;
2897 3598 : unsigned int ofs = 0;
2898 :
2899 3598 : if (max_data_bytes < 32) {
2900 128 : return NT_STATUS_INFO_LENGTH_MISMATCH;
2901 : }
2902 :
2903 7478 : for (i = 0; i < num_streams; i++) {
2904 0 : unsigned int next_offset;
2905 0 : size_t namelen;
2906 0 : smb_ucs2_t *namebuf;
2907 :
2908 4032 : if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2909 4032 : streams[i].name, &namelen) ||
2910 4032 : namelen <= 2)
2911 : {
2912 0 : return NT_STATUS_INVALID_PARAMETER;
2913 : }
2914 :
2915 : /*
2916 : * name_buf is now null-terminated, we need to marshall as not
2917 : * terminated
2918 : */
2919 :
2920 4032 : namelen -= 2;
2921 :
2922 : /*
2923 : * We cannot overflow ...
2924 : */
2925 4032 : if ((ofs + 24 + namelen) > max_data_bytes) {
2926 24 : DEBUG(10, ("refusing to overflow reply at stream %u\n",
2927 : i));
2928 24 : TALLOC_FREE(namebuf);
2929 24 : return STATUS_BUFFER_OVERFLOW;
2930 : }
2931 :
2932 4008 : SIVAL(data, ofs+4, namelen);
2933 4008 : SOFF_T(data, ofs+8, streams[i].size);
2934 4008 : SOFF_T(data, ofs+16, streams[i].alloc_size);
2935 4008 : memcpy(data+ofs+24, namebuf, namelen);
2936 4008 : TALLOC_FREE(namebuf);
2937 :
2938 4008 : next_offset = ofs + 24 + namelen;
2939 :
2940 4008 : if (i == num_streams-1) {
2941 3210 : SIVAL(data, ofs, 0);
2942 : }
2943 : else {
2944 798 : unsigned int align = ndr_align_size(next_offset, 8);
2945 :
2946 798 : if ((next_offset + align) > max_data_bytes) {
2947 0 : DEBUG(10, ("refusing to overflow align "
2948 : "reply at stream %u\n",
2949 : i));
2950 0 : TALLOC_FREE(namebuf);
2951 0 : return STATUS_BUFFER_OVERFLOW;
2952 : }
2953 :
2954 798 : memset(data+next_offset, 0, align);
2955 798 : next_offset += align;
2956 :
2957 798 : SIVAL(data, ofs, next_offset - ofs);
2958 798 : ofs = next_offset;
2959 : }
2960 :
2961 4008 : ofs = next_offset;
2962 : }
2963 :
2964 3446 : DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2965 :
2966 3446 : *data_size = ofs;
2967 :
2968 3446 : return NT_STATUS_OK;
2969 : }
2970 :
2971 24515 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2972 : TALLOC_CTX *mem_ctx,
2973 : struct smb_request *req,
2974 : uint16_t info_level,
2975 : files_struct *fsp,
2976 : struct smb_filename *smb_fname,
2977 : bool delete_pending,
2978 : struct timespec write_time_ts,
2979 : struct ea_list *ea_list,
2980 : uint16_t flags2,
2981 : unsigned int max_data_bytes,
2982 : size_t *fixed_portion,
2983 : char **ppdata,
2984 : unsigned int *pdata_size)
2985 : {
2986 24515 : char *pdata = *ppdata;
2987 743 : char *dstart, *dend;
2988 743 : unsigned int data_size;
2989 743 : struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2990 743 : time_t create_time, mtime, atime, c_time;
2991 24515 : SMB_STRUCT_STAT *psbuf = NULL;
2992 24515 : SMB_STRUCT_STAT *base_sp = NULL;
2993 743 : char *p;
2994 743 : char *base_name;
2995 743 : char *dos_fname;
2996 743 : int mode;
2997 743 : int nlink;
2998 743 : NTSTATUS status;
2999 24515 : uint64_t file_size = 0;
3000 24515 : uint64_t pos = 0;
3001 24515 : uint64_t allocation_size = 0;
3002 24515 : uint64_t file_id = 0;
3003 24515 : uint32_t access_mask = 0;
3004 24515 : size_t len = 0;
3005 :
3006 24515 : if (INFO_LEVEL_IS_UNIX(info_level)) {
3007 8 : bool ok = false;
3008 :
3009 8 : if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3010 8 : DBG_DEBUG("SMB1 unix extensions activated\n");
3011 8 : ok = true;
3012 : }
3013 :
3014 8 : if ((fsp != NULL) &&
3015 8 : (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3016 0 : DBG_DEBUG("SMB2 posix open\n");
3017 0 : ok = true;
3018 : }
3019 :
3020 8 : if (!ok) {
3021 0 : return NT_STATUS_INVALID_LEVEL;
3022 : }
3023 : }
3024 :
3025 24515 : DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3026 : smb_fname_str_dbg(smb_fname),
3027 : fsp_fnum_dbg(fsp),
3028 : info_level, max_data_bytes));
3029 :
3030 : /*
3031 : * In case of querying a symlink in POSIX context,
3032 : * fsp will be NULL. fdos_mode() deals with it.
3033 : */
3034 24515 : if (fsp != NULL) {
3035 24515 : smb_fname = fsp->fsp_name;
3036 : }
3037 24515 : mode = fdos_mode(fsp);
3038 24515 : psbuf = &smb_fname->st;
3039 :
3040 24515 : if (fsp != NULL) {
3041 24515 : base_sp = fsp->base_fsp ?
3042 24515 : &fsp->base_fsp->fsp_name->st :
3043 23947 : &fsp->fsp_name->st;
3044 : } else {
3045 0 : base_sp = &smb_fname->st;
3046 : }
3047 :
3048 24515 : nlink = psbuf->st_ex_nlink;
3049 :
3050 24515 : if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3051 2784 : nlink = 1;
3052 : }
3053 :
3054 24515 : if ((nlink > 0) && delete_pending) {
3055 233 : nlink -= 1;
3056 : }
3057 :
3058 24515 : if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3059 0 : return NT_STATUS_INVALID_PARAMETER;
3060 : }
3061 :
3062 24515 : data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3063 24515 : *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3064 24515 : if (*ppdata == NULL) {
3065 0 : return NT_STATUS_NO_MEMORY;
3066 : }
3067 24515 : pdata = *ppdata;
3068 24515 : dstart = pdata;
3069 24515 : dend = dstart + data_size - 1;
3070 :
3071 24515 : if (!is_omit_timespec(&write_time_ts) &&
3072 16878 : !INFO_LEVEL_IS_UNIX(info_level))
3073 : {
3074 16878 : update_stat_ex_mtime(psbuf, write_time_ts);
3075 : }
3076 :
3077 24515 : create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3078 24515 : mtime_ts = psbuf->st_ex_mtime;
3079 24515 : atime_ts = psbuf->st_ex_atime;
3080 24515 : ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3081 :
3082 24515 : if (lp_dos_filetime_resolution(SNUM(conn))) {
3083 0 : dos_filetime_timespec(&create_time_ts);
3084 0 : dos_filetime_timespec(&mtime_ts);
3085 0 : dos_filetime_timespec(&atime_ts);
3086 0 : dos_filetime_timespec(&ctime_ts);
3087 : }
3088 :
3089 24515 : create_time = convert_timespec_to_time_t(create_time_ts);
3090 24515 : mtime = convert_timespec_to_time_t(mtime_ts);
3091 24515 : atime = convert_timespec_to_time_t(atime_ts);
3092 24515 : c_time = convert_timespec_to_time_t(ctime_ts);
3093 :
3094 24515 : p = strrchr_m(smb_fname->base_name,'/');
3095 24515 : if (!p)
3096 12804 : base_name = smb_fname->base_name;
3097 : else
3098 11711 : base_name = p+1;
3099 :
3100 : /* NT expects the name to be in an exact form of the *full*
3101 : filename. See the trans2 torture test */
3102 24515 : if (ISDOT(base_name)) {
3103 402 : dos_fname = talloc_strdup(mem_ctx, "\\");
3104 402 : if (!dos_fname) {
3105 0 : return NT_STATUS_NO_MEMORY;
3106 : }
3107 : } else {
3108 24113 : dos_fname = talloc_asprintf(mem_ctx,
3109 : "\\%s",
3110 : smb_fname->base_name);
3111 24113 : if (!dos_fname) {
3112 0 : return NT_STATUS_NO_MEMORY;
3113 : }
3114 24113 : if (is_named_stream(smb_fname)) {
3115 568 : dos_fname = talloc_asprintf(dos_fname, "%s",
3116 : smb_fname->stream_name);
3117 568 : if (!dos_fname) {
3118 0 : return NT_STATUS_NO_MEMORY;
3119 : }
3120 : }
3121 :
3122 24113 : string_replace(dos_fname, '/', '\\');
3123 : }
3124 :
3125 24515 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3126 :
3127 24515 : if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3128 : /* Do we have this path open ? */
3129 7784 : struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3130 7784 : files_struct *fsp1 = file_find_di_first(
3131 : conn->sconn, fileid, true);
3132 7784 : if (fsp1 && fsp1->initial_allocation_size) {
3133 105 : allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3134 : }
3135 : }
3136 :
3137 24515 : if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3138 21731 : file_size = get_file_size_stat(psbuf);
3139 : }
3140 :
3141 24515 : if (fsp) {
3142 24515 : pos = fh_get_position_information(fsp->fh);
3143 : }
3144 :
3145 24515 : if (fsp) {
3146 24515 : access_mask = fsp->access_mask;
3147 : } else {
3148 : /* GENERIC_EXECUTE mapping from Windows */
3149 0 : access_mask = 0x12019F;
3150 : }
3151 :
3152 : /* This should be an index number - looks like
3153 : dev/ino to me :-)
3154 :
3155 : I think this causes us to fail the IFSKIT
3156 : BasicFileInformationTest. -tpot */
3157 24515 : file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3158 :
3159 24515 : *fixed_portion = 0;
3160 :
3161 24515 : switch (info_level) {
3162 411 : case SMB_INFO_STANDARD:
3163 411 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3164 411 : data_size = 22;
3165 411 : srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3166 411 : srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3167 411 : srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3168 411 : SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3169 411 : SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3170 411 : SSVAL(pdata,l1_attrFile,mode);
3171 411 : break;
3172 :
3173 8 : case SMB_INFO_QUERY_EA_SIZE:
3174 : {
3175 0 : unsigned int ea_size =
3176 8 : estimate_ea_size(smb_fname->fsp);
3177 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3178 8 : data_size = 26;
3179 8 : srv_put_dos_date2(pdata,0,create_time);
3180 8 : srv_put_dos_date2(pdata,4,atime);
3181 8 : srv_put_dos_date2(pdata,8,mtime); /* write time */
3182 8 : SIVAL(pdata,12,(uint32_t)file_size);
3183 8 : SIVAL(pdata,16,(uint32_t)allocation_size);
3184 8 : SSVAL(pdata,20,mode);
3185 8 : SIVAL(pdata,22,ea_size);
3186 8 : break;
3187 : }
3188 :
3189 8 : case SMB_INFO_IS_NAME_VALID:
3190 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3191 8 : if (fsp) {
3192 : /* os/2 needs this ? really ?*/
3193 8 : return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3194 : }
3195 : /* This is only reached for qpathinfo */
3196 0 : data_size = 0;
3197 0 : break;
3198 :
3199 152 : case SMB_INFO_QUERY_EAS_FROM_LIST:
3200 : {
3201 152 : size_t total_ea_len = 0;
3202 152 : struct ea_list *ea_file_list = NULL;
3203 152 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3204 :
3205 28 : status =
3206 180 : get_ea_list_from_fsp(mem_ctx,
3207 152 : smb_fname->fsp,
3208 : &total_ea_len, &ea_file_list);
3209 152 : if (!NT_STATUS_IS_OK(status)) {
3210 4 : return status;
3211 : }
3212 :
3213 148 : ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3214 :
3215 148 : if (!ea_list || (total_ea_len > data_size)) {
3216 0 : data_size = 4;
3217 0 : SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3218 148 : break;
3219 : }
3220 :
3221 148 : data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3222 148 : break;
3223 : }
3224 :
3225 20 : case SMB_INFO_QUERY_ALL_EAS:
3226 : {
3227 : /* We have data_size bytes to put EA's into. */
3228 20 : size_t total_ea_len = 0;
3229 20 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3230 :
3231 20 : status = get_ea_list_from_fsp(mem_ctx,
3232 20 : smb_fname->fsp,
3233 : &total_ea_len, &ea_list);
3234 20 : if (!NT_STATUS_IS_OK(status)) {
3235 4 : return status;
3236 : }
3237 :
3238 16 : if (!ea_list || (total_ea_len > data_size)) {
3239 12 : data_size = 4;
3240 12 : SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3241 16 : break;
3242 : }
3243 :
3244 4 : data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3245 4 : break;
3246 : }
3247 :
3248 22 : case SMB2_FILE_FULL_EA_INFORMATION:
3249 : {
3250 : /* We have data_size bytes to put EA's into. */
3251 22 : size_t total_ea_len = 0;
3252 22 : struct ea_list *ea_file_list = NULL;
3253 :
3254 22 : DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3255 :
3256 : /*TODO: add filtering and index handling */
3257 :
3258 0 : status =
3259 22 : get_ea_list_from_fsp(mem_ctx,
3260 22 : smb_fname->fsp,
3261 : &total_ea_len, &ea_file_list);
3262 22 : if (!NT_STATUS_IS_OK(status)) {
3263 12 : return status;
3264 : }
3265 22 : if (!ea_file_list) {
3266 12 : return NT_STATUS_NO_EAS_ON_FILE;
3267 : }
3268 :
3269 10 : status = fill_ea_chained_buffer(mem_ctx,
3270 : pdata,
3271 : data_size,
3272 : &data_size,
3273 : conn, ea_file_list);
3274 10 : if (!NT_STATUS_IS_OK(status)) {
3275 0 : return status;
3276 : }
3277 10 : break;
3278 : }
3279 :
3280 4295 : case SMB_FILE_BASIC_INFORMATION:
3281 : case SMB_QUERY_FILE_BASIC_INFO:
3282 :
3283 4295 : if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3284 3739 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3285 3739 : data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3286 : } else {
3287 556 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3288 556 : data_size = 40;
3289 556 : SIVAL(pdata,36,0);
3290 : }
3291 4295 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3292 4295 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3293 4295 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3294 4295 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3295 4295 : SIVAL(pdata,32,mode);
3296 :
3297 4295 : DEBUG(5,("SMB_QFBI - "));
3298 4295 : DEBUG(5,("create: %s ", ctime(&create_time)));
3299 4295 : DEBUG(5,("access: %s ", ctime(&atime)));
3300 4295 : DEBUG(5,("write: %s ", ctime(&mtime)));
3301 4295 : DEBUG(5,("change: %s ", ctime(&c_time)));
3302 4295 : DEBUG(5,("mode: %x\n", mode));
3303 4295 : *fixed_portion = data_size;
3304 4295 : break;
3305 :
3306 2659 : case SMB_FILE_STANDARD_INFORMATION:
3307 : case SMB_QUERY_FILE_STANDARD_INFO:
3308 :
3309 2659 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3310 2659 : data_size = 24;
3311 2659 : SOFF_T(pdata,0,allocation_size);
3312 2659 : SOFF_T(pdata,8,file_size);
3313 2659 : SIVAL(pdata,16,nlink);
3314 2659 : SCVAL(pdata,20,delete_pending?1:0);
3315 2659 : SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3316 2659 : SSVAL(pdata,22,0); /* Padding. */
3317 2659 : *fixed_portion = 24;
3318 2659 : break;
3319 :
3320 40 : case SMB_FILE_EA_INFORMATION:
3321 : case SMB_QUERY_FILE_EA_INFO:
3322 : {
3323 0 : unsigned int ea_size =
3324 40 : estimate_ea_size(smb_fname->fsp);
3325 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3326 40 : data_size = 4;
3327 40 : *fixed_portion = 4;
3328 40 : SIVAL(pdata,0,ea_size);
3329 40 : break;
3330 : }
3331 :
3332 : /* Get the 8.3 name - used if NT SMB was negotiated. */
3333 1730 : case SMB_QUERY_FILE_ALT_NAME_INFO:
3334 : case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3335 : {
3336 0 : char mangled_name[13];
3337 1730 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3338 1730 : if (!name_to_8_3(base_name,mangled_name,
3339 1730 : True,conn->params)) {
3340 0 : return NT_STATUS_NO_MEMORY;
3341 : }
3342 1730 : status = srvstr_push(dstart, flags2,
3343 : pdata+4, mangled_name,
3344 : PTR_DIFF(dend, pdata+4),
3345 : STR_UNICODE, &len);
3346 1730 : if (!NT_STATUS_IS_OK(status)) {
3347 0 : return status;
3348 : }
3349 1730 : data_size = 4 + len;
3350 1730 : SIVAL(pdata,0,len);
3351 1730 : *fixed_portion = 8;
3352 1730 : break;
3353 : }
3354 :
3355 151 : case SMB_QUERY_FILE_NAME_INFO:
3356 : {
3357 : /*
3358 : this must be *exactly* right for ACLs on mapped drives to work
3359 : */
3360 151 : status = srvstr_push(dstart, flags2,
3361 : pdata+4, dos_fname,
3362 : PTR_DIFF(dend, pdata+4),
3363 : STR_UNICODE, &len);
3364 151 : if (!NT_STATUS_IS_OK(status)) {
3365 0 : return status;
3366 : }
3367 151 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3368 151 : data_size = 4 + len;
3369 151 : SIVAL(pdata,0,len);
3370 151 : break;
3371 : }
3372 :
3373 104 : case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3374 : {
3375 104 : char *nfname = NULL;
3376 :
3377 104 : if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3378 8 : return NT_STATUS_INVALID_LEVEL;
3379 : }
3380 :
3381 96 : nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3382 96 : if (nfname == NULL) {
3383 0 : return NT_STATUS_NO_MEMORY;
3384 : }
3385 :
3386 96 : if (ISDOT(nfname)) {
3387 4 : nfname[0] = '\0';
3388 : }
3389 96 : string_replace(nfname, '/', '\\');
3390 :
3391 96 : if (fsp_is_alternate_stream(fsp)) {
3392 32 : const char *s = smb_fname->stream_name;
3393 32 : const char *e = NULL;
3394 0 : size_t n;
3395 :
3396 32 : SMB_ASSERT(s[0] != '\0');
3397 :
3398 : /*
3399 : * smb_fname->stream_name is in form
3400 : * of ':StrEam:$DATA', but we should only
3401 : * append ':StrEam' here.
3402 : */
3403 :
3404 32 : e = strchr(&s[1], ':');
3405 32 : if (e == NULL) {
3406 8 : n = strlen(s);
3407 : } else {
3408 24 : n = PTR_DIFF(e, s);
3409 : }
3410 32 : nfname = talloc_strndup_append(nfname, s, n);
3411 32 : if (nfname == NULL) {
3412 0 : return NT_STATUS_NO_MEMORY;
3413 : }
3414 : }
3415 :
3416 96 : status = srvstr_push(dstart, flags2,
3417 : pdata+4, nfname,
3418 : PTR_DIFF(dend, pdata+4),
3419 : STR_UNICODE, &len);
3420 96 : if (!NT_STATUS_IS_OK(status)) {
3421 0 : return status;
3422 : }
3423 96 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3424 96 : data_size = 4 + len;
3425 96 : SIVAL(pdata,0,len);
3426 96 : *fixed_portion = 8;
3427 96 : break;
3428 : }
3429 :
3430 8 : case SMB_FILE_ALLOCATION_INFORMATION:
3431 : case SMB_QUERY_FILE_ALLOCATION_INFO:
3432 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3433 8 : data_size = 8;
3434 8 : SOFF_T(pdata,0,allocation_size);
3435 8 : break;
3436 :
3437 8 : case SMB_FILE_END_OF_FILE_INFORMATION:
3438 : case SMB_QUERY_FILE_END_OF_FILEINFO:
3439 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3440 8 : data_size = 8;
3441 8 : SOFF_T(pdata,0,file_size);
3442 8 : break;
3443 :
3444 1922 : case SMB_QUERY_FILE_ALL_INFO:
3445 : case SMB_FILE_ALL_INFORMATION:
3446 : {
3447 252 : unsigned int ea_size =
3448 1922 : estimate_ea_size(smb_fname->fsp);
3449 1922 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3450 1922 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3451 1922 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3452 1922 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3453 1922 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3454 1922 : SIVAL(pdata,32,mode);
3455 1922 : SIVAL(pdata,36,0); /* padding. */
3456 1922 : pdata += 40;
3457 1922 : SOFF_T(pdata,0,allocation_size);
3458 1922 : SOFF_T(pdata,8,file_size);
3459 1922 : SIVAL(pdata,16,nlink);
3460 1922 : SCVAL(pdata,20,delete_pending);
3461 1922 : SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3462 1922 : SSVAL(pdata,22,0);
3463 1922 : pdata += 24;
3464 1922 : SIVAL(pdata,0,ea_size);
3465 1922 : pdata += 4; /* EA info */
3466 1922 : status = srvstr_push(dstart, flags2,
3467 : pdata+4, dos_fname,
3468 : PTR_DIFF(dend, pdata+4),
3469 : STR_UNICODE, &len);
3470 1922 : if (!NT_STATUS_IS_OK(status)) {
3471 0 : return status;
3472 : }
3473 1922 : SIVAL(pdata,0,len);
3474 1922 : pdata += 4 + len;
3475 1922 : data_size = PTR_DIFF(pdata,(*ppdata));
3476 1922 : *fixed_portion = 10;
3477 1922 : break;
3478 : }
3479 :
3480 5590 : case SMB2_FILE_ALL_INFORMATION:
3481 : {
3482 0 : unsigned int ea_size =
3483 5590 : estimate_ea_size(smb_fname->fsp);
3484 5590 : DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3485 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3486 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3487 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3488 5590 : put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3489 5590 : SIVAL(pdata, 0x20, mode);
3490 5590 : SIVAL(pdata, 0x24, 0); /* padding. */
3491 5590 : SBVAL(pdata, 0x28, allocation_size);
3492 5590 : SBVAL(pdata, 0x30, file_size);
3493 5590 : SIVAL(pdata, 0x38, nlink);
3494 5590 : SCVAL(pdata, 0x3C, delete_pending);
3495 5590 : SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3496 5590 : SSVAL(pdata, 0x3E, 0); /* padding */
3497 5590 : SBVAL(pdata, 0x40, file_id);
3498 5590 : SIVAL(pdata, 0x48, ea_size);
3499 5590 : SIVAL(pdata, 0x4C, access_mask);
3500 5590 : SBVAL(pdata, 0x50, pos);
3501 5590 : SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3502 5590 : SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3503 :
3504 5590 : pdata += 0x60;
3505 :
3506 5590 : status = srvstr_push(dstart, flags2,
3507 : pdata+4, dos_fname,
3508 : PTR_DIFF(dend, pdata+4),
3509 : STR_UNICODE, &len);
3510 5590 : if (!NT_STATUS_IS_OK(status)) {
3511 0 : return status;
3512 : }
3513 5590 : SIVAL(pdata,0,len);
3514 5590 : pdata += 4 + len;
3515 5590 : data_size = PTR_DIFF(pdata,(*ppdata));
3516 5590 : *fixed_portion = 104;
3517 5590 : break;
3518 : }
3519 62 : case SMB_FILE_INTERNAL_INFORMATION:
3520 :
3521 62 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3522 62 : SBVAL(pdata, 0, file_id);
3523 62 : data_size = 8;
3524 62 : *fixed_portion = 8;
3525 62 : break;
3526 :
3527 1072 : case SMB_FILE_ACCESS_INFORMATION:
3528 1072 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3529 1072 : SIVAL(pdata, 0, access_mask);
3530 1072 : data_size = 4;
3531 1072 : *fixed_portion = 4;
3532 1072 : break;
3533 :
3534 8 : case SMB_FILE_NAME_INFORMATION:
3535 : /* Pathname with leading '\'. */
3536 : {
3537 0 : size_t byte_len;
3538 8 : byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3539 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3540 8 : SIVAL(pdata,0,byte_len);
3541 8 : data_size = 4 + byte_len;
3542 8 : break;
3543 : }
3544 :
3545 8 : case SMB_FILE_DISPOSITION_INFORMATION:
3546 8 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3547 8 : data_size = 1;
3548 8 : SCVAL(pdata,0,delete_pending);
3549 8 : *fixed_portion = 1;
3550 8 : break;
3551 :
3552 2103 : case SMB_FILE_POSITION_INFORMATION:
3553 2103 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3554 2103 : data_size = 8;
3555 2103 : SOFF_T(pdata,0,pos);
3556 2103 : *fixed_portion = 8;
3557 2103 : break;
3558 :
3559 40 : case SMB_FILE_MODE_INFORMATION:
3560 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3561 40 : SIVAL(pdata,0,mode);
3562 40 : data_size = 4;
3563 40 : *fixed_portion = 4;
3564 40 : break;
3565 :
3566 40 : case SMB_FILE_ALIGNMENT_INFORMATION:
3567 40 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3568 40 : SIVAL(pdata,0,0); /* No alignment needed. */
3569 40 : data_size = 4;
3570 40 : *fixed_portion = 4;
3571 40 : break;
3572 :
3573 : /*
3574 : * NT4 server just returns "invalid query" to this - if we try
3575 : * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3576 : * want this. JRA.
3577 : */
3578 : /* The first statement above is false - verified using Thursby
3579 : * client against NT4 -- gcolley.
3580 : */
3581 3662 : case SMB_QUERY_FILE_STREAM_INFO:
3582 : case SMB_FILE_STREAM_INFORMATION: {
3583 3662 : unsigned int num_streams = 0;
3584 3662 : struct stream_struct *streams = NULL;
3585 :
3586 3662 : DEBUG(10,("smbd_do_qfilepathinfo: "
3587 : "SMB_FILE_STREAM_INFORMATION\n"));
3588 :
3589 3662 : if (is_ntfs_stream_smb_fname(smb_fname)) {
3590 64 : return NT_STATUS_INVALID_PARAMETER;
3591 : }
3592 :
3593 3598 : status = vfs_fstreaminfo(fsp,
3594 : mem_ctx,
3595 : &num_streams,
3596 : &streams);
3597 :
3598 3598 : if (!NT_STATUS_IS_OK(status)) {
3599 0 : DEBUG(10, ("could not get stream info: %s\n",
3600 : nt_errstr(status)));
3601 0 : return status;
3602 : }
3603 :
3604 3598 : status = marshall_stream_info(num_streams, streams,
3605 : pdata, max_data_bytes,
3606 : &data_size);
3607 :
3608 3598 : if (!NT_STATUS_IS_OK(status)) {
3609 152 : DEBUG(10, ("marshall_stream_info failed: %s\n",
3610 : nt_errstr(status)));
3611 152 : TALLOC_FREE(streams);
3612 152 : return status;
3613 : }
3614 :
3615 3446 : TALLOC_FREE(streams);
3616 :
3617 3446 : *fixed_portion = 32;
3618 :
3619 3446 : break;
3620 : }
3621 88 : case SMB_QUERY_COMPRESSION_INFO:
3622 : case SMB_FILE_COMPRESSION_INFORMATION:
3623 88 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3624 88 : SOFF_T(pdata,0,file_size);
3625 88 : SIVAL(pdata,8,0); /* ??? */
3626 88 : SIVAL(pdata,12,0); /* ??? */
3627 88 : data_size = 16;
3628 88 : *fixed_portion = 16;
3629 88 : break;
3630 :
3631 244 : case SMB_FILE_NETWORK_OPEN_INFORMATION:
3632 244 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3633 244 : put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3634 244 : put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3635 244 : put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3636 244 : put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3637 244 : SOFF_T(pdata,32,allocation_size);
3638 244 : SOFF_T(pdata,40,file_size);
3639 244 : SIVAL(pdata,48,mode);
3640 244 : SIVAL(pdata,52,0); /* ??? */
3641 244 : data_size = 56;
3642 244 : *fixed_portion = 56;
3643 244 : break;
3644 :
3645 52 : case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3646 52 : DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3647 52 : SIVAL(pdata,0,mode);
3648 52 : SIVAL(pdata,4,0);
3649 52 : data_size = 8;
3650 52 : *fixed_portion = 8;
3651 52 : break;
3652 :
3653 : /*
3654 : * SMB2 UNIX Extensions.
3655 : */
3656 0 : case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3657 : {
3658 0 : struct smb3_file_posix_information info = {};
3659 0 : uint8_t buf[sizeof(info)];
3660 0 : struct ndr_push ndr = {
3661 : .data = buf,
3662 : .alloc_size = sizeof(buf),
3663 : .fixed_buf_size = true,
3664 : };
3665 0 : enum ndr_err_code ndr_err;
3666 :
3667 0 : if (!(conn->sconn->using_smb2)) {
3668 0 : return NT_STATUS_INVALID_LEVEL;
3669 : }
3670 0 : if (fsp == NULL) {
3671 0 : return NT_STATUS_INVALID_HANDLE;
3672 : }
3673 0 : if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3674 0 : return NT_STATUS_INVALID_LEVEL;
3675 : }
3676 :
3677 0 : smb3_file_posix_information_init(
3678 0 : conn, &smb_fname->st, 0, mode, &info);
3679 :
3680 0 : ndr_err = ndr_push_smb3_file_posix_information(
3681 : &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3682 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3683 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
3684 : }
3685 :
3686 0 : memcpy(pdata, buf, ndr.offset);
3687 0 : data_size = ndr.offset;
3688 0 : break;
3689 : }
3690 :
3691 8 : default:
3692 8 : return NT_STATUS_INVALID_LEVEL;
3693 : }
3694 :
3695 24255 : *pdata_size = data_size;
3696 24255 : return NT_STATUS_OK;
3697 : }
3698 :
3699 : /****************************************************************************
3700 : Set a hard link (called by UNIX extensions and by NT rename with HARD link
3701 : code.
3702 : ****************************************************************************/
3703 :
3704 51 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3705 : connection_struct *conn,
3706 : struct smb_request *req,
3707 : bool overwrite_if_exists,
3708 : const struct smb_filename *smb_fname_old,
3709 : struct smb_filename *smb_fname_new)
3710 : {
3711 51 : NTSTATUS status = NT_STATUS_OK;
3712 1 : int ret;
3713 1 : bool ok;
3714 51 : struct smb_filename *parent_fname_old = NULL;
3715 51 : struct smb_filename *base_name_old = NULL;
3716 51 : struct smb_filename *parent_fname_new = NULL;
3717 51 : struct smb_filename *base_name_new = NULL;
3718 :
3719 : /* source must already exist. */
3720 51 : if (!VALID_STAT(smb_fname_old->st)) {
3721 0 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3722 0 : goto out;
3723 : }
3724 :
3725 : /* No links from a directory. */
3726 51 : if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3727 8 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3728 8 : goto out;
3729 : }
3730 :
3731 : /* Setting a hardlink to/from a stream isn't currently supported. */
3732 43 : ok = is_ntfs_stream_smb_fname(smb_fname_old);
3733 43 : if (ok) {
3734 0 : DBG_DEBUG("Old name has streams\n");
3735 0 : status = NT_STATUS_INVALID_PARAMETER;
3736 0 : goto out;
3737 : }
3738 43 : ok = is_ntfs_stream_smb_fname(smb_fname_new);
3739 43 : if (ok) {
3740 0 : DBG_DEBUG("New name has streams\n");
3741 0 : status = NT_STATUS_INVALID_PARAMETER;
3742 0 : goto out;
3743 : }
3744 :
3745 43 : status = parent_pathref(talloc_tos(),
3746 : conn->cwd_fsp,
3747 : smb_fname_old,
3748 : &parent_fname_old,
3749 : &base_name_old);
3750 43 : if (!NT_STATUS_IS_OK(status)) {
3751 0 : goto out;
3752 : }
3753 :
3754 43 : status = parent_pathref(talloc_tos(),
3755 : conn->cwd_fsp,
3756 : smb_fname_new,
3757 : &parent_fname_new,
3758 : &base_name_new);
3759 43 : if (!NT_STATUS_IS_OK(status)) {
3760 0 : goto out;
3761 : }
3762 :
3763 43 : if (VALID_STAT(smb_fname_new->st)) {
3764 0 : if (overwrite_if_exists) {
3765 0 : if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3766 0 : status = NT_STATUS_FILE_IS_A_DIRECTORY;
3767 0 : goto out;
3768 : }
3769 0 : status = unlink_internals(conn,
3770 : req,
3771 : FILE_ATTRIBUTE_NORMAL,
3772 : NULL, /* new_dirfsp */
3773 : smb_fname_new);
3774 0 : if (!NT_STATUS_IS_OK(status)) {
3775 0 : goto out;
3776 : }
3777 : } else {
3778 : /* Disallow if newname already exists. */
3779 0 : status = NT_STATUS_OBJECT_NAME_COLLISION;
3780 0 : goto out;
3781 : }
3782 : }
3783 :
3784 43 : DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3785 : smb_fname_old->base_name, smb_fname_new->base_name));
3786 :
3787 43 : ret = SMB_VFS_LINKAT(conn,
3788 : parent_fname_old->fsp,
3789 : base_name_old,
3790 : parent_fname_new->fsp,
3791 : base_name_new,
3792 : 0);
3793 :
3794 43 : if (ret != 0) {
3795 0 : status = map_nt_error_from_unix(errno);
3796 0 : DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3797 : nt_errstr(status), smb_fname_old->base_name,
3798 : smb_fname_new->base_name));
3799 : }
3800 :
3801 43 : out:
3802 :
3803 51 : TALLOC_FREE(parent_fname_old);
3804 51 : TALLOC_FREE(parent_fname_new);
3805 51 : return status;
3806 : }
3807 :
3808 : /****************************************************************************
3809 : Deal with setting the time from any of the setfilepathinfo functions.
3810 : NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3811 : calling this function.
3812 : ****************************************************************************/
3813 :
3814 11062 : NTSTATUS smb_set_file_time(connection_struct *conn,
3815 : files_struct *fsp,
3816 : struct smb_filename *smb_fname,
3817 : struct smb_file_time *ft,
3818 : bool setting_write_time)
3819 : {
3820 11062 : struct files_struct *set_fsp = NULL;
3821 115 : struct timeval_buf tbuf[4];
3822 11062 : uint32_t action =
3823 : FILE_NOTIFY_CHANGE_LAST_ACCESS
3824 : |FILE_NOTIFY_CHANGE_LAST_WRITE
3825 : |FILE_NOTIFY_CHANGE_CREATION;
3826 115 : int ret;
3827 :
3828 11062 : if (!VALID_STAT(smb_fname->st)) {
3829 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3830 : }
3831 :
3832 11062 : if (fsp == NULL) {
3833 : /* A symlink */
3834 0 : return NT_STATUS_OK;
3835 : }
3836 :
3837 11062 : set_fsp = metadata_fsp(fsp);
3838 :
3839 : /* get some defaults (no modifications) if any info is zero or -1. */
3840 11062 : if (is_omit_timespec(&ft->create_time)) {
3841 10210 : action &= ~FILE_NOTIFY_CHANGE_CREATION;
3842 : }
3843 :
3844 11062 : if (is_omit_timespec(&ft->atime)) {
3845 10155 : action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3846 : }
3847 :
3848 11062 : if (is_omit_timespec(&ft->mtime)) {
3849 3124 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3850 : }
3851 :
3852 11062 : if (!setting_write_time) {
3853 : /* ft->mtime comes from change time, not write time. */
3854 6717 : action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3855 : }
3856 :
3857 : /* Ensure the resolution is the correct for
3858 : * what we can store on this filesystem. */
3859 :
3860 11062 : round_timespec(conn->ts_res, &ft->create_time);
3861 11062 : round_timespec(conn->ts_res, &ft->ctime);
3862 11062 : round_timespec(conn->ts_res, &ft->atime);
3863 11062 : round_timespec(conn->ts_res, &ft->mtime);
3864 :
3865 11062 : DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3866 : timespec_string_buf(&ft->atime, true, &tbuf[0]));
3867 11062 : DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3868 : timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3869 11062 : DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3870 : timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3871 11062 : DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3872 : timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3873 :
3874 11062 : if (setting_write_time) {
3875 : /*
3876 : * This was a Windows setfileinfo on an open file.
3877 : * NT does this a lot. We also need to
3878 : * set the time here, as it can be read by
3879 : * FindFirst/FindNext and with the patch for bug #2045
3880 : * in smbd/fileio.c it ensures that this timestamp is
3881 : * kept sticky even after a write. We save the request
3882 : * away and will set it on file close and after a write. JRA.
3883 : */
3884 :
3885 4345 : DBG_DEBUG("setting pending modtime to %s\n",
3886 : timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3887 :
3888 4345 : if (set_fsp != NULL) {
3889 4345 : set_sticky_write_time_fsp(set_fsp, ft->mtime);
3890 : } else {
3891 0 : set_sticky_write_time_path(
3892 0 : vfs_file_id_from_sbuf(conn, &smb_fname->st),
3893 : ft->mtime);
3894 : }
3895 : }
3896 :
3897 11062 : DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3898 :
3899 11062 : ret = file_ntimes(conn, set_fsp, ft);
3900 11062 : if (ret != 0) {
3901 2 : return map_nt_error_from_unix(errno);
3902 : }
3903 :
3904 11060 : notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3905 11060 : smb_fname->base_name);
3906 11060 : return NT_STATUS_OK;
3907 : }
3908 :
3909 : /****************************************************************************
3910 : Deal with setting the dosmode from any of the setfilepathinfo functions.
3911 : NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3912 : done before calling this function.
3913 : ****************************************************************************/
3914 :
3915 2824 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3916 : struct files_struct *fsp,
3917 : uint32_t dosmode)
3918 : {
3919 2824 : struct files_struct *dos_fsp = NULL;
3920 31 : uint32_t current_dosmode;
3921 31 : int ret;
3922 :
3923 2824 : if (!VALID_STAT(fsp->fsp_name->st)) {
3924 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3925 : }
3926 :
3927 2824 : dos_fsp = metadata_fsp(fsp);
3928 :
3929 2824 : if (dosmode != 0) {
3930 1279 : if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3931 187 : dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3932 : } else {
3933 1092 : dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3934 : }
3935 : }
3936 :
3937 2824 : DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3938 :
3939 : /* check the mode isn't different, before changing it */
3940 2824 : if (dosmode == 0) {
3941 1545 : return NT_STATUS_OK;
3942 : }
3943 1279 : current_dosmode = fdos_mode(dos_fsp);
3944 1279 : if (dosmode == current_dosmode) {
3945 292 : return NT_STATUS_OK;
3946 : }
3947 :
3948 987 : DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3949 : fsp_str_dbg(dos_fsp), dosmode);
3950 :
3951 987 : ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3952 987 : if (ret != 0) {
3953 5 : DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3954 : fsp_str_dbg(dos_fsp), strerror(errno));
3955 5 : return map_nt_error_from_unix(errno);
3956 : }
3957 :
3958 982 : return NT_STATUS_OK;
3959 : }
3960 :
3961 : /****************************************************************************
3962 : Deal with setting the size from any of the setfilepathinfo functions.
3963 : ****************************************************************************/
3964 :
3965 471 : NTSTATUS smb_set_file_size(connection_struct *conn,
3966 : struct smb_request *req,
3967 : files_struct *fsp,
3968 : struct smb_filename *smb_fname,
3969 : const SMB_STRUCT_STAT *psbuf,
3970 : off_t size,
3971 : bool fail_after_createfile)
3972 : {
3973 471 : NTSTATUS status = NT_STATUS_OK;
3974 471 : files_struct *new_fsp = NULL;
3975 :
3976 471 : if (!VALID_STAT(*psbuf)) {
3977 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3978 : }
3979 :
3980 471 : DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3981 : (uint64_t)size,
3982 : get_file_size_stat(psbuf));
3983 :
3984 471 : if (size == get_file_size_stat(psbuf)) {
3985 148 : if (fsp == NULL) {
3986 0 : return NT_STATUS_OK;
3987 : }
3988 148 : if (!fsp->fsp_flags.modified) {
3989 144 : return NT_STATUS_OK;
3990 : }
3991 4 : trigger_write_time_update_immediate(fsp);
3992 4 : return NT_STATUS_OK;
3993 : }
3994 :
3995 323 : DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
3996 : smb_fname_str_dbg(smb_fname), (double)size));
3997 :
3998 323 : if (fsp &&
3999 606 : !fsp->fsp_flags.is_pathref &&
4000 283 : fsp_get_io_fd(fsp) != -1)
4001 : {
4002 : /* Handle based call. */
4003 283 : if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4004 0 : return NT_STATUS_ACCESS_DENIED;
4005 : }
4006 :
4007 283 : if (vfs_set_filelen(fsp, size) == -1) {
4008 8 : return map_nt_error_from_unix(errno);
4009 : }
4010 275 : trigger_write_time_update_immediate(fsp);
4011 275 : return NT_STATUS_OK;
4012 : }
4013 :
4014 40 : status = SMB_VFS_CREATE_FILE(
4015 : conn, /* conn */
4016 : req, /* req */
4017 : NULL, /* dirfsp */
4018 : smb_fname, /* fname */
4019 : FILE_WRITE_DATA, /* access_mask */
4020 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4021 : FILE_SHARE_DELETE),
4022 : FILE_OPEN, /* create_disposition*/
4023 : 0, /* create_options */
4024 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4025 : 0, /* oplock_request */
4026 : NULL, /* lease */
4027 : 0, /* allocation_size */
4028 : 0, /* private_flags */
4029 : NULL, /* sd */
4030 : NULL, /* ea_list */
4031 : &new_fsp, /* result */
4032 : NULL, /* pinfo */
4033 : NULL, NULL); /* create context */
4034 :
4035 40 : if (!NT_STATUS_IS_OK(status)) {
4036 : /* NB. We check for open_was_deferred in the caller. */
4037 28 : return status;
4038 : }
4039 :
4040 : /* See RAW-SFILEINFO-END-OF-FILE */
4041 12 : if (fail_after_createfile) {
4042 4 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4043 4 : return NT_STATUS_INVALID_LEVEL;
4044 : }
4045 :
4046 8 : if (vfs_set_filelen(new_fsp, size) == -1) {
4047 0 : status = map_nt_error_from_unix(errno);
4048 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4049 0 : return status;
4050 : }
4051 :
4052 8 : trigger_write_time_update_immediate(new_fsp);
4053 8 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4054 8 : return NT_STATUS_OK;
4055 : }
4056 :
4057 : /****************************************************************************
4058 : Deal with SMB_INFO_SET_EA.
4059 : ****************************************************************************/
4060 :
4061 2939 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
4062 : const char *pdata,
4063 : int total_data,
4064 : files_struct *fsp,
4065 : struct smb_filename *smb_fname)
4066 : {
4067 2939 : struct ea_list *ea_list = NULL;
4068 2939 : TALLOC_CTX *ctx = NULL;
4069 2939 : NTSTATUS status = NT_STATUS_OK;
4070 :
4071 2939 : if (total_data < 10) {
4072 :
4073 : /* OS/2 workplace shell seems to send SET_EA requests of "null"
4074 : length. They seem to have no effect. Bug #3212. JRA */
4075 :
4076 0 : if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4077 : /* We're done. We only get EA info in this call. */
4078 0 : return NT_STATUS_OK;
4079 : }
4080 :
4081 0 : return NT_STATUS_INVALID_PARAMETER;
4082 : }
4083 :
4084 2939 : if (IVAL(pdata,0) > total_data) {
4085 0 : DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4086 : IVAL(pdata,0), (unsigned int)total_data));
4087 0 : return NT_STATUS_INVALID_PARAMETER;
4088 : }
4089 :
4090 2939 : ctx = talloc_tos();
4091 2939 : ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4092 2939 : if (!ea_list) {
4093 8 : return NT_STATUS_INVALID_PARAMETER;
4094 : }
4095 :
4096 2931 : if (fsp == NULL) {
4097 : /*
4098 : * The only way fsp can be NULL here is if
4099 : * smb_fname points at a symlink and
4100 : * and we're in POSIX context.
4101 : * Ensure this is the case.
4102 : *
4103 : * In this case we cannot set the EA.
4104 : */
4105 0 : SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4106 0 : return NT_STATUS_ACCESS_DENIED;
4107 : }
4108 :
4109 2931 : status = set_ea(conn, fsp, ea_list);
4110 :
4111 2931 : return status;
4112 : }
4113 :
4114 : /****************************************************************************
4115 : Deal with SMB_FILE_FULL_EA_INFORMATION set.
4116 : ****************************************************************************/
4117 :
4118 12 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4119 : const char *pdata,
4120 : int total_data,
4121 : files_struct *fsp)
4122 : {
4123 12 : struct ea_list *ea_list = NULL;
4124 0 : NTSTATUS status;
4125 :
4126 12 : if (fsp == NULL) {
4127 0 : return NT_STATUS_INVALID_HANDLE;
4128 : }
4129 :
4130 12 : if (!lp_ea_support(SNUM(conn))) {
4131 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4132 : "EA's not supported.\n",
4133 : (unsigned int)total_data));
4134 0 : return NT_STATUS_EAS_NOT_SUPPORTED;
4135 : }
4136 :
4137 12 : if (total_data < 10) {
4138 0 : DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4139 : "too small.\n",
4140 : (unsigned int)total_data));
4141 0 : return NT_STATUS_INVALID_PARAMETER;
4142 : }
4143 :
4144 12 : ea_list = read_nttrans_ea_list(talloc_tos(),
4145 : pdata,
4146 : total_data);
4147 :
4148 12 : if (!ea_list) {
4149 0 : return NT_STATUS_INVALID_PARAMETER;
4150 : }
4151 :
4152 12 : status = set_ea(conn, fsp, ea_list);
4153 :
4154 12 : DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4155 : smb_fname_str_dbg(fsp->fsp_name),
4156 : nt_errstr(status) ));
4157 :
4158 12 : return status;
4159 : }
4160 :
4161 :
4162 : /****************************************************************************
4163 : Deal with SMB_SET_FILE_DISPOSITION_INFO.
4164 : ****************************************************************************/
4165 :
4166 3810 : NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4167 : const char *pdata,
4168 : int total_data,
4169 : files_struct *fsp,
4170 : struct smb_filename *smb_fname)
4171 : {
4172 3810 : NTSTATUS status = NT_STATUS_OK;
4173 21 : bool delete_on_close;
4174 3810 : uint32_t dosmode = 0;
4175 :
4176 3810 : if (total_data < 1) {
4177 0 : return NT_STATUS_INVALID_PARAMETER;
4178 : }
4179 :
4180 3810 : if (fsp == NULL) {
4181 0 : return NT_STATUS_INVALID_HANDLE;
4182 : }
4183 :
4184 3810 : delete_on_close = (CVAL(pdata,0) ? True : False);
4185 3810 : dosmode = fdos_mode(fsp);
4186 :
4187 3810 : DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4188 : "delete_on_close = %u\n",
4189 : smb_fname_str_dbg(smb_fname),
4190 : (unsigned int)dosmode,
4191 : (unsigned int)delete_on_close ));
4192 :
4193 3810 : if (delete_on_close) {
4194 3755 : status = can_set_delete_on_close(fsp, dosmode);
4195 3755 : if (!NT_STATUS_IS_OK(status)) {
4196 88 : return status;
4197 : }
4198 : }
4199 :
4200 : /* The set is across all open files on this dev/inode pair. */
4201 3722 : if (!set_delete_on_close(fsp, delete_on_close,
4202 3722 : conn->session_info->security_token,
4203 3722 : conn->session_info->unix_token)) {
4204 8 : return NT_STATUS_ACCESS_DENIED;
4205 : }
4206 3714 : return NT_STATUS_OK;
4207 : }
4208 :
4209 : /****************************************************************************
4210 : Deal with SMB_FILE_POSITION_INFORMATION.
4211 : ****************************************************************************/
4212 :
4213 94 : static NTSTATUS smb_file_position_information(connection_struct *conn,
4214 : const char *pdata,
4215 : int total_data,
4216 : files_struct *fsp)
4217 : {
4218 2 : uint64_t position_information;
4219 :
4220 94 : if (total_data < 8) {
4221 0 : return NT_STATUS_INVALID_PARAMETER;
4222 : }
4223 :
4224 94 : if (fsp == NULL) {
4225 : /* Ignore on pathname based set. */
4226 0 : return NT_STATUS_OK;
4227 : }
4228 :
4229 94 : position_information = (uint64_t)IVAL(pdata,0);
4230 94 : position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4231 :
4232 94 : DEBUG(10,("smb_file_position_information: Set file position "
4233 : "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4234 : (double)position_information));
4235 94 : fh_set_position_information(fsp->fh, position_information);
4236 94 : return NT_STATUS_OK;
4237 : }
4238 :
4239 : /****************************************************************************
4240 : Deal with SMB_FILE_MODE_INFORMATION.
4241 : ****************************************************************************/
4242 :
4243 8 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
4244 : const char *pdata,
4245 : int total_data)
4246 : {
4247 0 : uint32_t mode;
4248 :
4249 8 : if (total_data < 4) {
4250 0 : return NT_STATUS_INVALID_PARAMETER;
4251 : }
4252 8 : mode = IVAL(pdata,0);
4253 8 : if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4254 0 : return NT_STATUS_INVALID_PARAMETER;
4255 : }
4256 8 : return NT_STATUS_OK;
4257 : }
4258 :
4259 : /****************************************************************************
4260 : Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4261 : ****************************************************************************/
4262 :
4263 791 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4264 : struct smb_request *req,
4265 : const char *pdata,
4266 : int total_data,
4267 : files_struct *fsp,
4268 : struct smb_filename *smb_fname_src)
4269 : {
4270 0 : bool overwrite;
4271 0 : uint32_t len;
4272 791 : char *newname = NULL;
4273 791 : struct files_struct *dst_dirfsp = NULL;
4274 791 : struct smb_filename *smb_fname_dst = NULL;
4275 791 : const char *dst_original_lcomp = NULL;
4276 791 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4277 791 : NTSTATUS status = NT_STATUS_OK;
4278 791 : TALLOC_CTX *ctx = talloc_tos();
4279 :
4280 791 : if (!fsp) {
4281 0 : return NT_STATUS_INVALID_HANDLE;
4282 : }
4283 :
4284 791 : if (total_data < 20) {
4285 0 : return NT_STATUS_INVALID_PARAMETER;
4286 : }
4287 :
4288 791 : overwrite = (CVAL(pdata,0) ? True : False);
4289 791 : len = IVAL(pdata,16);
4290 :
4291 791 : if (len > (total_data - 20) || (len == 0)) {
4292 0 : return NT_STATUS_INVALID_PARAMETER;
4293 : }
4294 :
4295 791 : (void)srvstr_pull_talloc(ctx,
4296 : pdata,
4297 : req->flags2,
4298 : &newname,
4299 : &pdata[20],
4300 : len,
4301 : STR_TERMINATE);
4302 :
4303 791 : if (newname == NULL) {
4304 0 : return NT_STATUS_INVALID_PARAMETER;
4305 : }
4306 :
4307 : /* SMB2 rename paths are never DFS. */
4308 791 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4309 791 : ucf_flags &= ~UCF_DFS_PATHNAME;
4310 :
4311 791 : status = check_path_syntax(newname,
4312 791 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4313 791 : if (!NT_STATUS_IS_OK(status)) {
4314 0 : return status;
4315 : }
4316 :
4317 791 : DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4318 : newname));
4319 :
4320 791 : if (newname[0] == ':') {
4321 : /* Create an smb_fname to call rename_internals_fsp() with. */
4322 16 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4323 16 : fsp->base_fsp->fsp_name->base_name,
4324 : newname,
4325 : NULL,
4326 16 : fsp->base_fsp->fsp_name->twrp,
4327 16 : fsp->base_fsp->fsp_name->flags);
4328 16 : if (smb_fname_dst == NULL) {
4329 0 : status = NT_STATUS_NO_MEMORY;
4330 0 : goto out;
4331 : }
4332 : } else {
4333 775 : status = filename_convert_dirfsp(ctx,
4334 : conn,
4335 : newname,
4336 : ucf_flags,
4337 : 0, /* Never a TWRP. */
4338 : &dst_dirfsp,
4339 : &smb_fname_dst);
4340 775 : if (!NT_STATUS_IS_OK(status)) {
4341 130 : goto out;
4342 : }
4343 : }
4344 :
4345 : /*
4346 : * Set the original last component, since
4347 : * rename_internals_fsp() requires it.
4348 : */
4349 661 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4350 : conn,
4351 : newname,
4352 : ucf_flags);
4353 661 : if (dst_original_lcomp == NULL) {
4354 0 : status = NT_STATUS_NO_MEMORY;
4355 0 : goto out;
4356 : }
4357 :
4358 661 : DEBUG(10,("smb2_file_rename_information: "
4359 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4360 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4361 : smb_fname_str_dbg(smb_fname_dst)));
4362 661 : status = rename_internals_fsp(conn,
4363 : fsp,
4364 : smb_fname_dst,
4365 : dst_original_lcomp,
4366 : (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4367 : overwrite);
4368 :
4369 791 : out:
4370 791 : TALLOC_FREE(smb_fname_dst);
4371 791 : return status;
4372 : }
4373 :
4374 18 : static NTSTATUS smb2_file_link_information(connection_struct *conn,
4375 : struct smb_request *req,
4376 : const char *pdata,
4377 : int total_data,
4378 : files_struct *fsp,
4379 : struct smb_filename *smb_fname_src)
4380 : {
4381 0 : bool overwrite;
4382 0 : uint32_t len;
4383 18 : char *newname = NULL;
4384 18 : struct files_struct *dst_dirfsp = NULL;
4385 18 : struct smb_filename *smb_fname_dst = NULL;
4386 18 : NTSTATUS status = NT_STATUS_OK;
4387 18 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4388 0 : size_t ret;
4389 18 : TALLOC_CTX *ctx = talloc_tos();
4390 :
4391 18 : if (!fsp) {
4392 0 : return NT_STATUS_INVALID_HANDLE;
4393 : }
4394 :
4395 18 : if (total_data < 20) {
4396 0 : return NT_STATUS_INVALID_PARAMETER;
4397 : }
4398 :
4399 18 : overwrite = (CVAL(pdata,0) ? true : false);
4400 18 : len = IVAL(pdata,16);
4401 :
4402 18 : if (len > (total_data - 20) || (len == 0)) {
4403 0 : return NT_STATUS_INVALID_PARAMETER;
4404 : }
4405 :
4406 18 : ret = srvstr_pull_talloc(ctx,
4407 : pdata,
4408 : req->flags2,
4409 : &newname,
4410 : &pdata[20],
4411 : len,
4412 : STR_TERMINATE);
4413 :
4414 18 : if (ret == (size_t)-1 || newname == NULL) {
4415 0 : return NT_STATUS_INVALID_PARAMETER;
4416 : }
4417 :
4418 : /* SMB2 hardlink paths are never DFS. */
4419 18 : req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4420 18 : ucf_flags &= ~UCF_DFS_PATHNAME;
4421 :
4422 18 : status = check_path_syntax(newname,
4423 18 : fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4424 18 : if (!NT_STATUS_IS_OK(status)) {
4425 0 : return status;
4426 : }
4427 :
4428 18 : DBG_DEBUG("got name |%s|\n", newname);
4429 :
4430 18 : status = filename_convert_dirfsp(ctx,
4431 : conn,
4432 : newname,
4433 : ucf_flags,
4434 : 0, /* No TWRP. */
4435 : &dst_dirfsp,
4436 : &smb_fname_dst);
4437 18 : if (!NT_STATUS_IS_OK(status)) {
4438 2 : return status;
4439 : }
4440 :
4441 16 : if (fsp->base_fsp) {
4442 : /* No stream names. */
4443 0 : return NT_STATUS_NOT_SUPPORTED;
4444 : }
4445 :
4446 16 : DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4447 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4448 : smb_fname_str_dbg(smb_fname_dst));
4449 16 : status = hardlink_internals(ctx,
4450 : conn,
4451 : req,
4452 : overwrite,
4453 16 : fsp->fsp_name,
4454 : smb_fname_dst);
4455 :
4456 16 : TALLOC_FREE(smb_fname_dst);
4457 16 : return status;
4458 : }
4459 :
4460 8 : static NTSTATUS smb_file_link_information(connection_struct *conn,
4461 : struct smb_request *req,
4462 : const char *pdata,
4463 : int total_data,
4464 : files_struct *fsp,
4465 : struct smb_filename *smb_fname_src)
4466 : {
4467 0 : bool overwrite;
4468 0 : uint32_t len;
4469 8 : char *newname = NULL;
4470 8 : struct files_struct *dst_dirfsp = NULL;
4471 8 : struct smb_filename *smb_fname_dst = NULL;
4472 8 : NTSTATUS status = NT_STATUS_OK;
4473 8 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4474 8 : NTTIME dst_twrp = 0;
4475 8 : TALLOC_CTX *ctx = talloc_tos();
4476 :
4477 8 : if (!fsp) {
4478 0 : return NT_STATUS_INVALID_HANDLE;
4479 : }
4480 :
4481 8 : if (total_data < 20) {
4482 0 : return NT_STATUS_INVALID_PARAMETER;
4483 : }
4484 :
4485 8 : overwrite = (CVAL(pdata,0) ? true : false);
4486 8 : len = IVAL(pdata,16);
4487 :
4488 8 : if (len > (total_data - 20) || (len == 0)) {
4489 8 : return NT_STATUS_INVALID_PARAMETER;
4490 : }
4491 :
4492 0 : if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4493 0 : srvstr_get_path_posix(ctx,
4494 : pdata,
4495 0 : req->flags2,
4496 : &newname,
4497 : &pdata[20],
4498 : len,
4499 : STR_TERMINATE,
4500 : &status);
4501 0 : ucf_flags |= UCF_POSIX_PATHNAMES;
4502 : } else {
4503 0 : srvstr_get_path(ctx,
4504 : pdata,
4505 0 : req->flags2,
4506 : &newname,
4507 : &pdata[20],
4508 : len,
4509 : STR_TERMINATE,
4510 : &status);
4511 : }
4512 0 : if (!NT_STATUS_IS_OK(status)) {
4513 0 : return status;
4514 : }
4515 :
4516 0 : DEBUG(10,("smb_file_link_information: got name |%s|\n",
4517 : newname));
4518 :
4519 0 : if (ucf_flags & UCF_GMT_PATHNAME) {
4520 0 : extract_snapshot_token(newname, &dst_twrp);
4521 : }
4522 : /* hardlink paths are never DFS. */
4523 0 : ucf_flags &= ~UCF_DFS_PATHNAME;
4524 :
4525 0 : status = filename_convert_dirfsp(ctx,
4526 : conn,
4527 : newname,
4528 : ucf_flags,
4529 : dst_twrp,
4530 : &dst_dirfsp,
4531 : &smb_fname_dst);
4532 0 : if (!NT_STATUS_IS_OK(status)) {
4533 0 : return status;
4534 : }
4535 :
4536 0 : if (fsp->base_fsp) {
4537 : /* No stream names. */
4538 0 : return NT_STATUS_NOT_SUPPORTED;
4539 : }
4540 :
4541 0 : DEBUG(10,("smb_file_link_information: "
4542 : "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4543 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4544 : smb_fname_str_dbg(smb_fname_dst)));
4545 0 : status = hardlink_internals(ctx,
4546 : conn,
4547 : req,
4548 : overwrite,
4549 0 : fsp->fsp_name,
4550 : smb_fname_dst);
4551 :
4552 0 : TALLOC_FREE(smb_fname_dst);
4553 0 : return status;
4554 : }
4555 :
4556 :
4557 : /****************************************************************************
4558 : Deal with SMB_FILE_RENAME_INFORMATION.
4559 : ****************************************************************************/
4560 :
4561 139 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
4562 : struct smb_request *req,
4563 : const char *pdata,
4564 : int total_data,
4565 : files_struct *fsp,
4566 : struct smb_filename *smb_fname_src)
4567 : {
4568 3 : bool overwrite;
4569 3 : uint32_t root_fid;
4570 3 : uint32_t len;
4571 139 : char *newname = NULL;
4572 139 : struct files_struct *dst_dirfsp = NULL;
4573 139 : struct smb_filename *smb_fname_dst = NULL;
4574 139 : const char *dst_original_lcomp = NULL;
4575 139 : NTSTATUS status = NT_STATUS_OK;
4576 3 : char *p;
4577 139 : TALLOC_CTX *ctx = talloc_tos();
4578 :
4579 139 : if (total_data < 13) {
4580 0 : return NT_STATUS_INVALID_PARAMETER;
4581 : }
4582 :
4583 139 : overwrite = (CVAL(pdata,0) != 0);
4584 139 : root_fid = IVAL(pdata,4);
4585 139 : len = IVAL(pdata,8);
4586 :
4587 139 : if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4588 12 : return NT_STATUS_INVALID_PARAMETER;
4589 : }
4590 :
4591 127 : if (req->posix_pathnames) {
4592 0 : srvstr_get_path_posix(ctx,
4593 : pdata,
4594 0 : req->flags2,
4595 : &newname,
4596 : &pdata[12],
4597 : len,
4598 : 0,
4599 : &status);
4600 : } else {
4601 127 : srvstr_get_path(ctx,
4602 : pdata,
4603 127 : req->flags2,
4604 : &newname,
4605 : &pdata[12],
4606 : len,
4607 : 0,
4608 : &status);
4609 : }
4610 127 : if (!NT_STATUS_IS_OK(status)) {
4611 0 : return status;
4612 : }
4613 :
4614 127 : DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4615 : newname));
4616 :
4617 : /* Check the new name has no '/' characters. */
4618 127 : if (strchr_m(newname, '/')) {
4619 8 : return NT_STATUS_NOT_SUPPORTED;
4620 : }
4621 :
4622 119 : if (fsp && fsp->base_fsp) {
4623 : /* newname must be a stream name. */
4624 28 : if (newname[0] != ':') {
4625 0 : return NT_STATUS_NOT_SUPPORTED;
4626 : }
4627 :
4628 : /* Create an smb_fname to call rename_internals_fsp() with. */
4629 28 : smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4630 28 : fsp->base_fsp->fsp_name->base_name,
4631 : newname,
4632 : NULL,
4633 28 : fsp->base_fsp->fsp_name->twrp,
4634 28 : fsp->base_fsp->fsp_name->flags);
4635 28 : if (smb_fname_dst == NULL) {
4636 0 : status = NT_STATUS_NO_MEMORY;
4637 0 : goto out;
4638 : }
4639 :
4640 : /*
4641 : * Get the original last component, since
4642 : * rename_internals_fsp() requires it.
4643 : */
4644 28 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4645 : conn,
4646 : newname,
4647 : 0);
4648 28 : if (dst_original_lcomp == NULL) {
4649 0 : status = NT_STATUS_NO_MEMORY;
4650 0 : goto out;
4651 : }
4652 :
4653 : } else {
4654 : /*
4655 : * Build up an smb_fname_dst based on the filename passed in.
4656 : * We basically just strip off the last component, and put on
4657 : * the newname instead.
4658 : */
4659 91 : char *base_name = NULL;
4660 91 : uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4661 91 : NTTIME dst_twrp = 0;
4662 :
4663 : /* newname must *not* be a stream name. */
4664 91 : if (newname[0] == ':') {
4665 0 : return NT_STATUS_NOT_SUPPORTED;
4666 : }
4667 :
4668 : /*
4669 : * Strip off the last component (filename) of the path passed
4670 : * in.
4671 : */
4672 91 : base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4673 91 : if (!base_name) {
4674 0 : return NT_STATUS_NO_MEMORY;
4675 : }
4676 91 : p = strrchr_m(base_name, '/');
4677 91 : if (p) {
4678 80 : p[1] = '\0';
4679 : } else {
4680 11 : base_name = talloc_strdup(ctx, "");
4681 11 : if (!base_name) {
4682 0 : return NT_STATUS_NO_MEMORY;
4683 : }
4684 : }
4685 : /* Append the new name. */
4686 91 : base_name = talloc_asprintf_append(base_name,
4687 : "%s",
4688 : newname);
4689 91 : if (!base_name) {
4690 0 : return NT_STATUS_NO_MEMORY;
4691 : }
4692 :
4693 91 : if (ucf_flags & UCF_GMT_PATHNAME) {
4694 0 : extract_snapshot_token(base_name, &dst_twrp);
4695 : }
4696 :
4697 : /* The newname is *not* a DFS path. */
4698 91 : ucf_flags &= ~UCF_DFS_PATHNAME;
4699 :
4700 91 : status = filename_convert_dirfsp(ctx,
4701 : conn,
4702 : base_name,
4703 : ucf_flags,
4704 : dst_twrp,
4705 : &dst_dirfsp,
4706 : &smb_fname_dst);
4707 :
4708 91 : if (!NT_STATUS_IS_OK(status)) {
4709 0 : goto out;
4710 : }
4711 91 : dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4712 : conn,
4713 : newname,
4714 : ucf_flags);
4715 91 : if (dst_original_lcomp == NULL) {
4716 0 : status = NT_STATUS_NO_MEMORY;
4717 0 : goto out;
4718 : }
4719 : }
4720 :
4721 119 : if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4722 80 : DEBUG(10,("smb_file_rename_information: "
4723 : "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4724 : fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4725 : smb_fname_str_dbg(smb_fname_dst)));
4726 80 : status = rename_internals_fsp(conn,
4727 : fsp,
4728 : smb_fname_dst,
4729 : dst_original_lcomp,
4730 : 0,
4731 : overwrite);
4732 : } else {
4733 39 : DEBUG(10,("smb_file_rename_information: "
4734 : "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4735 : smb_fname_str_dbg(smb_fname_src),
4736 : smb_fname_str_dbg(smb_fname_dst)));
4737 39 : status = rename_internals(ctx,
4738 : conn,
4739 : req,
4740 : NULL, /* src_dirfsp */
4741 : smb_fname_src,
4742 : smb_fname_dst,
4743 : dst_original_lcomp,
4744 : 0,
4745 : overwrite,
4746 : FILE_WRITE_ATTRIBUTES);
4747 : }
4748 119 : out:
4749 119 : TALLOC_FREE(smb_fname_dst);
4750 119 : return status;
4751 : }
4752 :
4753 : /****************************************************************************
4754 : Deal with SMB_SET_FILE_BASIC_INFO.
4755 : ****************************************************************************/
4756 :
4757 2828 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4758 : const char *pdata,
4759 : int total_data,
4760 : files_struct *fsp,
4761 : struct smb_filename *smb_fname)
4762 : {
4763 : /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4764 31 : struct smb_file_time ft;
4765 2828 : uint32_t dosmode = 0;
4766 2828 : NTSTATUS status = NT_STATUS_OK;
4767 :
4768 2828 : init_smb_file_time(&ft);
4769 :
4770 2828 : if (total_data < 36) {
4771 0 : return NT_STATUS_INVALID_PARAMETER;
4772 : }
4773 :
4774 2828 : if (fsp == NULL) {
4775 0 : return NT_STATUS_INVALID_HANDLE;
4776 : }
4777 :
4778 2828 : status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4779 2828 : if (!NT_STATUS_IS_OK(status)) {
4780 4 : return status;
4781 : }
4782 :
4783 : /* Set the attributes */
4784 2824 : dosmode = IVAL(pdata,32);
4785 2824 : status = smb_set_file_dosmode(conn, fsp, dosmode);
4786 2824 : if (!NT_STATUS_IS_OK(status)) {
4787 5 : return status;
4788 : }
4789 :
4790 : /* create time */
4791 2819 : ft.create_time = pull_long_date_full_timespec(pdata);
4792 :
4793 : /* access time */
4794 2819 : ft.atime = pull_long_date_full_timespec(pdata+8);
4795 :
4796 : /* write time. */
4797 2819 : ft.mtime = pull_long_date_full_timespec(pdata+16);
4798 :
4799 : /* change time. */
4800 2819 : ft.ctime = pull_long_date_full_timespec(pdata+24);
4801 :
4802 2819 : DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4803 : smb_fname_str_dbg(smb_fname)));
4804 :
4805 2819 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4806 2819 : if (!NT_STATUS_IS_OK(status)) {
4807 0 : return status;
4808 : }
4809 :
4810 2819 : if (fsp->fsp_flags.modified) {
4811 1076 : trigger_write_time_update_immediate(fsp);
4812 : }
4813 2819 : return NT_STATUS_OK;
4814 : }
4815 :
4816 : /****************************************************************************
4817 : Deal with SMB_INFO_STANDARD.
4818 : ****************************************************************************/
4819 :
4820 8 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
4821 : const char *pdata,
4822 : int total_data,
4823 : files_struct *fsp,
4824 : struct smb_filename *smb_fname)
4825 : {
4826 0 : NTSTATUS status;
4827 0 : struct smb_file_time ft;
4828 :
4829 8 : init_smb_file_time(&ft);
4830 :
4831 8 : if (total_data < 12) {
4832 0 : return NT_STATUS_INVALID_PARAMETER;
4833 : }
4834 :
4835 8 : if (fsp == NULL) {
4836 0 : return NT_STATUS_INVALID_HANDLE;
4837 : }
4838 :
4839 : /* create time */
4840 8 : ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4841 : /* access time */
4842 8 : ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4843 : /* write time */
4844 8 : ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4845 :
4846 8 : DEBUG(10,("smb_set_info_standard: file %s\n",
4847 : smb_fname_str_dbg(smb_fname)));
4848 :
4849 8 : status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4850 8 : if (!NT_STATUS_IS_OK(status)) {
4851 4 : return status;
4852 : }
4853 :
4854 4 : status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4855 4 : if (!NT_STATUS_IS_OK(status)) {
4856 0 : return status;
4857 : }
4858 :
4859 4 : if (fsp->fsp_flags.modified) {
4860 0 : trigger_write_time_update_immediate(fsp);
4861 : }
4862 4 : return NT_STATUS_OK;
4863 : }
4864 :
4865 : /****************************************************************************
4866 : Deal with SMB_SET_FILE_ALLOCATION_INFO.
4867 : ****************************************************************************/
4868 :
4869 16 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4870 : struct smb_request *req,
4871 : const char *pdata,
4872 : int total_data,
4873 : files_struct *fsp,
4874 : struct smb_filename *smb_fname)
4875 : {
4876 16 : uint64_t allocation_size = 0;
4877 16 : NTSTATUS status = NT_STATUS_OK;
4878 16 : files_struct *new_fsp = NULL;
4879 :
4880 16 : if (!VALID_STAT(smb_fname->st)) {
4881 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4882 : }
4883 :
4884 16 : if (total_data < 8) {
4885 0 : return NT_STATUS_INVALID_PARAMETER;
4886 : }
4887 :
4888 16 : allocation_size = (uint64_t)IVAL(pdata,0);
4889 16 : allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4890 16 : DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4891 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4892 : (double)allocation_size));
4893 :
4894 16 : if (allocation_size) {
4895 6 : allocation_size = smb_roundup(conn, allocation_size);
4896 : }
4897 :
4898 16 : DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4899 : "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4900 : (double)allocation_size));
4901 :
4902 16 : if (fsp &&
4903 20 : !fsp->fsp_flags.is_pathref &&
4904 4 : fsp_get_io_fd(fsp) != -1)
4905 : {
4906 : /* Open file handle. */
4907 4 : if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4908 0 : return NT_STATUS_ACCESS_DENIED;
4909 : }
4910 :
4911 : /* Only change if needed. */
4912 4 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4913 4 : if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4914 0 : return map_nt_error_from_unix(errno);
4915 : }
4916 : }
4917 : /* But always update the time. */
4918 : /*
4919 : * This is equivalent to a write. Ensure it's seen immediately
4920 : * if there are no pending writes.
4921 : */
4922 4 : trigger_write_time_update_immediate(fsp);
4923 4 : return NT_STATUS_OK;
4924 : }
4925 :
4926 : /* Pathname or stat or directory file. */
4927 12 : status = SMB_VFS_CREATE_FILE(
4928 : conn, /* conn */
4929 : req, /* req */
4930 : NULL, /* dirfsp */
4931 : smb_fname, /* fname */
4932 : FILE_WRITE_DATA, /* access_mask */
4933 : (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4934 : FILE_SHARE_DELETE),
4935 : FILE_OPEN, /* create_disposition*/
4936 : 0, /* create_options */
4937 : FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4938 : 0, /* oplock_request */
4939 : NULL, /* lease */
4940 : 0, /* allocation_size */
4941 : 0, /* private_flags */
4942 : NULL, /* sd */
4943 : NULL, /* ea_list */
4944 : &new_fsp, /* result */
4945 : NULL, /* pinfo */
4946 : NULL, NULL); /* create context */
4947 :
4948 12 : if (!NT_STATUS_IS_OK(status)) {
4949 : /* NB. We check for open_was_deferred in the caller. */
4950 10 : return status;
4951 : }
4952 :
4953 : /* Only change if needed. */
4954 2 : if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4955 2 : if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4956 0 : status = map_nt_error_from_unix(errno);
4957 0 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4958 0 : return status;
4959 : }
4960 : }
4961 :
4962 : /* Changing the allocation size should set the last mod time. */
4963 : /*
4964 : * This is equivalent to a write. Ensure it's seen immediately
4965 : * if there are no pending writes.
4966 : */
4967 2 : trigger_write_time_update_immediate(new_fsp);
4968 2 : close_file_free(req, &new_fsp, NORMAL_CLOSE);
4969 2 : return NT_STATUS_OK;
4970 : }
4971 :
4972 : /****************************************************************************
4973 : Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4974 : ****************************************************************************/
4975 :
4976 331 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4977 : struct smb_request *req,
4978 : const char *pdata,
4979 : int total_data,
4980 : files_struct *fsp,
4981 : struct smb_filename *smb_fname,
4982 : bool fail_after_createfile)
4983 : {
4984 1 : off_t size;
4985 :
4986 331 : if (total_data < 8) {
4987 0 : return NT_STATUS_INVALID_PARAMETER;
4988 : }
4989 :
4990 331 : size = IVAL(pdata,0);
4991 331 : size |= (((off_t)IVAL(pdata,4)) << 32);
4992 331 : DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4993 : "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4994 : (double)size));
4995 :
4996 331 : return smb_set_file_size(conn, req,
4997 : fsp,
4998 : smb_fname,
4999 331 : &smb_fname->st,
5000 : size,
5001 : fail_after_createfile);
5002 : }
5003 :
5004 10778 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5005 : struct smb_request *req,
5006 : TALLOC_CTX *mem_ctx,
5007 : uint16_t info_level,
5008 : files_struct *fsp,
5009 : struct smb_filename *smb_fname,
5010 : char **ppdata, int total_data,
5011 : int *ret_data_size)
5012 : {
5013 10778 : char *pdata = *ppdata;
5014 10778 : NTSTATUS status = NT_STATUS_OK;
5015 10778 : int data_return_size = 0;
5016 :
5017 10778 : *ret_data_size = 0;
5018 :
5019 10778 : DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5020 : "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5021 : fsp_fnum_dbg(fsp),
5022 : info_level, total_data));
5023 :
5024 10778 : switch (info_level) {
5025 :
5026 8 : case SMB_INFO_STANDARD:
5027 : {
5028 8 : status = smb_set_info_standard(conn,
5029 : pdata,
5030 : total_data,
5031 : fsp,
5032 : smb_fname);
5033 8 : break;
5034 : }
5035 :
5036 2939 : case SMB_INFO_SET_EA:
5037 : {
5038 2939 : status = smb_info_set_ea(conn,
5039 : pdata,
5040 : total_data,
5041 : fsp,
5042 : smb_fname);
5043 2939 : break;
5044 : }
5045 :
5046 2828 : case SMB_SET_FILE_BASIC_INFO:
5047 : case SMB_FILE_BASIC_INFORMATION:
5048 : {
5049 2828 : status = smb_set_file_basic_info(conn,
5050 : pdata,
5051 : total_data,
5052 : fsp,
5053 : smb_fname);
5054 2828 : break;
5055 : }
5056 :
5057 16 : case SMB_FILE_ALLOCATION_INFORMATION:
5058 : case SMB_SET_FILE_ALLOCATION_INFO:
5059 : {
5060 16 : status = smb_set_file_allocation_info(conn, req,
5061 : pdata,
5062 : total_data,
5063 : fsp,
5064 : smb_fname);
5065 16 : break;
5066 : }
5067 :
5068 331 : case SMB_FILE_END_OF_FILE_INFORMATION:
5069 : case SMB_SET_FILE_END_OF_FILE_INFO:
5070 : {
5071 : /*
5072 : * XP/Win7 both fail after the createfile with
5073 : * SMB_SET_FILE_END_OF_FILE_INFO but not
5074 : * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5075 : * The level is known here, so pass it down
5076 : * appropriately.
5077 : */
5078 331 : bool should_fail =
5079 : (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5080 :
5081 331 : status = smb_set_file_end_of_file_info(conn, req,
5082 : pdata,
5083 : total_data,
5084 : fsp,
5085 : smb_fname,
5086 : should_fail);
5087 331 : break;
5088 : }
5089 :
5090 3570 : case SMB_FILE_DISPOSITION_INFORMATION:
5091 : case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5092 : {
5093 : #if 0
5094 : /* JRA - We used to just ignore this on a path ?
5095 : * Shouldn't this be invalid level on a pathname
5096 : * based call ?
5097 : */
5098 : if (tran_call != TRANSACT2_SETFILEINFO) {
5099 : return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5100 : }
5101 : #endif
5102 3570 : status = smb_set_file_disposition_info(conn,
5103 : pdata,
5104 : total_data,
5105 : fsp,
5106 : smb_fname);
5107 3570 : break;
5108 : }
5109 :
5110 94 : case SMB_FILE_POSITION_INFORMATION:
5111 : {
5112 94 : status = smb_file_position_information(conn,
5113 : pdata,
5114 : total_data,
5115 : fsp);
5116 94 : break;
5117 : }
5118 :
5119 12 : case SMB_FILE_FULL_EA_INFORMATION:
5120 : {
5121 12 : status = smb_set_file_full_ea_info(conn,
5122 : pdata,
5123 : total_data,
5124 : fsp);
5125 12 : break;
5126 : }
5127 :
5128 : /* From tridge Samba4 :
5129 : * MODE_INFORMATION in setfileinfo (I have no
5130 : * idea what "mode information" on a file is - it takes a value of 0,
5131 : * 2, 4 or 6. What could it be?).
5132 : */
5133 :
5134 8 : case SMB_FILE_MODE_INFORMATION:
5135 : {
5136 8 : status = smb_file_mode_information(conn,
5137 : pdata,
5138 : total_data);
5139 8 : break;
5140 : }
5141 :
5142 : /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5143 8 : case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5144 : case SMB_FILE_SHORT_NAME_INFORMATION:
5145 16 : return NT_STATUS_NOT_SUPPORTED;
5146 :
5147 139 : case SMB_FILE_RENAME_INFORMATION:
5148 : {
5149 139 : status = smb_file_rename_information(conn, req,
5150 : pdata, total_data,
5151 : fsp, smb_fname);
5152 139 : break;
5153 : }
5154 :
5155 791 : case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5156 : {
5157 : /* SMB2 rename information. */
5158 791 : status = smb2_file_rename_information(conn, req,
5159 : pdata, total_data,
5160 : fsp, smb_fname);
5161 791 : break;
5162 : }
5163 :
5164 26 : case SMB_FILE_LINK_INFORMATION:
5165 : {
5166 26 : if (conn->sconn->using_smb2) {
5167 18 : status = smb2_file_link_information(conn,
5168 : req,
5169 : pdata,
5170 : total_data,
5171 : fsp,
5172 : smb_fname);
5173 : } else {
5174 8 : status = smb_file_link_information(conn,
5175 : req,
5176 : pdata,
5177 : total_data,
5178 : fsp,
5179 : smb_fname);
5180 : }
5181 26 : break;
5182 : }
5183 :
5184 8 : default:
5185 8 : return NT_STATUS_INVALID_LEVEL;
5186 : }
5187 :
5188 10762 : if (!NT_STATUS_IS_OK(status)) {
5189 663 : return status;
5190 : }
5191 :
5192 10099 : *ret_data_size = data_return_size;
5193 10099 : return NT_STATUS_OK;
5194 : }
5195 :
5196 130 : static uint32_t generate_volume_serial_number(
5197 : const struct loadparm_substitution *lp_sub,
5198 : int snum)
5199 : {
5200 130 : int serial = lp_volume_serial_number(snum);
5201 258 : return serial != -1 ? serial:
5202 128 : str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5203 128 : (str_checksum(get_local_machine_name())<<16);
5204 : }
|