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 "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "librpc/gen_ndr/open_files.h"
48 #include "smb1_utils.h"
50 /****************************************************************************
51 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
52 path or anything including wildcards.
53 We're assuming here that '/' is not the second byte in any multibyte char
54 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
56 ****************************************************************************/
58 /* Custom version for processing POSIX paths. */
59 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
61 static NTSTATUS
check_path_syntax_internal(char *path
,
63 bool *p_last_component_contains_wcard
)
67 NTSTATUS ret
= NT_STATUS_OK
;
68 bool start_of_name_component
= True
;
69 bool stream_started
= false;
71 *p_last_component_contains_wcard
= False
;
78 return NT_STATUS_OBJECT_NAME_INVALID
;
81 return NT_STATUS_OBJECT_NAME_INVALID
;
83 if (strchr_m(&s
[1], ':')) {
84 return NT_STATUS_OBJECT_NAME_INVALID
;
90 if ((*s
== ':') && !posix_path
&& !stream_started
) {
91 if (*p_last_component_contains_wcard
) {
92 return NT_STATUS_OBJECT_NAME_INVALID
;
94 /* Stream names allow more characters than file names.
95 We're overloading posix_path here to allow a wider
96 range of characters. If stream_started is true this
97 is still a Windows path even if posix_path is true.
100 stream_started
= true;
101 start_of_name_component
= false;
105 return NT_STATUS_OBJECT_NAME_INVALID
;
109 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
111 * Safe to assume is not the second part of a mb char
112 * as this is handled below.
114 /* Eat multiple '/' or '\\' */
115 while (IS_PATH_SEP(*s
,posix_path
)) {
118 if ((d
!= path
) && (*s
!= '\0')) {
119 /* We only care about non-leading or trailing '/' or '\\' */
123 start_of_name_component
= True
;
125 *p_last_component_contains_wcard
= False
;
129 if (start_of_name_component
) {
130 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
131 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
134 * No mb char starts with '.' so we're safe checking the directory separator here.
137 /* If we just added a '/' - delete it */
138 if ((d
> path
) && (*(d
-1) == '/')) {
143 /* Are we at the start ? Can't go back further if so. */
145 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
148 /* Go back one level... */
149 /* We know this is safe as '/' cannot be part of a mb sequence. */
150 /* NOTE - if this assumption is invalid we are not in good shape... */
151 /* Decrement d first as d points to the *next* char to write into. */
152 for (d
--; d
> path
; d
--) {
156 s
+= 2; /* Else go past the .. */
157 /* We're still at the start of a name component, just the previous one. */
160 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
172 if (*s
<= 0x1f || *s
== '|') {
173 return NT_STATUS_OBJECT_NAME_INVALID
;
181 *p_last_component_contains_wcard
= True
;
190 /* Get the size of the next MB character. */
191 next_codepoint(s
,&siz
);
209 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211 return NT_STATUS_INVALID_PARAMETER
;
214 start_of_name_component
= False
;
222 /****************************************************************************
223 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
224 No wildcards allowed.
225 ****************************************************************************/
227 NTSTATUS
check_path_syntax(char *path
)
230 return check_path_syntax_internal(path
, False
, &ignore
);
233 /****************************************************************************
234 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
235 Wildcards allowed - p_contains_wcard returns true if the last component contained
237 ****************************************************************************/
239 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
241 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
244 /****************************************************************************
245 Check the path for a POSIX client.
246 We're assuming here that '/' is not the second byte in any multibyte char
247 set (a safe assumption).
248 ****************************************************************************/
250 NTSTATUS
check_path_syntax_posix(char *path
)
253 return check_path_syntax_internal(path
, True
, &ignore
);
256 /****************************************************************************
257 Pull a string and check the path allowing a wilcard - provide for error return.
258 Passes in posix flag.
259 ****************************************************************************/
261 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX
*ctx
,
262 const char *base_ptr
,
268 bool posix_pathnames
,
270 bool *contains_wcard
)
276 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
280 *err
= NT_STATUS_INVALID_PARAMETER
;
284 *contains_wcard
= False
;
286 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
288 * For a DFS path the function parse_dfs_path()
289 * will do the path processing, just make a copy.
295 if (posix_pathnames
) {
296 *err
= check_path_syntax_posix(*pp_dest
);
298 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
304 /****************************************************************************
305 Pull a string and check the path allowing a wilcard - provide for error return.
306 ****************************************************************************/
308 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
309 const char *base_ptr
,
316 bool *contains_wcard
)
318 return srvstr_get_path_wcard_internal(ctx
,
330 /****************************************************************************
331 Pull a string and check the path allowing a wilcard - provide for error return.
332 posix_pathnames version.
333 ****************************************************************************/
335 size_t srvstr_get_path_wcard_posix(TALLOC_CTX
*ctx
,
336 const char *base_ptr
,
343 bool *contains_wcard
)
345 return srvstr_get_path_wcard_internal(ctx
,
357 /****************************************************************************
358 Pull a string and check the path - provide for error return.
359 ****************************************************************************/
361 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
362 const char *base_ptr
,
371 return srvstr_get_path_wcard_internal(ctx
,
383 /****************************************************************************
384 Pull a string and check the path - provide for error return.
385 posix_pathnames version.
386 ****************************************************************************/
388 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
389 const char *base_ptr
,
398 return srvstr_get_path_wcard_internal(ctx
,
411 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
412 char **pp_dest
, const char *src
, int flags
,
413 NTSTATUS
*err
, bool *contains_wcard
)
415 ssize_t bufrem
= smbreq_bufrem(req
, src
);
418 *err
= NT_STATUS_INVALID_PARAMETER
;
422 if (req
->posix_pathnames
) {
423 return srvstr_get_path_wcard_internal(mem_ctx
,
424 (const char *)req
->inbuf
,
434 return srvstr_get_path_wcard_internal(mem_ctx
,
435 (const char *)req
->inbuf
,
447 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
448 char **pp_dest
, const char *src
, int flags
,
452 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
453 flags
, err
, &ignore
);
457 * pull a string from the smb_buf part of a packet. In this case the
458 * string can either be null terminated or it can be terminated by the
459 * end of the smbbuf area
461 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
462 char **dest
, const uint8_t *src
, int flags
)
464 ssize_t bufrem
= smbreq_bufrem(req
, src
);
470 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
474 /****************************************************************************
475 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
476 ****************************************************************************/
478 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
481 if ((fsp
== NULL
) || (conn
== NULL
)) {
482 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
485 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
486 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
492 /****************************************************************************
493 Check if we have a correct fsp pointing to a file.
494 ****************************************************************************/
496 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
499 if (!check_fsp_open(conn
, req
, fsp
)) {
502 if (fsp
->is_directory
) {
503 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
506 if (fsp
->fh
->fd
== -1) {
507 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
510 fsp
->num_smb_operations
++;
514 /****************************************************************************
515 Check if we have a correct fsp pointing to a quota fake file. Replacement for
516 the CHECK_NTQUOTA_HANDLE_OK macro.
517 ****************************************************************************/
519 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
522 if (!check_fsp_open(conn
, req
, fsp
)) {
526 if (fsp
->is_directory
) {
530 if (fsp
->fake_file_handle
== NULL
) {
534 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
538 if (fsp
->fake_file_handle
->private_data
== NULL
) {
545 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
546 const char *name
, int name_type
)
549 char *trim_name_type
;
550 const char *retarget_parm
;
553 int retarget_type
= 0x20;
554 int retarget_port
= NBT_SMB_PORT
;
555 struct sockaddr_storage retarget_addr
;
556 struct sockaddr_in
*in_addr
;
560 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
564 trim_name
= talloc_strdup(talloc_tos(), name
);
565 if (trim_name
== NULL
) {
568 trim_char(trim_name
, ' ', ' ');
570 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
572 if (trim_name_type
== NULL
) {
576 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
577 trim_name_type
, NULL
);
578 if (retarget_parm
== NULL
) {
579 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
582 if (retarget_parm
== NULL
) {
586 retarget
= talloc_strdup(trim_name
, retarget_parm
);
587 if (retarget
== NULL
) {
591 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
593 p
= strchr(retarget
, ':');
596 retarget_port
= atoi(p
);
599 p
= strchr_m(retarget
, '#');
602 if (sscanf(p
, "%x", &retarget_type
) != 1) {
607 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
609 DEBUG(10, ("could not resolve %s\n", retarget
));
613 if (retarget_addr
.ss_family
!= AF_INET
) {
614 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
618 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
620 _smb_setlen(outbuf
, 6);
621 SCVAL(outbuf
, 0, 0x84);
622 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
623 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
625 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
627 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
633 TALLOC_FREE(trim_name
);
637 static void reply_called_name_not_present(char *outbuf
)
639 smb_setlen(outbuf
, 1);
640 SCVAL(outbuf
, 0, 0x83);
641 SCVAL(outbuf
, 4, 0x82);
644 /****************************************************************************
645 Reply to a (netbios-level) special message.
646 ****************************************************************************/
648 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
650 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
651 int msg_type
= CVAL(inbuf
,0);
652 int msg_flags
= CVAL(inbuf
,1);
654 * We only really use 4 bytes of the outbuf, but for the smb_setlen
655 * calculation & friends (srv_send_smb uses that) we need the full smb
658 char outbuf
[smb_size
];
660 memset(outbuf
, '\0', sizeof(outbuf
));
662 smb_setlen(outbuf
,0);
665 case NBSSrequest
: /* session request */
667 /* inbuf_size is guarenteed to be at least 4. */
669 int name_type1
, name_type2
;
670 int name_len1
, name_len2
;
674 if (xconn
->transport
.nbt
.got_session
) {
675 exit_server_cleanly("multiple session request not permitted");
678 SCVAL(outbuf
,0,NBSSpositive
);
681 /* inbuf_size is guaranteed to be at least 4. */
682 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
683 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
684 DEBUG(0,("Invalid name length in session request\n"));
685 reply_called_name_not_present(outbuf
);
688 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
689 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
690 DEBUG(0,("Invalid name length in session request\n"));
691 reply_called_name_not_present(outbuf
);
695 name_type1
= name_extract((unsigned char *)inbuf
,
696 inbuf_size
,(unsigned int)4,name1
);
697 name_type2
= name_extract((unsigned char *)inbuf
,
698 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
700 if (name_type1
== -1 || name_type2
== -1) {
701 DEBUG(0,("Invalid name type in session request\n"));
702 reply_called_name_not_present(outbuf
);
706 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
707 name1
, name_type1
, name2
, name_type2
));
709 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
710 exit_server_cleanly("retargeted client");
714 * Windows NT/2k uses "*SMBSERVER" and XP uses
715 * "*SMBSERV" arrggg!!!
717 if (strequal(name1
, "*SMBSERVER ")
718 || strequal(name1
, "*SMBSERV ")) {
721 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
724 exit_server_cleanly("could not allocate raddr");
727 fstrcpy(name1
, raddr
);
730 set_local_machine_name(name1
, True
);
731 set_remote_machine_name(name2
, True
);
733 if (is_ipaddress(sconn
->remote_hostname
)) {
734 char *p
= discard_const_p(char, sconn
->remote_hostname
);
738 sconn
->remote_hostname
= talloc_strdup(sconn
,
739 get_remote_machine_name());
740 if (sconn
->remote_hostname
== NULL
) {
741 exit_server_cleanly("could not copy remote name");
743 xconn
->remote_hostname
= sconn
->remote_hostname
;
746 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
747 get_local_machine_name(), get_remote_machine_name(),
750 if (name_type2
== 'R') {
751 /* We are being asked for a pathworks session ---
753 reply_called_name_not_present(outbuf
);
757 reload_services(sconn
, conn_snum_used
, true);
760 xconn
->transport
.nbt
.got_session
= true;
764 case 0x89: /* session keepalive request
765 (some old clients produce this?) */
766 SCVAL(outbuf
,0,NBSSkeepalive
);
770 case NBSSpositive
: /* positive session response */
771 case NBSSnegative
: /* negative session response */
772 case NBSSretarget
: /* retarget session response */
773 DEBUG(0,("Unexpected session response\n"));
776 case NBSSkeepalive
: /* session keepalive */
781 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
782 msg_type
, msg_flags
));
784 if (!srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
)) {
785 exit_server_cleanly("reply_special: srv_send_smb failed.");
788 if (CVAL(outbuf
, 0) != 0x82) {
789 exit_server_cleanly("invalid netbios session");
794 /****************************************************************************
796 conn POINTER CAN BE NULL HERE !
797 ****************************************************************************/
799 void reply_tcon(struct smb_request
*req
)
801 connection_struct
*conn
= req
->conn
;
803 char *service_buf
= NULL
;
804 char *password
= NULL
;
810 TALLOC_CTX
*ctx
= talloc_tos();
811 struct smbXsrv_connection
*xconn
= req
->xconn
;
812 NTTIME now
= timeval_to_nttime(&req
->request_time
);
814 START_PROFILE(SMBtcon
);
816 if (req
->buflen
< 4) {
817 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
818 END_PROFILE(SMBtcon
);
823 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
825 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
827 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
830 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
831 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
832 END_PROFILE(SMBtcon
);
835 p2
= strrchr_m(service_buf
,'\\');
839 service
= service_buf
;
842 conn
= make_connection(req
, now
, service
, dev
,
843 req
->vuid
,&nt_status
);
847 reply_nterror(req
, nt_status
);
848 END_PROFILE(SMBtcon
);
852 reply_outbuf(req
, 2, 0);
853 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
854 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
855 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
857 DEBUG(3,("tcon service=%s cnum=%d\n",
858 service
, conn
->cnum
));
860 END_PROFILE(SMBtcon
);
864 /****************************************************************************
865 Reply to a tcon and X.
866 conn POINTER CAN BE NULL HERE !
867 ****************************************************************************/
869 void reply_tcon_and_X(struct smb_request
*req
)
871 connection_struct
*conn
= req
->conn
;
872 const char *service
= NULL
;
873 TALLOC_CTX
*ctx
= talloc_tos();
874 /* what the client thinks the device is */
875 char *client_devicetype
= NULL
;
876 /* what the server tells the client the share represents */
877 const char *server_devicetype
;
884 struct smbXsrv_session
*session
= NULL
;
885 NTTIME now
= timeval_to_nttime(&req
->request_time
);
886 bool session_key_updated
= false;
887 uint16_t optional_support
= 0;
888 struct smbXsrv_connection
*xconn
= req
->xconn
;
890 START_PROFILE(SMBtconX
);
893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
894 END_PROFILE(SMBtconX
);
898 passlen
= SVAL(req
->vwv
+3, 0);
899 tcon_flags
= SVAL(req
->vwv
+2, 0);
901 /* we might have to close an old one */
902 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
903 struct smbXsrv_tcon
*tcon
;
911 * TODO: cancel all outstanding requests on the tcon
913 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
914 if (!NT_STATUS_IS_OK(status
)) {
915 DEBUG(0, ("reply_tcon_and_X: "
916 "smbXsrv_tcon_disconnect() failed: %s\n",
919 * If we hit this case, there is something completely
920 * wrong, so we better disconnect the transport connection.
922 END_PROFILE(SMBtconX
);
923 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
929 * This tree id is gone. Make sure we can't re-use it
935 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
936 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
937 END_PROFILE(SMBtconX
);
941 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
942 p
= req
->buf
+ passlen
;
944 p
= req
->buf
+ passlen
+ 1;
947 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
950 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
951 END_PROFILE(SMBtconX
);
956 * the service name can be either: \\server\share
957 * or share directly like on the DELL PowerVault 705
960 q
= strchr_m(path
+2,'\\');
962 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
963 END_PROFILE(SMBtconX
);
971 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
972 &client_devicetype
, p
,
973 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
975 if (client_devicetype
== NULL
) {
976 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
977 END_PROFILE(SMBtconX
);
981 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
983 nt_status
= smb1srv_session_lookup(xconn
,
984 req
->vuid
, now
, &session
);
985 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
986 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
987 END_PROFILE(SMBtconX
);
990 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
991 reply_nterror(req
, nt_status
);
992 END_PROFILE(SMBtconX
);
995 if (!NT_STATUS_IS_OK(nt_status
)) {
996 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
997 END_PROFILE(SMBtconX
);
1001 if (session
->global
->auth_session_info
== NULL
) {
1002 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1003 END_PROFILE(SMBtconX
);
1008 * If there is no application key defined yet
1011 * This means we setup the application key on the
1012 * first tcon that happens via the given session.
1014 * Once the application key is defined, it does not
1017 if (session
->global
->application_key
.length
== 0 &&
1018 smb2_signing_key_valid(session
->global
->signing_key
))
1020 struct smbXsrv_session
*x
= session
;
1021 struct auth_session_info
*session_info
=
1022 session
->global
->auth_session_info
;
1023 uint8_t session_key
[16];
1025 ZERO_STRUCT(session_key
);
1026 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
1027 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
1030 * The application key is truncated/padded to 16 bytes
1032 x
->global
->application_key
= data_blob_talloc(x
->global
,
1034 sizeof(session_key
));
1035 ZERO_STRUCT(session_key
);
1036 if (x
->global
->application_key
.data
== NULL
) {
1037 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1038 END_PROFILE(SMBtconX
);
1042 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
1045 status
= smb_key_derivation(x
->global
->application_key
.data
,
1046 x
->global
->application_key
.length
,
1047 x
->global
->application_key
.data
);
1048 if (!NT_STATUS_IS_OK(status
)) {
1049 DBG_ERR("smb_key_derivation failed: %s\n",
1053 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1057 * Place the application key into the session_info
1059 data_blob_clear_free(&session_info
->session_key
);
1060 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1061 x
->global
->application_key
);
1062 if (session_info
->session_key
.data
== NULL
) {
1063 data_blob_clear_free(&x
->global
->application_key
);
1064 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1065 END_PROFILE(SMBtconX
);
1068 session_key_updated
= true;
1071 conn
= make_connection(req
, now
, service
, client_devicetype
,
1072 req
->vuid
, &nt_status
);
1076 if (session_key_updated
) {
1077 struct smbXsrv_session
*x
= session
;
1078 struct auth_session_info
*session_info
=
1079 session
->global
->auth_session_info
;
1080 data_blob_clear_free(&x
->global
->application_key
);
1081 data_blob_clear_free(&session_info
->session_key
);
1083 reply_nterror(req
, nt_status
);
1084 END_PROFILE(SMBtconX
);
1089 server_devicetype
= "IPC";
1090 else if ( IS_PRINT(conn
) )
1091 server_devicetype
= "LPT1:";
1093 server_devicetype
= "A:";
1095 if (get_Protocol() < PROTOCOL_NT1
) {
1096 reply_outbuf(req
, 2, 0);
1097 if (message_push_string(&req
->outbuf
, server_devicetype
,
1098 STR_TERMINATE
|STR_ASCII
) == -1) {
1099 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1100 END_PROFILE(SMBtconX
);
1104 /* NT sets the fstype of IPC$ to the null string */
1105 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1107 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1108 /* Return permissions. */
1112 reply_outbuf(req
, 7, 0);
1115 perm1
= FILE_ALL_ACCESS
;
1116 perm2
= FILE_ALL_ACCESS
;
1118 perm1
= conn
->share_access
;
1121 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1122 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1124 reply_outbuf(req
, 3, 0);
1127 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1128 STR_TERMINATE
|STR_ASCII
) == -1)
1129 || (message_push_string(&req
->outbuf
, fstype
,
1130 STR_TERMINATE
) == -1)) {
1131 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1132 END_PROFILE(SMBtconX
);
1136 /* what does setting this bit do? It is set by NT4 and
1137 may affect the ability to autorun mounted cdroms */
1138 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1140 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1142 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1143 DEBUG(2,("Serving %s as a Dfs root\n",
1144 lp_servicename(ctx
, SNUM(conn
)) ));
1145 optional_support
|= SMB_SHARE_IN_DFS
;
1148 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1151 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1152 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1154 DEBUG(3,("tconX service=%s \n",
1157 /* set the incoming and outgoing tid to the just created one */
1158 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1159 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1161 END_PROFILE(SMBtconX
);
1163 req
->tid
= conn
->cnum
;
1166 /****************************************************************************
1167 Reply to an unknown type.
1168 ****************************************************************************/
1170 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1172 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1173 smb_fn_name(type
), type
, type
));
1174 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1178 /****************************************************************************
1180 conn POINTER CAN BE NULL HERE !
1181 ****************************************************************************/
1183 void reply_ioctl(struct smb_request
*req
)
1185 connection_struct
*conn
= req
->conn
;
1188 uint32_t ioctl_code
;
1192 START_PROFILE(SMBioctl
);
1195 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1196 END_PROFILE(SMBioctl
);
1200 device
= SVAL(req
->vwv
+1, 0);
1201 function
= SVAL(req
->vwv
+2, 0);
1202 ioctl_code
= (device
<< 16) + function
;
1204 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1206 switch (ioctl_code
) {
1207 case IOCTL_QUERY_JOB_INFO
:
1211 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1212 END_PROFILE(SMBioctl
);
1216 reply_outbuf(req
, 8, replysize
+1);
1217 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1218 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1219 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1220 p
= smb_buf(req
->outbuf
);
1221 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1222 p
+= 1; /* Allow for alignment */
1224 switch (ioctl_code
) {
1225 case IOCTL_QUERY_JOB_INFO
:
1229 files_struct
*fsp
= file_fsp(
1230 req
, SVAL(req
->vwv
+0, 0));
1232 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1233 END_PROFILE(SMBioctl
);
1237 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1239 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1240 lp_netbios_name(), 15,
1241 STR_TERMINATE
|STR_ASCII
, &len
);
1242 if (!NT_STATUS_IS_OK(status
)) {
1243 reply_nterror(req
, status
);
1244 END_PROFILE(SMBioctl
);
1248 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1250 lp_servicename(talloc_tos(),
1252 13, STR_TERMINATE
|STR_ASCII
, &len
);
1253 if (!NT_STATUS_IS_OK(status
)) {
1254 reply_nterror(req
, status
);
1255 END_PROFILE(SMBioctl
);
1259 memset(p
+18, 0, 13);
1265 END_PROFILE(SMBioctl
);
1269 /****************************************************************************
1270 Strange checkpath NTSTATUS mapping.
1271 ****************************************************************************/
1273 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1275 /* Strange DOS error code semantics only for checkpath... */
1276 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1277 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1278 /* We need to map to ERRbadpath */
1279 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1285 /****************************************************************************
1286 Reply to a checkpath.
1287 ****************************************************************************/
1289 void reply_checkpath(struct smb_request
*req
)
1291 connection_struct
*conn
= req
->conn
;
1292 struct smb_filename
*smb_fname
= NULL
;
1295 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1296 TALLOC_CTX
*ctx
= talloc_tos();
1298 START_PROFILE(SMBcheckpath
);
1300 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1301 STR_TERMINATE
, &status
);
1303 if (!NT_STATUS_IS_OK(status
)) {
1304 status
= map_checkpath_error(req
->flags2
, status
);
1305 reply_nterror(req
, status
);
1306 END_PROFILE(SMBcheckpath
);
1310 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1312 status
= filename_convert(ctx
,
1320 if (!NT_STATUS_IS_OK(status
)) {
1321 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1322 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1323 ERRSRV
, ERRbadpath
);
1324 END_PROFILE(SMBcheckpath
);
1330 if (!VALID_STAT(smb_fname
->st
) &&
1331 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1332 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1333 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1334 status
= map_nt_error_from_unix(errno
);
1338 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1339 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1340 ERRDOS
, ERRbadpath
);
1344 reply_outbuf(req
, 0, 0);
1347 /* We special case this - as when a Windows machine
1348 is parsing a path is steps through the components
1349 one at a time - if a component fails it expects
1350 ERRbadpath, not ERRbadfile.
1352 status
= map_checkpath_error(req
->flags2
, status
);
1353 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1355 * Windows returns different error codes if
1356 * the parent directory is valid but not the
1357 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1358 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1359 * if the path is invalid.
1361 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1362 ERRDOS
, ERRbadpath
);
1366 reply_nterror(req
, status
);
1369 TALLOC_FREE(smb_fname
);
1370 END_PROFILE(SMBcheckpath
);
1374 /****************************************************************************
1376 ****************************************************************************/
1378 void reply_getatr(struct smb_request
*req
)
1380 connection_struct
*conn
= req
->conn
;
1381 struct smb_filename
*smb_fname
= NULL
;
1388 TALLOC_CTX
*ctx
= talloc_tos();
1389 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1391 START_PROFILE(SMBgetatr
);
1393 p
= (const char *)req
->buf
+ 1;
1394 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1395 if (!NT_STATUS_IS_OK(status
)) {
1396 reply_nterror(req
, status
);
1400 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1401 under WfWg - weird! */
1402 if (*fname
== '\0') {
1403 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1404 if (!CAN_WRITE(conn
)) {
1405 mode
|= FILE_ATTRIBUTE_READONLY
;
1410 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1411 status
= filename_convert(ctx
,
1418 if (!NT_STATUS_IS_OK(status
)) {
1419 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1420 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1421 ERRSRV
, ERRbadpath
);
1424 reply_nterror(req
, status
);
1427 if (!VALID_STAT(smb_fname
->st
) &&
1428 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1429 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1430 smb_fname_str_dbg(smb_fname
),
1432 reply_nterror(req
, map_nt_error_from_unix(errno
));
1436 mode
= dos_mode(conn
, smb_fname
);
1437 size
= smb_fname
->st
.st_ex_size
;
1439 if (ask_sharemode
) {
1440 struct timespec write_time_ts
;
1441 struct file_id fileid
;
1443 ZERO_STRUCT(write_time_ts
);
1444 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1445 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1446 if (!null_timespec(write_time_ts
)) {
1447 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1451 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1452 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1457 reply_outbuf(req
, 10, 0);
1459 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1460 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1461 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1463 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1465 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1467 if (get_Protocol() >= PROTOCOL_NT1
) {
1468 SSVAL(req
->outbuf
, smb_flg2
,
1469 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1472 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1473 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1476 TALLOC_FREE(smb_fname
);
1478 END_PROFILE(SMBgetatr
);
1482 /****************************************************************************
1484 ****************************************************************************/
1486 void reply_setatr(struct smb_request
*req
)
1488 struct smb_file_time ft
;
1489 connection_struct
*conn
= req
->conn
;
1490 struct smb_filename
*smb_fname
= NULL
;
1496 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1497 TALLOC_CTX
*ctx
= talloc_tos();
1499 START_PROFILE(SMBsetatr
);
1502 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1506 p
= (const char *)req
->buf
+ 1;
1507 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1508 if (!NT_STATUS_IS_OK(status
)) {
1509 reply_nterror(req
, status
);
1513 status
= filename_convert(ctx
,
1520 if (!NT_STATUS_IS_OK(status
)) {
1521 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1522 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1523 ERRSRV
, ERRbadpath
);
1526 reply_nterror(req
, status
);
1530 if (ISDOT(smb_fname
->base_name
)) {
1532 * Not sure here is the right place to catch this
1533 * condition. Might be moved to somewhere else later -- vl
1535 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1539 mode
= SVAL(req
->vwv
+0, 0);
1540 mtime
= srv_make_unix_date3(req
->vwv
+1);
1542 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1543 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1544 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1546 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1548 status
= smbd_check_access_rights(
1549 conn
, smb_fname
, false, FILE_WRITE_ATTRIBUTES
);
1550 if (!NT_STATUS_IS_OK(status
)) {
1551 reply_nterror(req
, status
);
1555 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1557 reply_nterror(req
, map_nt_error_from_unix(errno
));
1562 ft
= (struct smb_file_time
) {
1563 .mtime
= convert_time_t_to_timespec(mtime
)
1566 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 reply_nterror(req
, status
);
1572 reply_outbuf(req
, 0, 0);
1574 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1577 TALLOC_FREE(smb_fname
);
1578 END_PROFILE(SMBsetatr
);
1582 /****************************************************************************
1584 ****************************************************************************/
1586 void reply_dskattr(struct smb_request
*req
)
1588 connection_struct
*conn
= req
->conn
;
1590 uint64_t dfree
,dsize
,bsize
;
1591 struct smb_filename smb_fname
;
1592 START_PROFILE(SMBdskattr
);
1594 ZERO_STRUCT(smb_fname
);
1595 smb_fname
.base_name
= discard_const_p(char, ".");
1597 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1598 reply_nterror(req
, map_nt_error_from_unix(errno
));
1599 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1600 END_PROFILE(SMBdskattr
);
1604 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1605 if (ret
== (uint64_t)-1) {
1606 reply_nterror(req
, map_nt_error_from_unix(errno
));
1607 END_PROFILE(SMBdskattr
);
1612 * Force max to fit in 16 bit fields.
1614 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1618 if (bsize
> (WORDMAX
*512)) {
1619 bsize
= (WORDMAX
*512);
1620 if (dsize
> WORDMAX
)
1622 if (dfree
> WORDMAX
)
1628 reply_outbuf(req
, 5, 0);
1630 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1631 double total_space
, free_space
;
1632 /* we need to scale this to a number that DOS6 can handle. We
1633 use floating point so we can handle large drives on systems
1634 that don't have 64 bit integers
1636 we end up displaying a maximum of 2G to DOS systems
1638 total_space
= dsize
* (double)bsize
;
1639 free_space
= dfree
* (double)bsize
;
1641 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1642 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1644 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1645 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1647 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1648 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1649 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1650 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1652 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1653 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1654 SSVAL(req
->outbuf
,smb_vwv2
,512);
1655 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1658 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1660 END_PROFILE(SMBdskattr
);
1665 * Utility function to split the filename from the directory.
1667 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1668 char **fname_dir_out
,
1669 char **fname_mask_out
)
1671 const char *p
= NULL
;
1672 char *fname_dir
= NULL
;
1673 char *fname_mask
= NULL
;
1675 p
= strrchr_m(fname_in
, '/');
1677 fname_dir
= talloc_strdup(ctx
, ".");
1678 fname_mask
= talloc_strdup(ctx
, fname_in
);
1680 fname_dir
= talloc_strndup(ctx
, fname_in
,
1681 PTR_DIFF(p
, fname_in
));
1682 fname_mask
= talloc_strdup(ctx
, p
+1);
1685 if (!fname_dir
|| !fname_mask
) {
1686 TALLOC_FREE(fname_dir
);
1687 TALLOC_FREE(fname_mask
);
1688 return NT_STATUS_NO_MEMORY
;
1691 *fname_dir_out
= fname_dir
;
1692 *fname_mask_out
= fname_mask
;
1693 return NT_STATUS_OK
;
1696 /****************************************************************************
1698 ****************************************************************************/
1700 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1710 char *mask2
= talloc_strdup(ctx
, mask
);
1716 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1720 memset(buf
+1,' ',11);
1721 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1723 push_ascii(buf
+1,mask2
,8, 0);
1724 push_ascii(buf
+9,p
+1,3, 0);
1727 push_ascii(buf
+1,mask2
,11, 0);
1730 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1732 srv_put_dos_date(buf
,22,date
);
1733 SSVAL(buf
,26,size
& 0xFFFF);
1734 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1735 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1736 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1737 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1738 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1742 /****************************************************************************
1744 Can be called from SMBsearch, SMBffirst or SMBfunique.
1745 ****************************************************************************/
1747 void reply_search(struct smb_request
*req
)
1749 connection_struct
*conn
= req
->conn
;
1752 char *directory
= NULL
;
1753 struct smb_filename
*smb_fname
= NULL
;
1757 struct timespec date
;
1759 unsigned int numentries
= 0;
1760 unsigned int maxentries
= 0;
1761 bool finished
= False
;
1766 bool check_descend
= False
;
1767 bool expect_close
= False
;
1769 bool mask_contains_wcard
= False
;
1770 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1771 TALLOC_CTX
*ctx
= talloc_tos();
1772 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1773 struct smbXsrv_connection
*xconn
= req
->xconn
;
1774 struct smbd_server_connection
*sconn
= req
->sconn
;
1775 files_struct
*fsp
= NULL
;
1777 START_PROFILE(SMBsearch
);
1780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1784 if (req
->posix_pathnames
) {
1785 reply_unknown_new(req
, req
->cmd
);
1789 /* If we were called as SMBffirst then we must expect close. */
1790 if(req
->cmd
== SMBffirst
) {
1791 expect_close
= True
;
1794 reply_outbuf(req
, 1, 3);
1795 maxentries
= SVAL(req
->vwv
+0, 0);
1796 dirtype
= SVAL(req
->vwv
+1, 0);
1797 p
= (const char *)req
->buf
+ 1;
1798 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1799 &nt_status
, &mask_contains_wcard
);
1800 if (!NT_STATUS_IS_OK(nt_status
)) {
1801 reply_nterror(req
, nt_status
);
1805 if (smbreq_bufrem(req
, p
) < 3) {
1806 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1811 status_len
= SVAL(p
, 0);
1814 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1816 if (status_len
== 0) {
1818 struct smb_filename
*smb_dname
= NULL
;
1819 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1820 ucf_flags_from_smb_request(req
);
1821 nt_status
= filename_convert(ctx
, conn
,
1825 &mask_contains_wcard
,
1827 if (!NT_STATUS_IS_OK(nt_status
)) {
1828 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1829 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1830 ERRSRV
, ERRbadpath
);
1833 reply_nterror(req
, nt_status
);
1837 directory
= smb_fname
->base_name
;
1839 p
= strrchr_m(directory
,'/');
1840 if ((p
!= NULL
) && (*directory
!= '/')) {
1841 mask
= talloc_strdup(ctx
, p
+ 1);
1842 directory
= talloc_strndup(ctx
, directory
,
1843 PTR_DIFF(p
, directory
));
1845 mask
= talloc_strdup(ctx
, directory
);
1846 directory
= talloc_strdup(ctx
,".");
1850 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1854 memset((char *)status
,'\0',21);
1855 SCVAL(status
,0,(dirtype
& 0x1F));
1857 smb_dname
= synthetic_smb_fname(talloc_tos(),
1862 if (smb_dname
== NULL
) {
1863 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1868 * As we've cut off the last component from
1869 * smb_fname we need to re-stat smb_dname
1870 * so FILE_OPEN disposition knows the directory
1873 if (req
->posix_pathnames
) {
1874 ret
= SMB_VFS_LSTAT(conn
, smb_dname
);
1876 ret
= SMB_VFS_STAT(conn
, smb_dname
);
1879 nt_status
= map_nt_error_from_unix(errno
);
1880 reply_nterror(req
, nt_status
);
1885 * Open an fsp on this directory for the dptr.
1887 nt_status
= SMB_VFS_CREATE_FILE(
1890 0, /* root_dir_fid */
1891 smb_dname
, /* dname */
1892 FILE_LIST_DIRECTORY
, /* access_mask */
1894 FILE_SHARE_WRITE
, /* share_access */
1895 FILE_OPEN
, /* create_disposition*/
1896 FILE_DIRECTORY_FILE
, /* create_options */
1897 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1898 NO_OPLOCK
, /* oplock_request */
1900 0, /* allocation_size */
1901 0, /* private_flags */
1906 NULL
, /* in_context */
1907 NULL
);/* out_context */
1909 if (!NT_STATUS_IS_OK(nt_status
)) {
1910 DBG_ERR("failed to open directory %s\n",
1911 smb_fname_str_dbg(smb_dname
));
1912 reply_nterror(req
, nt_status
);
1916 nt_status
= dptr_create(conn
,
1923 mask_contains_wcard
,
1927 TALLOC_FREE(smb_dname
);
1929 if (!NT_STATUS_IS_OK(nt_status
)) {
1931 * Use NULL here for the first parameter (req)
1932 * as this is not a client visible handle so
1933 * can'tbe part of an SMB1 chain.
1935 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1937 reply_nterror(req
, nt_status
);
1941 dptr_num
= dptr_dnum(fsp
->dptr
);
1945 const char *dirpath
;
1947 if (smbreq_bufrem(req
, p
) < 21) {
1948 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1952 memcpy(status
,p
,21);
1953 status_dirtype
= CVAL(status
,0) & 0x1F;
1954 if (status_dirtype
!= (dirtype
& 0x1F)) {
1955 dirtype
= status_dirtype
;
1958 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
1962 dirpath
= dptr_path(sconn
, dptr_num
);
1963 directory
= talloc_strdup(ctx
, dirpath
);
1965 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1969 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1974 * For a 'continue' search we have no string. So
1975 * check from the initial saved string.
1977 if (!req
->posix_pathnames
) {
1978 mask_contains_wcard
= ms_has_wild(mask
);
1980 dirtype
= dptr_attr(sconn
, dptr_num
);
1983 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1985 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1986 char buf
[DIR_STRUCT_SIZE
];
1987 memcpy(buf
,status
,21);
1988 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1989 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1990 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1993 dptr_fill(sconn
, buf
+12,dptr_num
);
1994 if (dptr_zero(buf
+12) && (status_len
==0)) {
1999 if (message_push_blob(&req
->outbuf
,
2000 data_blob_const(buf
, sizeof(buf
)))
2002 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2007 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
2008 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
2010 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
2012 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2013 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2014 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
2015 check_descend
= True
;
2018 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
2019 finished
= !get_dir_entry(ctx
,
2030 char buf
[DIR_STRUCT_SIZE
];
2031 memcpy(buf
,status
,21);
2032 if (!make_dir_struct(ctx
,
2038 convert_timespec_to_time_t(date
),
2039 !allow_long_path_components
)) {
2040 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2043 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
2046 if (message_push_blob(&req
->outbuf
,
2047 data_blob_const(buf
, sizeof(buf
)))
2049 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2059 /* If we were called as SMBffirst with smb_search_id == NULL
2060 and no entries were found then return error and close fsp->dptr
2063 if (numentries
== 0) {
2066 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2069 } else if(expect_close
&& status_len
== 0) {
2070 /* Close the dptr - we know it's gone */
2073 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2078 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2079 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
2081 /* fsp may have been closed above. */
2083 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2088 if ((numentries
== 0) && !mask_contains_wcard
) {
2089 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2093 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2094 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2095 SCVAL(smb_buf(req
->outbuf
),0,5);
2096 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2098 /* The replies here are never long name. */
2099 SSVAL(req
->outbuf
, smb_flg2
,
2100 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2101 if (!allow_long_path_components
) {
2102 SSVAL(req
->outbuf
, smb_flg2
,
2103 SVAL(req
->outbuf
, smb_flg2
)
2104 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2107 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2108 SSVAL(req
->outbuf
, smb_flg2
,
2109 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2111 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2112 smb_fn_name(req
->cmd
),
2119 TALLOC_FREE(directory
);
2121 TALLOC_FREE(smb_fname
);
2122 END_PROFILE(SMBsearch
);
2126 /****************************************************************************
2127 Reply to a fclose (stop directory search).
2128 ****************************************************************************/
2130 void reply_fclose(struct smb_request
*req
)
2138 bool path_contains_wcard
= False
;
2139 TALLOC_CTX
*ctx
= talloc_tos();
2140 struct smbd_server_connection
*sconn
= req
->sconn
;
2141 files_struct
*fsp
= NULL
;
2143 START_PROFILE(SMBfclose
);
2145 if (req
->posix_pathnames
) {
2146 reply_unknown_new(req
, req
->cmd
);
2147 END_PROFILE(SMBfclose
);
2151 p
= (const char *)req
->buf
+ 1;
2152 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2153 &err
, &path_contains_wcard
);
2154 if (!NT_STATUS_IS_OK(err
)) {
2155 reply_nterror(req
, err
);
2156 END_PROFILE(SMBfclose
);
2160 if (smbreq_bufrem(req
, p
) < 3) {
2161 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2162 END_PROFILE(SMBfclose
);
2167 status_len
= SVAL(p
,0);
2170 if (status_len
== 0) {
2171 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2172 END_PROFILE(SMBfclose
);
2176 if (smbreq_bufrem(req
, p
) < 21) {
2177 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2178 END_PROFILE(SMBfclose
);
2182 memcpy(status
,p
,21);
2184 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
2186 /* Close the file - we know it's gone */
2187 close_file(NULL
, fsp
, NORMAL_CLOSE
);
2192 reply_outbuf(req
, 1, 0);
2193 SSVAL(req
->outbuf
,smb_vwv0
,0);
2195 DEBUG(3,("search close\n"));
2197 END_PROFILE(SMBfclose
);
2201 /****************************************************************************
2203 ****************************************************************************/
2205 void reply_open(struct smb_request
*req
)
2207 connection_struct
*conn
= req
->conn
;
2208 struct smb_filename
*smb_fname
= NULL
;
2218 uint32_t access_mask
;
2219 uint32_t share_mode
;
2220 uint32_t create_disposition
;
2221 uint32_t create_options
= 0;
2222 uint32_t private_flags
= 0;
2225 TALLOC_CTX
*ctx
= talloc_tos();
2227 START_PROFILE(SMBopen
);
2230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2234 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2235 deny_mode
= SVAL(req
->vwv
+0, 0);
2236 dos_attr
= SVAL(req
->vwv
+1, 0);
2238 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2239 STR_TERMINATE
, &status
);
2240 if (!NT_STATUS_IS_OK(status
)) {
2241 reply_nterror(req
, status
);
2245 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2246 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2247 &share_mode
, &create_disposition
,
2248 &create_options
, &private_flags
)) {
2249 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2253 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2255 status
= filename_convert(ctx
,
2262 if (!NT_STATUS_IS_OK(status
)) {
2263 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2264 reply_botherror(req
,
2265 NT_STATUS_PATH_NOT_COVERED
,
2266 ERRSRV
, ERRbadpath
);
2269 reply_nterror(req
, status
);
2273 status
= SMB_VFS_CREATE_FILE(
2276 0, /* root_dir_fid */
2277 smb_fname
, /* fname */
2278 access_mask
, /* access_mask */
2279 share_mode
, /* share_access */
2280 create_disposition
, /* create_disposition*/
2281 create_options
, /* create_options */
2282 dos_attr
, /* file_attributes */
2283 oplock_request
, /* oplock_request */
2285 0, /* allocation_size */
2291 NULL
, NULL
); /* create context */
2293 if (!NT_STATUS_IS_OK(status
)) {
2294 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2295 /* We have re-scheduled this call. */
2299 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2300 reply_openerror(req
, status
);
2304 fsp
= fcb_or_dos_open(
2311 bool ok
= defer_smb1_sharing_violation(req
);
2315 reply_openerror(req
, status
);
2320 /* Ensure we're pointing at the correct stat struct. */
2321 TALLOC_FREE(smb_fname
);
2322 smb_fname
= fsp
->fsp_name
;
2324 size
= smb_fname
->st
.st_ex_size
;
2325 fattr
= dos_mode(conn
, smb_fname
);
2327 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2329 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2330 DEBUG(3,("attempt to open a directory %s\n",
2332 close_file(req
, fsp
, ERROR_CLOSE
);
2333 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2334 ERRDOS
, ERRnoaccess
);
2338 reply_outbuf(req
, 7, 0);
2339 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2340 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2341 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2342 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2344 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2346 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2347 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2349 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2350 SCVAL(req
->outbuf
,smb_flg
,
2351 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2354 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2355 SCVAL(req
->outbuf
,smb_flg
,
2356 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2359 END_PROFILE(SMBopen
);
2363 /****************************************************************************
2364 Reply to an open and X.
2365 ****************************************************************************/
2367 void reply_open_and_X(struct smb_request
*req
)
2369 connection_struct
*conn
= req
->conn
;
2370 struct smb_filename
*smb_fname
= NULL
;
2372 uint16_t open_flags
;
2375 /* Breakout the oplock request bits so we can set the
2376 reply bits separately. */
2377 int ex_oplock_request
;
2378 int core_oplock_request
;
2381 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2382 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2390 uint64_t allocation_size
;
2391 ssize_t retval
= -1;
2392 uint32_t access_mask
;
2393 uint32_t share_mode
;
2394 uint32_t create_disposition
;
2395 uint32_t create_options
= 0;
2396 uint32_t private_flags
= 0;
2398 TALLOC_CTX
*ctx
= talloc_tos();
2400 START_PROFILE(SMBopenX
);
2402 if (req
->wct
< 15) {
2403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2407 open_flags
= SVAL(req
->vwv
+2, 0);
2408 deny_mode
= SVAL(req
->vwv
+3, 0);
2409 smb_attr
= SVAL(req
->vwv
+5, 0);
2410 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2411 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2412 oplock_request
= ex_oplock_request
| core_oplock_request
;
2413 smb_ofun
= SVAL(req
->vwv
+8, 0);
2414 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2416 /* If it's an IPC, pass off the pipe handler. */
2418 if (lp_nt_pipe_support()) {
2419 reply_open_pipe_and_X(conn
, req
);
2421 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2426 /* XXXX we need to handle passed times, sattr and flags */
2427 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2428 STR_TERMINATE
, &status
);
2429 if (!NT_STATUS_IS_OK(status
)) {
2430 reply_nterror(req
, status
);
2434 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2436 &access_mask
, &share_mode
,
2437 &create_disposition
,
2440 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2444 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2446 status
= filename_convert(ctx
,
2453 if (!NT_STATUS_IS_OK(status
)) {
2454 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2455 reply_botherror(req
,
2456 NT_STATUS_PATH_NOT_COVERED
,
2457 ERRSRV
, ERRbadpath
);
2460 reply_nterror(req
, status
);
2464 status
= SMB_VFS_CREATE_FILE(
2467 0, /* root_dir_fid */
2468 smb_fname
, /* fname */
2469 access_mask
, /* access_mask */
2470 share_mode
, /* share_access */
2471 create_disposition
, /* create_disposition*/
2472 create_options
, /* create_options */
2473 smb_attr
, /* file_attributes */
2474 oplock_request
, /* oplock_request */
2476 0, /* allocation_size */
2481 &smb_action
, /* pinfo */
2482 NULL
, NULL
); /* create context */
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2486 /* We have re-scheduled this call. */
2490 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2491 reply_openerror(req
, status
);
2495 fsp
= fcb_or_dos_open(
2502 bool ok
= defer_smb1_sharing_violation(req
);
2506 reply_openerror(req
, status
);
2511 smb_action
= FILE_WAS_OPENED
;
2514 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2515 if the file is truncated or created. */
2516 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2517 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2518 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2519 close_file(req
, fsp
, ERROR_CLOSE
);
2520 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2523 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2525 close_file(req
, fsp
, ERROR_CLOSE
);
2526 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2529 status
= vfs_stat_fsp(fsp
);
2530 if (!NT_STATUS_IS_OK(status
)) {
2531 close_file(req
, fsp
, ERROR_CLOSE
);
2532 reply_nterror(req
, status
);
2537 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2538 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2539 close_file(req
, fsp
, ERROR_CLOSE
);
2540 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2543 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2545 /* If the caller set the extended oplock request bit
2546 and we granted one (by whatever means) - set the
2547 correct bit for extended oplock reply.
2550 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2551 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2554 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2555 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2558 /* If the caller set the core oplock request bit
2559 and we granted one (by whatever means) - set the
2560 correct bit for core oplock reply.
2563 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2564 reply_outbuf(req
, 19, 0);
2566 reply_outbuf(req
, 15, 0);
2569 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2570 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2572 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2573 SCVAL(req
->outbuf
, smb_flg
,
2574 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2577 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2578 SCVAL(req
->outbuf
, smb_flg
,
2579 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2582 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2583 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2584 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2585 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2587 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2589 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2590 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2591 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2593 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2594 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2598 TALLOC_FREE(smb_fname
);
2599 END_PROFILE(SMBopenX
);
2603 /****************************************************************************
2604 Reply to a SMBulogoffX.
2605 ****************************************************************************/
2607 void reply_ulogoffX(struct smb_request
*req
)
2609 struct smbd_server_connection
*sconn
= req
->sconn
;
2610 struct user_struct
*vuser
;
2611 struct smbXsrv_session
*session
= NULL
;
2614 START_PROFILE(SMBulogoffX
);
2616 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2619 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2620 (unsigned long long)req
->vuid
));
2622 req
->vuid
= UID_FIELD_INVALID
;
2623 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2624 END_PROFILE(SMBulogoffX
);
2628 session
= vuser
->session
;
2632 * TODO: cancel all outstanding requests on the session
2634 status
= smbXsrv_session_logoff(session
);
2635 if (!NT_STATUS_IS_OK(status
)) {
2636 DEBUG(0, ("reply_ulogoff: "
2637 "smbXsrv_session_logoff() failed: %s\n",
2638 nt_errstr(status
)));
2640 * If we hit this case, there is something completely
2641 * wrong, so we better disconnect the transport connection.
2643 END_PROFILE(SMBulogoffX
);
2644 exit_server(__location__
": smbXsrv_session_logoff failed");
2648 TALLOC_FREE(session
);
2650 reply_outbuf(req
, 2, 0);
2651 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2652 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2654 DEBUG(3, ("ulogoffX vuid=%llu\n",
2655 (unsigned long long)req
->vuid
));
2657 END_PROFILE(SMBulogoffX
);
2658 req
->vuid
= UID_FIELD_INVALID
;
2661 /****************************************************************************
2662 Reply to a mknew or a create.
2663 ****************************************************************************/
2665 void reply_mknew(struct smb_request
*req
)
2667 connection_struct
*conn
= req
->conn
;
2668 struct smb_filename
*smb_fname
= NULL
;
2671 struct smb_file_time ft
;
2673 int oplock_request
= 0;
2675 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2676 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2677 uint32_t create_disposition
;
2678 uint32_t create_options
= 0;
2680 TALLOC_CTX
*ctx
= talloc_tos();
2682 START_PROFILE(SMBcreate
);
2686 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2690 fattr
= SVAL(req
->vwv
+0, 0);
2691 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2693 if (req
->cmd
== SMBmknew
) {
2694 /* We should fail if file exists. */
2695 create_disposition
= FILE_CREATE
;
2697 /* Create if file doesn't exist, truncate if it does. */
2698 create_disposition
= FILE_OVERWRITE_IF
;
2702 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2704 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2705 STR_TERMINATE
, &status
);
2706 if (!NT_STATUS_IS_OK(status
)) {
2707 reply_nterror(req
, status
);
2711 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2712 status
= filename_convert(ctx
,
2719 if (!NT_STATUS_IS_OK(status
)) {
2720 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2721 reply_botherror(req
,
2722 NT_STATUS_PATH_NOT_COVERED
,
2723 ERRSRV
, ERRbadpath
);
2726 reply_nterror(req
, status
);
2730 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2731 DEBUG(0,("Attempt to create file (%s) with volid set - "
2732 "please report this\n",
2733 smb_fname_str_dbg(smb_fname
)));
2736 status
= SMB_VFS_CREATE_FILE(
2739 0, /* root_dir_fid */
2740 smb_fname
, /* fname */
2741 access_mask
, /* access_mask */
2742 share_mode
, /* share_access */
2743 create_disposition
, /* create_disposition*/
2744 create_options
, /* create_options */
2745 fattr
, /* file_attributes */
2746 oplock_request
, /* oplock_request */
2748 0, /* allocation_size */
2749 0, /* private_flags */
2754 NULL
, NULL
); /* create context */
2756 if (!NT_STATUS_IS_OK(status
)) {
2757 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2758 /* We have re-scheduled this call. */
2761 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2762 bool ok
= defer_smb1_sharing_violation(req
);
2767 reply_openerror(req
, status
);
2771 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2772 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2773 if (!NT_STATUS_IS_OK(status
)) {
2774 END_PROFILE(SMBcreate
);
2778 reply_outbuf(req
, 1, 0);
2779 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2781 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2782 SCVAL(req
->outbuf
,smb_flg
,
2783 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2786 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2787 SCVAL(req
->outbuf
,smb_flg
,
2788 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2791 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2792 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2793 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2794 (unsigned int)fattr
));
2797 TALLOC_FREE(smb_fname
);
2798 END_PROFILE(SMBcreate
);
2802 /****************************************************************************
2803 Reply to a create temporary file.
2804 ****************************************************************************/
2806 void reply_ctemp(struct smb_request
*req
)
2808 connection_struct
*conn
= req
->conn
;
2809 struct smb_filename
*smb_fname
= NULL
;
2810 char *wire_name
= NULL
;
2819 TALLOC_CTX
*ctx
= talloc_tos();
2821 START_PROFILE(SMBctemp
);
2824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2828 fattr
= SVAL(req
->vwv
+0, 0);
2829 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2831 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2832 STR_TERMINATE
, &status
);
2833 if (!NT_STATUS_IS_OK(status
)) {
2834 reply_nterror(req
, status
);
2838 for (i
= 0; i
< 10; i
++) {
2840 fname
= talloc_asprintf(ctx
,
2843 generate_random_str_list(ctx
, 5, "0123456789"));
2845 fname
= talloc_asprintf(ctx
,
2847 generate_random_str_list(ctx
, 5, "0123456789"));
2851 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2855 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2856 status
= filename_convert(ctx
, conn
,
2862 if (!NT_STATUS_IS_OK(status
)) {
2863 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2864 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2865 ERRSRV
, ERRbadpath
);
2868 reply_nterror(req
, status
);
2872 /* Create the file. */
2873 status
= SMB_VFS_CREATE_FILE(
2876 0, /* root_dir_fid */
2877 smb_fname
, /* fname */
2878 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2879 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2880 FILE_CREATE
, /* create_disposition*/
2881 0, /* create_options */
2882 fattr
, /* file_attributes */
2883 oplock_request
, /* oplock_request */
2885 0, /* allocation_size */
2886 0, /* private_flags */
2891 NULL
, NULL
); /* create context */
2893 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2895 TALLOC_FREE(smb_fname
);
2899 if (!NT_STATUS_IS_OK(status
)) {
2900 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2901 /* We have re-scheduled this call. */
2904 if (NT_STATUS_EQUAL(
2905 status
, NT_STATUS_SHARING_VIOLATION
)) {
2906 bool ok
= defer_smb1_sharing_violation(req
);
2911 reply_openerror(req
, status
);
2919 /* Collision after 10 times... */
2920 reply_nterror(req
, status
);
2924 reply_outbuf(req
, 1, 0);
2925 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2927 /* the returned filename is relative to the directory */
2928 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2930 s
= fsp
->fsp_name
->base_name
;
2936 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2937 thing in the byte section. JRA */
2938 SSVALS(p
, 0, -1); /* what is this? not in spec */
2940 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2942 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2946 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2947 SCVAL(req
->outbuf
, smb_flg
,
2948 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2951 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2952 SCVAL(req
->outbuf
, smb_flg
,
2953 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2956 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2957 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2958 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2960 TALLOC_FREE(smb_fname
);
2961 TALLOC_FREE(wire_name
);
2962 END_PROFILE(SMBctemp
);
2966 /*******************************************************************
2967 Check if a user is allowed to rename a file.
2968 ********************************************************************/
2970 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2973 if (!CAN_WRITE(conn
)) {
2974 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2977 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2978 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2979 /* Only bother to read the DOS attribute if we might deny the
2980 rename on the grounds of attribute mismatch. */
2981 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2982 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2983 return NT_STATUS_NO_SUCH_FILE
;
2987 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2988 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2989 return NT_STATUS_OK
;
2992 /* If no pathnames are open below this
2993 directory, allow the rename. */
2995 if (lp_strict_rename(SNUM(conn
))) {
2997 * Strict rename, check open file db.
2999 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
3000 return NT_STATUS_ACCESS_DENIED
;
3002 } else if (file_find_subpath(fsp
)) {
3004 * No strict rename, just look in local process.
3006 return NT_STATUS_ACCESS_DENIED
;
3008 return NT_STATUS_OK
;
3011 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
3012 return NT_STATUS_OK
;
3015 return NT_STATUS_ACCESS_DENIED
;
3018 /*******************************************************************
3019 * unlink a file with all relevant access checks
3020 *******************************************************************/
3022 static NTSTATUS
do_unlink(connection_struct
*conn
,
3023 struct smb_request
*req
,
3024 struct smb_filename
*smb_fname
,
3029 uint32_t dirtype_orig
= dirtype
;
3032 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
3034 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3035 smb_fname_str_dbg(smb_fname
),
3038 if (!CAN_WRITE(conn
)) {
3039 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
3043 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
3045 ret
= SMB_VFS_STAT(conn
, smb_fname
);
3048 return map_nt_error_from_unix(errno
);
3051 fattr
= dos_mode(conn
, smb_fname
);
3053 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
3054 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
3057 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
3059 return NT_STATUS_NO_SUCH_FILE
;
3062 if (!dir_check_ftype(fattr
, dirtype
)) {
3063 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3064 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3066 return NT_STATUS_NO_SUCH_FILE
;
3069 if (dirtype_orig
& 0x8000) {
3070 /* These will never be set for POSIX. */
3071 return NT_STATUS_NO_SUCH_FILE
;
3075 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
3076 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3079 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
3080 return NT_STATUS_NO_SUCH_FILE
;
3083 if (dirtype
& 0xFF00) {
3084 /* These will never be set for POSIX. */
3085 return NT_STATUS_NO_SUCH_FILE
;
3090 return NT_STATUS_NO_SUCH_FILE
;
3093 /* Can't delete a directory. */
3094 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
3095 return NT_STATUS_FILE_IS_A_DIRECTORY
;
3100 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
3101 return NT_STATUS_OBJECT_NAME_INVALID
;
3102 #endif /* JRATEST */
3104 /* On open checks the open itself will check the share mode, so
3105 don't do it here as we'll get it wrong. */
3107 status
= SMB_VFS_CREATE_FILE
3110 0, /* root_dir_fid */
3111 smb_fname
, /* fname */
3112 DELETE_ACCESS
, /* access_mask */
3113 FILE_SHARE_NONE
, /* share_access */
3114 FILE_OPEN
, /* create_disposition*/
3115 FILE_NON_DIRECTORY_FILE
, /* create_options */
3116 /* file_attributes */
3117 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
3118 FILE_ATTRIBUTE_NORMAL
,
3119 0, /* oplock_request */
3121 0, /* allocation_size */
3122 0, /* private_flags */
3127 NULL
, NULL
); /* create context */
3129 if (!NT_STATUS_IS_OK(status
)) {
3130 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3131 nt_errstr(status
)));
3135 status
= can_set_delete_on_close(fsp
, fattr
);
3136 if (!NT_STATUS_IS_OK(status
)) {
3137 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3139 smb_fname_str_dbg(smb_fname
),
3140 nt_errstr(status
)));
3141 close_file(req
, fsp
, NORMAL_CLOSE
);
3145 /* The set is across all open files on this dev/inode pair. */
3146 if (!set_delete_on_close(fsp
, True
,
3147 conn
->session_info
->security_token
,
3148 conn
->session_info
->unix_token
)) {
3149 close_file(req
, fsp
, NORMAL_CLOSE
);
3150 return NT_STATUS_ACCESS_DENIED
;
3153 return close_file(req
, fsp
, NORMAL_CLOSE
);
3156 /****************************************************************************
3157 The guts of the unlink command, split out so it may be called by the NT SMB
3159 ****************************************************************************/
3161 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
3162 uint32_t dirtype
, struct smb_filename
*smb_fname
,
3165 char *fname_dir
= NULL
;
3166 char *fname_mask
= NULL
;
3168 NTSTATUS status
= NT_STATUS_OK
;
3169 struct smb_filename
*smb_fname_dir
= NULL
;
3170 TALLOC_CTX
*ctx
= talloc_tos();
3172 /* Split up the directory from the filename/mask. */
3173 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3174 &fname_dir
, &fname_mask
);
3175 if (!NT_STATUS_IS_OK(status
)) {
3180 * We should only check the mangled cache
3181 * here if unix_convert failed. This means
3182 * that the path in 'mask' doesn't exist
3183 * on the file system and so we need to look
3184 * for a possible mangle. This patch from
3185 * Tine Smukavec <valentin.smukavec@hermes.si>.
3188 if (!VALID_STAT(smb_fname
->st
) &&
3189 mangle_is_mangled(fname_mask
, conn
->params
)) {
3190 char *new_mask
= NULL
;
3191 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3192 &new_mask
, conn
->params
);
3194 TALLOC_FREE(fname_mask
);
3195 fname_mask
= new_mask
;
3202 * Only one file needs to be unlinked. Append the mask back
3203 * onto the directory.
3205 TALLOC_FREE(smb_fname
->base_name
);
3206 if (ISDOT(fname_dir
)) {
3207 /* Ensure we use canonical names on open. */
3208 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3212 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3217 if (!smb_fname
->base_name
) {
3218 status
= NT_STATUS_NO_MEMORY
;
3222 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3225 status
= check_name(conn
, smb_fname
);
3226 if (!NT_STATUS_IS_OK(status
)) {
3230 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3231 if (!NT_STATUS_IS_OK(status
)) {
3237 struct smb_Dir
*dir_hnd
= NULL
;
3239 const char *dname
= NULL
;
3240 char *talloced
= NULL
;
3242 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3243 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3247 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3250 if (strequal(fname_mask
,"????????.???")) {
3251 TALLOC_FREE(fname_mask
);
3252 fname_mask
= talloc_strdup(ctx
, "*");
3254 status
= NT_STATUS_NO_MEMORY
;
3259 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3264 if (smb_fname_dir
== NULL
) {
3265 status
= NT_STATUS_NO_MEMORY
;
3269 status
= check_name(conn
, smb_fname_dir
);
3270 if (!NT_STATUS_IS_OK(status
)) {
3274 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3276 if (dir_hnd
== NULL
) {
3277 status
= map_nt_error_from_unix(errno
);
3281 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3282 the pattern matches against the long name, otherwise the short name
3283 We don't implement this yet XXXX
3286 status
= NT_STATUS_NO_SUCH_FILE
;
3288 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3289 &smb_fname
->st
, &talloced
))) {
3290 TALLOC_CTX
*frame
= talloc_stackframe();
3292 if (!is_visible_file(conn
, fname_dir
, dname
,
3293 &smb_fname
->st
, true)) {
3295 TALLOC_FREE(talloced
);
3299 /* Quick check for "." and ".." */
3300 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3302 TALLOC_FREE(talloced
);
3306 if(!mask_match(dname
, fname_mask
,
3307 conn
->case_sensitive
)) {
3309 TALLOC_FREE(talloced
);
3313 TALLOC_FREE(smb_fname
->base_name
);
3314 if (ISDOT(fname_dir
)) {
3315 /* Ensure we use canonical names on open. */
3316 smb_fname
->base_name
=
3317 talloc_asprintf(smb_fname
, "%s",
3320 smb_fname
->base_name
=
3321 talloc_asprintf(smb_fname
, "%s/%s",
3325 if (!smb_fname
->base_name
) {
3326 TALLOC_FREE(dir_hnd
);
3327 status
= NT_STATUS_NO_MEMORY
;
3329 TALLOC_FREE(talloced
);
3333 status
= check_name(conn
, smb_fname
);
3334 if (!NT_STATUS_IS_OK(status
)) {
3335 TALLOC_FREE(dir_hnd
);
3337 TALLOC_FREE(talloced
);
3341 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3342 if (!NT_STATUS_IS_OK(status
)) {
3343 TALLOC_FREE(dir_hnd
);
3345 TALLOC_FREE(talloced
);
3350 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3351 smb_fname
->base_name
));
3354 TALLOC_FREE(talloced
);
3356 TALLOC_FREE(dir_hnd
);
3359 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3360 status
= map_nt_error_from_unix(errno
);
3364 TALLOC_FREE(smb_fname_dir
);
3365 TALLOC_FREE(fname_dir
);
3366 TALLOC_FREE(fname_mask
);
3370 /****************************************************************************
3372 ****************************************************************************/
3374 void reply_unlink(struct smb_request
*req
)
3376 connection_struct
*conn
= req
->conn
;
3378 struct smb_filename
*smb_fname
= NULL
;
3381 bool path_contains_wcard
= False
;
3382 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3383 ucf_flags_from_smb_request(req
);
3384 TALLOC_CTX
*ctx
= talloc_tos();
3386 START_PROFILE(SMBunlink
);
3389 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3393 dirtype
= SVAL(req
->vwv
+0, 0);
3395 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3396 STR_TERMINATE
, &status
,
3397 &path_contains_wcard
);
3398 if (!NT_STATUS_IS_OK(status
)) {
3399 reply_nterror(req
, status
);
3403 status
= filename_convert(ctx
, conn
,
3407 &path_contains_wcard
,
3409 if (!NT_STATUS_IS_OK(status
)) {
3410 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3411 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3412 ERRSRV
, ERRbadpath
);
3415 reply_nterror(req
, status
);
3419 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3421 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3422 path_contains_wcard
);
3423 if (!NT_STATUS_IS_OK(status
)) {
3424 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3425 /* We have re-scheduled this call. */
3428 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
3429 bool ok
= defer_smb1_sharing_violation(req
);
3434 reply_nterror(req
, status
);
3438 reply_outbuf(req
, 0, 0);
3440 TALLOC_FREE(smb_fname
);
3441 END_PROFILE(SMBunlink
);
3445 /****************************************************************************
3447 ****************************************************************************/
3449 static void fail_readraw(void)
3451 const char *errstr
= talloc_asprintf(talloc_tos(),
3452 "FAIL ! reply_readbraw: socket write fail (%s)",
3457 exit_server_cleanly(errstr
);
3460 /****************************************************************************
3461 Fake (read/write) sendfile. Returns -1 on read or write fail.
3462 ****************************************************************************/
3464 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3465 off_t startpos
, size_t nread
)
3468 size_t tosend
= nread
;
3475 bufsize
= MIN(nread
, 65536);
3477 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3481 while (tosend
> 0) {
3485 cur_read
= MIN(tosend
, bufsize
);
3486 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3492 /* If we had a short read, fill with zeros. */
3493 if (ret
< cur_read
) {
3494 memset(buf
+ ret
, '\0', cur_read
- ret
);
3497 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3498 if (ret
!= cur_read
) {
3499 int saved_errno
= errno
;
3501 * Try and give an error message saying what
3504 DEBUG(0, ("write_data failed for client %s. "
3506 smbXsrv_connection_dbg(xconn
),
3507 strerror(saved_errno
)));
3509 errno
= saved_errno
;
3513 startpos
+= cur_read
;
3517 return (ssize_t
)nread
;
3520 /****************************************************************************
3521 Deal with the case of sendfile reading less bytes from the file than
3522 requested. Fill with zeros (all we can do). Returns 0 on success
3523 ****************************************************************************/
3525 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3531 #define SHORT_SEND_BUFSIZE 1024
3532 if (nread
< headersize
) {
3533 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3534 "header for file %s (%s). Terminating\n",
3535 fsp_str_dbg(fsp
), strerror(errno
)));
3539 nread
-= headersize
;
3541 if (nread
< smb_maxcnt
) {
3542 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3544 DEBUG(0,("sendfile_short_send: malloc failed "
3545 "for file %s (%s). Terminating\n",
3546 fsp_str_dbg(fsp
), strerror(errno
)));
3550 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3551 "with zeros !\n", fsp_str_dbg(fsp
)));
3553 while (nread
< smb_maxcnt
) {
3555 * We asked for the real file size and told sendfile
3556 * to not go beyond the end of the file. But it can
3557 * happen that in between our fstat call and the
3558 * sendfile call the file was truncated. This is very
3559 * bad because we have already announced the larger
3560 * number of bytes to the client.
3562 * The best we can do now is to send 0-bytes, just as
3563 * a read from a hole in a sparse file would do.
3565 * This should happen rarely enough that I don't care
3566 * about efficiency here :-)
3571 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3572 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3573 if (ret
!= to_write
) {
3574 int saved_errno
= errno
;
3576 * Try and give an error message saying what
3579 DEBUG(0, ("write_data failed for client %s. "
3581 smbXsrv_connection_dbg(xconn
),
3582 strerror(saved_errno
)));
3583 errno
= saved_errno
;
3594 /****************************************************************************
3595 Return a readbraw error (4 bytes of zero).
3596 ****************************************************************************/
3598 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3604 smbd_lock_socket(xconn
);
3605 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3606 int saved_errno
= errno
;
3608 * Try and give an error message saying what
3611 DEBUG(0, ("write_data failed for client %s. "
3613 smbXsrv_connection_dbg(xconn
),
3614 strerror(saved_errno
)));
3615 errno
= saved_errno
;
3619 smbd_unlock_socket(xconn
);
3622 /****************************************************************************
3623 Use sendfile in readbraw.
3624 ****************************************************************************/
3626 static void send_file_readbraw(connection_struct
*conn
,
3627 struct smb_request
*req
,
3633 struct smbXsrv_connection
*xconn
= req
->xconn
;
3634 char *outbuf
= NULL
;
3638 * We can only use sendfile on a non-chained packet
3639 * but we can use on a non-oplocked file. tridge proved this
3640 * on a train in Germany :-). JRA.
3641 * reply_readbraw has already checked the length.
3644 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3645 (fsp
->wcp
== NULL
) &&
3646 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3647 ssize_t sendfile_read
= -1;
3649 DATA_BLOB header_blob
;
3651 _smb_setlen(header
,nread
);
3652 header_blob
= data_blob_const(header
, 4);
3654 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3655 &header_blob
, startpos
,
3657 if (sendfile_read
== -1) {
3658 /* Returning ENOSYS means no data at all was sent.
3659 * Do this as a normal read. */
3660 if (errno
== ENOSYS
) {
3661 goto normal_readbraw
;
3665 * Special hack for broken Linux with no working sendfile. If we
3666 * return EINTR we sent the header but not the rest of the data.
3667 * Fake this up by doing read/write calls.
3669 if (errno
== EINTR
) {
3670 /* Ensure we don't do this again. */
3671 set_use_sendfile(SNUM(conn
), False
);
3672 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3674 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3675 DEBUG(0,("send_file_readbraw: "
3676 "fake_sendfile failed for "
3680 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3685 DEBUG(0,("send_file_readbraw: sendfile failed for "
3686 "file %s (%s). Terminating\n",
3687 fsp_str_dbg(fsp
), strerror(errno
)));
3688 exit_server_cleanly("send_file_readbraw sendfile failed");
3689 } else if (sendfile_read
== 0) {
3691 * Some sendfile implementations return 0 to indicate
3692 * that there was a short read, but nothing was
3693 * actually written to the socket. In this case,
3694 * fallback to the normal read path so the header gets
3695 * the correct byte count.
3697 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3698 "bytes falling back to the normal read: "
3699 "%s\n", fsp_str_dbg(fsp
)));
3700 goto normal_readbraw
;
3703 /* Deal with possible short send. */
3704 if (sendfile_read
!= 4+nread
) {
3705 ret
= sendfile_short_send(xconn
, fsp
,
3706 sendfile_read
, 4, nread
);
3716 outbuf
= talloc_array(NULL
, char, nread
+4);
3718 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3719 (unsigned)(nread
+4)));
3720 reply_readbraw_error(xconn
);
3725 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3726 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3735 _smb_setlen(outbuf
,ret
);
3736 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3737 int saved_errno
= errno
;
3739 * Try and give an error message saying what
3742 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3743 smbXsrv_connection_dbg(xconn
),
3744 strerror(saved_errno
)));
3745 errno
= saved_errno
;
3750 TALLOC_FREE(outbuf
);
3753 /****************************************************************************
3754 Reply to a readbraw (core+ protocol).
3755 ****************************************************************************/
3757 void reply_readbraw(struct smb_request
*req
)
3759 connection_struct
*conn
= req
->conn
;
3760 struct smbXsrv_connection
*xconn
= req
->xconn
;
3761 ssize_t maxcount
,mincount
;
3765 struct lock_struct lock
;
3769 START_PROFILE(SMBreadbraw
);
3771 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3772 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3773 "raw reads/writes are disallowed.");
3777 reply_readbraw_error(xconn
);
3778 END_PROFILE(SMBreadbraw
);
3782 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3783 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3784 "'async smb echo handler = yes'\n"));
3785 reply_readbraw_error(xconn
);
3786 END_PROFILE(SMBreadbraw
);
3791 * Special check if an oplock break has been issued
3792 * and the readraw request croses on the wire, we must
3793 * return a zero length response here.
3796 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3799 * We have to do a check_fsp by hand here, as
3800 * we must always return 4 zero bytes on error,
3804 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3805 req
->vuid
!= fsp
->vuid
||
3806 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3808 * fsp could be NULL here so use the value from the packet. JRA.
3810 DEBUG(3,("reply_readbraw: fnum %d not valid "
3812 (int)SVAL(req
->vwv
+0, 0)));
3813 reply_readbraw_error(xconn
);
3814 END_PROFILE(SMBreadbraw
);
3818 /* Do a "by hand" version of CHECK_READ. */
3819 if (!(fsp
->can_read
||
3820 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3821 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3822 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3823 (int)SVAL(req
->vwv
+0, 0)));
3824 reply_readbraw_error(xconn
);
3825 END_PROFILE(SMBreadbraw
);
3829 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3831 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3832 if(req
->wct
== 10) {
3834 * This is a large offset (64 bit) read.
3837 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3840 DEBUG(0,("reply_readbraw: negative 64 bit "
3841 "readraw offset (%.0f) !\n",
3842 (double)startpos
));
3843 reply_readbraw_error(xconn
);
3844 END_PROFILE(SMBreadbraw
);
3849 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3850 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3852 /* ensure we don't overrun the packet size */
3853 maxcount
= MIN(65535,maxcount
);
3855 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3856 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3859 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3860 reply_readbraw_error(xconn
);
3861 END_PROFILE(SMBreadbraw
);
3865 status
= vfs_stat_fsp(fsp
);
3866 if (NT_STATUS_IS_OK(status
)) {
3867 size
= fsp
->fsp_name
->st
.st_ex_size
;
3870 if (startpos
>= size
) {
3873 nread
= MIN(maxcount
,(size
- startpos
));
3876 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3877 if (nread
< mincount
)
3881 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3882 "min=%lu nread=%lu\n",
3883 fsp_fnum_dbg(fsp
), (double)startpos
,
3884 (unsigned long)maxcount
,
3885 (unsigned long)mincount
,
3886 (unsigned long)nread
) );
3888 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3890 DEBUG(5,("reply_readbraw finished\n"));
3892 END_PROFILE(SMBreadbraw
);
3897 #define DBGC_CLASS DBGC_LOCKING
3899 /****************************************************************************
3900 Reply to a lockread (core+ protocol).
3901 ****************************************************************************/
3903 static void reply_lockread_locked(struct tevent_req
*subreq
);
3905 void reply_lockread(struct smb_request
*req
)
3907 struct tevent_req
*subreq
= NULL
;
3908 connection_struct
*conn
= req
->conn
;
3910 struct smbd_lock_element
*lck
= NULL
;
3912 START_PROFILE(SMBlockread
);
3915 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3916 END_PROFILE(SMBlockread
);
3920 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3922 if (!check_fsp(conn
, req
, fsp
)) {
3923 END_PROFILE(SMBlockread
);
3927 if (!CHECK_READ(fsp
,req
)) {
3928 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3929 END_PROFILE(SMBlockread
);
3933 lck
= talloc(req
, struct smbd_lock_element
);
3935 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3936 END_PROFILE(SMBlockread
);
3941 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3942 * protocol request that predates the read/write lock concept.
3943 * Thus instead of asking for a read lock here we need to ask
3944 * for a write lock. JRA.
3945 * Note that the requested lock size is unaffected by max_send.
3948 *lck
= (struct smbd_lock_element
) {
3949 .req_guid
= smbd_request_guid(req
, 0),
3950 .smblctx
= req
->smbpid
,
3951 .brltype
= WRITE_LOCK
,
3952 .count
= SVAL(req
->vwv
+1, 0),
3953 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
3956 subreq
= smbd_smb1_do_locks_send(
3962 false, /* large_offset */
3966 if (subreq
== NULL
) {
3967 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3968 END_PROFILE(SMBlockread
);
3971 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
3972 END_PROFILE(SMBlockread
);
3975 static void reply_lockread_locked(struct tevent_req
*subreq
)
3977 struct smb_request
*req
= NULL
;
3983 size_t numtoread
, maxtoread
;
3984 struct files_struct
*fsp
= NULL
;
3987 START_PROFILE(SMBlockread
);
3989 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
3992 status
= smbd_smb1_do_locks_recv(subreq
);
3993 TALLOC_FREE(subreq
);
3995 if (!NT_STATUS_IS_OK(status
)) {
3996 reply_nterror(req
, status
);
4000 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4002 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
4006 numtoread
= SVAL(req
->vwv
+1, 0);
4007 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4010 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4012 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4014 if (numtoread
> maxtoread
) {
4015 DBG_WARNING("requested read size (%zu) is greater than "
4016 "maximum allowed (%zu/%d). "
4017 "Returning short read of maximum allowed for "
4018 "compatibility with Windows 2000.\n",
4021 req
->xconn
->smb1
.sessions
.max_send
);
4022 numtoread
= maxtoread
;
4025 reply_outbuf(req
, 5, numtoread
+ 3);
4027 data
= smb_buf(req
->outbuf
) + 3;
4029 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4032 reply_nterror(req
, map_nt_error_from_unix(errno
));
4036 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4038 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4039 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4040 p
= smb_buf(req
->outbuf
);
4041 SCVAL(p
,0,0); /* pad byte. */
4044 DEBUG(3,("lockread %s num=%d nread=%d\n",
4045 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4048 ok
= srv_send_smb(req
->xconn
,
4049 (char *)req
->outbuf
,
4052 IS_CONN_ENCRYPTED(req
->conn
),
4055 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4058 END_PROFILE(SMBlockread
);
4063 #define DBGC_CLASS DBGC_ALL
4065 /****************************************************************************
4067 ****************************************************************************/
4069 void reply_read(struct smb_request
*req
)
4071 connection_struct
*conn
= req
->conn
;
4078 struct lock_struct lock
;
4079 struct smbXsrv_connection
*xconn
= req
->xconn
;
4081 START_PROFILE(SMBread
);
4084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4085 END_PROFILE(SMBread
);
4089 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4091 if (!check_fsp(conn
, req
, fsp
)) {
4092 END_PROFILE(SMBread
);
4096 if (!CHECK_READ(fsp
,req
)) {
4097 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4098 END_PROFILE(SMBread
);
4102 numtoread
= SVAL(req
->vwv
+1, 0);
4103 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4106 * The requested read size cannot be greater than max_send. JRA.
4108 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
4110 if (numtoread
> maxtoread
) {
4111 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4112 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4113 (unsigned int)numtoread
, (unsigned int)maxtoread
,
4114 (unsigned int)xconn
->smb1
.sessions
.max_send
));
4115 numtoread
= maxtoread
;
4118 reply_outbuf(req
, 5, numtoread
+3);
4120 data
= smb_buf(req
->outbuf
) + 3;
4122 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4123 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
4126 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4127 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4128 END_PROFILE(SMBread
);
4133 nread
= read_file(fsp
,data
,startpos
,numtoread
);
4136 reply_nterror(req
, map_nt_error_from_unix(errno
));
4140 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
4142 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
4143 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
4144 SCVAL(smb_buf(req
->outbuf
),0,1);
4145 SSVAL(smb_buf(req
->outbuf
),1,nread
);
4147 DEBUG(3, ("read %s num=%d nread=%d\n",
4148 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
4151 END_PROFILE(SMBread
);
4155 /****************************************************************************
4157 ****************************************************************************/
4159 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
4163 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
4166 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
4168 SCVAL(outbuf
,smb_vwv0
,0xFF);
4169 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
4170 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
4171 SSVAL(outbuf
,smb_vwv6
,
4172 (smb_wct
- 4) /* offset from smb header to wct */
4173 + 1 /* the wct field */
4174 + 12 * sizeof(uint16_t) /* vwv */
4175 + 2 /* the buflen field */
4176 + 1); /* padding byte */
4177 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
4178 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
4179 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4180 _smb_setlen_large(outbuf
,
4181 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
4185 /****************************************************************************
4186 Reply to a read and X - possibly using sendfile.
4187 ****************************************************************************/
4189 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
4190 files_struct
*fsp
, off_t startpos
,
4193 struct smbXsrv_connection
*xconn
= req
->xconn
;
4195 struct lock_struct lock
;
4196 int saved_errno
= 0;
4199 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4200 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
4203 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4204 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4209 * We can only use sendfile on a non-chained packet
4210 * but we can use on a non-oplocked file. tridge proved this
4211 * on a train in Germany :-). JRA.
4214 if (!req_is_in_chain(req
) &&
4216 (fsp
->base_fsp
== NULL
) &&
4217 (fsp
->wcp
== NULL
) &&
4218 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
4219 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4222 status
= vfs_stat_fsp(fsp
);
4223 if (!NT_STATUS_IS_OK(status
)) {
4224 reply_nterror(req
, status
);
4228 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4229 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4230 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4232 * We already know that we would do a short read, so don't
4233 * try the sendfile() path.
4235 goto nosendfile_read
;
4239 * Set up the packet header before send. We
4240 * assume here the sendfile will work (get the
4241 * correct amount of data).
4244 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4246 construct_reply_common_req(req
, (char *)headerbuf
);
4247 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4249 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4250 startpos
, smb_maxcnt
);
4252 saved_errno
= errno
;
4254 /* Returning ENOSYS means no data at all was sent.
4255 Do this as a normal read. */
4256 if (errno
== ENOSYS
) {
4261 * Special hack for broken Linux with no working sendfile. If we
4262 * return EINTR we sent the header but not the rest of the data.
4263 * Fake this up by doing read/write calls.
4266 if (errno
== EINTR
) {
4267 /* Ensure we don't do this again. */
4268 set_use_sendfile(SNUM(conn
), False
);
4269 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4270 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4273 saved_errno
= errno
;
4274 DEBUG(0,("send_file_readX: "
4275 "fake_sendfile failed for "
4276 "file %s (%s) for client %s. "
4279 smbXsrv_connection_dbg(xconn
),
4280 strerror(saved_errno
)));
4281 errno
= saved_errno
;
4282 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4284 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4285 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4286 /* No outbuf here means successful sendfile. */
4290 DEBUG(0,("send_file_readX: sendfile failed for file "
4291 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4293 exit_server_cleanly("send_file_readX sendfile failed");
4294 } else if (nread
== 0) {
4296 * Some sendfile implementations return 0 to indicate
4297 * that there was a short read, but nothing was
4298 * actually written to the socket. In this case,
4299 * fallback to the normal read path so the header gets
4300 * the correct byte count.
4302 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4303 "falling back to the normal read: %s\n",
4308 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4309 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4311 /* Deal with possible short send. */
4312 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4315 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4316 sizeof(headerbuf
), smb_maxcnt
);
4319 r
= "send_file_readX: sendfile_short_send failed";
4320 DEBUG(0,("%s for file %s (%s).\n",
4321 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4322 exit_server_cleanly(r
);
4325 /* No outbuf here means successful sendfile. */
4326 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4327 SMB_PERFCOUNT_END(&req
->pcd
);
4333 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4334 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4337 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4338 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4339 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4341 * We already know that we would do a short
4342 * read, so don't try the sendfile() path.
4344 goto nosendfile_read
;
4347 construct_reply_common_req(req
, (char *)headerbuf
);
4348 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4350 /* Send out the header. */
4351 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4353 if (ret
!= sizeof(headerbuf
)) {
4354 saved_errno
= errno
;
4356 * Try and give an error message saying what
4359 DEBUG(0,("send_file_readX: write_data failed for file "
4360 "%s (%s) for client %s. Terminating\n",
4362 smbXsrv_connection_dbg(xconn
),
4363 strerror(saved_errno
)));
4364 errno
= saved_errno
;
4365 exit_server_cleanly("send_file_readX sendfile failed");
4367 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4369 saved_errno
= errno
;
4370 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4371 "%s (%s) for client %s. Terminating\n",
4373 smbXsrv_connection_dbg(xconn
),
4374 strerror(saved_errno
)));
4375 errno
= saved_errno
;
4376 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4383 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4384 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4385 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4387 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4388 startpos
, smb_maxcnt
);
4389 saved_errno
= errno
;
4392 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4396 setup_readX_header((char *)req
->outbuf
, nread
);
4398 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4399 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4403 TALLOC_FREE(req
->outbuf
);
4407 /****************************************************************************
4408 Work out how much space we have for a read return.
4409 ****************************************************************************/
4411 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4413 struct smbXsrv_connection
*xconn
= req
->xconn
;
4415 if (xconn
->protocol
< PROTOCOL_NT1
) {
4416 return xconn
->smb1
.sessions
.max_send
;
4419 if (!lp_large_readwrite()) {
4420 return xconn
->smb1
.sessions
.max_send
;
4423 if (req_is_in_chain(req
)) {
4424 return xconn
->smb1
.sessions
.max_send
;
4427 if (req
->encrypted
) {
4429 * Don't take encrypted traffic up to the
4430 * limit. There are padding considerations
4431 * that make that tricky.
4433 return xconn
->smb1
.sessions
.max_send
;
4436 if (srv_is_signing_active(xconn
)) {
4440 if (!lp_unix_extensions()) {
4445 * We can do ultra-large POSIX reads.
4450 /****************************************************************************
4451 Calculate how big a read can be. Copes with all clients. It's always
4452 safe to return a short read - Windows does this.
4453 ****************************************************************************/
4455 static size_t calc_read_size(const struct smb_request
*req
,
4459 struct smbXsrv_connection
*xconn
= req
->xconn
;
4460 size_t max_pdu
= calc_max_read_pdu(req
);
4461 size_t total_size
= 0;
4462 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4463 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4466 * Windows explicitly ignores upper size of 0xFFFF.
4467 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4468 * We must do the same as these will never fit even in
4469 * an extended size NetBIOS packet.
4471 if (upper_size
== 0xFFFF) {
4475 if (xconn
->protocol
< PROTOCOL_NT1
) {
4479 total_size
= ((upper_size
<<16) | lower_size
);
4482 * LARGE_READX test shows it's always safe to return
4483 * a short read. Windows does so.
4485 return MIN(total_size
, max_len
);
4488 /****************************************************************************
4489 Reply to a read and X.
4490 ****************************************************************************/
4492 void reply_read_and_X(struct smb_request
*req
)
4494 connection_struct
*conn
= req
->conn
;
4499 bool big_readX
= False
;
4501 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4504 START_PROFILE(SMBreadX
);
4506 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4507 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4511 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4512 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4513 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4515 /* If it's an IPC, pass off the pipe handler. */
4517 reply_pipe_read_and_X(req
);
4518 END_PROFILE(SMBreadX
);
4522 if (!check_fsp(conn
, req
, fsp
)) {
4523 END_PROFILE(SMBreadX
);
4527 if (!CHECK_READ(fsp
,req
)) {
4528 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4529 END_PROFILE(SMBreadX
);
4533 upper_size
= SVAL(req
->vwv
+7, 0);
4534 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4535 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4537 * This is a heuristic to avoid keeping large
4538 * outgoing buffers around over long-lived aio
4544 if (req
->wct
== 12) {
4546 * This is a large offset (64 bit) read.
4548 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4553 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4558 if (NT_STATUS_IS_OK(status
)) {
4559 /* Read scheduled - we're done. */
4562 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4563 /* Real error - report to client. */
4564 END_PROFILE(SMBreadX
);
4565 reply_nterror(req
, status
);
4568 /* NT_STATUS_RETRY - fall back to sync read. */
4571 smbd_lock_socket(req
->xconn
);
4572 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4573 smbd_unlock_socket(req
->xconn
);
4576 END_PROFILE(SMBreadX
);
4580 /****************************************************************************
4581 Error replies to writebraw must have smb_wct == 1. Fix this up.
4582 ****************************************************************************/
4584 void error_to_writebrawerr(struct smb_request
*req
)
4586 uint8_t *old_outbuf
= req
->outbuf
;
4588 reply_outbuf(req
, 1, 0);
4590 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4591 TALLOC_FREE(old_outbuf
);
4594 /****************************************************************************
4595 Read 4 bytes of a smb packet and return the smb length of the packet.
4596 Store the result in the buffer. This version of the function will
4597 never return a session keepalive (length of zero).
4598 Timeout is in milliseconds.
4599 ****************************************************************************/
4601 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4604 uint8_t msgtype
= NBSSkeepalive
;
4606 while (msgtype
== NBSSkeepalive
) {
4609 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4611 if (!NT_STATUS_IS_OK(status
)) {
4612 char addr
[INET6_ADDRSTRLEN
];
4613 /* Try and give an error message
4614 * saying what client failed. */
4615 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4616 "client %s read error = %s.\n",
4617 get_peer_addr(fd
,addr
,sizeof(addr
)),
4618 nt_errstr(status
)));
4622 msgtype
= CVAL(inbuf
, 0);
4625 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4626 (unsigned long)len
));
4628 return NT_STATUS_OK
;
4631 /****************************************************************************
4632 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4633 ****************************************************************************/
4635 void reply_writebraw(struct smb_request
*req
)
4637 connection_struct
*conn
= req
->conn
;
4638 struct smbXsrv_connection
*xconn
= req
->xconn
;
4641 ssize_t total_written
=0;
4642 size_t numtowrite
=0;
4645 const char *data
=NULL
;
4648 struct lock_struct lock
;
4651 START_PROFILE(SMBwritebraw
);
4654 * If we ever reply with an error, it must have the SMB command
4655 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4658 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4660 if (srv_is_signing_active(xconn
)) {
4661 END_PROFILE(SMBwritebraw
);
4662 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4663 "raw reads/writes are disallowed.");
4666 if (req
->wct
< 12) {
4667 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4668 error_to_writebrawerr(req
);
4669 END_PROFILE(SMBwritebraw
);
4673 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4674 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4675 "'async smb echo handler = yes'\n"));
4676 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4677 error_to_writebrawerr(req
);
4678 END_PROFILE(SMBwritebraw
);
4682 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4683 if (!check_fsp(conn
, req
, fsp
)) {
4684 error_to_writebrawerr(req
);
4685 END_PROFILE(SMBwritebraw
);
4689 if (!CHECK_WRITE(fsp
)) {
4690 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4691 error_to_writebrawerr(req
);
4692 END_PROFILE(SMBwritebraw
);
4696 tcount
= IVAL(req
->vwv
+1, 0);
4697 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4698 write_through
= BITSETW(req
->vwv
+7,0);
4700 /* We have to deal with slightly different formats depending
4701 on whether we are using the core+ or lanman1.0 protocol */
4703 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4704 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4705 data
= smb_buf_const(req
->inbuf
);
4707 numtowrite
= SVAL(req
->vwv
+10, 0);
4708 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4711 /* Ensure we don't write bytes past the end of this packet. */
4713 * This already protects us against CVE-2017-12163.
4715 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4716 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4717 error_to_writebrawerr(req
);
4718 END_PROFILE(SMBwritebraw
);
4722 if (!fsp
->print_file
) {
4723 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4724 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4727 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4728 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4729 error_to_writebrawerr(req
);
4730 END_PROFILE(SMBwritebraw
);
4736 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4739 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4740 "wrote=%d sync=%d\n",
4741 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4742 (int)nwritten
, (int)write_through
));
4744 if (nwritten
< (ssize_t
)numtowrite
) {
4745 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4746 error_to_writebrawerr(req
);
4750 total_written
= nwritten
;
4752 /* Allocate a buffer of 64k + length. */
4753 buf
= talloc_array(NULL
, char, 65540);
4755 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4756 error_to_writebrawerr(req
);
4760 /* Return a SMBwritebraw message to the redirector to tell
4761 * it to send more bytes */
4763 memcpy(buf
, req
->inbuf
, smb_size
);
4764 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4765 SCVAL(buf
,smb_com
,SMBwritebraw
);
4766 SSVALS(buf
,smb_vwv0
,0xFFFF);
4768 if (!srv_send_smb(req
->xconn
,
4770 false, 0, /* no signing */
4771 IS_CONN_ENCRYPTED(conn
),
4773 exit_server_cleanly("reply_writebraw: srv_send_smb "
4777 /* Now read the raw data into the buffer and write it */
4778 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4780 if (!NT_STATUS_IS_OK(status
)) {
4781 exit_server_cleanly("secondary writebraw failed");
4784 /* Set up outbuf to return the correct size */
4785 reply_outbuf(req
, 1, 0);
4787 if (numtowrite
!= 0) {
4789 if (numtowrite
> 0xFFFF) {
4790 DEBUG(0,("reply_writebraw: Oversize secondary write "
4791 "raw requested (%u). Terminating\n",
4792 (unsigned int)numtowrite
));
4793 exit_server_cleanly("secondary writebraw failed");
4796 if (tcount
> nwritten
+numtowrite
) {
4797 DEBUG(3,("reply_writebraw: Client overestimated the "
4799 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4802 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4805 if (!NT_STATUS_IS_OK(status
)) {
4806 /* Try and give an error message
4807 * saying what client failed. */
4808 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4809 "raw read failed (%s) for client %s. "
4810 "Terminating\n", nt_errstr(status
),
4811 smbXsrv_connection_dbg(xconn
)));
4812 exit_server_cleanly("secondary writebraw failed");
4816 * We are not vulnerable to CVE-2017-12163
4817 * here as we are guaranteed to have numtowrite
4818 * bytes available - we just read from the client.
4820 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4821 if (nwritten
== -1) {
4823 reply_nterror(req
, map_nt_error_from_unix(errno
));
4824 error_to_writebrawerr(req
);
4828 if (nwritten
< (ssize_t
)numtowrite
) {
4829 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4830 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4834 total_written
+= nwritten
;
4839 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4841 status
= sync_file(conn
, fsp
, write_through
);
4842 if (!NT_STATUS_IS_OK(status
)) {
4843 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4844 fsp_str_dbg(fsp
), nt_errstr(status
)));
4845 reply_nterror(req
, status
);
4846 error_to_writebrawerr(req
);
4850 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4852 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4853 (int)total_written
));
4855 /* We won't return a status if write through is not selected - this
4856 * follows what WfWg does */
4857 END_PROFILE(SMBwritebraw
);
4859 if (!write_through
&& total_written
==tcount
) {
4861 #if RABBIT_PELLET_FIX
4863 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4864 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4867 if (!send_keepalive(xconn
->transport
.sock
)) {
4868 exit_server_cleanly("reply_writebraw: send of "
4869 "keepalive failed");
4872 TALLOC_FREE(req
->outbuf
);
4877 END_PROFILE(SMBwritebraw
);
4882 #define DBGC_CLASS DBGC_LOCKING
4884 /****************************************************************************
4885 Reply to a writeunlock (core+).
4886 ****************************************************************************/
4888 void reply_writeunlock(struct smb_request
*req
)
4890 connection_struct
*conn
= req
->conn
;
4891 ssize_t nwritten
= -1;
4896 NTSTATUS status
= NT_STATUS_OK
;
4898 struct lock_struct lock
;
4899 int saved_errno
= 0;
4901 START_PROFILE(SMBwriteunlock
);
4904 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4905 END_PROFILE(SMBwriteunlock
);
4909 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4911 if (!check_fsp(conn
, req
, fsp
)) {
4912 END_PROFILE(SMBwriteunlock
);
4916 if (!CHECK_WRITE(fsp
)) {
4917 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4918 END_PROFILE(SMBwriteunlock
);
4922 numtowrite
= SVAL(req
->vwv
+1, 0);
4923 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4924 data
= (const char *)req
->buf
+ 3;
4927 * Ensure client isn't asking us to write more than
4928 * they sent. CVE-2017-12163.
4930 remaining
= smbreq_bufrem(req
, data
);
4931 if (numtowrite
> remaining
) {
4932 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4933 END_PROFILE(SMBwriteunlock
);
4937 if (!fsp
->print_file
&& numtowrite
> 0) {
4938 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4939 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4942 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4943 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4944 END_PROFILE(SMBwriteunlock
);
4949 /* The special X/Open SMB protocol handling of
4950 zero length writes is *NOT* done for
4952 if(numtowrite
== 0) {
4955 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4956 saved_errno
= errno
;
4959 status
= sync_file(conn
, fsp
, False
/* write through */);
4960 if (!NT_STATUS_IS_OK(status
)) {
4961 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4962 fsp_str_dbg(fsp
), nt_errstr(status
)));
4963 reply_nterror(req
, status
);
4968 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4972 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4973 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4977 if (numtowrite
&& !fsp
->print_file
) {
4978 struct smbd_lock_element l
= {
4979 .req_guid
= smbd_request_guid(req
, 0),
4980 .smblctx
= req
->smbpid
,
4981 .brltype
= UNLOCK_LOCK
,
4983 .count
= numtowrite
,
4985 status
= smbd_do_unlocking(req
, fsp
, 1, &l
, WINDOWS_LOCK
);
4986 if (NT_STATUS_V(status
)) {
4987 reply_nterror(req
, status
);
4992 reply_outbuf(req
, 1, 0);
4994 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4996 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4997 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5000 END_PROFILE(SMBwriteunlock
);
5005 #define DBGC_CLASS DBGC_ALL
5007 /****************************************************************************
5009 ****************************************************************************/
5011 void reply_write(struct smb_request
*req
)
5013 connection_struct
*conn
= req
->conn
;
5016 ssize_t nwritten
= -1;
5020 struct lock_struct lock
;
5022 int saved_errno
= 0;
5024 START_PROFILE(SMBwrite
);
5027 END_PROFILE(SMBwrite
);
5028 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5032 /* If it's an IPC, pass off the pipe handler. */
5034 reply_pipe_write(req
);
5035 END_PROFILE(SMBwrite
);
5039 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5041 if (!check_fsp(conn
, req
, fsp
)) {
5042 END_PROFILE(SMBwrite
);
5046 if (!CHECK_WRITE(fsp
)) {
5047 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5048 END_PROFILE(SMBwrite
);
5052 numtowrite
= SVAL(req
->vwv
+1, 0);
5053 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5054 data
= (const char *)req
->buf
+ 3;
5057 * Ensure client isn't asking us to write more than
5058 * they sent. CVE-2017-12163.
5060 remaining
= smbreq_bufrem(req
, data
);
5061 if (numtowrite
> remaining
) {
5062 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5063 END_PROFILE(SMBwrite
);
5067 if (!fsp
->print_file
) {
5068 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5069 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5072 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5073 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5074 END_PROFILE(SMBwrite
);
5080 * X/Open SMB protocol says that if smb_vwv1 is
5081 * zero then the file size should be extended or
5082 * truncated to the size given in smb_vwv[2-3].
5085 if(numtowrite
== 0) {
5087 * This is actually an allocate call, and set EOF. JRA.
5089 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
5091 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5094 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
5096 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5099 trigger_write_time_update_immediate(fsp
);
5101 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5104 status
= sync_file(conn
, fsp
, False
);
5105 if (!NT_STATUS_IS_OK(status
)) {
5106 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5107 fsp_str_dbg(fsp
), nt_errstr(status
)));
5108 reply_nterror(req
, status
);
5113 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5117 if((nwritten
== 0) && (numtowrite
!= 0)) {
5118 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5122 reply_outbuf(req
, 1, 0);
5124 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5126 if (nwritten
< (ssize_t
)numtowrite
) {
5127 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
5128 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
5131 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5134 END_PROFILE(SMBwrite
);
5138 /****************************************************************************
5139 Ensure a buffer is a valid writeX for recvfile purposes.
5140 ****************************************************************************/
5142 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5143 (2*14) + /* word count (including bcc) */ \
5146 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
5147 const uint8_t *inbuf
)
5150 unsigned int doff
= 0;
5151 size_t len
= smb_len_large(inbuf
);
5153 struct smbXsrv_open
*op
= NULL
;
5154 struct files_struct
*fsp
= NULL
;
5157 if (is_encrypted_packet(inbuf
)) {
5158 /* Can't do this on encrypted
5163 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
5167 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
5168 CVAL(inbuf
,smb_wct
) != 14) {
5169 DEBUG(10,("is_valid_writeX_buffer: chained or "
5170 "invalid word length.\n"));
5174 fnum
= SVAL(inbuf
, smb_vwv2
);
5175 status
= smb1srv_open_lookup(xconn
,
5179 if (!NT_STATUS_IS_OK(status
)) {
5180 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5185 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5188 if (fsp
->conn
== NULL
) {
5189 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5193 if (IS_IPC(fsp
->conn
)) {
5194 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5197 if (IS_PRINT(fsp
->conn
)) {
5198 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5201 if (fsp
->base_fsp
!= NULL
) {
5202 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5205 doff
= SVAL(inbuf
,smb_vwv11
);
5207 numtowrite
= SVAL(inbuf
,smb_vwv10
);
5209 if (len
> doff
&& len
- doff
> 0xFFFF) {
5210 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
5213 if (numtowrite
== 0) {
5214 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5218 /* Ensure the sizes match up. */
5219 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
5220 /* no pad byte...old smbclient :-( */
5221 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5223 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
5227 if (len
- doff
!= numtowrite
) {
5228 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5229 "len = %u, doff = %u, numtowrite = %u\n",
5232 (unsigned int)numtowrite
));
5236 DEBUG(10,("is_valid_writeX_buffer: true "
5237 "len = %u, doff = %u, numtowrite = %u\n",
5240 (unsigned int)numtowrite
));
5245 /****************************************************************************
5246 Reply to a write and X.
5247 ****************************************************************************/
5249 void reply_write_and_X(struct smb_request
*req
)
5251 connection_struct
*conn
= req
->conn
;
5252 struct smbXsrv_connection
*xconn
= req
->xconn
;
5254 struct lock_struct lock
;
5259 unsigned int smb_doff
;
5260 unsigned int smblen
;
5263 int saved_errno
= 0;
5265 START_PROFILE(SMBwriteX
);
5267 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5272 numtowrite
= SVAL(req
->vwv
+10, 0);
5273 smb_doff
= SVAL(req
->vwv
+11, 0);
5274 smblen
= smb_len(req
->inbuf
);
5276 if (req
->unread_bytes
> 0xFFFF ||
5277 (smblen
> smb_doff
&&
5278 smblen
- smb_doff
> 0xFFFF)) {
5279 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5282 if (req
->unread_bytes
) {
5283 /* Can't do a recvfile write on IPC$ */
5285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5288 if (numtowrite
!= req
->unread_bytes
) {
5289 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5294 * This already protects us against CVE-2017-12163.
5296 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5297 smb_doff
+ numtowrite
> smblen
) {
5298 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5303 /* If it's an IPC, pass off the pipe handler. */
5305 if (req
->unread_bytes
) {
5306 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5309 reply_pipe_write_and_X(req
);
5313 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5314 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5315 write_through
= BITSETW(req
->vwv
+7,0);
5317 if (!check_fsp(conn
, req
, fsp
)) {
5321 if (!CHECK_WRITE(fsp
)) {
5322 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5326 data
= smb_base(req
->inbuf
) + smb_doff
;
5328 if(req
->wct
== 14) {
5330 * This is a large offset (64 bit) write.
5332 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5336 /* X/Open SMB protocol says that, unlike SMBwrite
5337 if the length is zero then NO truncation is
5338 done, just a write of zero. To truncate a file,
5341 if(numtowrite
== 0) {
5344 if (req
->unread_bytes
== 0) {
5345 status
= schedule_aio_write_and_X(conn
,
5352 if (NT_STATUS_IS_OK(status
)) {
5353 /* write scheduled - we're done. */
5356 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5357 /* Real error - report to client. */
5358 reply_nterror(req
, status
);
5361 /* NT_STATUS_RETRY - fall through to sync write. */
5364 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5365 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5368 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5369 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5373 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5374 saved_errno
= errno
;
5378 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5382 if((nwritten
== 0) && (numtowrite
!= 0)) {
5383 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5387 reply_outbuf(req
, 6, 0);
5388 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5389 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5390 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5391 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5393 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5394 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5396 status
= sync_file(conn
, fsp
, write_through
);
5397 if (!NT_STATUS_IS_OK(status
)) {
5398 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5399 fsp_str_dbg(fsp
), nt_errstr(status
)));
5400 reply_nterror(req
, status
);
5404 END_PROFILE(SMBwriteX
);
5408 if (req
->unread_bytes
) {
5409 /* writeX failed. drain socket. */
5410 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5411 req
->unread_bytes
) {
5412 smb_panic("failed to drain pending bytes");
5414 req
->unread_bytes
= 0;
5417 END_PROFILE(SMBwriteX
);
5421 /****************************************************************************
5423 ****************************************************************************/
5425 void reply_lseek(struct smb_request
*req
)
5427 connection_struct
*conn
= req
->conn
;
5434 START_PROFILE(SMBlseek
);
5437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5438 END_PROFILE(SMBlseek
);
5442 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5444 if (!check_fsp(conn
, req
, fsp
)) {
5448 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5450 mode
= SVAL(req
->vwv
+1, 0) & 3;
5451 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5452 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5461 res
= fsp
->fh
->pos
+ startpos
;
5472 if (umode
== SEEK_END
) {
5473 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5474 if(errno
== EINVAL
) {
5475 off_t current_pos
= startpos
;
5477 status
= vfs_stat_fsp(fsp
);
5478 if (!NT_STATUS_IS_OK(status
)) {
5479 reply_nterror(req
, status
);
5480 END_PROFILE(SMBlseek
);
5484 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5486 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5491 reply_nterror(req
, map_nt_error_from_unix(errno
));
5492 END_PROFILE(SMBlseek
);
5499 reply_outbuf(req
, 2, 0);
5500 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5502 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5503 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5505 END_PROFILE(SMBlseek
);
5509 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
5512 connection_struct
*conn
= talloc_get_type_abort(
5513 private_data
, connection_struct
);
5515 if (conn
!= fsp
->conn
) {
5518 if (fsp
->fh
->fd
== -1) {
5521 sync_file(conn
, fsp
, True
/* write through */);
5526 /****************************************************************************
5528 ****************************************************************************/
5530 void reply_flush(struct smb_request
*req
)
5532 connection_struct
*conn
= req
->conn
;
5536 START_PROFILE(SMBflush
);
5539 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5543 fnum
= SVAL(req
->vwv
+0, 0);
5544 fsp
= file_fsp(req
, fnum
);
5546 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5551 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
5553 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5554 if (!NT_STATUS_IS_OK(status
)) {
5555 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5556 fsp_str_dbg(fsp
), nt_errstr(status
)));
5557 reply_nterror(req
, status
);
5558 END_PROFILE(SMBflush
);
5563 reply_outbuf(req
, 0, 0);
5565 DEBUG(3,("flush\n"));
5566 END_PROFILE(SMBflush
);
5570 /****************************************************************************
5572 conn POINTER CAN BE NULL HERE !
5573 ****************************************************************************/
5575 void reply_exit(struct smb_request
*req
)
5577 START_PROFILE(SMBexit
);
5579 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5581 reply_outbuf(req
, 0, 0);
5583 DEBUG(3,("exit\n"));
5585 END_PROFILE(SMBexit
);
5589 struct reply_close_state
{
5591 struct smb_request
*smbreq
;
5594 static void do_smb1_close(struct tevent_req
*req
);
5596 void reply_close(struct smb_request
*req
)
5598 connection_struct
*conn
= req
->conn
;
5599 NTSTATUS status
= NT_STATUS_OK
;
5600 files_struct
*fsp
= NULL
;
5601 START_PROFILE(SMBclose
);
5604 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5605 END_PROFILE(SMBclose
);
5609 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5612 * We can only use check_fsp if we know it's not a directory.
5615 if (!check_fsp_open(conn
, req
, fsp
)) {
5616 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5617 END_PROFILE(SMBclose
);
5621 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5622 fsp
->is_directory
? "directory" : "file",
5623 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5624 conn
->num_files_open
));
5626 if (!fsp
->is_directory
) {
5630 * Take care of any time sent in the close.
5633 t
= srv_make_unix_date3(req
->vwv
+1);
5634 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5637 if (fsp
->num_aio_requests
!= 0) {
5639 struct reply_close_state
*state
;
5641 DEBUG(10, ("closing with aio %u requests pending\n",
5642 fsp
->num_aio_requests
));
5645 * We depend on the aio_extra destructor to take care of this
5646 * close request once fsp->num_aio_request drops to 0.
5649 fsp
->deferred_close
= tevent_wait_send(
5650 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5651 if (fsp
->deferred_close
== NULL
) {
5652 status
= NT_STATUS_NO_MEMORY
;
5656 state
= talloc(fsp
, struct reply_close_state
);
5657 if (state
== NULL
) {
5658 TALLOC_FREE(fsp
->deferred_close
);
5659 status
= NT_STATUS_NO_MEMORY
;
5663 state
->smbreq
= talloc_move(fsp
, &req
);
5664 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5666 END_PROFILE(SMBclose
);
5671 * close_file() returns the unix errno if an error was detected on
5672 * close - normally this is due to a disk full error. If not then it
5673 * was probably an I/O error.
5676 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5678 if (!NT_STATUS_IS_OK(status
)) {
5679 reply_nterror(req
, status
);
5680 END_PROFILE(SMBclose
);
5684 reply_outbuf(req
, 0, 0);
5685 END_PROFILE(SMBclose
);
5689 static void do_smb1_close(struct tevent_req
*req
)
5691 struct reply_close_state
*state
= tevent_req_callback_data(
5692 req
, struct reply_close_state
);
5693 struct smb_request
*smbreq
;
5697 ret
= tevent_wait_recv(req
);
5700 DEBUG(10, ("tevent_wait_recv returned %s\n",
5703 * Continue anyway, this should never happen
5708 * fsp->smb2_close_request right now is a talloc grandchild of
5709 * fsp. When we close_file(fsp), it would go with it. No chance to
5712 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5714 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5715 if (NT_STATUS_IS_OK(status
)) {
5716 reply_outbuf(smbreq
, 0, 0);
5718 reply_nterror(smbreq
, status
);
5720 if (!srv_send_smb(smbreq
->xconn
,
5721 (char *)smbreq
->outbuf
,
5724 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5726 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5729 TALLOC_FREE(smbreq
);
5732 /****************************************************************************
5733 Reply to a writeclose (Core+ protocol).
5734 ****************************************************************************/
5736 void reply_writeclose(struct smb_request
*req
)
5738 connection_struct
*conn
= req
->conn
;
5741 ssize_t nwritten
= -1;
5742 NTSTATUS close_status
= NT_STATUS_OK
;
5745 struct timespec mtime
;
5747 struct lock_struct lock
;
5749 START_PROFILE(SMBwriteclose
);
5752 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5753 END_PROFILE(SMBwriteclose
);
5757 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5759 if (!check_fsp(conn
, req
, fsp
)) {
5760 END_PROFILE(SMBwriteclose
);
5763 if (!CHECK_WRITE(fsp
)) {
5764 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5765 END_PROFILE(SMBwriteclose
);
5769 numtowrite
= SVAL(req
->vwv
+1, 0);
5770 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5771 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5772 data
= (const char *)req
->buf
+ 1;
5775 * Ensure client isn't asking us to write more than
5776 * they sent. CVE-2017-12163.
5778 remaining
= smbreq_bufrem(req
, data
);
5779 if (numtowrite
> remaining
) {
5780 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5781 END_PROFILE(SMBwriteclose
);
5785 if (fsp
->print_file
== NULL
) {
5786 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5787 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5790 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5791 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5792 END_PROFILE(SMBwriteclose
);
5797 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5799 set_close_write_time(fsp
, mtime
);
5802 * More insanity. W2K only closes the file if writelen > 0.
5806 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5807 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5808 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5811 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5812 "file %s\n", fsp_str_dbg(fsp
)));
5813 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5817 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5818 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5822 if(!NT_STATUS_IS_OK(close_status
)) {
5823 reply_nterror(req
, close_status
);
5827 reply_outbuf(req
, 1, 0);
5829 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5833 END_PROFILE(SMBwriteclose
);
5838 #define DBGC_CLASS DBGC_LOCKING
5840 /****************************************************************************
5842 ****************************************************************************/
5844 static void reply_lock_done(struct tevent_req
*subreq
);
5846 void reply_lock(struct smb_request
*req
)
5848 struct tevent_req
*subreq
= NULL
;
5849 connection_struct
*conn
= req
->conn
;
5851 struct smbd_lock_element
*lck
= NULL
;
5853 START_PROFILE(SMBlock
);
5856 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5857 END_PROFILE(SMBlock
);
5861 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5863 if (!check_fsp(conn
, req
, fsp
)) {
5864 END_PROFILE(SMBlock
);
5868 lck
= talloc(req
, struct smbd_lock_element
);
5870 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5871 END_PROFILE(SMBlock
);
5875 *lck
= (struct smbd_lock_element
) {
5876 .req_guid
= smbd_request_guid(req
, 0),
5877 .smblctx
= req
->smbpid
,
5878 .brltype
= WRITE_LOCK
,
5879 .count
= IVAL(req
->vwv
+1, 0),
5880 .offset
= IVAL(req
->vwv
+3, 0),
5883 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5889 subreq
= smbd_smb1_do_locks_send(
5895 false, /* large_offset */
5899 if (subreq
== NULL
) {
5900 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5901 END_PROFILE(SMBlock
);
5904 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
5905 END_PROFILE(SMBlock
);
5908 static void reply_lock_done(struct tevent_req
*subreq
)
5910 struct smb_request
*req
= NULL
;
5914 START_PROFILE(SMBlock
);
5916 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
5919 status
= smbd_smb1_do_locks_recv(subreq
);
5920 TALLOC_FREE(subreq
);
5922 if (NT_STATUS_IS_OK(status
)) {
5923 reply_outbuf(req
, 0, 0);
5925 reply_nterror(req
, status
);
5928 ok
= srv_send_smb(req
->xconn
,
5929 (char *)req
->outbuf
,
5932 IS_CONN_ENCRYPTED(req
->conn
),
5935 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5938 END_PROFILE(SMBlock
);
5941 /****************************************************************************
5943 ****************************************************************************/
5945 void reply_unlock(struct smb_request
*req
)
5947 connection_struct
*conn
= req
->conn
;
5950 struct smbd_lock_element lck
;
5952 START_PROFILE(SMBunlock
);
5955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5956 END_PROFILE(SMBunlock
);
5960 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5962 if (!check_fsp(conn
, req
, fsp
)) {
5963 END_PROFILE(SMBunlock
);
5967 lck
= (struct smbd_lock_element
) {
5968 .req_guid
= smbd_request_guid(req
, 0),
5969 .smblctx
= req
->smbpid
,
5970 .brltype
= UNLOCK_LOCK
,
5971 .offset
= IVAL(req
->vwv
+3, 0),
5972 .count
= IVAL(req
->vwv
+1, 0),
5975 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
, WINDOWS_LOCK
);
5977 if (!NT_STATUS_IS_OK(status
)) {
5978 reply_nterror(req
, status
);
5979 END_PROFILE(SMBunlock
);
5983 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5989 reply_outbuf(req
, 0, 0);
5991 END_PROFILE(SMBunlock
);
5996 #define DBGC_CLASS DBGC_ALL
5998 /****************************************************************************
6000 conn POINTER CAN BE NULL HERE !
6001 ****************************************************************************/
6003 void reply_tdis(struct smb_request
*req
)
6006 connection_struct
*conn
= req
->conn
;
6007 struct smbXsrv_tcon
*tcon
;
6009 START_PROFILE(SMBtdis
);
6012 DEBUG(4,("Invalid connection in tdis\n"));
6013 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
6014 END_PROFILE(SMBtdis
);
6022 * TODO: cancel all outstanding requests on the tcon
6024 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
6025 if (!NT_STATUS_IS_OK(status
)) {
6026 DEBUG(0, ("reply_tdis: "
6027 "smbXsrv_tcon_disconnect() failed: %s\n",
6028 nt_errstr(status
)));
6030 * If we hit this case, there is something completely
6031 * wrong, so we better disconnect the transport connection.
6033 END_PROFILE(SMBtdis
);
6034 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
6040 reply_outbuf(req
, 0, 0);
6041 END_PROFILE(SMBtdis
);
6045 /****************************************************************************
6047 conn POINTER CAN BE NULL HERE !
6048 ****************************************************************************/
6050 void reply_echo(struct smb_request
*req
)
6052 connection_struct
*conn
= req
->conn
;
6053 struct smb_perfcount_data local_pcd
;
6054 struct smb_perfcount_data
*cur_pcd
;
6058 START_PROFILE(SMBecho
);
6060 smb_init_perfcount_data(&local_pcd
);
6063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6064 END_PROFILE(SMBecho
);
6068 smb_reverb
= SVAL(req
->vwv
+0, 0);
6070 reply_outbuf(req
, 1, req
->buflen
);
6072 /* copy any incoming data back out */
6073 if (req
->buflen
> 0) {
6074 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
6077 if (smb_reverb
> 100) {
6078 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
6082 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
6084 /* this makes sure we catch the request pcd */
6085 if (seq_num
== smb_reverb
) {
6086 cur_pcd
= &req
->pcd
;
6088 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
6089 cur_pcd
= &local_pcd
;
6092 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
6094 show_msg((char *)req
->outbuf
);
6095 if (!srv_send_smb(req
->xconn
,
6096 (char *)req
->outbuf
,
6097 true, req
->seqnum
+1,
6098 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
6100 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6103 DEBUG(3,("echo %d times\n", smb_reverb
));
6105 TALLOC_FREE(req
->outbuf
);
6107 END_PROFILE(SMBecho
);
6111 /****************************************************************************
6112 Reply to a printopen.
6113 ****************************************************************************/
6115 void reply_printopen(struct smb_request
*req
)
6117 connection_struct
*conn
= req
->conn
;
6121 START_PROFILE(SMBsplopen
);
6124 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6125 END_PROFILE(SMBsplopen
);
6129 if (!CAN_PRINT(conn
)) {
6130 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6131 END_PROFILE(SMBsplopen
);
6135 status
= file_new(req
, conn
, &fsp
);
6136 if(!NT_STATUS_IS_OK(status
)) {
6137 reply_nterror(req
, status
);
6138 END_PROFILE(SMBsplopen
);
6142 /* Open for exclusive use, write only. */
6143 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
6145 if (!NT_STATUS_IS_OK(status
)) {
6146 file_free(req
, fsp
);
6147 reply_nterror(req
, status
);
6148 END_PROFILE(SMBsplopen
);
6152 reply_outbuf(req
, 1, 0);
6153 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
6155 DEBUG(3,("openprint fd=%d %s\n",
6156 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
6158 END_PROFILE(SMBsplopen
);
6162 /****************************************************************************
6163 Reply to a printclose.
6164 ****************************************************************************/
6166 void reply_printclose(struct smb_request
*req
)
6168 connection_struct
*conn
= req
->conn
;
6172 START_PROFILE(SMBsplclose
);
6175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6176 END_PROFILE(SMBsplclose
);
6180 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6182 if (!check_fsp(conn
, req
, fsp
)) {
6183 END_PROFILE(SMBsplclose
);
6187 if (!CAN_PRINT(conn
)) {
6188 reply_force_doserror(req
, ERRSRV
, ERRerror
);
6189 END_PROFILE(SMBsplclose
);
6193 DEBUG(3,("printclose fd=%d %s\n",
6194 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
6196 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6198 if(!NT_STATUS_IS_OK(status
)) {
6199 reply_nterror(req
, status
);
6200 END_PROFILE(SMBsplclose
);
6204 reply_outbuf(req
, 0, 0);
6206 END_PROFILE(SMBsplclose
);
6210 /****************************************************************************
6211 Reply to a printqueue.
6212 ****************************************************************************/
6214 void reply_printqueue(struct smb_request
*req
)
6216 connection_struct
*conn
= req
->conn
;
6220 START_PROFILE(SMBsplretq
);
6223 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6224 END_PROFILE(SMBsplretq
);
6228 max_count
= SVAL(req
->vwv
+0, 0);
6229 start_index
= SVAL(req
->vwv
+1, 0);
6231 /* we used to allow the client to get the cnum wrong, but that
6232 is really quite gross and only worked when there was only
6233 one printer - I think we should now only accept it if they
6234 get it right (tridge) */
6235 if (!CAN_PRINT(conn
)) {
6236 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6237 END_PROFILE(SMBsplretq
);
6241 reply_outbuf(req
, 2, 3);
6242 SSVAL(req
->outbuf
,smb_vwv0
,0);
6243 SSVAL(req
->outbuf
,smb_vwv1
,0);
6244 SCVAL(smb_buf(req
->outbuf
),0,1);
6245 SSVAL(smb_buf(req
->outbuf
),1,0);
6247 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6248 start_index
, max_count
));
6251 TALLOC_CTX
*mem_ctx
= talloc_tos();
6254 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
6255 struct rpc_pipe_client
*cli
= NULL
;
6256 struct dcerpc_binding_handle
*b
= NULL
;
6257 struct policy_handle handle
;
6258 struct spoolss_DevmodeContainer devmode_ctr
;
6259 union spoolss_JobInfo
*info
;
6261 uint32_t num_to_get
;
6265 ZERO_STRUCT(handle
);
6267 status
= rpc_pipe_open_interface(mem_ctx
,
6270 conn
->sconn
->remote_address
,
6271 conn
->sconn
->local_address
,
6272 conn
->sconn
->msg_ctx
,
6274 if (!NT_STATUS_IS_OK(status
)) {
6275 DEBUG(0, ("reply_printqueue: "
6276 "could not connect to spoolss: %s\n",
6277 nt_errstr(status
)));
6278 reply_nterror(req
, status
);
6281 b
= cli
->binding_handle
;
6283 ZERO_STRUCT(devmode_ctr
);
6285 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
6288 SEC_FLAG_MAXIMUM_ALLOWED
,
6291 if (!NT_STATUS_IS_OK(status
)) {
6292 reply_nterror(req
, status
);
6295 if (!W_ERROR_IS_OK(werr
)) {
6296 reply_nterror(req
, werror_to_ntstatus(werr
));
6300 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6308 if (!W_ERROR_IS_OK(werr
)) {
6309 reply_nterror(req
, werror_to_ntstatus(werr
));
6313 if (max_count
> 0) {
6314 first
= start_index
;
6316 first
= start_index
+ max_count
+ 1;
6319 if (first
>= count
) {
6322 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6325 for (i
= first
; i
< num_to_get
; i
++) {
6328 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6331 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6332 info
[i
].info2
.job_id
);
6334 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6340 srv_put_dos_date2(p
, 0, qtime
);
6341 SCVAL(p
, 4, qstatus
);
6342 SSVAL(p
, 5, qrapjobid
);
6343 SIVAL(p
, 7, info
[i
].info2
.size
);
6345 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6346 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6347 if (!NT_STATUS_IS_OK(status
)) {
6348 reply_nterror(req
, status
);
6351 if (message_push_blob(
6354 blob
, sizeof(blob
))) == -1) {
6355 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6361 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6362 SSVAL(req
->outbuf
,smb_vwv1
,
6363 (max_count
>0?first
+count
:first
-1));
6364 SCVAL(smb_buf(req
->outbuf
),0,1);
6365 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6369 DEBUG(3, ("%u entries returned in queue\n",
6373 if (b
&& is_valid_policy_hnd(&handle
)) {
6374 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6379 END_PROFILE(SMBsplretq
);
6383 /****************************************************************************
6384 Reply to a printwrite.
6385 ****************************************************************************/
6387 void reply_printwrite(struct smb_request
*req
)
6389 connection_struct
*conn
= req
->conn
;
6394 START_PROFILE(SMBsplwr
);
6397 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6398 END_PROFILE(SMBsplwr
);
6402 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6404 if (!check_fsp(conn
, req
, fsp
)) {
6405 END_PROFILE(SMBsplwr
);
6409 if (!fsp
->print_file
) {
6410 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6411 END_PROFILE(SMBsplwr
);
6415 if (!CHECK_WRITE(fsp
)) {
6416 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6417 END_PROFILE(SMBsplwr
);
6421 numtowrite
= SVAL(req
->buf
, 1);
6424 * This already protects us against CVE-2017-12163.
6426 if (req
->buflen
< numtowrite
+ 3) {
6427 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6428 END_PROFILE(SMBsplwr
);
6432 data
= (const char *)req
->buf
+ 3;
6434 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6435 reply_nterror(req
, map_nt_error_from_unix(errno
));
6436 END_PROFILE(SMBsplwr
);
6440 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6442 END_PROFILE(SMBsplwr
);
6446 /****************************************************************************
6448 ****************************************************************************/
6450 void reply_mkdir(struct smb_request
*req
)
6452 connection_struct
*conn
= req
->conn
;
6453 struct smb_filename
*smb_dname
= NULL
;
6454 char *directory
= NULL
;
6457 TALLOC_CTX
*ctx
= talloc_tos();
6459 START_PROFILE(SMBmkdir
);
6461 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6462 STR_TERMINATE
, &status
);
6463 if (!NT_STATUS_IS_OK(status
)) {
6464 reply_nterror(req
, status
);
6468 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6469 status
= filename_convert(ctx
, conn
,
6475 if (!NT_STATUS_IS_OK(status
)) {
6476 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6477 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6478 ERRSRV
, ERRbadpath
);
6481 reply_nterror(req
, status
);
6485 status
= create_directory(conn
, req
, smb_dname
);
6487 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6489 if (!NT_STATUS_IS_OK(status
)) {
6491 if (!use_nt_status()
6492 && NT_STATUS_EQUAL(status
,
6493 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6495 * Yes, in the DOS error code case we get a
6496 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6497 * samba4 torture test.
6499 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6502 reply_nterror(req
, status
);
6506 reply_outbuf(req
, 0, 0);
6508 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6510 TALLOC_FREE(smb_dname
);
6511 END_PROFILE(SMBmkdir
);
6515 /****************************************************************************
6517 ****************************************************************************/
6519 void reply_rmdir(struct smb_request
*req
)
6521 connection_struct
*conn
= req
->conn
;
6522 struct smb_filename
*smb_dname
= NULL
;
6523 char *directory
= NULL
;
6525 TALLOC_CTX
*ctx
= talloc_tos();
6526 files_struct
*fsp
= NULL
;
6528 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6530 START_PROFILE(SMBrmdir
);
6532 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6533 STR_TERMINATE
, &status
);
6534 if (!NT_STATUS_IS_OK(status
)) {
6535 reply_nterror(req
, status
);
6539 status
= filename_convert(ctx
, conn
,
6545 if (!NT_STATUS_IS_OK(status
)) {
6546 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6547 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6548 ERRSRV
, ERRbadpath
);
6551 reply_nterror(req
, status
);
6555 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6556 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6560 status
= SMB_VFS_CREATE_FILE(
6563 0, /* root_dir_fid */
6564 smb_dname
, /* fname */
6565 DELETE_ACCESS
, /* access_mask */
6566 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6568 FILE_OPEN
, /* create_disposition*/
6569 FILE_DIRECTORY_FILE
, /* create_options */
6570 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6571 0, /* oplock_request */
6573 0, /* allocation_size */
6574 0, /* private_flags */
6579 NULL
, NULL
); /* create context */
6581 if (!NT_STATUS_IS_OK(status
)) {
6582 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6583 /* We have re-scheduled this call. */
6586 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6587 bool ok
= defer_smb1_sharing_violation(req
);
6592 reply_nterror(req
, status
);
6596 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6597 if (!NT_STATUS_IS_OK(status
)) {
6598 close_file(req
, fsp
, ERROR_CLOSE
);
6599 reply_nterror(req
, status
);
6603 if (!set_delete_on_close(fsp
, true,
6604 conn
->session_info
->security_token
,
6605 conn
->session_info
->unix_token
)) {
6606 close_file(req
, fsp
, ERROR_CLOSE
);
6607 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6611 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6612 if (!NT_STATUS_IS_OK(status
)) {
6613 reply_nterror(req
, status
);
6615 reply_outbuf(req
, 0, 0);
6618 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6620 TALLOC_FREE(smb_dname
);
6621 END_PROFILE(SMBrmdir
);
6625 /*******************************************************************
6626 Resolve wildcards in a filename rename.
6627 ********************************************************************/
6629 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6634 char *name2_copy
= NULL
;
6639 char *p
,*p2
, *pname1
, *pname2
;
6641 name2_copy
= talloc_strdup(ctx
, name2
);
6646 pname1
= strrchr_m(name1
,'/');
6647 pname2
= strrchr_m(name2_copy
,'/');
6649 if (!pname1
|| !pname2
) {
6653 /* Truncate the copy of name2 at the last '/' */
6656 /* Now go past the '/' */
6660 root1
= talloc_strdup(ctx
, pname1
);
6661 root2
= talloc_strdup(ctx
, pname2
);
6663 if (!root1
|| !root2
) {
6667 p
= strrchr_m(root1
,'.');
6670 ext1
= talloc_strdup(ctx
, p
+1);
6672 ext1
= talloc_strdup(ctx
, "");
6674 p
= strrchr_m(root2
,'.');
6677 ext2
= talloc_strdup(ctx
, p
+1);
6679 ext2
= talloc_strdup(ctx
, "");
6682 if (!ext1
|| !ext2
) {
6690 /* Hmmm. Should this be mb-aware ? */
6693 } else if (*p2
== '*') {
6695 root2
= talloc_asprintf(ctx
, "%s%s",
6714 /* Hmmm. Should this be mb-aware ? */
6717 } else if (*p2
== '*') {
6719 ext2
= talloc_asprintf(ctx
, "%s%s",
6735 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6740 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6752 /****************************************************************************
6753 Ensure open files have their names updated. Updated to notify other smbd's
6755 ****************************************************************************/
6757 static void rename_open_files(connection_struct
*conn
,
6758 struct share_mode_lock
*lck
,
6760 uint32_t orig_name_hash
,
6761 const struct smb_filename
*smb_fname_dst
)
6764 bool did_rename
= False
;
6766 uint32_t new_name_hash
= 0;
6768 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6769 fsp
= file_find_di_next(fsp
)) {
6770 /* fsp_name is a relative path under the fsp. To change this for other
6771 sharepaths we need to manipulate relative paths. */
6772 /* TODO - create the absolute path and manipulate the newname
6773 relative to the sharepath. */
6774 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6777 if (fsp
->name_hash
!= orig_name_hash
) {
6780 DEBUG(10, ("rename_open_files: renaming file %s "
6781 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6782 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6783 smb_fname_str_dbg(smb_fname_dst
)));
6785 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6786 if (NT_STATUS_IS_OK(status
)) {
6788 new_name_hash
= fsp
->name_hash
;
6793 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6794 "for %s\n", file_id_string_tos(&id
),
6795 smb_fname_str_dbg(smb_fname_dst
)));
6798 /* Send messages to all smbd's (not ourself) that the name has changed. */
6799 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6800 orig_name_hash
, new_name_hash
,
6805 /****************************************************************************
6806 We need to check if the source path is a parent directory of the destination
6807 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6808 refuse the rename with a sharing violation. Under UNIX the above call can
6809 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6810 probably need to check that the client is a Windows one before disallowing
6811 this as a UNIX client (one with UNIX extensions) can know the source is a
6812 symlink and make this decision intelligently. Found by an excellent bug
6813 report from <AndyLiebman@aol.com>.
6814 ****************************************************************************/
6816 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6817 const struct smb_filename
*smb_fname_dst
)
6819 const char *psrc
= smb_fname_src
->base_name
;
6820 const char *pdst
= smb_fname_dst
->base_name
;
6823 if (psrc
[0] == '.' && psrc
[1] == '/') {
6826 if (pdst
[0] == '.' && pdst
[1] == '/') {
6829 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6832 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6836 * Do the notify calls from a rename
6839 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6840 const struct smb_filename
*smb_fname_src
,
6841 const struct smb_filename
*smb_fname_dst
)
6843 char *parent_dir_src
= NULL
;
6844 char *parent_dir_dst
= NULL
;
6847 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6848 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6850 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6851 &parent_dir_src
, NULL
) ||
6852 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6853 &parent_dir_dst
, NULL
)) {
6857 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6858 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6859 smb_fname_src
->base_name
);
6860 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6861 smb_fname_dst
->base_name
);
6864 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6865 smb_fname_src
->base_name
);
6866 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6867 smb_fname_dst
->base_name
);
6870 /* this is a strange one. w2k3 gives an additional event for
6871 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6872 files, but not directories */
6874 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6875 FILE_NOTIFY_CHANGE_ATTRIBUTES
6876 |FILE_NOTIFY_CHANGE_CREATION
,
6877 smb_fname_dst
->base_name
);
6880 TALLOC_FREE(parent_dir_src
);
6881 TALLOC_FREE(parent_dir_dst
);
6884 /****************************************************************************
6885 Returns an error if the parent directory for a filename is open in an
6887 ****************************************************************************/
6889 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6890 const struct smb_filename
*smb_fname_dst_in
)
6892 char *parent_dir
= NULL
;
6893 struct smb_filename smb_fname_parent
;
6895 files_struct
*fsp
= NULL
;
6898 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6899 &parent_dir
, NULL
)) {
6900 return NT_STATUS_NO_MEMORY
;
6902 ZERO_STRUCT(smb_fname_parent
);
6903 smb_fname_parent
.base_name
= parent_dir
;
6905 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6907 return map_nt_error_from_unix(errno
);
6911 * We're only checking on this smbd here, mostly good
6912 * enough.. and will pass tests.
6915 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6916 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6917 fsp
= file_find_di_next(fsp
)) {
6918 if (fsp
->access_mask
& DELETE_ACCESS
) {
6919 return NT_STATUS_SHARING_VIOLATION
;
6922 return NT_STATUS_OK
;
6925 /****************************************************************************
6926 Rename an open file - given an fsp.
6927 ****************************************************************************/
6929 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6931 const struct smb_filename
*smb_fname_dst_in
,
6933 bool replace_if_exists
)
6935 TALLOC_CTX
*ctx
= talloc_tos();
6936 struct smb_filename
*smb_fname_dst
= NULL
;
6937 NTSTATUS status
= NT_STATUS_OK
;
6938 struct share_mode_lock
*lck
= NULL
;
6939 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6940 bool dst_exists
, old_is_stream
, new_is_stream
;
6943 status
= check_name(conn
, smb_fname_dst_in
);
6944 if (!NT_STATUS_IS_OK(status
)) {
6948 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6949 if (!NT_STATUS_IS_OK(status
)) {
6953 if (file_has_open_streams(fsp
)) {
6954 return NT_STATUS_ACCESS_DENIED
;
6957 /* Make a copy of the dst smb_fname structs */
6959 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6960 if (smb_fname_dst
== NULL
) {
6961 status
= NT_STATUS_NO_MEMORY
;
6966 * Check for special case with case preserving and not
6967 * case sensitive. If the new last component differs from the original
6968 * last component only by case, then we should allow
6969 * the rename (user is trying to change the case of the
6972 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6973 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6974 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6975 char *fname_dst_parent
= NULL
;
6976 const char *fname_dst_lcomp
= NULL
;
6977 char *orig_lcomp_path
= NULL
;
6978 char *orig_lcomp_stream
= NULL
;
6982 * Split off the last component of the processed
6983 * destination name. We will compare this to
6984 * the split components of smb_fname_dst->original_lcomp.
6986 if (!parent_dirname(ctx
,
6987 smb_fname_dst
->base_name
,
6989 &fname_dst_lcomp
)) {
6990 status
= NT_STATUS_NO_MEMORY
;
6995 * The original_lcomp component contains
6996 * the last_component of the path + stream
6997 * name (if a stream exists).
6999 * Split off the stream name so we
7000 * can check them separately.
7003 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
7004 /* POSIX - no stream component. */
7005 orig_lcomp_path
= talloc_strdup(ctx
,
7006 smb_fname_dst
->original_lcomp
);
7007 if (orig_lcomp_path
== NULL
) {
7011 ok
= split_stream_filename(ctx
,
7012 smb_fname_dst
->original_lcomp
,
7014 &orig_lcomp_stream
);
7018 TALLOC_FREE(fname_dst_parent
);
7019 status
= NT_STATUS_NO_MEMORY
;
7023 /* If the base names only differ by case, use original. */
7024 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
7027 * Replace the modified last component with the
7030 if (!ISDOT(fname_dst_parent
)) {
7031 tmp
= talloc_asprintf(smb_fname_dst
,
7036 tmp
= talloc_strdup(smb_fname_dst
,
7040 status
= NT_STATUS_NO_MEMORY
;
7041 TALLOC_FREE(fname_dst_parent
);
7042 TALLOC_FREE(orig_lcomp_path
);
7043 TALLOC_FREE(orig_lcomp_stream
);
7046 TALLOC_FREE(smb_fname_dst
->base_name
);
7047 smb_fname_dst
->base_name
= tmp
;
7050 /* If the stream_names only differ by case, use original. */
7051 if(!strcsequal(smb_fname_dst
->stream_name
,
7052 orig_lcomp_stream
)) {
7053 /* Use the original stream. */
7054 char *tmp
= talloc_strdup(smb_fname_dst
,
7057 status
= NT_STATUS_NO_MEMORY
;
7058 TALLOC_FREE(fname_dst_parent
);
7059 TALLOC_FREE(orig_lcomp_path
);
7060 TALLOC_FREE(orig_lcomp_stream
);
7063 TALLOC_FREE(smb_fname_dst
->stream_name
);
7064 smb_fname_dst
->stream_name
= tmp
;
7066 TALLOC_FREE(fname_dst_parent
);
7067 TALLOC_FREE(orig_lcomp_path
);
7068 TALLOC_FREE(orig_lcomp_stream
);
7072 * If the src and dest names are identical - including case,
7073 * don't do the rename, just return success.
7076 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
7077 strcsequal(fsp
->fsp_name
->stream_name
,
7078 smb_fname_dst
->stream_name
)) {
7079 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7080 "- returning success\n",
7081 smb_fname_str_dbg(smb_fname_dst
)));
7082 status
= NT_STATUS_OK
;
7086 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
7087 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
7089 /* Return the correct error code if both names aren't streams. */
7090 if (!old_is_stream
&& new_is_stream
) {
7091 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7095 if (old_is_stream
&& !new_is_stream
) {
7096 status
= NT_STATUS_INVALID_PARAMETER
;
7100 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
7102 if(!replace_if_exists
&& dst_exists
) {
7103 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7104 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7105 smb_fname_str_dbg(smb_fname_dst
)));
7106 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7111 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
7112 &smb_fname_dst
->st
);
7113 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
7115 /* The file can be open when renaming a stream */
7116 if (dst_fsp
&& !new_is_stream
) {
7117 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7118 status
= NT_STATUS_ACCESS_DENIED
;
7123 /* Ensure we have a valid stat struct for the source. */
7124 status
= vfs_stat_fsp(fsp
);
7125 if (!NT_STATUS_IS_OK(status
)) {
7129 status
= can_rename(conn
, fsp
, attrs
);
7131 if (!NT_STATUS_IS_OK(status
)) {
7132 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7133 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7134 smb_fname_str_dbg(smb_fname_dst
)));
7135 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
7136 status
= NT_STATUS_ACCESS_DENIED
;
7140 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
7141 status
= NT_STATUS_ACCESS_DENIED
;
7145 /* Do we have rights to move into the destination ? */
7146 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
7147 /* We're moving a directory. */
7148 access_mask
= SEC_DIR_ADD_SUBDIR
;
7150 status
= check_parent_access(conn
,
7153 if (!NT_STATUS_IS_OK(status
)) {
7154 DBG_INFO("check_parent_access on "
7155 "dst %s returned %s\n",
7156 smb_fname_str_dbg(smb_fname_dst
),
7161 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7164 * We have the file open ourselves, so not being able to get the
7165 * corresponding share mode lock is a fatal error.
7168 SMB_ASSERT(lck
!= NULL
);
7170 ret
= SMB_VFS_RENAMEAT(conn
,
7176 uint32_t create_options
= fsp
->fh
->private_options
;
7178 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7179 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
7180 smb_fname_str_dbg(smb_fname_dst
)));
7182 if (!fsp
->is_directory
&&
7183 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
7184 (lp_map_archive(SNUM(conn
)) ||
7185 lp_store_dos_attributes(SNUM(conn
)))) {
7186 /* We must set the archive bit on the newly
7188 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
7189 uint32_t old_dosmode
= dos_mode(conn
,
7191 file_set_dosmode(conn
,
7193 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
7199 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
7202 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
7206 * A rename acts as a new file create w.r.t. allowing an initial delete
7207 * on close, probably because in Windows there is a new handle to the
7208 * new file. If initial delete on close was requested but not
7209 * originally set, we need to set it here. This is probably not 100% correct,
7210 * but will work for the CIFSFS client which in non-posix mode
7211 * depends on these semantics. JRA.
7214 if (create_options
& FILE_DELETE_ON_CLOSE
) {
7215 status
= can_set_delete_on_close(fsp
, 0);
7217 if (NT_STATUS_IS_OK(status
)) {
7218 /* Note that here we set the *initial* delete on close flag,
7219 * not the regular one. The magic gets handled in close. */
7220 fsp
->initial_delete_on_close
= True
;
7224 status
= NT_STATUS_OK
;
7230 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
7231 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
7233 status
= map_nt_error_from_unix(errno
);
7236 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7237 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
7238 smb_fname_str_dbg(smb_fname_dst
)));
7241 TALLOC_FREE(smb_fname_dst
);
7246 /****************************************************************************
7247 The guts of the rename command, split out so it may be called by the NT SMB
7249 ****************************************************************************/
7251 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
7252 connection_struct
*conn
,
7253 struct smb_request
*req
,
7254 struct smb_filename
*smb_fname_src
,
7255 struct smb_filename
*smb_fname_dst
,
7257 bool replace_if_exists
,
7260 uint32_t access_mask
)
7262 char *fname_src_dir
= NULL
;
7263 struct smb_filename
*smb_fname_src_dir
= NULL
;
7264 char *fname_src_mask
= NULL
;
7266 NTSTATUS status
= NT_STATUS_OK
;
7267 struct smb_Dir
*dir_hnd
= NULL
;
7268 const char *dname
= NULL
;
7269 char *talloced
= NULL
;
7271 int create_options
= 0;
7272 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
7276 * Split the old name into directory and last component
7277 * strings. Note that unix_convert may have stripped off a
7278 * leading ./ from both name and newname if the rename is
7279 * at the root of the share. We need to make sure either both
7280 * name and newname contain a / character or neither of them do
7281 * as this is checked in resolve_wildcards().
7284 /* Split up the directory from the filename/mask. */
7285 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7286 &fname_src_dir
, &fname_src_mask
);
7287 if (!NT_STATUS_IS_OK(status
)) {
7288 status
= NT_STATUS_NO_MEMORY
;
7293 * We should only check the mangled cache
7294 * here if unix_convert failed. This means
7295 * that the path in 'mask' doesn't exist
7296 * on the file system and so we need to look
7297 * for a possible mangle. This patch from
7298 * Tine Smukavec <valentin.smukavec@hermes.si>.
7301 if (!VALID_STAT(smb_fname_src
->st
) &&
7302 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7303 char *new_mask
= NULL
;
7304 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
7307 TALLOC_FREE(fname_src_mask
);
7308 fname_src_mask
= new_mask
;
7312 if (!src_has_wild
) {
7316 * Only one file needs to be renamed. Append the mask back
7317 * onto the directory.
7319 TALLOC_FREE(smb_fname_src
->base_name
);
7320 if (ISDOT(fname_src_dir
)) {
7321 /* Ensure we use canonical names on open. */
7322 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7326 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7331 if (!smb_fname_src
->base_name
) {
7332 status
= NT_STATUS_NO_MEMORY
;
7336 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7337 "case_preserve = %d, short case preserve = %d, "
7338 "directory = %s, newname = %s, "
7339 "last_component_dest = %s\n",
7340 conn
->case_sensitive
, conn
->case_preserve
,
7341 conn
->short_case_preserve
,
7342 smb_fname_str_dbg(smb_fname_src
),
7343 smb_fname_str_dbg(smb_fname_dst
),
7344 smb_fname_dst
->original_lcomp
));
7346 /* The dest name still may have wildcards. */
7347 if (dest_has_wild
) {
7348 char *fname_dst_mod
= NULL
;
7349 if (!resolve_wildcards(smb_fname_dst
,
7350 smb_fname_src
->base_name
,
7351 smb_fname_dst
->base_name
,
7353 DEBUG(6, ("rename_internals: resolve_wildcards "
7355 smb_fname_src
->base_name
,
7356 smb_fname_dst
->base_name
));
7357 status
= NT_STATUS_NO_MEMORY
;
7360 TALLOC_FREE(smb_fname_dst
->base_name
);
7361 smb_fname_dst
->base_name
= fname_dst_mod
;
7364 ZERO_STRUCT(smb_fname_src
->st
);
7365 if (posix_pathnames
) {
7366 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7368 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7371 status
= map_nt_error_from_unix_common(errno
);
7375 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7376 create_options
|= FILE_DIRECTORY_FILE
;
7379 status
= SMB_VFS_CREATE_FILE(
7382 0, /* root_dir_fid */
7383 smb_fname_src
, /* fname */
7384 access_mask
, /* access_mask */
7385 (FILE_SHARE_READ
| /* share_access */
7387 FILE_OPEN
, /* create_disposition*/
7388 create_options
, /* create_options */
7389 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7390 0, /* oplock_request */
7392 0, /* allocation_size */
7393 0, /* private_flags */
7398 NULL
, NULL
); /* create context */
7400 if (!NT_STATUS_IS_OK(status
)) {
7401 DEBUG(3, ("Could not open rename source %s: %s\n",
7402 smb_fname_str_dbg(smb_fname_src
),
7403 nt_errstr(status
)));
7407 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7408 attrs
, replace_if_exists
);
7410 close_file(req
, fsp
, NORMAL_CLOSE
);
7412 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7413 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7414 smb_fname_str_dbg(smb_fname_dst
)));
7420 * Wildcards - process each file that matches.
7422 if (strequal(fname_src_mask
, "????????.???")) {
7423 TALLOC_FREE(fname_src_mask
);
7424 fname_src_mask
= talloc_strdup(ctx
, "*");
7425 if (!fname_src_mask
) {
7426 status
= NT_STATUS_NO_MEMORY
;
7431 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7435 smb_fname_src
->flags
);
7436 if (smb_fname_src_dir
== NULL
) {
7437 status
= NT_STATUS_NO_MEMORY
;
7441 status
= check_name(conn
, smb_fname_src_dir
);
7442 if (!NT_STATUS_IS_OK(status
)) {
7446 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7448 if (dir_hnd
== NULL
) {
7449 status
= map_nt_error_from_unix(errno
);
7453 status
= NT_STATUS_NO_SUCH_FILE
;
7455 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7456 * - gentest fix. JRA
7459 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7461 files_struct
*fsp
= NULL
;
7462 char *destname
= NULL
;
7463 bool sysdir_entry
= False
;
7465 /* Quick check for "." and ".." */
7466 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7467 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7468 sysdir_entry
= True
;
7470 TALLOC_FREE(talloced
);
7475 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7476 &smb_fname_src
->st
, false)) {
7477 TALLOC_FREE(talloced
);
7481 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7482 TALLOC_FREE(talloced
);
7487 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7491 TALLOC_FREE(smb_fname_src
->base_name
);
7492 if (ISDOT(fname_src_dir
)) {
7493 /* Ensure we use canonical names on open. */
7494 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7498 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7503 if (!smb_fname_src
->base_name
) {
7504 status
= NT_STATUS_NO_MEMORY
;
7508 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7509 smb_fname_dst
->base_name
,
7511 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7512 smb_fname_src
->base_name
, destname
));
7513 TALLOC_FREE(talloced
);
7517 status
= NT_STATUS_NO_MEMORY
;
7521 TALLOC_FREE(smb_fname_dst
->base_name
);
7522 smb_fname_dst
->base_name
= destname
;
7524 ZERO_STRUCT(smb_fname_src
->st
);
7525 if (posix_pathnames
) {
7526 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7528 SMB_VFS_STAT(conn
, smb_fname_src
);
7533 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7534 create_options
|= FILE_DIRECTORY_FILE
;
7537 status
= SMB_VFS_CREATE_FILE(
7540 0, /* root_dir_fid */
7541 smb_fname_src
, /* fname */
7542 access_mask
, /* access_mask */
7543 (FILE_SHARE_READ
| /* share_access */
7545 FILE_OPEN
, /* create_disposition*/
7546 create_options
, /* create_options */
7547 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7548 0, /* oplock_request */
7550 0, /* allocation_size */
7551 0, /* private_flags */
7556 NULL
, NULL
); /* create context */
7558 if (!NT_STATUS_IS_OK(status
)) {
7559 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7560 "returned %s rename %s -> %s\n",
7562 smb_fname_str_dbg(smb_fname_src
),
7563 smb_fname_str_dbg(smb_fname_dst
)));
7567 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7569 if (!smb_fname_dst
->original_lcomp
) {
7570 status
= NT_STATUS_NO_MEMORY
;
7574 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7575 attrs
, replace_if_exists
);
7577 close_file(req
, fsp
, NORMAL_CLOSE
);
7579 if (!NT_STATUS_IS_OK(status
)) {
7580 DEBUG(3, ("rename_internals_fsp returned %s for "
7581 "rename %s -> %s\n", nt_errstr(status
),
7582 smb_fname_str_dbg(smb_fname_src
),
7583 smb_fname_str_dbg(smb_fname_dst
)));
7589 DEBUG(3,("rename_internals: doing rename on %s -> "
7590 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7591 smb_fname_str_dbg(smb_fname_src
)));
7592 TALLOC_FREE(talloced
);
7594 TALLOC_FREE(dir_hnd
);
7596 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7597 status
= map_nt_error_from_unix(errno
);
7601 TALLOC_FREE(talloced
);
7602 TALLOC_FREE(smb_fname_src_dir
);
7603 TALLOC_FREE(fname_src_dir
);
7604 TALLOC_FREE(fname_src_mask
);
7608 /****************************************************************************
7610 ****************************************************************************/
7612 void reply_mv(struct smb_request
*req
)
7614 connection_struct
*conn
= req
->conn
;
7616 char *newname
= NULL
;
7620 bool src_has_wcard
= False
;
7621 bool dest_has_wcard
= False
;
7622 TALLOC_CTX
*ctx
= talloc_tos();
7623 struct smb_filename
*smb_fname_src
= NULL
;
7624 struct smb_filename
*smb_fname_dst
= NULL
;
7625 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7626 (req
->posix_pathnames
?
7627 UCF_UNIX_NAME_LOOKUP
:
7628 UCF_COND_ALLOW_WCARD_LCOMP
);
7629 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7631 (req
->posix_pathnames
?
7633 UCF_COND_ALLOW_WCARD_LCOMP
);
7634 bool stream_rename
= false;
7636 START_PROFILE(SMBmv
);
7639 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7643 attrs
= SVAL(req
->vwv
+0, 0);
7645 p
= (const char *)req
->buf
+ 1;
7646 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7647 &status
, &src_has_wcard
);
7648 if (!NT_STATUS_IS_OK(status
)) {
7649 reply_nterror(req
, status
);
7653 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7654 &status
, &dest_has_wcard
);
7655 if (!NT_STATUS_IS_OK(status
)) {
7656 reply_nterror(req
, status
);
7660 if (!req
->posix_pathnames
) {
7661 /* The newname must begin with a ':' if the
7662 name contains a ':'. */
7663 if (strchr_m(name
, ':')) {
7664 if (newname
[0] != ':') {
7665 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7668 stream_rename
= true;
7672 status
= filename_convert(ctx
,
7680 if (!NT_STATUS_IS_OK(status
)) {
7681 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7682 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7683 ERRSRV
, ERRbadpath
);
7686 reply_nterror(req
, status
);
7690 status
= filename_convert(ctx
,
7698 if (!NT_STATUS_IS_OK(status
)) {
7699 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7700 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7701 ERRSRV
, ERRbadpath
);
7704 reply_nterror(req
, status
);
7708 if (stream_rename
) {
7709 /* smb_fname_dst->base_name must be the same as
7710 smb_fname_src->base_name. */
7711 TALLOC_FREE(smb_fname_dst
->base_name
);
7712 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7713 smb_fname_src
->base_name
);
7714 if (!smb_fname_dst
->base_name
) {
7715 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7720 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7721 smb_fname_str_dbg(smb_fname_dst
)));
7723 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7724 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7726 if (!NT_STATUS_IS_OK(status
)) {
7727 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7728 /* We have re-scheduled this call. */
7731 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
7732 bool ok
= defer_smb1_sharing_violation(req
);
7737 reply_nterror(req
, status
);
7741 reply_outbuf(req
, 0, 0);
7743 TALLOC_FREE(smb_fname_src
);
7744 TALLOC_FREE(smb_fname_dst
);
7749 /*******************************************************************
7750 Copy a file as part of a reply_copy.
7751 ******************************************************************/
7754 * TODO: check error codes on all callers
7757 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7758 connection_struct
*conn
,
7759 struct smb_filename
*smb_fname_src
,
7760 struct smb_filename
*smb_fname_dst
,
7763 bool target_is_directory
)
7765 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7767 files_struct
*fsp1
,*fsp2
;
7769 uint32_t new_create_disposition
;
7773 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7774 if (smb_fname_dst_tmp
== NULL
) {
7775 return NT_STATUS_NO_MEMORY
;
7779 * If the target is a directory, extract the last component from the
7780 * src filename and append it to the dst filename
7782 if (target_is_directory
) {
7785 /* dest/target can't be a stream if it's a directory. */
7786 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7788 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7792 p
= smb_fname_src
->base_name
;
7794 smb_fname_dst_tmp
->base_name
=
7795 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7797 if (!smb_fname_dst_tmp
->base_name
) {
7798 status
= NT_STATUS_NO_MEMORY
;
7803 status
= vfs_file_exist(conn
, smb_fname_src
);
7804 if (!NT_STATUS_IS_OK(status
)) {
7808 if (!target_is_directory
&& count
) {
7809 new_create_disposition
= FILE_OPEN
;
7811 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7814 &new_create_disposition
,
7817 status
= NT_STATUS_INVALID_PARAMETER
;
7822 /* Open the src file for reading. */
7823 status
= SMB_VFS_CREATE_FILE(
7826 0, /* root_dir_fid */
7827 smb_fname_src
, /* fname */
7828 FILE_GENERIC_READ
, /* access_mask */
7829 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7830 FILE_OPEN
, /* create_disposition*/
7831 0, /* create_options */
7832 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7833 INTERNAL_OPEN_ONLY
, /* oplock_request */
7835 0, /* allocation_size */
7836 0, /* private_flags */
7841 NULL
, NULL
); /* create context */
7843 if (!NT_STATUS_IS_OK(status
)) {
7847 dosattrs
= dos_mode(conn
, smb_fname_src
);
7849 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7850 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7853 /* Open the dst file for writing. */
7854 status
= SMB_VFS_CREATE_FILE(
7857 0, /* root_dir_fid */
7858 smb_fname_dst
, /* fname */
7859 FILE_GENERIC_WRITE
, /* access_mask */
7860 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7861 new_create_disposition
, /* create_disposition*/
7862 0, /* create_options */
7863 dosattrs
, /* file_attributes */
7864 INTERNAL_OPEN_ONLY
, /* oplock_request */
7866 0, /* allocation_size */
7867 0, /* private_flags */
7872 NULL
, NULL
); /* create context */
7874 if (!NT_STATUS_IS_OK(status
)) {
7875 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7879 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7880 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7882 DEBUG(0, ("error - vfs lseek returned error %s\n",
7884 status
= map_nt_error_from_unix(errno
);
7885 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7886 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7891 /* Do the actual copy. */
7892 if (smb_fname_src
->st
.st_ex_size
) {
7893 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7898 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7900 /* Ensure the modtime is set correctly on the destination file. */
7901 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7904 * As we are opening fsp1 read-only we only expect
7905 * an error on close on fsp2 if we are out of space.
7906 * Thus we don't look at the error return from the
7909 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7911 if (!NT_STATUS_IS_OK(status
)) {
7915 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7916 status
= NT_STATUS_DISK_FULL
;
7920 status
= NT_STATUS_OK
;
7923 TALLOC_FREE(smb_fname_dst_tmp
);
7927 /****************************************************************************
7928 Reply to a file copy.
7929 ****************************************************************************/
7931 void reply_copy(struct smb_request
*req
)
7933 connection_struct
*conn
= req
->conn
;
7934 struct smb_filename
*smb_fname_src
= NULL
;
7935 struct smb_filename
*smb_fname_src_dir
= NULL
;
7936 struct smb_filename
*smb_fname_dst
= NULL
;
7937 char *fname_src
= NULL
;
7938 char *fname_dst
= NULL
;
7939 char *fname_src_mask
= NULL
;
7940 char *fname_src_dir
= NULL
;
7943 int error
= ERRnoaccess
;
7947 bool target_is_directory
=False
;
7948 bool source_has_wild
= False
;
7949 bool dest_has_wild
= False
;
7951 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7952 ucf_flags_from_smb_request(req
);
7953 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7954 ucf_flags_from_smb_request(req
);
7955 TALLOC_CTX
*ctx
= talloc_tos();
7957 START_PROFILE(SMBcopy
);
7960 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7964 tid2
= SVAL(req
->vwv
+0, 0);
7965 ofun
= SVAL(req
->vwv
+1, 0);
7966 flags
= SVAL(req
->vwv
+2, 0);
7968 p
= (const char *)req
->buf
;
7969 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7970 &status
, &source_has_wild
);
7971 if (!NT_STATUS_IS_OK(status
)) {
7972 reply_nterror(req
, status
);
7975 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7976 &status
, &dest_has_wild
);
7977 if (!NT_STATUS_IS_OK(status
)) {
7978 reply_nterror(req
, status
);
7982 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7984 if (tid2
!= conn
->cnum
) {
7985 /* can't currently handle inter share copies XXXX */
7986 DEBUG(3,("Rejecting inter-share copy\n"));
7987 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7991 status
= filename_convert(ctx
, conn
,
7997 if (!NT_STATUS_IS_OK(status
)) {
7998 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7999 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8000 ERRSRV
, ERRbadpath
);
8003 reply_nterror(req
, status
);
8007 status
= filename_convert(ctx
, conn
,
8013 if (!NT_STATUS_IS_OK(status
)) {
8014 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8015 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8016 ERRSRV
, ERRbadpath
);
8019 reply_nterror(req
, status
);
8023 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
8025 if ((flags
&1) && target_is_directory
) {
8026 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
8030 if ((flags
&2) && !target_is_directory
) {
8031 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8035 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
8036 /* wants a tree copy! XXXX */
8037 DEBUG(3,("Rejecting tree copy\n"));
8038 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8042 /* Split up the directory from the filename/mask. */
8043 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
8044 &fname_src_dir
, &fname_src_mask
);
8045 if (!NT_STATUS_IS_OK(status
)) {
8046 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8051 * We should only check the mangled cache
8052 * here if unix_convert failed. This means
8053 * that the path in 'mask' doesn't exist
8054 * on the file system and so we need to look
8055 * for a possible mangle. This patch from
8056 * Tine Smukavec <valentin.smukavec@hermes.si>.
8058 if (!VALID_STAT(smb_fname_src
->st
) &&
8059 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
8060 char *new_mask
= NULL
;
8061 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
8062 &new_mask
, conn
->params
);
8064 /* Use demangled name if one was successfully found. */
8066 TALLOC_FREE(fname_src_mask
);
8067 fname_src_mask
= new_mask
;
8071 if (!source_has_wild
) {
8074 * Only one file needs to be copied. Append the mask back onto
8077 TALLOC_FREE(smb_fname_src
->base_name
);
8078 if (ISDOT(fname_src_dir
)) {
8079 /* Ensure we use canonical names on open. */
8080 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8084 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
8089 if (!smb_fname_src
->base_name
) {
8090 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8094 if (dest_has_wild
) {
8095 char *fname_dst_mod
= NULL
;
8096 if (!resolve_wildcards(smb_fname_dst
,
8097 smb_fname_src
->base_name
,
8098 smb_fname_dst
->base_name
,
8100 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8103 TALLOC_FREE(smb_fname_dst
->base_name
);
8104 smb_fname_dst
->base_name
= fname_dst_mod
;
8107 status
= check_name(conn
, smb_fname_src
);
8108 if (!NT_STATUS_IS_OK(status
)) {
8109 reply_nterror(req
, status
);
8113 status
= check_name(conn
, smb_fname_dst
);
8114 if (!NT_STATUS_IS_OK(status
)) {
8115 reply_nterror(req
, status
);
8119 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
8120 ofun
, count
, target_is_directory
);
8122 if(!NT_STATUS_IS_OK(status
)) {
8123 reply_nterror(req
, status
);
8129 struct smb_Dir
*dir_hnd
= NULL
;
8130 const char *dname
= NULL
;
8131 char *talloced
= NULL
;
8135 * There is a wildcard that requires us to actually read the
8136 * src dir and copy each file matching the mask to the dst.
8137 * Right now streams won't be copied, but this could
8138 * presumably be added with a nested loop for reach dir entry.
8140 SMB_ASSERT(!smb_fname_src
->stream_name
);
8141 SMB_ASSERT(!smb_fname_dst
->stream_name
);
8143 smb_fname_src
->stream_name
= NULL
;
8144 smb_fname_dst
->stream_name
= NULL
;
8146 if (strequal(fname_src_mask
,"????????.???")) {
8147 TALLOC_FREE(fname_src_mask
);
8148 fname_src_mask
= talloc_strdup(ctx
, "*");
8149 if (!fname_src_mask
) {
8150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8155 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
8159 smb_fname_src
->flags
);
8160 if (smb_fname_src_dir
== NULL
) {
8161 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8165 status
= check_name(conn
, smb_fname_src_dir
);
8166 if (!NT_STATUS_IS_OK(status
)) {
8167 reply_nterror(req
, status
);
8171 dir_hnd
= OpenDir(ctx
,
8176 if (dir_hnd
== NULL
) {
8177 status
= map_nt_error_from_unix(errno
);
8178 reply_nterror(req
, status
);
8184 /* Iterate over the src dir copying each entry to the dst. */
8185 while ((dname
= ReadDirName(dir_hnd
, &offset
,
8186 &smb_fname_src
->st
, &talloced
))) {
8187 char *destname
= NULL
;
8189 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
8190 TALLOC_FREE(talloced
);
8194 if (!is_visible_file(conn
, fname_src_dir
, dname
,
8195 &smb_fname_src
->st
, false)) {
8196 TALLOC_FREE(talloced
);
8200 if(!mask_match(dname
, fname_src_mask
,
8201 conn
->case_sensitive
)) {
8202 TALLOC_FREE(talloced
);
8206 error
= ERRnoaccess
;
8208 /* Get the src smb_fname struct setup. */
8209 TALLOC_FREE(smb_fname_src
->base_name
);
8210 if (ISDOT(fname_src_dir
)) {
8211 /* Ensure we use canonical names on open. */
8212 smb_fname_src
->base_name
=
8213 talloc_asprintf(smb_fname_src
, "%s",
8216 smb_fname_src
->base_name
=
8217 talloc_asprintf(smb_fname_src
, "%s/%s",
8218 fname_src_dir
, dname
);
8221 if (!smb_fname_src
->base_name
) {
8222 TALLOC_FREE(dir_hnd
);
8223 TALLOC_FREE(talloced
);
8224 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8228 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
8229 smb_fname_dst
->base_name
,
8231 TALLOC_FREE(talloced
);
8235 TALLOC_FREE(dir_hnd
);
8236 TALLOC_FREE(talloced
);
8237 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8241 TALLOC_FREE(smb_fname_dst
->base_name
);
8242 smb_fname_dst
->base_name
= destname
;
8244 status
= check_name(conn
, smb_fname_src
);
8245 if (!NT_STATUS_IS_OK(status
)) {
8246 TALLOC_FREE(dir_hnd
);
8247 TALLOC_FREE(talloced
);
8248 reply_nterror(req
, status
);
8252 status
= check_name(conn
, smb_fname_dst
);
8253 if (!NT_STATUS_IS_OK(status
)) {
8254 TALLOC_FREE(dir_hnd
);
8255 TALLOC_FREE(talloced
);
8256 reply_nterror(req
, status
);
8260 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8261 smb_fname_src
->base_name
,
8262 smb_fname_dst
->base_name
));
8264 status
= copy_file(ctx
, conn
, smb_fname_src
,
8265 smb_fname_dst
, ofun
, count
,
8266 target_is_directory
);
8267 if (NT_STATUS_IS_OK(status
)) {
8271 TALLOC_FREE(talloced
);
8273 TALLOC_FREE(dir_hnd
);
8277 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
8281 reply_outbuf(req
, 1, 0);
8282 SSVAL(req
->outbuf
,smb_vwv0
,count
);
8284 TALLOC_FREE(smb_fname_src
);
8285 TALLOC_FREE(smb_fname_src_dir
);
8286 TALLOC_FREE(smb_fname_dst
);
8287 TALLOC_FREE(fname_src
);
8288 TALLOC_FREE(fname_dst
);
8289 TALLOC_FREE(fname_src_mask
);
8290 TALLOC_FREE(fname_src_dir
);
8292 END_PROFILE(SMBcopy
);
8297 #define DBGC_CLASS DBGC_LOCKING
8299 /****************************************************************************
8300 Get a lock pid, dealing with large count requests.
8301 ****************************************************************************/
8303 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
8304 bool large_file_format
)
8306 if(!large_file_format
)
8307 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
8309 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
8312 /****************************************************************************
8313 Get a lock count, dealing with large count requests.
8314 ****************************************************************************/
8316 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
8317 bool large_file_format
)
8321 if(!large_file_format
) {
8322 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
8325 * No BVAL, this is reversed!
8327 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
8328 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
8334 /****************************************************************************
8335 Get a lock offset, dealing with large offset requests.
8336 ****************************************************************************/
8338 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8339 bool large_file_format
)
8341 uint64_t offset
= 0;
8343 if(!large_file_format
) {
8344 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8347 * No BVAL, this is reversed!
8349 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8350 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8356 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8358 uint16_t num_ulocks
,
8359 struct smbd_lock_element
*ulocks
,
8360 enum brl_flavour lock_flav
)
8362 struct share_mode_lock
*lck
;
8363 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8366 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
8368 for(i
= 0; i
< num_ulocks
; i
++) {
8369 struct smbd_lock_element
*e
= &ulocks
[i
];
8371 DBG_DEBUG("unlock start=%"PRIu64
", len=%"PRIu64
" for "
8372 "pid %"PRIu64
", file %s\n",
8378 if (e
->brltype
!= UNLOCK_LOCK
) {
8379 /* this can only happen with SMB2 */
8380 status
= NT_STATUS_INVALID_PARAMETER
;
8391 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8392 nt_errstr(status
)));
8394 if (!NT_STATUS_IS_OK(status
)) {
8399 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8403 if (NT_STATUS_IS_OK(status
) && (lck
!= NULL
)) {
8404 lck
->data
->modified
= true;
8411 /****************************************************************************
8412 Reply to a lockingX request.
8413 ****************************************************************************/
8415 static void reply_lockingx_done(struct tevent_req
*subreq
);
8417 void reply_lockingX(struct smb_request
*req
)
8419 connection_struct
*conn
= req
->conn
;
8421 unsigned char locktype
;
8422 enum brl_type brltype
;
8423 unsigned char oplocklevel
;
8424 uint16_t num_ulocks
;
8426 int32_t lock_timeout
;
8428 const uint8_t *data
;
8429 bool large_file_format
;
8430 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8431 struct smbd_lock_element
*locks
= NULL
;
8432 struct tevent_req
*subreq
= NULL
;
8434 START_PROFILE(SMBlockingX
);
8437 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8438 END_PROFILE(SMBlockingX
);
8442 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8443 locktype
= CVAL(req
->vwv
+3, 0);
8444 oplocklevel
= CVAL(req
->vwv
+3, 1);
8445 num_ulocks
= SVAL(req
->vwv
+6, 0);
8446 num_locks
= SVAL(req
->vwv
+7, 0);
8447 lock_timeout
= IVAL(req
->vwv
+4, 0);
8448 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8450 if (!check_fsp(conn
, req
, fsp
)) {
8451 END_PROFILE(SMBlockingX
);
8457 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8458 /* we don't support these - and CANCEL_LOCK makes w2k
8459 and XP reboot so I don't really want to be
8460 compatible! (tridge) */
8461 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8462 END_PROFILE(SMBlockingX
);
8466 /* Check if this is an oplock break on a file
8467 we have granted an oplock on.
8469 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8470 /* Client can insist on breaking to none. */
8471 bool break_to_none
= (oplocklevel
== 0);
8474 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8475 "for %s\n", (unsigned int)oplocklevel
,
8476 fsp_fnum_dbg(fsp
)));
8479 * Make sure we have granted an exclusive or batch oplock on
8483 if (fsp
->oplock_type
== 0) {
8485 /* The Samba4 nbench simulator doesn't understand
8486 the difference between break to level2 and break
8487 to none from level2 - it sends oplock break
8488 replies in both cases. Don't keep logging an error
8489 message here - just ignore it. JRA. */
8491 DEBUG(5,("reply_lockingX: Error : oplock break from "
8492 "client for %s (oplock=%d) and no "
8493 "oplock granted on this file (%s).\n",
8494 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8497 /* if this is a pure oplock break request then don't
8499 if (num_locks
== 0 && num_ulocks
== 0) {
8500 END_PROFILE(SMBlockingX
);
8504 END_PROFILE(SMBlockingX
);
8505 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8509 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8511 result
= remove_oplock(fsp
);
8513 result
= downgrade_oplock(fsp
);
8517 DEBUG(0, ("reply_lockingX: error in removing "
8518 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8519 /* Hmmm. Is this panic justified? */
8520 smb_panic("internal tdb error");
8523 /* if this is a pure oplock break request then don't send a
8525 if (num_locks
== 0 && num_ulocks
== 0) {
8526 /* Sanity check - ensure a pure oplock break is not a
8528 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8529 DEBUG(0,("reply_lockingX: Error : pure oplock "
8530 "break is a chained %d request !\n",
8531 (unsigned int)CVAL(req
->vwv
+0, 0)));
8533 END_PROFILE(SMBlockingX
);
8539 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8541 END_PROFILE(SMBlockingX
);
8545 if (num_ulocks
!= 0) {
8546 struct smbd_lock_element
*ulocks
= NULL
;
8549 ulocks
= talloc_array(
8550 req
, struct smbd_lock_element
, num_ulocks
);
8551 if (ulocks
== NULL
) {
8552 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8553 END_PROFILE(SMBlockingX
);
8558 * Data now points at the beginning of the list of
8559 * smb_unlkrng structs
8561 for (i
= 0; i
< num_ulocks
; i
++) {
8562 ulocks
[i
].req_guid
= smbd_request_guid(req
,
8564 ulocks
[i
].smblctx
= get_lock_pid(
8565 data
, i
, large_file_format
);
8566 ulocks
[i
].count
= get_lock_count(
8567 data
, i
, large_file_format
);
8568 ulocks
[i
].offset
= get_lock_offset(
8569 data
, i
, large_file_format
);
8570 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8574 * Unlock cancels pending locks
8577 ok
= smbd_smb1_brl_finish_by_lock(
8584 reply_outbuf(req
, 2, 0);
8585 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
8586 SSVAL(req
->outbuf
, smb_vwv1
, 0);
8587 END_PROFILE(SMBlockingX
);
8591 status
= smbd_do_unlocking(
8592 req
, fsp
, num_ulocks
, ulocks
, WINDOWS_LOCK
);
8593 TALLOC_FREE(ulocks
);
8594 if (!NT_STATUS_IS_OK(status
)) {
8595 END_PROFILE(SMBlockingX
);
8596 reply_nterror(req
, status
);
8601 /* Now do any requested locks */
8602 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8604 /* Data now points at the beginning of the list
8605 of smb_lkrng structs */
8607 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8608 brltype
= READ_LOCK
;
8610 brltype
= WRITE_LOCK
;
8613 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8614 if (locks
== NULL
) {
8615 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8616 END_PROFILE(SMBlockingX
);
8620 for (i
= 0; i
< num_locks
; i
++) {
8621 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
8622 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8623 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8624 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8625 locks
[i
].brltype
= brltype
;
8628 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8632 if (num_locks
== 0) {
8633 /* See smbtorture3 lock11 test */
8634 reply_outbuf(req
, 2, 0);
8635 /* andx chain ends */
8636 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
8637 SSVAL(req
->outbuf
, smb_vwv1
, 0);
8638 END_PROFILE(SMBlockingX
);
8642 ok
= smbd_smb1_brl_finish_by_lock(
8646 locks
[0], /* Windows only cancels the first lock */
8647 NT_STATUS_FILE_LOCK_CONFLICT
);
8650 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
8651 END_PROFILE(SMBlockingX
);
8655 reply_outbuf(req
, 2, 0);
8656 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
8657 SSVAL(req
->outbuf
, smb_vwv1
, 0);
8658 END_PROFILE(SMBlockingX
);
8662 subreq
= smbd_smb1_do_locks_send(
8672 if (subreq
== NULL
) {
8673 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8674 END_PROFILE(SMBlockingX
);
8677 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
8678 END_PROFILE(SMBlockingX
);
8681 static void reply_lockingx_done(struct tevent_req
*subreq
)
8683 struct smb_request
*req
= NULL
;
8687 START_PROFILE(SMBlockingX
);
8689 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
8692 status
= smbd_smb1_do_locks_recv(subreq
);
8693 TALLOC_FREE(subreq
);
8695 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
8697 if (NT_STATUS_IS_OK(status
)) {
8698 reply_outbuf(req
, 2, 0);
8699 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8700 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8702 reply_nterror(req
, status
);
8705 ok
= srv_send_smb(req
->xconn
,
8706 (char *)req
->outbuf
,
8709 IS_CONN_ENCRYPTED(req
->conn
),
8712 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
8715 END_PROFILE(SMBlockingX
);
8719 #define DBGC_CLASS DBGC_ALL
8721 /****************************************************************************
8722 Reply to a SMBreadbmpx (read block multiplex) request.
8723 Always reply with an error, if someone has a platform really needs this,
8724 please contact vl@samba.org
8725 ****************************************************************************/
8727 void reply_readbmpx(struct smb_request
*req
)
8729 START_PROFILE(SMBreadBmpx
);
8730 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8731 END_PROFILE(SMBreadBmpx
);
8735 /****************************************************************************
8736 Reply to a SMBreadbs (read block multiplex secondary) request.
8737 Always reply with an error, if someone has a platform really needs this,
8738 please contact vl@samba.org
8739 ****************************************************************************/
8741 void reply_readbs(struct smb_request
*req
)
8743 START_PROFILE(SMBreadBs
);
8744 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8745 END_PROFILE(SMBreadBs
);
8749 /****************************************************************************
8750 Reply to a SMBsetattrE.
8751 ****************************************************************************/
8753 void reply_setattrE(struct smb_request
*req
)
8755 connection_struct
*conn
= req
->conn
;
8756 struct smb_file_time ft
;
8760 START_PROFILE(SMBsetattrE
);
8764 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8768 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8770 if(!fsp
|| (fsp
->conn
!= conn
)) {
8771 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8776 * Convert the DOS times into unix times.
8779 ft
.atime
= convert_time_t_to_timespec(
8780 srv_make_unix_date2(req
->vwv
+3));
8781 ft
.mtime
= convert_time_t_to_timespec(
8782 srv_make_unix_date2(req
->vwv
+5));
8783 ft
.create_time
= convert_time_t_to_timespec(
8784 srv_make_unix_date2(req
->vwv
+1));
8786 reply_outbuf(req
, 0, 0);
8789 * Patch from Ray Frush <frush@engr.colostate.edu>
8790 * Sometimes times are sent as zero - ignore them.
8793 /* Ensure we have a valid stat struct for the source. */
8794 status
= vfs_stat_fsp(fsp
);
8795 if (!NT_STATUS_IS_OK(status
)) {
8796 reply_nterror(req
, status
);
8800 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8801 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8805 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8806 if (!NT_STATUS_IS_OK(status
)) {
8807 reply_nterror(req
, status
);
8811 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8814 (unsigned int)ft
.atime
.tv_sec
,
8815 (unsigned int)ft
.mtime
.tv_sec
,
8816 (unsigned int)ft
.create_time
.tv_sec
8819 END_PROFILE(SMBsetattrE
);
8824 /* Back from the dead for OS/2..... JRA. */
8826 /****************************************************************************
8827 Reply to a SMBwritebmpx (write block multiplex primary) request.
8828 Always reply with an error, if someone has a platform really needs this,
8829 please contact vl@samba.org
8830 ****************************************************************************/
8832 void reply_writebmpx(struct smb_request
*req
)
8834 START_PROFILE(SMBwriteBmpx
);
8835 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8836 END_PROFILE(SMBwriteBmpx
);
8840 /****************************************************************************
8841 Reply to a SMBwritebs (write block multiplex secondary) request.
8842 Always reply with an error, if someone has a platform really needs this,
8843 please contact vl@samba.org
8844 ****************************************************************************/
8846 void reply_writebs(struct smb_request
*req
)
8848 START_PROFILE(SMBwriteBs
);
8849 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8850 END_PROFILE(SMBwriteBs
);
8854 /****************************************************************************
8855 Reply to a SMBgetattrE.
8856 ****************************************************************************/
8858 void reply_getattrE(struct smb_request
*req
)
8860 connection_struct
*conn
= req
->conn
;
8863 struct timespec create_ts
;
8866 START_PROFILE(SMBgetattrE
);
8869 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8870 END_PROFILE(SMBgetattrE
);
8874 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8876 if(!fsp
|| (fsp
->conn
!= conn
)) {
8877 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8878 END_PROFILE(SMBgetattrE
);
8882 /* Do an fstat on this file */
8883 status
= vfs_stat_fsp(fsp
);
8884 if (!NT_STATUS_IS_OK(status
)) {
8885 reply_nterror(req
, status
);
8886 END_PROFILE(SMBgetattrE
);
8890 mode
= dos_mode(conn
, fsp
->fsp_name
);
8893 * Convert the times into dos times. Set create
8894 * date to be last modify date as UNIX doesn't save
8898 reply_outbuf(req
, 11, 0);
8900 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8901 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8902 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8903 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8904 /* Should we check pending modtime here ? JRA */
8905 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8906 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8908 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8909 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8910 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8912 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8913 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8914 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8916 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8918 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8920 END_PROFILE(SMBgetattrE
);