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
28 #include "libsmb/namequery.h"
29 #include "system/filesys.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"
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
61 ****************************************************************************/
63 /* Custom version for processing POSIX paths. */
64 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
66 NTSTATUS
check_path_syntax(char *path
, bool posix_path
)
70 NTSTATUS ret
= NT_STATUS_OK
;
71 bool start_of_name_component
= True
;
72 bool stream_started
= false;
73 bool last_component_contains_wcard
= false;
80 return NT_STATUS_OBJECT_NAME_INVALID
;
83 return NT_STATUS_OBJECT_NAME_INVALID
;
85 if (strchr_m(&s
[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID
;
92 if ((*s
== ':') && !posix_path
&& !stream_started
) {
93 if (last_component_contains_wcard
) {
94 return NT_STATUS_OBJECT_NAME_INVALID
;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
102 stream_started
= true;
103 start_of_name_component
= false;
107 return NT_STATUS_OBJECT_NAME_INVALID
;
111 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s
,posix_path
)) {
120 if ((d
!= path
) && (*s
!= '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
125 start_of_name_component
= True
;
127 last_component_contains_wcard
= false;
131 if (start_of_name_component
) {
132 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d
> path
) && (*(d
-1) == '/')) {
145 /* Are we at the start ? Can't go back further if so. */
147 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d
--; d
> path
; d
--) {
158 s
+= 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
162 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
174 if (*s
<= 0x1f || *s
== '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID
;
183 last_component_contains_wcard
= true;
192 /* Get the size of the next MB character. */
193 next_codepoint(s
,&ch_size
);
211 DBG_ERR("character length assumptions invalid !\n");
213 return NT_STATUS_INVALID_PARAMETER
;
216 start_of_name_component
= False
;
224 /****************************************************************************
225 SMB2-only code to strip an MSDFS prefix from an incoming pathname.
226 ****************************************************************************/
228 NTSTATUS
smb2_strip_dfs_path(const char *in_path
, const char **out_path
)
230 const char *path
= in_path
;
232 /* Match the Windows 2022 behavior for an empty DFS pathname. */
234 return NT_STATUS_INVALID_PARAMETER
;
236 /* Strip any leading '\\' characters - MacOSX client behavior. */
237 while (*path
== '\\') {
240 /* We should now be pointing at the server name. Go past it. */
243 /* End of complete path. Exit OK. */
247 /* End of server name. Go past and break. */
251 path
++; /* Continue looking for end of server name or string. */
254 /* We should now be pointing at the share name. Go past it. */
257 /* End of complete path. Exit OK. */
261 /* End of share name. Go past and break. */
266 /* Only invalid character in sharename. */
267 return NT_STATUS_OBJECT_NAME_INVALID
;
269 path
++; /* Continue looking for end of share name or string. */
272 /* path now points at the start of the real filename (if any). */
275 /* We have stripped the DFS path prefix (if any). */
280 /****************************************************************************
281 Pull a string and check the path allowing a wildcard - provide for error return.
282 Passes in posix flag.
283 ****************************************************************************/
285 static size_t srvstr_get_path_internal(TALLOC_CTX
*ctx
,
286 const char *base_ptr
,
292 bool posix_pathnames
,
300 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
304 *err
= NT_STATUS_INVALID_PARAMETER
;
310 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
312 * A valid DFS path looks either like
315 * (there may be more components after).
316 * Either way it must have at least two separators.
318 * Ensure we end up as /server/share
319 * so we don't need to special case
320 * separator characters elsewhere in
325 char *remaining_path
= NULL
;
329 if (posix_pathnames
&& (dst
[0] == '/')) {
331 } else if (dst
[0] == '\\') {
340 * We need some heuristics here,
341 * as clients differ on what constitutes
342 * a well-formed DFS path. If the path
343 * appears malformed, just fall back to
344 * processing as a local path.
349 * Cosmetic fix for Linux-only DFS clients.
350 * The Linux kernel SMB1 client has a bug - it sends
353 * \\server\share\path
355 * Causing us to mis-parse server,share,remaining_path here
356 * and jump into 'goto local_path' at 'share\path' instead
359 * This doesn't cause an error as the limits on share names
360 * are similar to those on pathnames.
362 * parse_dfs_path() which we call before filename parsing
363 * copes with this by calling trim_char on the leading '\'
364 * characters before processing.
365 * Do the same here so logging of pathnames looks better.
367 if (server
[1] == path_sep
) {
368 trim_char(&server
[1], path_sep
, '\0');
372 * Look to see if we also have /share following.
374 share
= strchr(server
+1, path_sep
);
379 * Ensure the server name does not contain
380 * any possible path components by converting
383 for (p
= server
+ 1; p
< share
; p
++) {
384 if (*p
== '/' || *p
== '\\') {
389 * It's a well formed DFS path with
390 * at least server and share components.
391 * Replace the slashes with '/' and
392 * pass the remainder to local_path.
397 * Skip past share so we don't pass the
398 * sharename into check_path_syntax().
400 remaining_path
= strchr(share
+1, path_sep
);
401 if (remaining_path
== NULL
) {
403 * Ensure the share name does not contain
404 * any possible path components by converting
407 for (p
= share
+ 1; *p
; p
++) {
408 if (*p
== '/' || *p
== '\\') {
413 * If no remaining path this was
414 * a bare /server/share path. Just return.
420 * Ensure the share name does not contain
421 * any possible path components by converting
424 for (p
= share
+ 1; p
< remaining_path
; p
++) {
425 if (*p
== '/' || *p
== '\\') {
429 *remaining_path
= '/';
430 dst
= remaining_path
+ 1;
431 /* dst now points at any following components. */
436 *err
= check_path_syntax(dst
, posix_pathnames
);
441 /****************************************************************************
442 Pull a string and check the path - provide for error return.
443 ****************************************************************************/
445 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
446 const char *base_ptr
,
454 return srvstr_get_path_internal(ctx
,
465 /****************************************************************************
466 Pull a string and check the path - provide for error return.
467 posix_pathnames version.
468 ****************************************************************************/
470 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
471 const char *base_ptr
,
479 return srvstr_get_path_internal(ctx
,
491 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
492 char **pp_dest
, const char *src
, int flags
,
495 ssize_t bufrem
= smbreq_bufrem(req
, src
);
498 *err
= NT_STATUS_INVALID_PARAMETER
;
502 if (req
->posix_pathnames
) {
503 return srvstr_get_path_internal(mem_ctx
,
504 (const char *)req
->inbuf
,
513 return srvstr_get_path_internal(mem_ctx
,
514 (const char *)req
->inbuf
,
526 * pull a string from the smb_buf part of a packet. In this case the
527 * string can either be null terminated or it can be terminated by the
528 * end of the smbbuf area
530 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
531 char **dest
, const uint8_t *src
, int flags
)
533 ssize_t bufrem
= smbreq_bufrem(req
, src
);
540 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
544 /****************************************************************************
545 Check if we have a correct fsp pointing to a quota fake file. Replacement for
546 the CHECK_NTQUOTA_HANDLE_OK macro.
547 ****************************************************************************/
549 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
552 if ((fsp
== NULL
) || (conn
== NULL
)) {
556 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
560 if (fsp
->fsp_flags
.is_directory
) {
564 if (fsp
->fake_file_handle
== NULL
) {
568 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
572 if (fsp
->fake_file_handle
->private_data
== NULL
) {
579 /****************************************************************************
580 Return the port number we've bound to on a socket.
581 ****************************************************************************/
583 static int get_socket_port(int fd
)
585 struct samba_sockaddr saddr
= {
586 .sa_socklen
= sizeof(struct sockaddr_storage
),
593 if (getsockname(fd
, &saddr
.u
.sa
, &saddr
.sa_socklen
) < 0) {
594 int level
= (errno
== ENOTCONN
) ? 2 : 0;
595 DEBUG(level
, ("getsockname failed. Error was %s\n",
600 #if defined(HAVE_IPV6)
601 if (saddr
.u
.sa
.sa_family
== AF_INET6
) {
602 return ntohs(saddr
.u
.in6
.sin6_port
);
605 if (saddr
.u
.sa
.sa_family
== AF_INET
) {
606 return ntohs(saddr
.u
.in
.sin_port
);
611 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
612 const char *name
, int name_type
)
615 char *trim_name_type
;
616 const char *retarget_parm
;
619 int retarget_type
= 0x20;
620 int retarget_port
= NBT_SMB_PORT
;
621 struct sockaddr_storage retarget_addr
;
622 struct sockaddr_in
*in_addr
;
626 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
630 trim_name
= talloc_strdup(talloc_tos(), name
);
631 if (trim_name
== NULL
) {
634 trim_char(trim_name
, ' ', ' ');
636 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
638 if (trim_name_type
== NULL
) {
642 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
643 trim_name_type
, NULL
);
644 if (retarget_parm
== NULL
) {
645 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
648 if (retarget_parm
== NULL
) {
652 retarget
= talloc_strdup(trim_name
, retarget_parm
);
653 if (retarget
== NULL
) {
657 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
659 p
= strchr(retarget
, ':');
662 retarget_port
= atoi(p
);
665 p
= strchr_m(retarget
, '#');
668 if (sscanf(p
, "%x", &retarget_type
) != 1) {
673 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
675 DEBUG(10, ("could not resolve %s\n", retarget
));
679 if (retarget_addr
.ss_family
!= AF_INET
) {
680 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
684 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
686 _smb_setlen(outbuf
, 6);
687 SCVAL(outbuf
, 0, 0x84);
688 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
689 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
691 if (!smb1_srv_send(xconn
, (char *)outbuf
, false, 0, false)) {
692 exit_server_cleanly("netbios_session_retarget: smb1_srv_send "
698 TALLOC_FREE(trim_name
);
702 static void reply_called_name_not_present(char *outbuf
)
704 smb_setlen(outbuf
, 1);
705 SCVAL(outbuf
, 0, 0x83);
706 SCVAL(outbuf
, 4, 0x82);
709 /****************************************************************************
710 Reply to a (netbios-level) special message.
711 ****************************************************************************/
713 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
715 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
716 int msg_type
= CVAL(inbuf
,0);
717 int msg_flags
= CVAL(inbuf
,1);
719 * We only really use 4 bytes of the outbuf, but for the smb_setlen
720 * calculation & friends (smb1_srv_send uses that) we need the full smb
723 char outbuf
[smb_size
];
725 memset(outbuf
, '\0', sizeof(outbuf
));
727 smb_setlen(outbuf
,0);
730 case NBSSrequest
: /* session request */
732 /* inbuf_size is guaranteed to be at least 4. */
734 int name_type1
, name_type2
;
735 int name_len1
, name_len2
;
739 if (xconn
->transport
.nbt
.got_session
) {
740 exit_server_cleanly("multiple session request not permitted");
743 SCVAL(outbuf
,0,NBSSpositive
);
746 /* inbuf_size is guaranteed to be at least 4. */
747 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
748 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
749 DEBUG(0,("Invalid name length in session request\n"));
750 reply_called_name_not_present(outbuf
);
753 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
754 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
755 DEBUG(0,("Invalid name length in session request\n"));
756 reply_called_name_not_present(outbuf
);
760 name_type1
= name_extract((unsigned char *)inbuf
,
761 inbuf_size
,(unsigned int)4,name1
);
762 name_type2
= name_extract((unsigned char *)inbuf
,
763 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
765 if (name_type1
== -1 || name_type2
== -1) {
766 DEBUG(0,("Invalid name type in session request\n"));
767 reply_called_name_not_present(outbuf
);
771 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
772 name1
, name_type1
, name2
, name_type2
));
774 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
775 exit_server_cleanly("retargeted client");
779 * Windows NT/2k uses "*SMBSERVER" and XP uses
780 * "*SMBSERV" arrggg!!!
782 if (strequal(name1
, "*SMBSERVER ")
783 || strequal(name1
, "*SMBSERV ")) {
786 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
789 exit_server_cleanly("could not allocate raddr");
792 fstrcpy(name1
, raddr
);
795 set_local_machine_name(name1
, True
);
796 set_remote_machine_name(name2
, True
);
798 if (is_ipaddress(sconn
->remote_hostname
)) {
799 char *p
= discard_const_p(char, sconn
->remote_hostname
);
803 sconn
->remote_hostname
= talloc_strdup(sconn
,
804 get_remote_machine_name());
805 if (sconn
->remote_hostname
== NULL
) {
806 exit_server_cleanly("could not copy remote name");
808 xconn
->remote_hostname
= sconn
->remote_hostname
;
811 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
812 get_local_machine_name(), get_remote_machine_name(),
815 if (name_type2
== 'R') {
816 /* We are being asked for a pathworks session ---
818 reply_called_name_not_present(outbuf
);
822 reload_services(sconn
, conn_snum_used
, true);
825 xconn
->transport
.nbt
.got_session
= true;
829 case 0x89: /* session keepalive request
830 (some old clients produce this?) */
831 SCVAL(outbuf
,0,NBSSkeepalive
);
835 case NBSSpositive
: /* positive session response */
836 case NBSSnegative
: /* negative session response */
837 case NBSSretarget
: /* retarget session response */
838 DEBUG(0,("Unexpected session response\n"));
841 case NBSSkeepalive
: /* session keepalive */
846 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
847 msg_type
, msg_flags
));
849 if (!smb1_srv_send(xconn
, outbuf
, false, 0, false)) {
850 exit_server_cleanly("reply_special: smb1_srv_send failed.");
853 if (CVAL(outbuf
, 0) != 0x82) {
854 exit_server_cleanly("invalid netbios session");
859 /*******************************************************************
860 * unlink a file with all relevant access checks
861 *******************************************************************/
863 NTSTATUS
unlink_internals(connection_struct
*conn
,
864 struct smb_request
*req
,
866 struct files_struct
*dirfsp
,
867 struct smb_filename
*smb_fname
)
871 uint32_t dirtype_orig
= dirtype
;
874 struct smb2_create_blobs
*posx
= NULL
;
877 dirtype
= FILE_ATTRIBUTE_NORMAL
;
880 DBG_DEBUG("%s, dirtype = %d\n",
881 smb_fname_str_dbg(smb_fname
),
884 if (!CAN_WRITE(conn
)) {
885 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
888 ret
= vfs_stat(conn
, smb_fname
);
890 return map_nt_error_from_unix(errno
);
893 fattr
= fdos_mode(smb_fname
->fsp
);
895 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
896 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
899 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
901 return NT_STATUS_NO_SUCH_FILE
;
904 if (!dir_check_ftype(fattr
, dirtype
)) {
905 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
906 return NT_STATUS_FILE_IS_A_DIRECTORY
;
908 return NT_STATUS_NO_SUCH_FILE
;
911 if (dirtype_orig
& 0x8000) {
912 /* These will never be set for POSIX. */
913 return NT_STATUS_NO_SUCH_FILE
;
917 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
918 return NT_STATUS_FILE_IS_A_DIRECTORY
;
921 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
922 return NT_STATUS_NO_SUCH_FILE
;
925 if (dirtype
& 0xFF00) {
926 /* These will never be set for POSIX. */
927 return NT_STATUS_NO_SUCH_FILE
;
932 return NT_STATUS_NO_SUCH_FILE
;
935 /* Can't delete a directory. */
936 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
937 return NT_STATUS_FILE_IS_A_DIRECTORY
;
942 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
943 return NT_STATUS_OBJECT_NAME_INVALID
;
946 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
947 status
= make_smb2_posix_create_ctx(
948 talloc_tos(), &posx
, 0777);
949 if (!NT_STATUS_IS_OK(status
)) {
950 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
956 /* On open checks the open itself will check the share mode, so
957 don't do it here as we'll get it wrong. */
959 status
= SMB_VFS_CREATE_FILE
963 smb_fname
, /* fname */
964 DELETE_ACCESS
, /* access_mask */
965 FILE_SHARE_NONE
, /* share_access */
966 FILE_OPEN
, /* create_disposition*/
967 FILE_NON_DIRECTORY_FILE
|
968 FILE_OPEN_REPARSE_POINT
, /* create_options */
969 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
970 0, /* oplock_request */
972 0, /* allocation_size */
973 0, /* private_flags */
978 posx
, /* in_context_blobs */
979 NULL
); /* out_context_blobs */
983 if (!NT_STATUS_IS_OK(status
)) {
984 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
989 status
= can_set_delete_on_close(fsp
, fattr
);
990 if (!NT_STATUS_IS_OK(status
)) {
991 DBG_DEBUG("can_set_delete_on_close for file %s - "
993 smb_fname_str_dbg(smb_fname
),
995 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
999 /* The set is across all open files on this dev/inode pair. */
1000 if (!set_delete_on_close(fsp
, True
,
1001 conn
->session_info
->security_token
,
1002 conn
->session_info
->unix_token
)) {
1003 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
1004 return NT_STATUS_ACCESS_DENIED
;
1007 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
1010 /****************************************************************************
1011 Fake (read/write) sendfile. Returns -1 on read or write fail.
1012 ****************************************************************************/
1014 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
1015 off_t startpos
, size_t nread
)
1018 size_t tosend
= nread
;
1025 bufsize
= MIN(nread
, 65536);
1027 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
1031 while (tosend
> 0) {
1035 cur_read
= MIN(tosend
, bufsize
);
1036 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
1042 /* If we had a short read, fill with zeros. */
1043 if (ret
< cur_read
) {
1044 memset(buf
+ ret
, '\0', cur_read
- ret
);
1047 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
1048 if (ret
!= cur_read
) {
1049 int saved_errno
= errno
;
1051 * Try and give an error message saying what
1054 DEBUG(0, ("write_data failed for client %s. "
1056 smbXsrv_connection_dbg(xconn
),
1057 strerror(saved_errno
)));
1059 errno
= saved_errno
;
1063 startpos
+= cur_read
;
1067 return (ssize_t
)nread
;
1070 /****************************************************************************
1071 Deal with the case of sendfile reading less bytes from the file than
1072 requested. Fill with zeros (all we can do). Returns 0 on success
1073 ****************************************************************************/
1075 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
1081 #define SHORT_SEND_BUFSIZE 1024
1082 if (nread
< headersize
) {
1083 DEBUG(0,("sendfile_short_send: sendfile failed to send "
1084 "header for file %s (%s). Terminating\n",
1085 fsp_str_dbg(fsp
), strerror(errno
)));
1089 nread
-= headersize
;
1091 if (nread
< smb_maxcnt
) {
1092 char buf
[SHORT_SEND_BUFSIZE
] = { 0 };
1094 DEBUG(0,("sendfile_short_send: filling truncated file %s "
1095 "with zeros !\n", fsp_str_dbg(fsp
)));
1097 while (nread
< smb_maxcnt
) {
1099 * We asked for the real file size and told sendfile
1100 * to not go beyond the end of the file. But it can
1101 * happen that in between our fstat call and the
1102 * sendfile call the file was truncated. This is very
1103 * bad because we have already announced the larger
1104 * number of bytes to the client.
1106 * The best we can do now is to send 0-bytes, just as
1107 * a read from a hole in a sparse file would do.
1109 * This should happen rarely enough that I don't care
1110 * about efficiency here :-)
1115 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
1116 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
1117 if (ret
!= to_write
) {
1118 int saved_errno
= errno
;
1120 * Try and give an error message saying what
1123 DEBUG(0, ("write_data failed for client %s. "
1125 smbXsrv_connection_dbg(xconn
),
1126 strerror(saved_errno
)));
1127 errno
= saved_errno
;
1137 /*******************************************************************
1138 Check if a user is allowed to rename a file.
1139 ********************************************************************/
1141 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
1144 if (!CAN_WRITE(conn
)) {
1145 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1148 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
1149 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
1150 /* Only bother to read the DOS attribute if we might deny the
1151 rename on the grounds of attribute mismatch. */
1152 uint32_t fmode
= fdos_mode(fsp
);
1153 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
1154 return NT_STATUS_NO_SUCH_FILE
;
1158 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
1159 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
1160 return NT_STATUS_OK
;
1163 /* If no pathnames are open below this
1164 directory, allow the rename. */
1166 if (lp_strict_rename(SNUM(conn
))) {
1168 * Strict rename, check open file db.
1170 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
1171 return NT_STATUS_ACCESS_DENIED
;
1173 } else if (file_find_subpath(fsp
)) {
1175 * No strict rename, just look in local process.
1177 return NT_STATUS_ACCESS_DENIED
;
1179 return NT_STATUS_OK
;
1182 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
1183 return NT_STATUS_OK
;
1186 return NT_STATUS_ACCESS_DENIED
;
1189 /****************************************************************************
1190 Ensure open files have their names updated. Updated to notify other smbd's
1192 ****************************************************************************/
1194 static void rename_open_files(connection_struct
*conn
,
1195 struct share_mode_lock
*lck
,
1197 uint32_t orig_name_hash
,
1198 const struct smb_filename
*smb_fname_dst
)
1201 bool did_rename
= False
;
1203 uint32_t new_name_hash
= 0;
1205 for(fsp
= file_find_di_first(conn
->sconn
, id
, false); fsp
;
1206 fsp
= file_find_di_next(fsp
, false)) {
1207 SMB_STRUCT_STAT fsp_orig_sbuf
;
1208 struct file_id_buf idbuf
;
1209 /* fsp_name is a relative path under the fsp. To change this for other
1210 sharepaths we need to manipulate relative paths. */
1211 /* TODO - create the absolute path and manipulate the newname
1212 relative to the sharepath. */
1213 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
1216 if (fsp
->name_hash
!= orig_name_hash
) {
1219 DBG_DEBUG("renaming file %s "
1220 "(file_id %s) from %s -> %s\n",
1222 file_id_str_buf(fsp
->file_id
, &idbuf
),
1224 smb_fname_str_dbg(smb_fname_dst
));
1227 * The incoming smb_fname_dst here has an
1228 * invalid stat struct (it must not have
1229 * existed for the rename to succeed).
1230 * Preserve the existing stat from the
1231 * open fsp after fsp_set_smb_fname()
1232 * overwrites with the invalid stat.
1234 * We will do an fstat before returning
1235 * any of this metadata to the client anyway.
1237 fsp_orig_sbuf
= fsp
->fsp_name
->st
;
1238 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
1239 if (NT_STATUS_IS_OK(status
)) {
1241 new_name_hash
= fsp
->name_hash
;
1242 /* Restore existing stat. */
1243 fsp
->fsp_name
->st
= fsp_orig_sbuf
;
1248 struct file_id_buf idbuf
;
1249 DBG_DEBUG("no open files on file_id %s "
1251 file_id_str_buf(id
, &idbuf
),
1252 smb_fname_str_dbg(smb_fname_dst
));
1255 /* Send messages to all smbd's (not ourself) that the name has changed. */
1256 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
1257 orig_name_hash
, new_name_hash
,
1262 /****************************************************************************
1263 We need to check if the source path is a parent directory of the destination
1264 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
1265 refuse the rename with a sharing violation. Under UNIX the above call can
1266 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
1267 probably need to check that the client is a Windows one before disallowing
1268 this as a UNIX client (one with UNIX extensions) can know the source is a
1269 symlink and make this decision intelligently. Found by an excellent bug
1270 report from <AndyLiebman@aol.com>.
1271 ****************************************************************************/
1273 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
1274 const struct smb_filename
*smb_fname_dst
)
1276 const char *psrc
= smb_fname_src
->base_name
;
1277 const char *pdst
= smb_fname_dst
->base_name
;
1280 if (psrc
[0] == '.' && psrc
[1] == '/') {
1283 if (pdst
[0] == '.' && pdst
[1] == '/') {
1286 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
1289 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
1293 * Do the notify calls from a rename
1296 static void notify_rename(connection_struct
*conn
, bool is_dir
,
1297 const struct smb_filename
*smb_fname_src
,
1298 const struct smb_filename
*smb_fname_dst
)
1300 char *parent_dir_src
= NULL
;
1301 char *parent_dir_dst
= NULL
;
1304 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
1305 : FILE_NOTIFY_CHANGE_FILE_NAME
;
1307 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
1308 &parent_dir_src
, NULL
) ||
1309 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
1310 &parent_dir_dst
, NULL
)) {
1314 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
1315 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
1316 smb_fname_src
->base_name
);
1317 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
1318 smb_fname_dst
->base_name
);
1321 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
1322 smb_fname_src
->base_name
);
1323 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
1324 smb_fname_dst
->base_name
);
1327 /* this is a strange one. w2k3 gives an additional event for
1328 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
1329 files, but not directories */
1331 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
1332 FILE_NOTIFY_CHANGE_ATTRIBUTES
1333 |FILE_NOTIFY_CHANGE_CREATION
,
1334 smb_fname_dst
->base_name
);
1337 TALLOC_FREE(parent_dir_src
);
1338 TALLOC_FREE(parent_dir_dst
);
1341 /****************************************************************************
1342 Returns an error if the parent directory for a filename is open in an
1344 ****************************************************************************/
1346 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
1347 const struct smb_filename
*smb_fname_dst_in
)
1349 struct smb_filename
*smb_fname_parent
= NULL
;
1351 files_struct
*fsp
= NULL
;
1355 status
= SMB_VFS_PARENT_PATHNAME(conn
,
1360 if (!NT_STATUS_IS_OK(status
)) {
1364 ret
= vfs_stat(conn
, smb_fname_parent
);
1366 return map_nt_error_from_unix(errno
);
1370 * We're only checking on this smbd here, mostly good
1371 * enough.. and will pass tests.
1374 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
->st
);
1375 for (fsp
= file_find_di_first(conn
->sconn
, id
, true); fsp
;
1376 fsp
= file_find_di_next(fsp
, true)) {
1377 if (fsp
->access_mask
& DELETE_ACCESS
) {
1378 return NT_STATUS_SHARING_VIOLATION
;
1381 return NT_STATUS_OK
;
1384 /****************************************************************************
1385 Rename an open file - given an fsp.
1386 ****************************************************************************/
1388 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
1390 struct smb_filename
*smb_fname_dst_in
,
1391 const char *dst_original_lcomp
,
1393 bool replace_if_exists
)
1395 TALLOC_CTX
*ctx
= talloc_tos();
1396 struct smb_filename
*parent_dir_fname_dst
= NULL
;
1397 struct smb_filename
*parent_dir_fname_dst_atname
= NULL
;
1398 struct smb_filename
*parent_dir_fname_src
= NULL
;
1399 struct smb_filename
*parent_dir_fname_src_atname
= NULL
;
1400 struct smb_filename
*smb_fname_dst
= NULL
;
1401 NTSTATUS status
= NT_STATUS_OK
;
1402 struct share_mode_lock
*lck
= NULL
;
1403 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
1404 bool dst_exists
, old_is_stream
, new_is_stream
;
1406 bool case_sensitive
= (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
) ?
1407 true : conn
->case_sensitive
;
1408 bool case_preserve
= (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
) ?
1409 true : conn
->case_preserve
;
1411 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
1412 if (!NT_STATUS_IS_OK(status
)) {
1416 if (file_has_open_streams(fsp
)) {
1417 return NT_STATUS_ACCESS_DENIED
;
1420 /* Make a copy of the dst smb_fname structs */
1422 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
1423 if (smb_fname_dst
== NULL
) {
1424 status
= NT_STATUS_NO_MEMORY
;
1429 * Check for special case with case preserving and not
1430 * case sensitive. If the new last component differs from the original
1431 * last component only by case, then we should allow
1432 * the rename (user is trying to change the case of the
1435 if (!case_sensitive
&& case_preserve
&&
1436 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
1437 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
1438 char *fname_dst_parent
= NULL
;
1439 const char *fname_dst_lcomp
= NULL
;
1440 char *orig_lcomp_path
= NULL
;
1441 char *orig_lcomp_stream
= NULL
;
1445 * Split off the last component of the processed
1446 * destination name. We will compare this to
1447 * the split components of dst_original_lcomp.
1449 if (!parent_dirname(ctx
,
1450 smb_fname_dst
->base_name
,
1452 &fname_dst_lcomp
)) {
1453 status
= NT_STATUS_NO_MEMORY
;
1458 * The dst_original_lcomp component contains
1459 * the last_component of the path + stream
1460 * name (if a stream exists).
1462 * Split off the stream name so we
1463 * can check them separately.
1466 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
1467 /* POSIX - no stream component. */
1468 orig_lcomp_path
= talloc_strdup(ctx
,
1469 dst_original_lcomp
);
1470 if (orig_lcomp_path
== NULL
) {
1474 ok
= split_stream_filename(ctx
,
1477 &orig_lcomp_stream
);
1481 TALLOC_FREE(fname_dst_parent
);
1482 status
= NT_STATUS_NO_MEMORY
;
1486 /* If the base names only differ by case, use original. */
1487 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
1490 * Replace the modified last component with the
1493 if (!ISDOT(fname_dst_parent
)) {
1494 tmp
= talloc_asprintf(smb_fname_dst
,
1499 tmp
= talloc_strdup(smb_fname_dst
,
1503 status
= NT_STATUS_NO_MEMORY
;
1504 TALLOC_FREE(fname_dst_parent
);
1505 TALLOC_FREE(orig_lcomp_path
);
1506 TALLOC_FREE(orig_lcomp_stream
);
1509 TALLOC_FREE(smb_fname_dst
->base_name
);
1510 smb_fname_dst
->base_name
= tmp
;
1513 /* If the stream_names only differ by case, use original. */
1514 if(!strcsequal(smb_fname_dst
->stream_name
,
1515 orig_lcomp_stream
)) {
1516 /* Use the original stream. */
1517 char *tmp
= talloc_strdup(smb_fname_dst
,
1520 status
= NT_STATUS_NO_MEMORY
;
1521 TALLOC_FREE(fname_dst_parent
);
1522 TALLOC_FREE(orig_lcomp_path
);
1523 TALLOC_FREE(orig_lcomp_stream
);
1526 TALLOC_FREE(smb_fname_dst
->stream_name
);
1527 smb_fname_dst
->stream_name
= tmp
;
1529 TALLOC_FREE(fname_dst_parent
);
1530 TALLOC_FREE(orig_lcomp_path
);
1531 TALLOC_FREE(orig_lcomp_stream
);
1535 * If the src and dest names are identical - including case,
1536 * don't do the rename, just return success.
1539 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
1540 strcsequal(fsp
->fsp_name
->stream_name
,
1541 smb_fname_dst
->stream_name
)) {
1542 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
1543 "- returning success\n",
1544 smb_fname_str_dbg(smb_fname_dst
)));
1545 status
= NT_STATUS_OK
;
1549 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
1550 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
1552 /* Return the correct error code if both names aren't streams. */
1553 if (!old_is_stream
&& new_is_stream
) {
1554 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1558 if (old_is_stream
&& !new_is_stream
) {
1559 status
= NT_STATUS_INVALID_PARAMETER
;
1563 dst_exists
= vfs_stat(conn
, smb_fname_dst
) == 0;
1565 if(!replace_if_exists
&& dst_exists
) {
1566 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
1567 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
1568 smb_fname_str_dbg(smb_fname_dst
)));
1569 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
1574 * Drop the pathref fsp on the destination otherwise we trip upon in in
1575 * the below check for open files check.
1577 if (smb_fname_dst_in
->fsp
!= NULL
) {
1578 fd_close(smb_fname_dst_in
->fsp
);
1579 file_free(NULL
, smb_fname_dst_in
->fsp
);
1580 SMB_ASSERT(smb_fname_dst_in
->fsp
== NULL
);
1584 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
1585 &smb_fname_dst
->st
);
1586 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
1588 /* The file can be open when renaming a stream */
1589 if (dst_fsp
&& !new_is_stream
) {
1590 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
1591 status
= NT_STATUS_ACCESS_DENIED
;
1596 /* Ensure we have a valid stat struct for the source. */
1597 status
= vfs_stat_fsp(fsp
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1602 status
= can_rename(conn
, fsp
, attrs
);
1604 if (!NT_STATUS_IS_OK(status
)) {
1605 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1606 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
1607 smb_fname_str_dbg(smb_fname_dst
)));
1608 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
1609 status
= NT_STATUS_ACCESS_DENIED
;
1613 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
1614 status
= NT_STATUS_ACCESS_DENIED
;
1618 /* Do we have rights to move into the destination ? */
1619 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
1620 /* We're moving a directory. */
1621 access_mask
= SEC_DIR_ADD_SUBDIR
;
1625 * Get a pathref on the destination parent directory, so
1626 * we can call check_parent_access_fsp().
1628 status
= parent_pathref(ctx
,
1631 &parent_dir_fname_dst
,
1632 &parent_dir_fname_dst_atname
);
1633 if (!NT_STATUS_IS_OK(status
)) {
1637 status
= check_parent_access_fsp(parent_dir_fname_dst
->fsp
,
1639 if (!NT_STATUS_IS_OK(status
)) {
1640 DBG_INFO("check_parent_access_fsp on "
1641 "dst %s returned %s\n",
1642 smb_fname_str_dbg(smb_fname_dst
),
1648 * If the target existed, make sure the destination
1649 * atname has the same stat struct.
1651 parent_dir_fname_dst_atname
->st
= smb_fname_dst
->st
;
1654 * It's very common that source and
1655 * destination directories are the same.
1656 * Optimize by not opening the
1657 * second parent_pathref if we know
1661 status
= SMB_VFS_PARENT_PATHNAME(conn
,
1664 &parent_dir_fname_src
,
1665 &parent_dir_fname_src_atname
);
1666 if (!NT_STATUS_IS_OK(status
)) {
1671 * We do a case-sensitive string comparison. We want to be *sure*
1672 * this is the same path. The worst that can happen if
1673 * the case doesn't match is we lose out on the optimization,
1674 * the code still works.
1676 * We can ignore twrp fields here. Rename is not allowed on
1677 * shadow copy handles.
1680 if (strcmp(parent_dir_fname_src
->base_name
,
1681 parent_dir_fname_dst
->base_name
) == 0) {
1683 * parent directory is the same for source
1686 /* Reparent the src_atname to the parent_dir_dest fname. */
1687 parent_dir_fname_src_atname
= talloc_move(
1688 parent_dir_fname_dst
,
1689 &parent_dir_fname_src_atname
);
1690 /* Free the unneeded duplicate parent name. */
1691 TALLOC_FREE(parent_dir_fname_src
);
1693 * And make the source parent name a copy of the
1694 * destination parent name.
1696 parent_dir_fname_src
= parent_dir_fname_dst
;
1699 * Ensure we have a pathref fsp on the
1700 * parent_dir_fname_src_atname to match the code in the else
1701 * branch where we use parent_pathref().
1703 status
= reference_smb_fname_fsp_link(
1704 parent_dir_fname_src_atname
,
1706 if (!NT_STATUS_IS_OK(status
)) {
1711 * source and destination parent directories are
1714 * Get a pathref on the source parent directory, so
1715 * we can do a relative rename.
1717 TALLOC_FREE(parent_dir_fname_src
);
1718 status
= parent_pathref(ctx
,
1721 &parent_dir_fname_src
,
1722 &parent_dir_fname_src_atname
);
1723 if (!NT_STATUS_IS_OK(status
)) {
1729 * Some modules depend on the source smb_fname having a valid stat.
1730 * The parent_dir_fname_src_atname is the relative name of the
1731 * currently open file, so just copy the stat from the open fsp.
1733 parent_dir_fname_src_atname
->st
= fsp
->fsp_name
->st
;
1735 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
1738 * We have the file open ourselves, so not being able to get the
1739 * corresponding share mode lock is a fatal error.
1742 SMB_ASSERT(lck
!= NULL
);
1744 ret
= SMB_VFS_RENAMEAT(conn
,
1745 parent_dir_fname_src
->fsp
,
1746 parent_dir_fname_src_atname
,
1747 parent_dir_fname_dst
->fsp
,
1748 parent_dir_fname_dst_atname
);
1750 uint32_t create_options
= fh_get_private_options(fsp
->fh
);
1752 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
1753 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
1754 smb_fname_str_dbg(smb_fname_dst
)));
1757 fsp
->fsp_flags
.is_directory
,
1761 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
1764 if (!fsp
->fsp_flags
.is_directory
&&
1765 (lp_map_archive(SNUM(conn
)) ||
1766 lp_store_dos_attributes(SNUM(conn
))))
1769 * We must set the archive bit on the newly renamed
1772 status
= vfs_stat_fsp(fsp
);
1773 if (NT_STATUS_IS_OK(status
)) {
1774 uint32_t old_dosmode
;
1775 old_dosmode
= fdos_mode(fsp
);
1777 * We can use fsp->fsp_name here as it has
1778 * already been changed to the new name.
1780 SMB_ASSERT(fsp
->fsp_name
->fsp
== fsp
);
1781 file_set_dosmode(conn
,
1783 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
1790 * A rename acts as a new file create w.r.t. allowing an initial delete
1791 * on close, probably because in Windows there is a new handle to the
1792 * new file. If initial delete on close was requested but not
1793 * originally set, we need to set it here. This is probably not 100% correct,
1794 * but will work for the CIFSFS client which in non-posix mode
1795 * depends on these semantics. JRA.
1798 if (create_options
& FILE_DELETE_ON_CLOSE
) {
1799 status
= can_set_delete_on_close(fsp
, 0);
1801 if (NT_STATUS_IS_OK(status
)) {
1802 /* Note that here we set the *initial* delete on close flag,
1803 * not the regular one. The magic gets handled in close. */
1804 fsp
->fsp_flags
.initial_delete_on_close
= true;
1808 status
= NT_STATUS_OK
;
1814 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
1815 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
1817 status
= map_nt_error_from_unix(errno
);
1820 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1821 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
1822 smb_fname_str_dbg(smb_fname_dst
)));
1827 * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
1828 * See the optimization for same source and destination directory
1829 * above. Only free one in that case.
1831 if (parent_dir_fname_src
!= parent_dir_fname_dst
) {
1832 TALLOC_FREE(parent_dir_fname_src
);
1834 TALLOC_FREE(parent_dir_fname_dst
);
1835 TALLOC_FREE(smb_fname_dst
);
1840 /****************************************************************************
1841 The guts of the rename command, split out so it may be called by the NT SMB
1843 ****************************************************************************/
1845 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
1846 connection_struct
*conn
,
1847 struct smb_request
*req
,
1848 struct files_struct
*src_dirfsp
,
1849 struct smb_filename
*smb_fname_src
,
1850 struct smb_filename
*smb_fname_dst
,
1851 const char *dst_original_lcomp
,
1853 bool replace_if_exists
,
1854 uint32_t access_mask
)
1856 NTSTATUS status
= NT_STATUS_OK
;
1857 int create_options
= FILE_OPEN_REPARSE_POINT
;
1858 struct smb2_create_blobs
*posx
= NULL
;
1859 struct files_struct
*fsp
= NULL
;
1860 bool posix_pathname
= (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
);
1861 bool case_sensitive
= posix_pathname
? true : conn
->case_sensitive
;
1862 bool case_preserve
= posix_pathname
? true : conn
->case_preserve
;
1863 bool short_case_preserve
= posix_pathname
? true :
1864 conn
->short_case_preserve
;
1866 if (posix_pathname
) {
1867 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
1868 if (!NT_STATUS_IS_OK(status
)) {
1869 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
1875 DBG_NOTICE("case_sensitive = %d, "
1876 "case_preserve = %d, short case preserve = %d, "
1877 "directory = %s, newname = %s, "
1878 "last_component_dest = %s\n",
1879 case_sensitive
, case_preserve
,
1880 short_case_preserve
,
1881 smb_fname_str_dbg(smb_fname_src
),
1882 smb_fname_str_dbg(smb_fname_dst
),
1883 dst_original_lcomp
);
1885 ZERO_STRUCT(smb_fname_src
->st
);
1887 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
1888 if (!NT_STATUS_IS_OK(status
)) {
1889 if (!NT_STATUS_EQUAL(status
,
1890 NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1894 * Possible symlink src.
1896 if (!(smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
)) {
1899 if (!S_ISLNK(smb_fname_src
->st
.st_ex_mode
)) {
1904 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
1905 create_options
|= FILE_DIRECTORY_FILE
;
1908 status
= SMB_VFS_CREATE_FILE(
1911 src_dirfsp
, /* dirfsp */
1912 smb_fname_src
, /* fname */
1913 access_mask
, /* access_mask */
1914 (FILE_SHARE_READ
| /* share_access */
1916 FILE_OPEN
, /* create_disposition*/
1917 create_options
, /* create_options */
1918 0, /* file_attributes */
1919 0, /* oplock_request */
1921 0, /* allocation_size */
1922 0, /* private_flags */
1927 posx
, /* in_context_blobs */
1928 NULL
); /* out_context_blobs */
1930 if (!NT_STATUS_IS_OK(status
)) {
1931 DBG_NOTICE("Could not open rename source %s: %s\n",
1932 smb_fname_str_dbg(smb_fname_src
),
1937 status
= rename_internals_fsp(conn
,
1944 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
1946 DBG_NOTICE("Error %s rename %s -> %s\n",
1947 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
1948 smb_fname_str_dbg(smb_fname_dst
));
1955 /*******************************************************************
1956 Copy a file as part of a reply_copy.
1957 ******************************************************************/
1960 * TODO: check error codes on all callers
1963 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
1964 connection_struct
*conn
,
1965 struct smb_filename
*smb_fname_src
,
1966 struct smb_filename
*smb_fname_dst
,
1967 uint32_t new_create_disposition
)
1969 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
1971 files_struct
*fsp1
,*fsp2
;
1976 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
1977 if (smb_fname_dst_tmp
== NULL
) {
1978 return NT_STATUS_NO_MEMORY
;
1981 status
= vfs_file_exist(conn
, smb_fname_src
);
1982 if (!NT_STATUS_IS_OK(status
)) {
1986 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_src
);
1987 if (!NT_STATUS_IS_OK(status
)) {
1991 /* Open the src file for reading. */
1992 status
= SMB_VFS_CREATE_FILE(
1996 smb_fname_src
, /* fname */
1997 FILE_GENERIC_READ
, /* access_mask */
1998 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1999 FILE_OPEN
, /* create_disposition*/
2000 0, /* create_options */
2001 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2002 INTERNAL_OPEN_ONLY
, /* oplock_request */
2004 0, /* allocation_size */
2005 0, /* private_flags */
2010 NULL
, NULL
); /* create context */
2012 if (!NT_STATUS_IS_OK(status
)) {
2016 dosattrs
= fdos_mode(fsp1
);
2018 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
2019 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
2022 status
= openat_pathref_fsp(conn
->cwd_fsp
, smb_fname_dst
);
2023 if (!NT_STATUS_IS_OK(status
) &&
2024 !NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
))
2029 /* Open the dst file for writing. */
2030 status
= SMB_VFS_CREATE_FILE(
2034 smb_fname_dst
, /* fname */
2035 FILE_GENERIC_WRITE
, /* access_mask */
2036 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2037 new_create_disposition
, /* create_disposition*/
2038 0, /* create_options */
2039 dosattrs
, /* file_attributes */
2040 INTERNAL_OPEN_ONLY
, /* oplock_request */
2042 0, /* allocation_size */
2043 0, /* private_flags */
2048 NULL
, NULL
); /* create context */
2050 if (!NT_STATUS_IS_OK(status
)) {
2051 close_file_free(NULL
, &fsp1
, ERROR_CLOSE
);
2055 /* Do the actual copy. */
2056 if (smb_fname_src
->st
.st_ex_size
) {
2057 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
2062 close_file_free(NULL
, &fsp1
, NORMAL_CLOSE
);
2064 /* Ensure the modtime is set correctly on the destination file. */
2065 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
2068 * As we are opening fsp1 read-only we only expect
2069 * an error on close on fsp2 if we are out of space.
2070 * Thus we don't look at the error return from the
2073 status
= close_file_free(NULL
, &fsp2
, NORMAL_CLOSE
);
2075 if (!NT_STATUS_IS_OK(status
)) {
2079 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
2080 status
= NT_STATUS_DISK_FULL
;
2084 status
= NT_STATUS_OK
;
2087 TALLOC_FREE(smb_fname_dst_tmp
);
2091 /****************************************************************************
2092 Get a lock offset, dealing with large offset requests.
2093 ****************************************************************************/
2095 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
2096 bool large_file_format
)
2098 uint64_t offset
= 0;
2100 if(!large_file_format
) {
2101 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
2104 * No BVAL, this is reversed!
2106 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
2107 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
2113 struct smbd_do_unlocking_state
{
2114 struct files_struct
*fsp
;
2115 uint16_t num_ulocks
;
2116 struct smbd_lock_element
*ulocks
;
2120 static void smbd_do_unlocking_fn(
2121 struct share_mode_lock
*lck
,
2124 struct smbd_do_unlocking_state
*state
= private_data
;
2125 struct files_struct
*fsp
= state
->fsp
;
2128 for (i
= 0; i
< state
->num_ulocks
; i
++) {
2129 struct smbd_lock_element
*e
= &state
->ulocks
[i
];
2131 DBG_DEBUG("unlock start=%"PRIu64
", len=%"PRIu64
" for "
2132 "pid %"PRIu64
", file %s\n",
2138 if (e
->brltype
!= UNLOCK_LOCK
) {
2139 /* this can only happen with SMB2 */
2140 state
->status
= NT_STATUS_INVALID_PARAMETER
;
2144 state
->status
= do_unlock(
2145 fsp
, e
->smblctx
, e
->count
, e
->offset
, e
->lock_flav
);
2147 DBG_DEBUG("do_unlock returned %s\n",
2148 nt_errstr(state
->status
));
2150 if (!NT_STATUS_IS_OK(state
->status
)) {
2155 share_mode_wakeup_waiters(fsp
->file_id
);
2158 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
2160 uint16_t num_ulocks
,
2161 struct smbd_lock_element
*ulocks
)
2163 struct smbd_do_unlocking_state state
= {
2165 .num_ulocks
= num_ulocks
,
2170 DBG_NOTICE("%s num_ulocks=%"PRIu16
"\n", fsp_fnum_dbg(fsp
), num_ulocks
);
2172 status
= share_mode_do_locked_vfs_allowed(
2173 fsp
->file_id
, smbd_do_unlocking_fn
, &state
);
2175 if (!NT_STATUS_IS_OK(status
)) {
2176 DBG_DEBUG("share_mode_do_locked_vfs_allowed failed: %s\n",
2180 if (!NT_STATUS_IS_OK(state
.status
)) {
2181 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
2183 return state
.status
;
2186 return NT_STATUS_OK
;