s3: smbd: Add utility function smb2_strip_dfs_path().
[Samba.git] / source3 / smbd / smb2_reply.c
blob7bd4b4a5a18326ec2b689a2f731859043b26cceb
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
43 #include "auth.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
53 #include "source3/lib/substitute.h"
55 /****************************************************************************
56 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
57 path or anything including wildcards.
58 We're assuming here that '/' is not the second byte in any multibyte char
59 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
60 set.
61 ****************************************************************************/
63 /* Custom version for processing POSIX paths. */
64 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
66 static NTSTATUS check_path_syntax_internal(char *path,
67 bool posix_path)
69 char *d = path;
70 const char *s = path;
71 NTSTATUS ret = NT_STATUS_OK;
72 bool start_of_name_component = True;
73 bool stream_started = false;
74 bool last_component_contains_wcard = false;
76 while (*s) {
77 if (stream_started) {
78 switch (*s) {
79 case '/':
80 case '\\':
81 return NT_STATUS_OBJECT_NAME_INVALID;
82 case ':':
83 if (s[1] == '\0') {
84 return NT_STATUS_OBJECT_NAME_INVALID;
86 if (strchr_m(&s[1], ':')) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 break;
93 if ((*s == ':') && !posix_path && !stream_started) {
94 if (last_component_contains_wcard) {
95 return NT_STATUS_OBJECT_NAME_INVALID;
97 /* Stream names allow more characters than file names.
98 We're overloading posix_path here to allow a wider
99 range of characters. If stream_started is true this
100 is still a Windows path even if posix_path is true.
101 JRA.
103 stream_started = true;
104 start_of_name_component = false;
105 posix_path = true;
107 if (s[1] == '\0') {
108 return NT_STATUS_OBJECT_NAME_INVALID;
112 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
114 * Safe to assume is not the second part of a mb char
115 * as this is handled below.
117 /* Eat multiple '/' or '\\' */
118 while (IS_PATH_SEP(*s,posix_path)) {
119 s++;
121 if ((d != path) && (*s != '\0')) {
122 /* We only care about non-leading or trailing '/' or '\\' */
123 *d++ = '/';
126 start_of_name_component = True;
127 /* New component. */
128 last_component_contains_wcard = false;
129 continue;
132 if (start_of_name_component) {
133 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
134 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
137 * No mb char starts with '.' so we're safe checking the directory separator here.
140 /* If we just added a '/' - delete it */
141 if ((d > path) && (*(d-1) == '/')) {
142 *(d-1) = '\0';
143 d--;
146 /* Are we at the start ? Can't go back further if so. */
147 if (d <= path) {
148 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
149 break;
151 /* Go back one level... */
152 /* We know this is safe as '/' cannot be part of a mb sequence. */
153 /* NOTE - if this assumption is invalid we are not in good shape... */
154 /* Decrement d first as d points to the *next* char to write into. */
155 for (d--; d > path; d--) {
156 if (*d == '/')
157 break;
159 s += 2; /* Else go past the .. */
160 /* We're still at the start of a name component, just the previous one. */
161 continue;
163 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
164 if (posix_path) {
165 /* Eat the '.' */
166 s++;
167 continue;
173 if (!(*s & 0x80)) {
174 if (!posix_path) {
175 if (*s <= 0x1f || *s == '|') {
176 return NT_STATUS_OBJECT_NAME_INVALID;
178 switch (*s) {
179 case '*':
180 case '?':
181 case '<':
182 case '>':
183 case '"':
184 last_component_contains_wcard = true;
185 break;
186 default:
187 break;
190 *d++ = *s++;
191 } else {
192 size_t siz;
193 /* Get the size of the next MB character. */
194 next_codepoint(s,&siz);
195 switch(siz) {
196 case 5:
197 *d++ = *s++;
198 FALL_THROUGH;
199 case 4:
200 *d++ = *s++;
201 FALL_THROUGH;
202 case 3:
203 *d++ = *s++;
204 FALL_THROUGH;
205 case 2:
206 *d++ = *s++;
207 FALL_THROUGH;
208 case 1:
209 *d++ = *s++;
210 break;
211 default:
212 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
213 *d = '\0';
214 return NT_STATUS_INVALID_PARAMETER;
217 start_of_name_component = False;
220 *d = '\0';
222 return ret;
225 /****************************************************************************
226 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
227 No wildcards allowed.
228 ****************************************************************************/
230 NTSTATUS check_path_syntax(char *path)
232 return check_path_syntax_internal(path, false);
235 /****************************************************************************
236 Check the path for a POSIX client.
237 We're assuming here that '/' is not the second byte in any multibyte char
238 set (a safe assumption).
239 ****************************************************************************/
241 NTSTATUS check_path_syntax_posix(char *path)
243 return check_path_syntax_internal(path, true);
246 /****************************************************************************
247 Check the path for an SMB2 DFS path.
248 SMB2 DFS paths look like hostname\share (followed by a possible \extrapath.
249 Path returned from here must look like:
250 hostname/share (followed by a possible /extrapath).
251 ****************************************************************************/
253 static NTSTATUS check_path_syntax_smb2_msdfs(char *path)
255 char *share = NULL;
256 char *remaining_path = NULL;
257 /* No SMB2 names can start with '\\' */
258 if (path[0] == '\\') {
259 return NT_STATUS_OBJECT_NAME_INVALID;
262 * smbclient libraries sometimes set the DFS flag and send
263 * local pathnames. Cope with this by just calling
264 * check_path_syntax() on the whole path if it doesn't
265 * look like a DFS path, similar to what parse_dfs_path() does.
267 /* servername should be at path[0] */
268 share = strchr(path, '\\');
269 if (share == NULL) {
270 return check_path_syntax(path);
272 *share++ = '/';
273 remaining_path = strchr(share, '\\');
274 if (remaining_path == NULL) {
275 /* Only hostname\share. We're done. */
276 return NT_STATUS_OK;
278 *remaining_path++ = '/';
279 return check_path_syntax(remaining_path);
282 NTSTATUS check_path_syntax_smb2(char *path, bool dfs_path)
284 if (dfs_path) {
285 return check_path_syntax_smb2_msdfs(path);
286 } else {
287 return check_path_syntax(path);
291 /****************************************************************************
292 SMB2-only code to strip an MSDFS prefix from an incoming pathname.
293 ****************************************************************************/
295 NTSTATUS smb2_strip_dfs_path(const char *in_path, const char **out_path)
297 const char *path = in_path;
299 /* Match the Windows 2022 behavior for an empty DFS pathname. */
300 if (*path == '\0') {
301 return NT_STATUS_INVALID_PARAMETER;
303 /* Stip any leading '\\' characters - MacOSX client behavior. */
304 while (*path == '\\') {
305 path++;
307 /* We should now be pointing at the server name. Go past it. */
308 for (;;) {
309 if (*path == '\0') {
310 /* End of complete path. Exit OK. */
311 goto out;
313 if (*path == '\\') {
314 /* End of server name. Go past and break. */
315 path++;
316 break;
318 path++; /* Continue looking for end of server name or string. */
321 /* We should now be pointing at the share name. Go past it. */
322 for (;;) {
323 if (*path == '\0') {
324 /* End of complete path. Exit OK. */
325 goto out;
327 if (*path == '\\') {
328 /* End of share name. Go past and break. */
329 path++;
330 break;
332 if (*path == ':') {
333 /* Only invalid character in sharename. */
334 return NT_STATUS_OBJECT_NAME_INVALID;
336 path++; /* Continue looking for end of share name or string. */
339 /* path now points at the start of the real filename (if any). */
341 out:
342 /* We have stripped the DFS path prefix (if any). */
343 *out_path = path;
344 return NT_STATUS_OK;
347 /****************************************************************************
348 Pull a string and check the path allowing a wildcard - provide for error return.
349 Passes in posix flag.
350 ****************************************************************************/
352 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
353 const char *base_ptr,
354 uint16_t smb_flags2,
355 char **pp_dest,
356 const char *src,
357 size_t src_len,
358 int flags,
359 bool posix_pathnames,
360 NTSTATUS *err)
362 size_t ret;
363 char *dst = NULL;
365 *pp_dest = NULL;
367 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
368 src_len, flags);
370 if (!*pp_dest) {
371 *err = NT_STATUS_INVALID_PARAMETER;
372 return ret;
375 dst = *pp_dest;
377 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
379 * A valid DFS path looks either like
380 * /server/share
381 * \server\share
382 * (there may be more components after).
383 * Either way it must have at least two separators.
385 * Ensure we end up as /server/share
386 * so we don't need to special case
387 * separator characters elsewhere in
388 * the code.
390 char *server = NULL;
391 char *share = NULL;
392 char *remaining_path = NULL;
393 char path_sep = 0;
395 if (posix_pathnames && (dst[0] == '/')) {
396 path_sep = dst[0];
397 } else if (dst[0] == '\\') {
398 path_sep = dst[0];
401 if (path_sep == 0) {
402 goto local_path;
405 * May be a DFS path.
406 * We need some heuristics here,
407 * as clients differ on what constitutes
408 * a well-formed DFS path. If the path
409 * appears malformed, just fall back to
410 * processing as a local path.
412 server = dst;
415 * Cosmetic fix for Linux-only DFS clients.
416 * The Linux kernel SMB1 client has a bug - it sends
417 * DFS pathnames as:
419 * \\server\share\path
421 * Causing us to mis-parse server,share,remaining_path here
422 * and jump into 'goto local_path' at 'share\path' instead
423 * of 'path'.
425 * This doesn't cause an error as the limits on share names
426 * are similar to those on pathnames.
428 * parse_dfs_path() which we call before filename parsing
429 * copes with this by calling trim_char on the leading '\'
430 * characters before processing.
431 * Do the same here so logging of pathnames looks better.
433 if (server[1] == path_sep) {
434 trim_char(&server[1], path_sep, '\0');
438 * Look to see if we also have /share following.
440 share = strchr(server+1, path_sep);
441 if (share == NULL) {
442 goto local_path;
445 * It's a well formed DFS path with
446 * at least server and share components.
447 * Replace the slashes with '/' and
448 * pass the remainder to local_path.
450 *server = '/';
451 *share = '/';
453 * Skip past share so we don't pass the
454 * sharename into check_path_syntax().
456 remaining_path = strchr(share+1, path_sep);
457 if (remaining_path == NULL) {
459 * If no remaining path this was
460 * a bare /server/share path. Just return.
462 *err = NT_STATUS_OK;
463 return ret;
465 *remaining_path = '/';
466 dst = remaining_path + 1;
467 /* dst now points at any following components. */
470 local_path:
472 if (posix_pathnames) {
473 *err = check_path_syntax_posix(dst);
474 } else {
475 *err = check_path_syntax(dst);
478 return ret;
481 /****************************************************************************
482 Pull a string and check the path - provide for error return.
483 ****************************************************************************/
485 size_t srvstr_get_path(TALLOC_CTX *ctx,
486 const char *base_ptr,
487 uint16_t smb_flags2,
488 char **pp_dest,
489 const char *src,
490 size_t src_len,
491 int flags,
492 NTSTATUS *err)
494 return srvstr_get_path_internal(ctx,
495 base_ptr,
496 smb_flags2,
497 pp_dest,
498 src,
499 src_len,
500 flags,
501 false,
502 err);
505 /****************************************************************************
506 Pull a string and check the path - provide for error return.
507 posix_pathnames version.
508 ****************************************************************************/
510 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
511 const char *base_ptr,
512 uint16_t smb_flags2,
513 char **pp_dest,
514 const char *src,
515 size_t src_len,
516 int flags,
517 NTSTATUS *err)
519 return srvstr_get_path_internal(ctx,
520 base_ptr,
521 smb_flags2,
522 pp_dest,
523 src,
524 src_len,
525 flags,
526 true,
527 err);
531 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
532 char **pp_dest, const char *src, int flags,
533 NTSTATUS *err)
535 ssize_t bufrem = smbreq_bufrem(req, src);
537 if (bufrem == 0) {
538 *err = NT_STATUS_INVALID_PARAMETER;
539 return 0;
542 if (req->posix_pathnames) {
543 return srvstr_get_path_internal(mem_ctx,
544 (const char *)req->inbuf,
545 req->flags2,
546 pp_dest,
547 src,
548 bufrem,
549 flags,
550 true,
551 err);
552 } else {
553 return srvstr_get_path_internal(mem_ctx,
554 (const char *)req->inbuf,
555 req->flags2,
556 pp_dest,
557 src,
558 bufrem,
559 flags,
560 false,
561 err);
566 * pull a string from the smb_buf part of a packet. In this case the
567 * string can either be null terminated or it can be terminated by the
568 * end of the smbbuf area
570 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
571 char **dest, const uint8_t *src, int flags)
573 ssize_t bufrem = smbreq_bufrem(req, src);
575 if (bufrem == 0) {
576 return 0;
579 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
580 bufrem, flags);
583 /****************************************************************************
584 Check if we have a correct fsp pointing to a quota fake file. Replacement for
585 the CHECK_NTQUOTA_HANDLE_OK macro.
586 ****************************************************************************/
588 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
589 files_struct *fsp)
591 if ((fsp == NULL) || (conn == NULL)) {
592 return false;
595 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
596 return false;
599 if (fsp->fsp_flags.is_directory) {
600 return false;
603 if (fsp->fake_file_handle == NULL) {
604 return false;
607 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
608 return false;
611 if (fsp->fake_file_handle->private_data == NULL) {
612 return false;
615 return true;
618 /****************************************************************************
619 Return the port number we've bound to on a socket.
620 ****************************************************************************/
622 static int get_socket_port(int fd)
624 struct samba_sockaddr saddr = {
625 .sa_socklen = sizeof(struct sockaddr_storage),
628 if (fd == -1) {
629 return -1;
632 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
633 int level = (errno == ENOTCONN) ? 2 : 0;
634 DEBUG(level, ("getsockname failed. Error was %s\n",
635 strerror(errno)));
636 return -1;
639 #if defined(HAVE_IPV6)
640 if (saddr.u.sa.sa_family == AF_INET6) {
641 return ntohs(saddr.u.in6.sin6_port);
643 #endif
644 if (saddr.u.sa.sa_family == AF_INET) {
645 return ntohs(saddr.u.in.sin_port);
647 return -1;
650 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
651 const char *name, int name_type)
653 char *trim_name;
654 char *trim_name_type;
655 const char *retarget_parm;
656 char *retarget;
657 char *p;
658 int retarget_type = 0x20;
659 int retarget_port = NBT_SMB_PORT;
660 struct sockaddr_storage retarget_addr;
661 struct sockaddr_in *in_addr;
662 bool ret = false;
663 uint8_t outbuf[10];
665 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
666 return false;
669 trim_name = talloc_strdup(talloc_tos(), name);
670 if (trim_name == NULL) {
671 goto fail;
673 trim_char(trim_name, ' ', ' ');
675 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
676 name_type);
677 if (trim_name_type == NULL) {
678 goto fail;
681 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
682 trim_name_type, NULL);
683 if (retarget_parm == NULL) {
684 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
685 trim_name, NULL);
687 if (retarget_parm == NULL) {
688 goto fail;
691 retarget = talloc_strdup(trim_name, retarget_parm);
692 if (retarget == NULL) {
693 goto fail;
696 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
698 p = strchr(retarget, ':');
699 if (p != NULL) {
700 *p++ = '\0';
701 retarget_port = atoi(p);
704 p = strchr_m(retarget, '#');
705 if (p != NULL) {
706 *p++ = '\0';
707 if (sscanf(p, "%x", &retarget_type) != 1) {
708 goto fail;
712 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
713 if (!ret) {
714 DEBUG(10, ("could not resolve %s\n", retarget));
715 goto fail;
718 if (retarget_addr.ss_family != AF_INET) {
719 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
720 goto fail;
723 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
725 _smb_setlen(outbuf, 6);
726 SCVAL(outbuf, 0, 0x84);
727 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
728 *(uint16_t *)(outbuf+8) = htons(retarget_port);
730 if (!smb1_srv_send(xconn, (char *)outbuf, false, 0, false,
731 NULL)) {
732 exit_server_cleanly("netbios_session_retarget: smb1_srv_send "
733 "failed.");
736 ret = true;
737 fail:
738 TALLOC_FREE(trim_name);
739 return ret;
742 static void reply_called_name_not_present(char *outbuf)
744 smb_setlen(outbuf, 1);
745 SCVAL(outbuf, 0, 0x83);
746 SCVAL(outbuf, 4, 0x82);
749 /****************************************************************************
750 Reply to a (netbios-level) special message.
751 ****************************************************************************/
753 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
755 struct smbd_server_connection *sconn = xconn->client->sconn;
756 int msg_type = CVAL(inbuf,0);
757 int msg_flags = CVAL(inbuf,1);
759 * We only really use 4 bytes of the outbuf, but for the smb_setlen
760 * calculation & friends (smb1_srv_send uses that) we need the full smb
761 * header.
763 char outbuf[smb_size];
765 memset(outbuf, '\0', sizeof(outbuf));
767 smb_setlen(outbuf,0);
769 switch (msg_type) {
770 case NBSSrequest: /* session request */
772 /* inbuf_size is guarenteed to be at least 4. */
773 fstring name1,name2;
774 int name_type1, name_type2;
775 int name_len1, name_len2;
777 *name1 = *name2 = 0;
779 if (xconn->transport.nbt.got_session) {
780 exit_server_cleanly("multiple session request not permitted");
783 SCVAL(outbuf,0,NBSSpositive);
784 SCVAL(outbuf,3,0);
786 /* inbuf_size is guaranteed to be at least 4. */
787 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
788 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
789 DEBUG(0,("Invalid name length in session request\n"));
790 reply_called_name_not_present(outbuf);
791 break;
793 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
794 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
795 DEBUG(0,("Invalid name length in session request\n"));
796 reply_called_name_not_present(outbuf);
797 break;
800 name_type1 = name_extract((unsigned char *)inbuf,
801 inbuf_size,(unsigned int)4,name1);
802 name_type2 = name_extract((unsigned char *)inbuf,
803 inbuf_size,(unsigned int)(4 + name_len1),name2);
805 if (name_type1 == -1 || name_type2 == -1) {
806 DEBUG(0,("Invalid name type in session request\n"));
807 reply_called_name_not_present(outbuf);
808 break;
811 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
812 name1, name_type1, name2, name_type2));
814 if (netbios_session_retarget(xconn, name1, name_type1)) {
815 exit_server_cleanly("retargeted client");
819 * Windows NT/2k uses "*SMBSERVER" and XP uses
820 * "*SMBSERV" arrggg!!!
822 if (strequal(name1, "*SMBSERVER ")
823 || strequal(name1, "*SMBSERV ")) {
824 char *raddr;
826 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
827 talloc_tos());
828 if (raddr == NULL) {
829 exit_server_cleanly("could not allocate raddr");
832 fstrcpy(name1, raddr);
835 set_local_machine_name(name1, True);
836 set_remote_machine_name(name2, True);
838 if (is_ipaddress(sconn->remote_hostname)) {
839 char *p = discard_const_p(char, sconn->remote_hostname);
841 talloc_free(p);
843 sconn->remote_hostname = talloc_strdup(sconn,
844 get_remote_machine_name());
845 if (sconn->remote_hostname == NULL) {
846 exit_server_cleanly("could not copy remote name");
848 xconn->remote_hostname = sconn->remote_hostname;
851 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
852 get_local_machine_name(), get_remote_machine_name(),
853 name_type2));
855 if (name_type2 == 'R') {
856 /* We are being asked for a pathworks session ---
857 no thanks! */
858 reply_called_name_not_present(outbuf);
859 break;
862 reload_services(sconn, conn_snum_used, true);
863 reopen_logs();
865 xconn->transport.nbt.got_session = true;
866 break;
869 case 0x89: /* session keepalive request
870 (some old clients produce this?) */
871 SCVAL(outbuf,0,NBSSkeepalive);
872 SCVAL(outbuf,3,0);
873 break;
875 case NBSSpositive: /* positive session response */
876 case NBSSnegative: /* negative session response */
877 case NBSSretarget: /* retarget session response */
878 DEBUG(0,("Unexpected session response\n"));
879 break;
881 case NBSSkeepalive: /* session keepalive */
882 default:
883 return;
886 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
887 msg_type, msg_flags));
889 if (!smb1_srv_send(xconn, outbuf, false, 0, false, NULL)) {
890 exit_server_cleanly("reply_special: smb1_srv_send failed.");
893 if (CVAL(outbuf, 0) != 0x82) {
894 exit_server_cleanly("invalid netbios session");
896 return;
899 /*******************************************************************
900 * unlink a file with all relevant access checks
901 *******************************************************************/
903 NTSTATUS unlink_internals(connection_struct *conn,
904 struct smb_request *req,
905 uint32_t dirtype,
906 struct files_struct *dirfsp,
907 struct smb_filename *smb_fname)
909 uint32_t fattr;
910 files_struct *fsp;
911 uint32_t dirtype_orig = dirtype;
912 NTSTATUS status;
913 int ret;
914 struct smb2_create_blobs *posx = NULL;
916 if (dirtype == 0) {
917 dirtype = FILE_ATTRIBUTE_NORMAL;
920 DBG_DEBUG("%s, dirtype = %d\n",
921 smb_fname_str_dbg(smb_fname),
922 dirtype);
924 if (!CAN_WRITE(conn)) {
925 return NT_STATUS_MEDIA_WRITE_PROTECTED;
928 ret = vfs_stat(conn, smb_fname);
929 if (ret != 0) {
930 return map_nt_error_from_unix(errno);
933 fattr = fdos_mode(smb_fname->fsp);
935 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
936 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
939 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
940 if (!dirtype) {
941 return NT_STATUS_NO_SUCH_FILE;
944 if (!dir_check_ftype(fattr, dirtype)) {
945 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
946 return NT_STATUS_FILE_IS_A_DIRECTORY;
948 return NT_STATUS_NO_SUCH_FILE;
951 if (dirtype_orig & 0x8000) {
952 /* These will never be set for POSIX. */
953 return NT_STATUS_NO_SUCH_FILE;
956 #if 0
957 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
958 return NT_STATUS_FILE_IS_A_DIRECTORY;
961 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
962 return NT_STATUS_NO_SUCH_FILE;
965 if (dirtype & 0xFF00) {
966 /* These will never be set for POSIX. */
967 return NT_STATUS_NO_SUCH_FILE;
970 dirtype &= 0xFF;
971 if (!dirtype) {
972 return NT_STATUS_NO_SUCH_FILE;
975 /* Can't delete a directory. */
976 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
977 return NT_STATUS_FILE_IS_A_DIRECTORY;
979 #endif
981 #if 0 /* JRATEST */
982 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
983 return NT_STATUS_OBJECT_NAME_INVALID;
984 #endif /* JRATEST */
986 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
987 status = make_smb2_posix_create_ctx(
988 talloc_tos(), &posx, 0777);
989 if (!NT_STATUS_IS_OK(status)) {
990 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
991 nt_errstr(status));
992 return status;
996 /* On open checks the open itself will check the share mode, so
997 don't do it here as we'll get it wrong. */
999 status = SMB_VFS_CREATE_FILE
1000 (conn, /* conn */
1001 req, /* req */
1002 dirfsp, /* dirfsp */
1003 smb_fname, /* fname */
1004 DELETE_ACCESS, /* access_mask */
1005 FILE_SHARE_NONE, /* share_access */
1006 FILE_OPEN, /* create_disposition*/
1007 FILE_NON_DIRECTORY_FILE, /* create_options */
1008 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1009 0, /* oplock_request */
1010 NULL, /* lease */
1011 0, /* allocation_size */
1012 0, /* private_flags */
1013 NULL, /* sd */
1014 NULL, /* ea_list */
1015 &fsp, /* result */
1016 NULL, /* pinfo */
1017 posx, /* in_context_blobs */
1018 NULL); /* out_context_blobs */
1020 TALLOC_FREE(posx);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
1024 nt_errstr(status));
1025 return status;
1028 status = can_set_delete_on_close(fsp, fattr);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 DBG_DEBUG("can_set_delete_on_close for file %s - "
1031 "(%s)\n",
1032 smb_fname_str_dbg(smb_fname),
1033 nt_errstr(status));
1034 close_file_free(req, &fsp, NORMAL_CLOSE);
1035 return status;
1038 /* The set is across all open files on this dev/inode pair. */
1039 if (!set_delete_on_close(fsp, True,
1040 conn->session_info->security_token,
1041 conn->session_info->unix_token)) {
1042 close_file_free(req, &fsp, NORMAL_CLOSE);
1043 return NT_STATUS_ACCESS_DENIED;
1046 return close_file_free(req, &fsp, NORMAL_CLOSE);
1049 /****************************************************************************
1050 Fake (read/write) sendfile. Returns -1 on read or write fail.
1051 ****************************************************************************/
1053 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
1054 off_t startpos, size_t nread)
1056 size_t bufsize;
1057 size_t tosend = nread;
1058 char *buf;
1060 if (nread == 0) {
1061 return 0;
1064 bufsize = MIN(nread, 65536);
1066 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
1067 return -1;
1070 while (tosend > 0) {
1071 ssize_t ret;
1072 size_t cur_read;
1074 cur_read = MIN(tosend, bufsize);
1075 ret = read_file(fsp,buf,startpos,cur_read);
1076 if (ret == -1) {
1077 SAFE_FREE(buf);
1078 return -1;
1081 /* If we had a short read, fill with zeros. */
1082 if (ret < cur_read) {
1083 memset(buf + ret, '\0', cur_read - ret);
1086 ret = write_data(xconn->transport.sock, buf, cur_read);
1087 if (ret != cur_read) {
1088 int saved_errno = errno;
1090 * Try and give an error message saying what
1091 * client failed.
1093 DEBUG(0, ("write_data failed for client %s. "
1094 "Error %s\n",
1095 smbXsrv_connection_dbg(xconn),
1096 strerror(saved_errno)));
1097 SAFE_FREE(buf);
1098 errno = saved_errno;
1099 return -1;
1101 tosend -= cur_read;
1102 startpos += cur_read;
1105 SAFE_FREE(buf);
1106 return (ssize_t)nread;
1109 /****************************************************************************
1110 Deal with the case of sendfile reading less bytes from the file than
1111 requested. Fill with zeros (all we can do). Returns 0 on success
1112 ****************************************************************************/
1114 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
1115 files_struct *fsp,
1116 ssize_t nread,
1117 size_t headersize,
1118 size_t smb_maxcnt)
1120 #define SHORT_SEND_BUFSIZE 1024
1121 if (nread < headersize) {
1122 DEBUG(0,("sendfile_short_send: sendfile failed to send "
1123 "header for file %s (%s). Terminating\n",
1124 fsp_str_dbg(fsp), strerror(errno)));
1125 return -1;
1128 nread -= headersize;
1130 if (nread < smb_maxcnt) {
1131 char buf[SHORT_SEND_BUFSIZE] = { 0 };
1133 DEBUG(0,("sendfile_short_send: filling truncated file %s "
1134 "with zeros !\n", fsp_str_dbg(fsp)));
1136 while (nread < smb_maxcnt) {
1138 * We asked for the real file size and told sendfile
1139 * to not go beyond the end of the file. But it can
1140 * happen that in between our fstat call and the
1141 * sendfile call the file was truncated. This is very
1142 * bad because we have already announced the larger
1143 * number of bytes to the client.
1145 * The best we can do now is to send 0-bytes, just as
1146 * a read from a hole in a sparse file would do.
1148 * This should happen rarely enough that I don't care
1149 * about efficiency here :-)
1151 size_t to_write;
1152 ssize_t ret;
1154 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
1155 ret = write_data(xconn->transport.sock, buf, to_write);
1156 if (ret != to_write) {
1157 int saved_errno = errno;
1159 * Try and give an error message saying what
1160 * client failed.
1162 DEBUG(0, ("write_data failed for client %s. "
1163 "Error %s\n",
1164 smbXsrv_connection_dbg(xconn),
1165 strerror(saved_errno)));
1166 errno = saved_errno;
1167 return -1;
1169 nread += to_write;
1173 return 0;
1176 /*******************************************************************
1177 Check if a user is allowed to rename a file.
1178 ********************************************************************/
1180 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1181 uint16_t dirtype)
1183 if (!CAN_WRITE(conn)) {
1184 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1187 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
1188 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1189 /* Only bother to read the DOS attribute if we might deny the
1190 rename on the grounds of attribute mismatch. */
1191 uint32_t fmode = fdos_mode(fsp);
1192 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1193 return NT_STATUS_NO_SUCH_FILE;
1197 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1198 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
1199 return NT_STATUS_OK;
1202 /* If no pathnames are open below this
1203 directory, allow the rename. */
1205 if (lp_strict_rename(SNUM(conn))) {
1207 * Strict rename, check open file db.
1209 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
1210 return NT_STATUS_ACCESS_DENIED;
1212 } else if (file_find_subpath(fsp)) {
1214 * No strict rename, just look in local process.
1216 return NT_STATUS_ACCESS_DENIED;
1218 return NT_STATUS_OK;
1221 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
1222 return NT_STATUS_OK;
1225 return NT_STATUS_ACCESS_DENIED;
1228 /****************************************************************************
1229 Ensure open files have their names updated. Updated to notify other smbd's
1230 asynchronously.
1231 ****************************************************************************/
1233 static void rename_open_files(connection_struct *conn,
1234 struct share_mode_lock *lck,
1235 struct file_id id,
1236 uint32_t orig_name_hash,
1237 const struct smb_filename *smb_fname_dst)
1239 files_struct *fsp;
1240 bool did_rename = False;
1241 NTSTATUS status;
1242 uint32_t new_name_hash = 0;
1244 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
1245 fsp = file_find_di_next(fsp, false)) {
1246 SMB_STRUCT_STAT fsp_orig_sbuf;
1247 struct file_id_buf idbuf;
1248 /* fsp_name is a relative path under the fsp. To change this for other
1249 sharepaths we need to manipulate relative paths. */
1250 /* TODO - create the absolute path and manipulate the newname
1251 relative to the sharepath. */
1252 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
1253 continue;
1255 if (fsp->name_hash != orig_name_hash) {
1256 continue;
1258 DBG_DEBUG("renaming file %s "
1259 "(file_id %s) from %s -> %s\n",
1260 fsp_fnum_dbg(fsp),
1261 file_id_str_buf(fsp->file_id, &idbuf),
1262 fsp_str_dbg(fsp),
1263 smb_fname_str_dbg(smb_fname_dst));
1266 * The incoming smb_fname_dst here has an
1267 * invalid stat struct (it must not have
1268 * existed for the rename to succeed).
1269 * Preserve the existing stat from the
1270 * open fsp after fsp_set_smb_fname()
1271 * overwrites with the invalid stat.
1273 * We will do an fstat before returning
1274 * any of this metadata to the client anyway.
1276 fsp_orig_sbuf = fsp->fsp_name->st;
1277 status = fsp_set_smb_fname(fsp, smb_fname_dst);
1278 if (NT_STATUS_IS_OK(status)) {
1279 did_rename = True;
1280 new_name_hash = fsp->name_hash;
1281 /* Restore existing stat. */
1282 fsp->fsp_name->st = fsp_orig_sbuf;
1286 if (!did_rename) {
1287 struct file_id_buf idbuf;
1288 DBG_DEBUG("no open files on file_id %s "
1289 "for %s\n",
1290 file_id_str_buf(id, &idbuf),
1291 smb_fname_str_dbg(smb_fname_dst));
1294 /* Send messages to all smbd's (not ourself) that the name has changed. */
1295 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
1296 orig_name_hash, new_name_hash,
1297 smb_fname_dst);
1301 /****************************************************************************
1302 We need to check if the source path is a parent directory of the destination
1303 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
1304 refuse the rename with a sharing violation. Under UNIX the above call can
1305 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
1306 probably need to check that the client is a Windows one before disallowing
1307 this as a UNIX client (one with UNIX extensions) can know the source is a
1308 symlink and make this decision intelligently. Found by an excellent bug
1309 report from <AndyLiebman@aol.com>.
1310 ****************************************************************************/
1312 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
1313 const struct smb_filename *smb_fname_dst)
1315 const char *psrc = smb_fname_src->base_name;
1316 const char *pdst = smb_fname_dst->base_name;
1317 size_t slen;
1319 if (psrc[0] == '.' && psrc[1] == '/') {
1320 psrc += 2;
1322 if (pdst[0] == '.' && pdst[1] == '/') {
1323 pdst += 2;
1325 if ((slen = strlen(psrc)) > strlen(pdst)) {
1326 return False;
1328 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
1332 * Do the notify calls from a rename
1335 static void notify_rename(connection_struct *conn, bool is_dir,
1336 const struct smb_filename *smb_fname_src,
1337 const struct smb_filename *smb_fname_dst)
1339 char *parent_dir_src = NULL;
1340 char *parent_dir_dst = NULL;
1341 uint32_t mask;
1343 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
1344 : FILE_NOTIFY_CHANGE_FILE_NAME;
1346 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
1347 &parent_dir_src, NULL) ||
1348 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
1349 &parent_dir_dst, NULL)) {
1350 goto out;
1353 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
1354 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
1355 smb_fname_src->base_name);
1356 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
1357 smb_fname_dst->base_name);
1359 else {
1360 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
1361 smb_fname_src->base_name);
1362 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
1363 smb_fname_dst->base_name);
1366 /* this is a strange one. w2k3 gives an additional event for
1367 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
1368 files, but not directories */
1369 if (!is_dir) {
1370 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
1371 FILE_NOTIFY_CHANGE_ATTRIBUTES
1372 |FILE_NOTIFY_CHANGE_CREATION,
1373 smb_fname_dst->base_name);
1375 out:
1376 TALLOC_FREE(parent_dir_src);
1377 TALLOC_FREE(parent_dir_dst);
1380 /****************************************************************************
1381 Returns an error if the parent directory for a filename is open in an
1382 incompatible way.
1383 ****************************************************************************/
1385 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
1386 const struct smb_filename *smb_fname_dst_in)
1388 struct smb_filename *smb_fname_parent = NULL;
1389 struct file_id id;
1390 files_struct *fsp = NULL;
1391 int ret;
1392 NTSTATUS status;
1394 status = SMB_VFS_PARENT_PATHNAME(conn,
1395 talloc_tos(),
1396 smb_fname_dst_in,
1397 &smb_fname_parent,
1398 NULL);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 return status;
1403 ret = vfs_stat(conn, smb_fname_parent);
1404 if (ret == -1) {
1405 return map_nt_error_from_unix(errno);
1409 * We're only checking on this smbd here, mostly good
1410 * enough.. and will pass tests.
1413 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
1414 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
1415 fsp = file_find_di_next(fsp, true)) {
1416 if (fsp->access_mask & DELETE_ACCESS) {
1417 return NT_STATUS_SHARING_VIOLATION;
1420 return NT_STATUS_OK;
1423 /****************************************************************************
1424 Rename an open file - given an fsp.
1425 ****************************************************************************/
1427 NTSTATUS rename_internals_fsp(connection_struct *conn,
1428 files_struct *fsp,
1429 struct files_struct *dst_dirfsp,
1430 struct smb_filename *smb_fname_dst_in,
1431 const char *dst_original_lcomp,
1432 uint32_t attrs,
1433 bool replace_if_exists)
1435 TALLOC_CTX *ctx = talloc_tos();
1436 struct smb_filename *parent_dir_fname_dst = NULL;
1437 struct smb_filename *parent_dir_fname_dst_atname = NULL;
1438 struct smb_filename *parent_dir_fname_src = NULL;
1439 struct smb_filename *parent_dir_fname_src_atname = NULL;
1440 struct smb_filename *smb_fname_dst = NULL;
1441 NTSTATUS status = NT_STATUS_OK;
1442 struct share_mode_lock *lck = NULL;
1443 uint32_t access_mask = SEC_DIR_ADD_FILE;
1444 bool dst_exists, old_is_stream, new_is_stream;
1445 int ret;
1446 bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1447 true : conn->case_sensitive;
1448 bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1449 true : conn->case_preserve;
1451 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 return status;
1456 if (file_has_open_streams(fsp)) {
1457 return NT_STATUS_ACCESS_DENIED;
1460 /* Make a copy of the dst smb_fname structs */
1462 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
1463 if (smb_fname_dst == NULL) {
1464 status = NT_STATUS_NO_MEMORY;
1465 goto out;
1469 * Check for special case with case preserving and not
1470 * case sensitive. If the new last component differs from the original
1471 * last component only by case, then we should allow
1472 * the rename (user is trying to change the case of the
1473 * filename).
1475 if (!case_sensitive && case_preserve &&
1476 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1477 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
1478 char *fname_dst_parent = NULL;
1479 const char *fname_dst_lcomp = NULL;
1480 char *orig_lcomp_path = NULL;
1481 char *orig_lcomp_stream = NULL;
1482 bool ok = true;
1485 * Split off the last component of the processed
1486 * destination name. We will compare this to
1487 * the split components of dst_original_lcomp.
1489 if (!parent_dirname(ctx,
1490 smb_fname_dst->base_name,
1491 &fname_dst_parent,
1492 &fname_dst_lcomp)) {
1493 status = NT_STATUS_NO_MEMORY;
1494 goto out;
1498 * The dst_original_lcomp component contains
1499 * the last_component of the path + stream
1500 * name (if a stream exists).
1502 * Split off the stream name so we
1503 * can check them separately.
1506 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
1507 /* POSIX - no stream component. */
1508 orig_lcomp_path = talloc_strdup(ctx,
1509 dst_original_lcomp);
1510 if (orig_lcomp_path == NULL) {
1511 ok = false;
1513 } else {
1514 ok = split_stream_filename(ctx,
1515 dst_original_lcomp,
1516 &orig_lcomp_path,
1517 &orig_lcomp_stream);
1520 if (!ok) {
1521 TALLOC_FREE(fname_dst_parent);
1522 status = NT_STATUS_NO_MEMORY;
1523 goto out;
1526 /* If the base names only differ by case, use original. */
1527 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
1528 char *tmp;
1530 * Replace the modified last component with the
1531 * original.
1533 if (!ISDOT(fname_dst_parent)) {
1534 tmp = talloc_asprintf(smb_fname_dst,
1535 "%s/%s",
1536 fname_dst_parent,
1537 orig_lcomp_path);
1538 } else {
1539 tmp = talloc_strdup(smb_fname_dst,
1540 orig_lcomp_path);
1542 if (tmp == NULL) {
1543 status = NT_STATUS_NO_MEMORY;
1544 TALLOC_FREE(fname_dst_parent);
1545 TALLOC_FREE(orig_lcomp_path);
1546 TALLOC_FREE(orig_lcomp_stream);
1547 goto out;
1549 TALLOC_FREE(smb_fname_dst->base_name);
1550 smb_fname_dst->base_name = tmp;
1553 /* If the stream_names only differ by case, use original. */
1554 if(!strcsequal(smb_fname_dst->stream_name,
1555 orig_lcomp_stream)) {
1556 /* Use the original stream. */
1557 char *tmp = talloc_strdup(smb_fname_dst,
1558 orig_lcomp_stream);
1559 if (tmp == NULL) {
1560 status = NT_STATUS_NO_MEMORY;
1561 TALLOC_FREE(fname_dst_parent);
1562 TALLOC_FREE(orig_lcomp_path);
1563 TALLOC_FREE(orig_lcomp_stream);
1564 goto out;
1566 TALLOC_FREE(smb_fname_dst->stream_name);
1567 smb_fname_dst->stream_name = tmp;
1569 TALLOC_FREE(fname_dst_parent);
1570 TALLOC_FREE(orig_lcomp_path);
1571 TALLOC_FREE(orig_lcomp_stream);
1575 * If the src and dest names are identical - including case,
1576 * don't do the rename, just return success.
1579 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1580 strcsequal(fsp->fsp_name->stream_name,
1581 smb_fname_dst->stream_name)) {
1582 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
1583 "- returning success\n",
1584 smb_fname_str_dbg(smb_fname_dst)));
1585 status = NT_STATUS_OK;
1586 goto out;
1589 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
1590 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
1592 /* Return the correct error code if both names aren't streams. */
1593 if (!old_is_stream && new_is_stream) {
1594 status = NT_STATUS_OBJECT_NAME_INVALID;
1595 goto out;
1598 if (old_is_stream && !new_is_stream) {
1599 status = NT_STATUS_INVALID_PARAMETER;
1600 goto out;
1603 dst_exists = vfs_stat(conn, smb_fname_dst) == 0;
1605 if(!replace_if_exists && dst_exists) {
1606 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
1607 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1608 smb_fname_str_dbg(smb_fname_dst)));
1609 status = NT_STATUS_OBJECT_NAME_COLLISION;
1610 goto out;
1614 * Drop the pathref fsp on the destination otherwise we trip upon in in
1615 * the below check for open files check.
1617 if (smb_fname_dst_in->fsp != NULL) {
1618 fd_close(smb_fname_dst_in->fsp);
1619 file_free(NULL, smb_fname_dst_in->fsp);
1620 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
1623 if (dst_exists) {
1624 struct file_id fileid = vfs_file_id_from_sbuf(conn,
1625 &smb_fname_dst->st);
1626 files_struct *dst_fsp = file_find_di_first(conn->sconn,
1627 fileid, true);
1628 /* The file can be open when renaming a stream */
1629 if (dst_fsp && !new_is_stream) {
1630 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
1631 status = NT_STATUS_ACCESS_DENIED;
1632 goto out;
1636 /* Ensure we have a valid stat struct for the source. */
1637 status = vfs_stat_fsp(fsp);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 goto out;
1642 status = can_rename(conn, fsp, attrs);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1646 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1647 smb_fname_str_dbg(smb_fname_dst)));
1648 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
1649 status = NT_STATUS_ACCESS_DENIED;
1650 goto out;
1653 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
1654 status = NT_STATUS_ACCESS_DENIED;
1655 goto out;
1658 /* Do we have rights to move into the destination ? */
1659 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1660 /* We're moving a directory. */
1661 access_mask = SEC_DIR_ADD_SUBDIR;
1665 * Get a pathref on the destination parent directory, so
1666 * we can call check_parent_access_fsp().
1668 status = parent_pathref(ctx,
1669 conn->cwd_fsp,
1670 smb_fname_dst,
1671 &parent_dir_fname_dst,
1672 &parent_dir_fname_dst_atname);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 goto out;
1677 status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
1678 access_mask);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 DBG_INFO("check_parent_access_fsp on "
1681 "dst %s returned %s\n",
1682 smb_fname_str_dbg(smb_fname_dst),
1683 nt_errstr(status));
1684 goto out;
1688 * If the target existed, make sure the destination
1689 * atname has the same stat struct.
1691 parent_dir_fname_dst_atname->st = smb_fname_dst->st;
1694 * It's very common that source and
1695 * destination directories are the same.
1696 * Optimize by not opening the
1697 * second parent_pathref if we know
1698 * this is the case.
1701 status = SMB_VFS_PARENT_PATHNAME(conn,
1702 ctx,
1703 fsp->fsp_name,
1704 &parent_dir_fname_src,
1705 &parent_dir_fname_src_atname);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 goto out;
1711 * We do a case-sensitive string comparison. We want to be *sure*
1712 * this is the same path. The worst that can happen if
1713 * the case doesn't match is we lose out on the optimization,
1714 * the code still works.
1716 * We can ignore twrp fields here. Rename is not allowed on
1717 * shadow copy handles.
1720 if (strcmp(parent_dir_fname_src->base_name,
1721 parent_dir_fname_dst->base_name) == 0) {
1723 * parent directory is the same for source
1724 * and destination.
1726 /* Reparent the src_atname to the parent_dir_dest fname. */
1727 parent_dir_fname_src_atname = talloc_move(
1728 parent_dir_fname_dst,
1729 &parent_dir_fname_src_atname);
1730 /* Free the unneeded duplicate parent name. */
1731 TALLOC_FREE(parent_dir_fname_src);
1733 * And make the source parent name a copy of the
1734 * destination parent name.
1736 parent_dir_fname_src = parent_dir_fname_dst;
1739 * Ensure we have a pathref fsp on the
1740 * parent_dir_fname_src_atname to match the code in the else
1741 * branch where we use parent_pathref().
1743 status = reference_smb_fname_fsp_link(
1744 parent_dir_fname_src_atname,
1745 fsp->fsp_name);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 goto out;
1749 } else {
1751 * source and destination parent directories are
1752 * different.
1754 * Get a pathref on the source parent directory, so
1755 * we can do a relative rename.
1757 TALLOC_FREE(parent_dir_fname_src);
1758 status = parent_pathref(ctx,
1759 conn->cwd_fsp,
1760 fsp->fsp_name,
1761 &parent_dir_fname_src,
1762 &parent_dir_fname_src_atname);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 goto out;
1769 * Some modules depend on the source smb_fname having a valid stat.
1770 * The parent_dir_fname_src_atname is the relative name of the
1771 * currently open file, so just copy the stat from the open fsp.
1773 parent_dir_fname_src_atname->st = fsp->fsp_name->st;
1775 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1778 * We have the file open ourselves, so not being able to get the
1779 * corresponding share mode lock is a fatal error.
1782 SMB_ASSERT(lck != NULL);
1784 ret = SMB_VFS_RENAMEAT(conn,
1785 parent_dir_fname_src->fsp,
1786 parent_dir_fname_src_atname,
1787 parent_dir_fname_dst->fsp,
1788 parent_dir_fname_dst_atname);
1789 if (ret == 0) {
1790 uint32_t create_options = fh_get_private_options(fsp->fh);
1792 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
1793 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1794 smb_fname_str_dbg(smb_fname_dst)));
1796 notify_rename(conn,
1797 fsp->fsp_flags.is_directory,
1798 fsp->fsp_name,
1799 smb_fname_dst);
1801 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
1802 smb_fname_dst);
1804 if (!fsp->fsp_flags.is_directory &&
1805 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
1806 (lp_map_archive(SNUM(conn)) ||
1807 lp_store_dos_attributes(SNUM(conn))))
1810 * We must set the archive bit on the newly renamed
1811 * file.
1813 status = vfs_stat_fsp(fsp);
1814 if (NT_STATUS_IS_OK(status)) {
1815 uint32_t old_dosmode;
1816 old_dosmode = fdos_mode(fsp);
1818 * We can use fsp->fsp_name here as it has
1819 * already been changed to the new name.
1821 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
1822 file_set_dosmode(conn,
1823 fsp->fsp_name,
1824 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
1825 NULL,
1826 true);
1831 * A rename acts as a new file create w.r.t. allowing an initial delete
1832 * on close, probably because in Windows there is a new handle to the
1833 * new file. If initial delete on close was requested but not
1834 * originally set, we need to set it here. This is probably not 100% correct,
1835 * but will work for the CIFSFS client which in non-posix mode
1836 * depends on these semantics. JRA.
1839 if (create_options & FILE_DELETE_ON_CLOSE) {
1840 status = can_set_delete_on_close(fsp, 0);
1842 if (NT_STATUS_IS_OK(status)) {
1843 /* Note that here we set the *initial* delete on close flag,
1844 * not the regular one. The magic gets handled in close. */
1845 fsp->fsp_flags.initial_delete_on_close = true;
1848 TALLOC_FREE(lck);
1849 status = NT_STATUS_OK;
1850 goto out;
1853 TALLOC_FREE(lck);
1855 if (errno == ENOTDIR || errno == EISDIR) {
1856 status = NT_STATUS_OBJECT_NAME_COLLISION;
1857 } else {
1858 status = map_nt_error_from_unix(errno);
1861 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1862 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1863 smb_fname_str_dbg(smb_fname_dst)));
1865 out:
1868 * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
1869 * See the optimization for same source and destination directory
1870 * above. Only free one in that case.
1872 if (parent_dir_fname_src != parent_dir_fname_dst) {
1873 TALLOC_FREE(parent_dir_fname_src);
1875 TALLOC_FREE(parent_dir_fname_dst);
1876 TALLOC_FREE(smb_fname_dst);
1878 return status;
1881 /****************************************************************************
1882 The guts of the rename command, split out so it may be called by the NT SMB
1883 code.
1884 ****************************************************************************/
1886 NTSTATUS rename_internals(TALLOC_CTX *ctx,
1887 connection_struct *conn,
1888 struct smb_request *req,
1889 struct files_struct *src_dirfsp,
1890 struct smb_filename *smb_fname_src,
1891 struct files_struct *dst_dirfsp,
1892 struct smb_filename *smb_fname_dst,
1893 const char *dst_original_lcomp,
1894 uint32_t attrs,
1895 bool replace_if_exists,
1896 uint32_t access_mask)
1898 NTSTATUS status = NT_STATUS_OK;
1899 int create_options = 0;
1900 struct smb2_create_blobs *posx = NULL;
1901 struct files_struct *fsp = NULL;
1902 bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
1903 bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
1904 bool case_preserve = posix_pathname ? true : conn->case_preserve;
1905 bool short_case_preserve = posix_pathname ? true :
1906 conn->short_case_preserve;
1908 if (posix_pathname) {
1909 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
1910 if (!NT_STATUS_IS_OK(status)) {
1911 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
1912 nt_errstr(status));
1913 goto out;
1917 DBG_NOTICE("case_sensitive = %d, "
1918 "case_preserve = %d, short case preserve = %d, "
1919 "directory = %s, newname = %s, "
1920 "last_component_dest = %s\n",
1921 case_sensitive, case_preserve,
1922 short_case_preserve,
1923 smb_fname_str_dbg(smb_fname_src),
1924 smb_fname_str_dbg(smb_fname_dst),
1925 dst_original_lcomp);
1927 ZERO_STRUCT(smb_fname_src->st);
1929 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
1930 if (!NT_STATUS_IS_OK(status)) {
1931 if (!NT_STATUS_EQUAL(status,
1932 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1933 goto out;
1936 * Possible symlink src.
1938 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
1939 goto out;
1941 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
1942 goto out;
1946 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
1947 create_options |= FILE_DIRECTORY_FILE;
1950 status = SMB_VFS_CREATE_FILE(
1951 conn, /* conn */
1952 req, /* req */
1953 src_dirfsp, /* dirfsp */
1954 smb_fname_src, /* fname */
1955 access_mask, /* access_mask */
1956 (FILE_SHARE_READ | /* share_access */
1957 FILE_SHARE_WRITE),
1958 FILE_OPEN, /* create_disposition*/
1959 create_options, /* create_options */
1960 0, /* file_attributes */
1961 0, /* oplock_request */
1962 NULL, /* lease */
1963 0, /* allocation_size */
1964 0, /* private_flags */
1965 NULL, /* sd */
1966 NULL, /* ea_list */
1967 &fsp, /* result */
1968 NULL, /* pinfo */
1969 posx, /* in_context_blobs */
1970 NULL); /* out_context_blobs */
1972 if (!NT_STATUS_IS_OK(status)) {
1973 DBG_NOTICE("Could not open rename source %s: %s\n",
1974 smb_fname_str_dbg(smb_fname_src),
1975 nt_errstr(status));
1976 goto out;
1979 status = rename_internals_fsp(conn,
1980 fsp,
1981 dst_dirfsp,
1982 smb_fname_dst,
1983 dst_original_lcomp,
1984 attrs,
1985 replace_if_exists);
1987 close_file_free(req, &fsp, NORMAL_CLOSE);
1989 DBG_NOTICE("Error %s rename %s -> %s\n",
1990 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
1991 smb_fname_str_dbg(smb_fname_dst));
1993 out:
1994 TALLOC_FREE(posx);
1995 return status;
1998 /*******************************************************************
1999 Copy a file as part of a reply_copy.
2000 ******************************************************************/
2003 * TODO: check error codes on all callers
2006 NTSTATUS copy_file(TALLOC_CTX *ctx,
2007 connection_struct *conn,
2008 struct smb_filename *smb_fname_src,
2009 struct smb_filename *smb_fname_dst,
2010 uint32_t new_create_disposition)
2012 struct smb_filename *smb_fname_dst_tmp = NULL;
2013 off_t ret=-1;
2014 files_struct *fsp1,*fsp2;
2015 uint32_t dosattrs;
2016 NTSTATUS status;
2019 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
2020 if (smb_fname_dst_tmp == NULL) {
2021 return NT_STATUS_NO_MEMORY;
2024 status = vfs_file_exist(conn, smb_fname_src);
2025 if (!NT_STATUS_IS_OK(status)) {
2026 goto out;
2029 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 goto out;
2034 /* Open the src file for reading. */
2035 status = SMB_VFS_CREATE_FILE(
2036 conn, /* conn */
2037 NULL, /* req */
2038 NULL, /* dirfsp */
2039 smb_fname_src, /* fname */
2040 FILE_GENERIC_READ, /* access_mask */
2041 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2042 FILE_OPEN, /* create_disposition*/
2043 0, /* create_options */
2044 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2045 INTERNAL_OPEN_ONLY, /* oplock_request */
2046 NULL, /* lease */
2047 0, /* allocation_size */
2048 0, /* private_flags */
2049 NULL, /* sd */
2050 NULL, /* ea_list */
2051 &fsp1, /* result */
2052 NULL, /* psbuf */
2053 NULL, NULL); /* create context */
2055 if (!NT_STATUS_IS_OK(status)) {
2056 goto out;
2059 dosattrs = fdos_mode(fsp1);
2061 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
2062 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
2065 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
2066 if (!NT_STATUS_IS_OK(status) &&
2067 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
2069 goto out;
2072 /* Open the dst file for writing. */
2073 status = SMB_VFS_CREATE_FILE(
2074 conn, /* conn */
2075 NULL, /* req */
2076 NULL, /* dirfsp */
2077 smb_fname_dst, /* fname */
2078 FILE_GENERIC_WRITE, /* access_mask */
2079 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2080 new_create_disposition, /* create_disposition*/
2081 0, /* create_options */
2082 dosattrs, /* file_attributes */
2083 INTERNAL_OPEN_ONLY, /* oplock_request */
2084 NULL, /* lease */
2085 0, /* allocation_size */
2086 0, /* private_flags */
2087 NULL, /* sd */
2088 NULL, /* ea_list */
2089 &fsp2, /* result */
2090 NULL, /* psbuf */
2091 NULL, NULL); /* create context */
2093 if (!NT_STATUS_IS_OK(status)) {
2094 close_file_free(NULL, &fsp1, ERROR_CLOSE);
2095 goto out;
2098 /* Do the actual copy. */
2099 if (smb_fname_src->st.st_ex_size) {
2100 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
2101 } else {
2102 ret = 0;
2105 close_file_free(NULL, &fsp1, NORMAL_CLOSE);
2107 /* Ensure the modtime is set correctly on the destination file. */
2108 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
2111 * As we are opening fsp1 read-only we only expect
2112 * an error on close on fsp2 if we are out of space.
2113 * Thus we don't look at the error return from the
2114 * close of fsp1.
2116 status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
2118 if (!NT_STATUS_IS_OK(status)) {
2119 goto out;
2122 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
2123 status = NT_STATUS_DISK_FULL;
2124 goto out;
2127 status = NT_STATUS_OK;
2129 out:
2130 TALLOC_FREE(smb_fname_dst_tmp);
2131 return status;
2134 /****************************************************************************
2135 Get a lock offset, dealing with large offset requests.
2136 ****************************************************************************/
2138 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
2139 bool large_file_format)
2141 uint64_t offset = 0;
2143 if(!large_file_format) {
2144 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
2145 } else {
2147 * No BVAL, this is reversed!
2149 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
2150 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
2153 return offset;
2156 struct smbd_do_unlocking_state {
2157 struct files_struct *fsp;
2158 uint16_t num_ulocks;
2159 struct smbd_lock_element *ulocks;
2160 NTSTATUS status;
2163 static void smbd_do_unlocking_fn(
2164 struct share_mode_lock *lck,
2165 void *private_data)
2167 struct smbd_do_unlocking_state *state = private_data;
2168 struct files_struct *fsp = state->fsp;
2169 uint16_t i;
2171 for (i = 0; i < state->num_ulocks; i++) {
2172 struct smbd_lock_element *e = &state->ulocks[i];
2174 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
2175 "pid %"PRIu64", file %s\n",
2176 e->offset,
2177 e->count,
2178 e->smblctx,
2179 fsp_str_dbg(fsp));
2181 if (e->brltype != UNLOCK_LOCK) {
2182 /* this can only happen with SMB2 */
2183 state->status = NT_STATUS_INVALID_PARAMETER;
2184 return;
2187 state->status = do_unlock(
2188 fsp, e->smblctx, e->count, e->offset, e->lock_flav);
2190 DBG_DEBUG("do_unlock returned %s\n",
2191 nt_errstr(state->status));
2193 if (!NT_STATUS_IS_OK(state->status)) {
2194 return;
2198 share_mode_wakeup_waiters(fsp->file_id);
2201 NTSTATUS smbd_do_unlocking(struct smb_request *req,
2202 files_struct *fsp,
2203 uint16_t num_ulocks,
2204 struct smbd_lock_element *ulocks)
2206 struct smbd_do_unlocking_state state = {
2207 .fsp = fsp,
2208 .num_ulocks = num_ulocks,
2209 .ulocks = ulocks,
2211 NTSTATUS status;
2213 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
2215 status = share_mode_do_locked_vfs_allowed(
2216 fsp->file_id, smbd_do_unlocking_fn, &state);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 DBG_DEBUG("share_mode_do_locked_vfs_allowed failed: %s\n",
2220 nt_errstr(status));
2221 return status;
2223 if (!NT_STATUS_IS_OK(state.status)) {
2224 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
2225 nt_errstr(status));
2226 return state.status;
2229 return NT_STATUS_OK;