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 "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.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"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS
check_path_syntax_internal(char *path
,
61 bool *p_last_component_contains_wcard
)
65 NTSTATUS ret
= NT_STATUS_OK
;
66 bool start_of_name_component
= True
;
67 bool stream_started
= false;
69 *p_last_component_contains_wcard
= False
;
76 return NT_STATUS_OBJECT_NAME_INVALID
;
79 return NT_STATUS_OBJECT_NAME_INVALID
;
81 if (strchr_m(&s
[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID
;
88 if ((*s
== ':') && !posix_path
&& !stream_started
) {
89 if (*p_last_component_contains_wcard
) {
90 return NT_STATUS_OBJECT_NAME_INVALID
;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started
= true;
99 start_of_name_component
= false;
103 return NT_STATUS_OBJECT_NAME_INVALID
;
107 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s
,posix_path
)) {
116 if ((d
!= path
) && (*s
!= '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component
= True
;
123 *p_last_component_contains_wcard
= False
;
127 if (start_of_name_component
) {
128 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d
> path
) && (*(d
-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d
--; d
> path
; d
--) {
154 s
+= 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
170 if (*s
<= 0x1f || *s
== '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID
;
179 *p_last_component_contains_wcard
= True
;
188 /* Get the size of the next MB character. */
189 next_codepoint(s
,&siz
);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER
;
212 start_of_name_component
= False
;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS
check_path_syntax(char *path
)
228 return check_path_syntax_internal(path
, False
, &ignore
);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
239 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS
check_path_syntax_posix(char *path
)
251 return check_path_syntax_internal(path
, True
, &ignore
);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX
*ctx
,
260 const char *base_ptr
,
266 bool posix_pathnames
,
268 bool *contains_wcard
)
274 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
278 *err
= NT_STATUS_INVALID_PARAMETER
;
282 *contains_wcard
= False
;
284 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames
) {
294 *err
= check_path_syntax_posix(*pp_dest
);
296 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
307 const char *base_ptr
,
314 bool *contains_wcard
)
316 return srvstr_get_path_wcard_internal(ctx
,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX
*ctx
,
334 const char *base_ptr
,
341 bool *contains_wcard
)
343 return srvstr_get_path_wcard_internal(ctx
,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
360 const char *base_ptr
,
369 return srvstr_get_path_wcard_internal(ctx
,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX
*ctx
,
387 const char *base_ptr
,
396 return srvstr_get_path_wcard_internal(ctx
,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
410 char **pp_dest
, const char *src
, int flags
,
411 NTSTATUS
*err
, bool *contains_wcard
)
413 ssize_t bufrem
= smbreq_bufrem(req
, src
);
416 *err
= NT_STATUS_INVALID_PARAMETER
;
420 if (req
->posix_pathnames
) {
421 return srvstr_get_path_wcard_internal(mem_ctx
,
422 (const char *)req
->inbuf
,
432 return srvstr_get_path_wcard_internal(mem_ctx
,
433 (const char *)req
->inbuf
,
445 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
446 char **pp_dest
, const char *src
, int flags
,
450 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
451 flags
, err
, &ignore
);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX
*ctx
, struct smb_request
*req
,
460 char **dest
, const uint8_t *src
, int flags
)
462 ssize_t bufrem
= smbreq_bufrem(req
, src
);
468 return pull_string_talloc(ctx
, req
->inbuf
, req
->flags2
, dest
, src
,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
479 if ((fsp
== NULL
) || (conn
== NULL
)) {
480 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
483 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
484 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
497 if (!check_fsp_open(conn
, req
, fsp
)) {
500 if (fsp
->is_directory
) {
501 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
504 if (fsp
->fh
->fd
== -1) {
505 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
508 fsp
->num_smb_operations
++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
520 if (!check_fsp_open(conn
, req
, fsp
)) {
524 if (fsp
->is_directory
) {
528 if (fsp
->fake_file_handle
== NULL
) {
532 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
536 if (fsp
->fake_file_handle
->private_data
== NULL
) {
543 static bool netbios_session_retarget(struct smbXsrv_connection
*xconn
,
544 const char *name
, int name_type
)
547 char *trim_name_type
;
548 const char *retarget_parm
;
551 int retarget_type
= 0x20;
552 int retarget_port
= NBT_SMB_PORT
;
553 struct sockaddr_storage retarget_addr
;
554 struct sockaddr_in
*in_addr
;
558 if (get_socket_port(xconn
->transport
.sock
) != NBT_SMB_PORT
) {
562 trim_name
= talloc_strdup(talloc_tos(), name
);
563 if (trim_name
== NULL
) {
566 trim_char(trim_name
, ' ', ' ');
568 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
570 if (trim_name_type
== NULL
) {
574 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type
, NULL
);
576 if (retarget_parm
== NULL
) {
577 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm
== NULL
) {
584 retarget
= talloc_strdup(trim_name
, retarget_parm
);
585 if (retarget
== NULL
) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
591 p
= strchr(retarget
, ':');
594 retarget_port
= atoi(p
);
597 p
= strchr_m(retarget
, '#');
600 if (sscanf(p
, "%x", &retarget_type
) != 1) {
605 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
607 DEBUG(10, ("could not resolve %s\n", retarget
));
611 if (retarget_addr
.ss_family
!= AF_INET
) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
618 _smb_setlen(outbuf
, 6);
619 SCVAL(outbuf
, 0, 0x84);
620 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
621 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
623 if (!srv_send_smb(xconn
, (char *)outbuf
, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name
);
635 static void reply_called_name_not_present(char *outbuf
)
637 smb_setlen(outbuf
, 1);
638 SCVAL(outbuf
, 0, 0x83);
639 SCVAL(outbuf
, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection
*xconn
, char *inbuf
, size_t inbuf_size
)
648 struct smbd_server_connection
*sconn
= xconn
->client
->sconn
;
649 int msg_type
= CVAL(inbuf
,0);
650 int msg_flags
= CVAL(inbuf
,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf
[smb_size
];
658 memset(outbuf
, '\0', sizeof(outbuf
));
660 smb_setlen(outbuf
,0);
663 case NBSSrequest
: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1
, name_type2
;
668 int name_len1
, name_len2
;
672 if (xconn
->transport
.nbt
.got_session
) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf
,0,NBSSpositive
);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1
= name_len((unsigned char *)(inbuf
+4),inbuf_size
- 4);
681 if (name_len1
<= 0 || name_len1
> inbuf_size
- 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf
);
686 name_len2
= name_len((unsigned char *)(inbuf
+4+name_len1
),inbuf_size
- 4 - name_len1
);
687 if (name_len2
<= 0 || name_len2
> inbuf_size
- 4 - name_len1
) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf
);
693 name_type1
= name_extract((unsigned char *)inbuf
,
694 inbuf_size
,(unsigned int)4,name1
);
695 name_type2
= name_extract((unsigned char *)inbuf
,
696 inbuf_size
,(unsigned int)(4 + name_len1
),name2
);
698 if (name_type1
== -1 || name_type2
== -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf
);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1
, name_type1
, name2
, name_type2
));
707 if (netbios_session_retarget(xconn
, name1
, name_type1
)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1
, "*SMBSERVER ")
716 || strequal(name1
, "*SMBSERV ")) {
719 raddr
= tsocket_address_inet_addr_string(sconn
->remote_address
,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1
, raddr
);
728 set_local_machine_name(name1
, True
);
729 set_remote_machine_name(name2
, True
);
731 if (is_ipaddress(sconn
->remote_hostname
)) {
732 char *p
= discard_const_p(char, sconn
->remote_hostname
);
736 sconn
->remote_hostname
= talloc_strdup(sconn
,
737 get_remote_machine_name());
738 if (sconn
->remote_hostname
== NULL
) {
739 exit_server_cleanly("could not copy remote name");
741 xconn
->remote_hostname
= sconn
->remote_hostname
;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2
== 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf
);
755 reload_services(sconn
, conn_snum_used
, true);
758 xconn
->transport
.nbt
.got_session
= true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf
,0,NBSSkeepalive
);
768 case NBSSpositive
: /* positive session response */
769 case NBSSnegative
: /* negative session response */
770 case NBSSretarget
: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive
: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type
, msg_flags
));
782 if (!srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf
, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
792 /****************************************************************************
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request
*req
)
799 connection_struct
*conn
= req
->conn
;
801 char *service_buf
= NULL
;
802 char *password
= NULL
;
808 TALLOC_CTX
*ctx
= talloc_tos();
809 struct smbXsrv_connection
*xconn
= req
->xconn
;
810 NTTIME now
= timeval_to_nttime(&req
->request_time
);
812 START_PROFILE(SMBtcon
);
814 if (req
->buflen
< 4) {
815 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
816 END_PROFILE(SMBtcon
);
821 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
823 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
825 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
828 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
830 END_PROFILE(SMBtcon
);
833 p2
= strrchr_m(service_buf
,'\\');
837 service
= service_buf
;
840 conn
= make_connection(req
, now
, service
, dev
,
841 req
->vuid
,&nt_status
);
845 reply_nterror(req
, nt_status
);
846 END_PROFILE(SMBtcon
);
850 reply_outbuf(req
, 2, 0);
851 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
852 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
853 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service
, conn
->cnum
));
858 END_PROFILE(SMBtcon
);
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request
*req
)
869 connection_struct
*conn
= req
->conn
;
870 const char *service
= NULL
;
871 TALLOC_CTX
*ctx
= talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype
= NULL
;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype
;
882 struct smbXsrv_session
*session
= NULL
;
883 NTTIME now
= timeval_to_nttime(&req
->request_time
);
884 bool session_key_updated
= false;
885 uint16_t optional_support
= 0;
886 struct smbXsrv_connection
*xconn
= req
->xconn
;
888 START_PROFILE(SMBtconX
);
891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
892 END_PROFILE(SMBtconX
);
896 passlen
= SVAL(req
->vwv
+3, 0);
897 tcon_flags
= SVAL(req
->vwv
+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
901 struct smbXsrv_tcon
*tcon
;
909 * TODO: cancel all outstanding requests on the tcon
911 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
912 if (!NT_STATUS_IS_OK(status
)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX
);
921 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
928 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
929 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
930 END_PROFILE(SMBtconX
);
934 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
935 p
= req
->buf
+ passlen
;
937 p
= req
->buf
+ passlen
+ 1;
940 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
943 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
944 END_PROFILE(SMBtconX
);
949 * the service name can be either: \\server\share
950 * or share directly like on the DELL PowerVault 705
953 q
= strchr_m(path
+2,'\\');
955 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
956 END_PROFILE(SMBtconX
);
964 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
965 &client_devicetype
, p
,
966 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
968 if (client_devicetype
== NULL
) {
969 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
970 END_PROFILE(SMBtconX
);
974 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
976 nt_status
= smb1srv_session_lookup(xconn
,
977 req
->vuid
, now
, &session
);
978 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
979 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
980 END_PROFILE(SMBtconX
);
983 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
984 reply_nterror(req
, nt_status
);
985 END_PROFILE(SMBtconX
);
988 if (!NT_STATUS_IS_OK(nt_status
)) {
989 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
990 END_PROFILE(SMBtconX
);
994 if (session
->global
->auth_session_info
== NULL
) {
995 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
996 END_PROFILE(SMBtconX
);
1001 * If there is no application key defined yet
1004 * This means we setup the application key on the
1005 * first tcon that happens via the given session.
1007 * Once the application key is defined, it does not
1010 if (session
->global
->application_key
.length
== 0 &&
1011 session
->global
->signing_key
.length
> 0)
1013 struct smbXsrv_session
*x
= session
;
1014 struct auth_session_info
*session_info
=
1015 session
->global
->auth_session_info
;
1016 uint8_t session_key
[16];
1018 ZERO_STRUCT(session_key
);
1019 memcpy(session_key
, x
->global
->signing_key
.data
,
1020 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
1023 * The application key is truncated/padded to 16 bytes
1025 x
->global
->application_key
= data_blob_talloc(x
->global
,
1027 sizeof(session_key
));
1028 ZERO_STRUCT(session_key
);
1029 if (x
->global
->application_key
.data
== NULL
) {
1030 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1031 END_PROFILE(SMBtconX
);
1035 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
1036 smb_key_derivation(x
->global
->application_key
.data
,
1037 x
->global
->application_key
.length
,
1038 x
->global
->application_key
.data
);
1039 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1043 * Place the application key into the session_info
1045 data_blob_clear_free(&session_info
->session_key
);
1046 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1047 x
->global
->application_key
);
1048 if (session_info
->session_key
.data
== NULL
) {
1049 data_blob_clear_free(&x
->global
->application_key
);
1050 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1051 END_PROFILE(SMBtconX
);
1054 session_key_updated
= true;
1057 conn
= make_connection(req
, now
, service
, client_devicetype
,
1058 req
->vuid
, &nt_status
);
1062 if (session_key_updated
) {
1063 struct smbXsrv_session
*x
= session
;
1064 struct auth_session_info
*session_info
=
1065 session
->global
->auth_session_info
;
1066 data_blob_clear_free(&x
->global
->application_key
);
1067 data_blob_clear_free(&session_info
->session_key
);
1069 reply_nterror(req
, nt_status
);
1070 END_PROFILE(SMBtconX
);
1075 server_devicetype
= "IPC";
1076 else if ( IS_PRINT(conn
) )
1077 server_devicetype
= "LPT1:";
1079 server_devicetype
= "A:";
1081 if (get_Protocol() < PROTOCOL_NT1
) {
1082 reply_outbuf(req
, 2, 0);
1083 if (message_push_string(&req
->outbuf
, server_devicetype
,
1084 STR_TERMINATE
|STR_ASCII
) == -1) {
1085 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1086 END_PROFILE(SMBtconX
);
1090 /* NT sets the fstype of IPC$ to the null string */
1091 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1093 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1094 /* Return permissions. */
1098 reply_outbuf(req
, 7, 0);
1101 perm1
= FILE_ALL_ACCESS
;
1102 perm2
= FILE_ALL_ACCESS
;
1104 perm1
= conn
->share_access
;
1107 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1108 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1110 reply_outbuf(req
, 3, 0);
1113 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1114 STR_TERMINATE
|STR_ASCII
) == -1)
1115 || (message_push_string(&req
->outbuf
, fstype
,
1116 STR_TERMINATE
) == -1)) {
1117 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1118 END_PROFILE(SMBtconX
);
1122 /* what does setting this bit do? It is set by NT4 and
1123 may affect the ability to autorun mounted cdroms */
1124 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1126 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1128 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1129 DEBUG(2,("Serving %s as a Dfs root\n",
1130 lp_servicename(ctx
, SNUM(conn
)) ));
1131 optional_support
|= SMB_SHARE_IN_DFS
;
1134 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1137 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1138 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1140 DEBUG(3,("tconX service=%s \n",
1143 /* set the incoming and outgoing tid to the just created one */
1144 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1145 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1147 END_PROFILE(SMBtconX
);
1149 req
->tid
= conn
->cnum
;
1152 /****************************************************************************
1153 Reply to an unknown type.
1154 ****************************************************************************/
1156 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1158 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1159 smb_fn_name(type
), type
, type
));
1160 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1164 /****************************************************************************
1166 conn POINTER CAN BE NULL HERE !
1167 ****************************************************************************/
1169 void reply_ioctl(struct smb_request
*req
)
1171 connection_struct
*conn
= req
->conn
;
1174 uint32_t ioctl_code
;
1178 START_PROFILE(SMBioctl
);
1181 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1182 END_PROFILE(SMBioctl
);
1186 device
= SVAL(req
->vwv
+1, 0);
1187 function
= SVAL(req
->vwv
+2, 0);
1188 ioctl_code
= (device
<< 16) + function
;
1190 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1192 switch (ioctl_code
) {
1193 case IOCTL_QUERY_JOB_INFO
:
1197 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1198 END_PROFILE(SMBioctl
);
1202 reply_outbuf(req
, 8, replysize
+1);
1203 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1204 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1205 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1206 p
= smb_buf(req
->outbuf
);
1207 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1208 p
+= 1; /* Allow for alignment */
1210 switch (ioctl_code
) {
1211 case IOCTL_QUERY_JOB_INFO
:
1215 files_struct
*fsp
= file_fsp(
1216 req
, SVAL(req
->vwv
+0, 0));
1218 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1219 END_PROFILE(SMBioctl
);
1223 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1225 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1226 lp_netbios_name(), 15,
1227 STR_TERMINATE
|STR_ASCII
, &len
);
1228 if (!NT_STATUS_IS_OK(status
)) {
1229 reply_nterror(req
, status
);
1230 END_PROFILE(SMBioctl
);
1234 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1236 lp_servicename(talloc_tos(),
1238 13, STR_TERMINATE
|STR_ASCII
, &len
);
1239 if (!NT_STATUS_IS_OK(status
)) {
1240 reply_nterror(req
, status
);
1241 END_PROFILE(SMBioctl
);
1245 memset(p
+18, 0, 13);
1251 END_PROFILE(SMBioctl
);
1255 /****************************************************************************
1256 Strange checkpath NTSTATUS mapping.
1257 ****************************************************************************/
1259 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1261 /* Strange DOS error code semantics only for checkpath... */
1262 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1263 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1264 /* We need to map to ERRbadpath */
1265 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1271 /****************************************************************************
1272 Reply to a checkpath.
1273 ****************************************************************************/
1275 void reply_checkpath(struct smb_request
*req
)
1277 connection_struct
*conn
= req
->conn
;
1278 struct smb_filename
*smb_fname
= NULL
;
1281 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1282 TALLOC_CTX
*ctx
= talloc_tos();
1284 START_PROFILE(SMBcheckpath
);
1286 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1287 STR_TERMINATE
, &status
);
1289 if (!NT_STATUS_IS_OK(status
)) {
1290 status
= map_checkpath_error(req
->flags2
, status
);
1291 reply_nterror(req
, status
);
1292 END_PROFILE(SMBcheckpath
);
1296 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1298 status
= filename_convert(ctx
,
1305 if (!NT_STATUS_IS_OK(status
)) {
1306 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1307 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1308 ERRSRV
, ERRbadpath
);
1309 END_PROFILE(SMBcheckpath
);
1315 if (!VALID_STAT(smb_fname
->st
) &&
1316 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1317 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1318 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1319 status
= map_nt_error_from_unix(errno
);
1323 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1324 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1325 ERRDOS
, ERRbadpath
);
1329 reply_outbuf(req
, 0, 0);
1332 /* We special case this - as when a Windows machine
1333 is parsing a path is steps through the components
1334 one at a time - if a component fails it expects
1335 ERRbadpath, not ERRbadfile.
1337 status
= map_checkpath_error(req
->flags2
, status
);
1338 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1340 * Windows returns different error codes if
1341 * the parent directory is valid but not the
1342 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1343 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1344 * if the path is invalid.
1346 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1347 ERRDOS
, ERRbadpath
);
1351 reply_nterror(req
, status
);
1354 TALLOC_FREE(smb_fname
);
1355 END_PROFILE(SMBcheckpath
);
1359 /****************************************************************************
1361 ****************************************************************************/
1363 void reply_getatr(struct smb_request
*req
)
1365 connection_struct
*conn
= req
->conn
;
1366 struct smb_filename
*smb_fname
= NULL
;
1373 TALLOC_CTX
*ctx
= talloc_tos();
1374 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1376 START_PROFILE(SMBgetatr
);
1378 p
= (const char *)req
->buf
+ 1;
1379 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1381 reply_nterror(req
, status
);
1385 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1386 under WfWg - weird! */
1387 if (*fname
== '\0') {
1388 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1389 if (!CAN_WRITE(conn
)) {
1390 mode
|= FILE_ATTRIBUTE_READONLY
;
1395 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1396 status
= filename_convert(ctx
,
1402 if (!NT_STATUS_IS_OK(status
)) {
1403 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1404 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1405 ERRSRV
, ERRbadpath
);
1408 reply_nterror(req
, status
);
1411 if (!VALID_STAT(smb_fname
->st
) &&
1412 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1413 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1414 smb_fname_str_dbg(smb_fname
),
1416 reply_nterror(req
, map_nt_error_from_unix(errno
));
1420 mode
= dos_mode(conn
, smb_fname
);
1421 size
= smb_fname
->st
.st_ex_size
;
1423 if (ask_sharemode
) {
1424 struct timespec write_time_ts
;
1425 struct file_id fileid
;
1427 ZERO_STRUCT(write_time_ts
);
1428 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1429 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1430 if (!null_timespec(write_time_ts
)) {
1431 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1435 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1436 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1441 reply_outbuf(req
, 10, 0);
1443 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1444 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1445 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1447 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1449 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1451 if (get_Protocol() >= PROTOCOL_NT1
) {
1452 SSVAL(req
->outbuf
, smb_flg2
,
1453 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1456 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1457 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1460 TALLOC_FREE(smb_fname
);
1462 END_PROFILE(SMBgetatr
);
1466 /****************************************************************************
1468 ****************************************************************************/
1470 void reply_setatr(struct smb_request
*req
)
1472 struct smb_file_time ft
;
1473 connection_struct
*conn
= req
->conn
;
1474 struct smb_filename
*smb_fname
= NULL
;
1480 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1481 TALLOC_CTX
*ctx
= talloc_tos();
1483 START_PROFILE(SMBsetatr
);
1488 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1492 p
= (const char *)req
->buf
+ 1;
1493 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1494 if (!NT_STATUS_IS_OK(status
)) {
1495 reply_nterror(req
, status
);
1499 status
= filename_convert(ctx
,
1505 if (!NT_STATUS_IS_OK(status
)) {
1506 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1507 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1508 ERRSRV
, ERRbadpath
);
1511 reply_nterror(req
, status
);
1515 if (smb_fname
->base_name
[0] == '.' &&
1516 smb_fname
->base_name
[1] == '\0') {
1518 * Not sure here is the right place to catch this
1519 * condition. Might be moved to somewhere else later -- vl
1521 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1525 mode
= SVAL(req
->vwv
+0, 0);
1526 mtime
= srv_make_unix_date3(req
->vwv
+1);
1528 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1529 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1530 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1532 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1534 status
= check_access(conn
, NULL
, smb_fname
,
1535 FILE_WRITE_ATTRIBUTES
);
1536 if (!NT_STATUS_IS_OK(status
)) {
1537 reply_nterror(req
, status
);
1541 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1543 reply_nterror(req
, map_nt_error_from_unix(errno
));
1548 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1549 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1550 if (!NT_STATUS_IS_OK(status
)) {
1551 reply_nterror(req
, status
);
1555 reply_outbuf(req
, 0, 0);
1557 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1560 TALLOC_FREE(smb_fname
);
1561 END_PROFILE(SMBsetatr
);
1565 /****************************************************************************
1567 ****************************************************************************/
1569 void reply_dskattr(struct smb_request
*req
)
1571 connection_struct
*conn
= req
->conn
;
1573 uint64_t dfree
,dsize
,bsize
;
1574 struct smb_filename smb_fname
;
1575 START_PROFILE(SMBdskattr
);
1577 ZERO_STRUCT(smb_fname
);
1578 smb_fname
.base_name
= discard_const_p(char, ".");
1580 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1581 reply_nterror(req
, map_nt_error_from_unix(errno
));
1582 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1583 END_PROFILE(SMBdskattr
);
1587 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1588 if (ret
== (uint64_t)-1) {
1589 reply_nterror(req
, map_nt_error_from_unix(errno
));
1590 END_PROFILE(SMBdskattr
);
1595 * Force max to fit in 16 bit fields.
1597 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1601 if (bsize
> (WORDMAX
*512)) {
1602 bsize
= (WORDMAX
*512);
1603 if (dsize
> WORDMAX
)
1605 if (dfree
> WORDMAX
)
1611 reply_outbuf(req
, 5, 0);
1613 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1614 double total_space
, free_space
;
1615 /* we need to scale this to a number that DOS6 can handle. We
1616 use floating point so we can handle large drives on systems
1617 that don't have 64 bit integers
1619 we end up displaying a maximum of 2G to DOS systems
1621 total_space
= dsize
* (double)bsize
;
1622 free_space
= dfree
* (double)bsize
;
1624 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1625 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1627 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1628 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1630 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1631 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1632 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1633 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1635 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1636 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1637 SSVAL(req
->outbuf
,smb_vwv2
,512);
1638 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1641 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1643 END_PROFILE(SMBdskattr
);
1648 * Utility function to split the filename from the directory.
1650 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1651 char **fname_dir_out
,
1652 char **fname_mask_out
)
1654 const char *p
= NULL
;
1655 char *fname_dir
= NULL
;
1656 char *fname_mask
= NULL
;
1658 p
= strrchr_m(fname_in
, '/');
1660 fname_dir
= talloc_strdup(ctx
, ".");
1661 fname_mask
= talloc_strdup(ctx
, fname_in
);
1663 fname_dir
= talloc_strndup(ctx
, fname_in
,
1664 PTR_DIFF(p
, fname_in
));
1665 fname_mask
= talloc_strdup(ctx
, p
+1);
1668 if (!fname_dir
|| !fname_mask
) {
1669 TALLOC_FREE(fname_dir
);
1670 TALLOC_FREE(fname_mask
);
1671 return NT_STATUS_NO_MEMORY
;
1674 *fname_dir_out
= fname_dir
;
1675 *fname_mask_out
= fname_mask
;
1676 return NT_STATUS_OK
;
1679 /****************************************************************************
1681 ****************************************************************************/
1683 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1693 char *mask2
= talloc_strdup(ctx
, mask
);
1699 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1703 memset(buf
+1,' ',11);
1704 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1706 push_ascii(buf
+1,mask2
,8, 0);
1707 push_ascii(buf
+9,p
+1,3, 0);
1710 push_ascii(buf
+1,mask2
,11, 0);
1713 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1715 srv_put_dos_date(buf
,22,date
);
1716 SSVAL(buf
,26,size
& 0xFFFF);
1717 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1718 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1719 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1720 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1721 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1725 /****************************************************************************
1727 Can be called from SMBsearch, SMBffirst or SMBfunique.
1728 ****************************************************************************/
1730 void reply_search(struct smb_request
*req
)
1732 connection_struct
*conn
= req
->conn
;
1735 char *directory
= NULL
;
1736 struct smb_filename
*smb_fname
= NULL
;
1740 struct timespec date
;
1742 unsigned int numentries
= 0;
1743 unsigned int maxentries
= 0;
1744 bool finished
= False
;
1749 bool check_descend
= False
;
1750 bool expect_close
= False
;
1752 bool mask_contains_wcard
= False
;
1753 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1754 TALLOC_CTX
*ctx
= talloc_tos();
1755 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1756 struct dptr_struct
*dirptr
= NULL
;
1757 struct smbXsrv_connection
*xconn
= req
->xconn
;
1758 struct smbd_server_connection
*sconn
= req
->sconn
;
1760 START_PROFILE(SMBsearch
);
1763 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1767 if (req
->posix_pathnames
) {
1768 reply_unknown_new(req
, req
->cmd
);
1772 /* If we were called as SMBffirst then we must expect close. */
1773 if(req
->cmd
== SMBffirst
) {
1774 expect_close
= True
;
1777 reply_outbuf(req
, 1, 3);
1778 maxentries
= SVAL(req
->vwv
+0, 0);
1779 dirtype
= SVAL(req
->vwv
+1, 0);
1780 p
= (const char *)req
->buf
+ 1;
1781 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1782 &nt_status
, &mask_contains_wcard
);
1783 if (!NT_STATUS_IS_OK(nt_status
)) {
1784 reply_nterror(req
, nt_status
);
1789 status_len
= SVAL(p
, 0);
1792 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1794 if (status_len
== 0) {
1795 struct smb_filename
*smb_dname
= NULL
;
1796 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1797 ucf_flags_from_smb_request(req
);
1798 nt_status
= filename_convert(ctx
, conn
,
1801 &mask_contains_wcard
,
1803 if (!NT_STATUS_IS_OK(nt_status
)) {
1804 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1805 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1806 ERRSRV
, ERRbadpath
);
1809 reply_nterror(req
, nt_status
);
1813 directory
= smb_fname
->base_name
;
1815 p
= strrchr_m(directory
,'/');
1816 if ((p
!= NULL
) && (*directory
!= '/')) {
1817 mask
= talloc_strdup(ctx
, p
+ 1);
1818 directory
= talloc_strndup(ctx
, directory
,
1819 PTR_DIFF(p
, directory
));
1821 mask
= talloc_strdup(ctx
, directory
);
1822 directory
= talloc_strdup(ctx
,".");
1826 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1830 memset((char *)status
,'\0',21);
1831 SCVAL(status
,0,(dirtype
& 0x1F));
1833 smb_dname
= synthetic_smb_fname(talloc_tos(),
1838 if (smb_dname
== NULL
) {
1839 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1843 nt_status
= dptr_create(conn
,
1851 mask_contains_wcard
,
1855 TALLOC_FREE(smb_dname
);
1857 if (!NT_STATUS_IS_OK(nt_status
)) {
1858 reply_nterror(req
, nt_status
);
1861 dptr_num
= dptr_dnum(dirptr
);
1864 const char *dirpath
;
1866 memcpy(status
,p
,21);
1867 status_dirtype
= CVAL(status
,0) & 0x1F;
1868 if (status_dirtype
!= (dirtype
& 0x1F)) {
1869 dirtype
= status_dirtype
;
1872 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1876 dirpath
= dptr_path(sconn
, dptr_num
);
1877 directory
= talloc_strdup(ctx
, dirpath
);
1879 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1883 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1888 * For a 'continue' search we have no string. So
1889 * check from the initial saved string.
1891 if (!req
->posix_pathnames
) {
1892 mask_contains_wcard
= ms_has_wild(mask
);
1894 dirtype
= dptr_attr(sconn
, dptr_num
);
1897 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1899 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1900 dptr_init_search_op(dirptr
);
1902 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1903 char buf
[DIR_STRUCT_SIZE
];
1904 memcpy(buf
,status
,21);
1905 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1906 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1907 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1910 dptr_fill(sconn
, buf
+12,dptr_num
);
1911 if (dptr_zero(buf
+12) && (status_len
==0)) {
1916 if (message_push_blob(&req
->outbuf
,
1917 data_blob_const(buf
, sizeof(buf
)))
1919 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1924 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1925 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1927 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1929 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1930 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1931 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1932 check_descend
= True
;
1935 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1936 finished
= !get_dir_entry(ctx
,
1947 char buf
[DIR_STRUCT_SIZE
];
1948 memcpy(buf
,status
,21);
1949 if (!make_dir_struct(ctx
,
1955 convert_timespec_to_time_t(date
),
1956 !allow_long_path_components
)) {
1957 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1960 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1963 if (message_push_blob(&req
->outbuf
,
1964 data_blob_const(buf
, sizeof(buf
)))
1966 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1976 /* If we were called as SMBffirst with smb_search_id == NULL
1977 and no entries were found then return error and close dirptr
1980 if (numentries
== 0) {
1981 dptr_close(sconn
, &dptr_num
);
1982 } else if(expect_close
&& status_len
== 0) {
1983 /* Close the dptr - we know it's gone */
1984 dptr_close(sconn
, &dptr_num
);
1987 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1988 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1989 dptr_close(sconn
, &dptr_num
);
1992 if ((numentries
== 0) && !mask_contains_wcard
) {
1993 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1997 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1998 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1999 SCVAL(smb_buf(req
->outbuf
),0,5);
2000 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2002 /* The replies here are never long name. */
2003 SSVAL(req
->outbuf
, smb_flg2
,
2004 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2005 if (!allow_long_path_components
) {
2006 SSVAL(req
->outbuf
, smb_flg2
,
2007 SVAL(req
->outbuf
, smb_flg2
)
2008 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2011 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2012 SSVAL(req
->outbuf
, smb_flg2
,
2013 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2015 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2016 smb_fn_name(req
->cmd
),
2023 TALLOC_FREE(directory
);
2025 TALLOC_FREE(smb_fname
);
2026 END_PROFILE(SMBsearch
);
2030 /****************************************************************************
2031 Reply to a fclose (stop directory search).
2032 ****************************************************************************/
2034 void reply_fclose(struct smb_request
*req
)
2042 bool path_contains_wcard
= False
;
2043 TALLOC_CTX
*ctx
= talloc_tos();
2044 struct smbd_server_connection
*sconn
= req
->sconn
;
2046 START_PROFILE(SMBfclose
);
2048 if (req
->posix_pathnames
) {
2049 reply_unknown_new(req
, req
->cmd
);
2050 END_PROFILE(SMBfclose
);
2054 p
= (const char *)req
->buf
+ 1;
2055 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2056 &err
, &path_contains_wcard
);
2057 if (!NT_STATUS_IS_OK(err
)) {
2058 reply_nterror(req
, err
);
2059 END_PROFILE(SMBfclose
);
2063 status_len
= SVAL(p
,0);
2066 if (status_len
== 0) {
2067 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2068 END_PROFILE(SMBfclose
);
2072 memcpy(status
,p
,21);
2074 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2075 /* Close the dptr - we know it's gone */
2076 dptr_close(sconn
, &dptr_num
);
2079 reply_outbuf(req
, 1, 0);
2080 SSVAL(req
->outbuf
,smb_vwv0
,0);
2082 DEBUG(3,("search close\n"));
2084 END_PROFILE(SMBfclose
);
2088 /****************************************************************************
2090 ****************************************************************************/
2092 void reply_open(struct smb_request
*req
)
2094 connection_struct
*conn
= req
->conn
;
2095 struct smb_filename
*smb_fname
= NULL
;
2105 uint32_t access_mask
;
2106 uint32_t share_mode
;
2107 uint32_t create_disposition
;
2108 uint32_t create_options
= 0;
2109 uint32_t private_flags
= 0;
2112 TALLOC_CTX
*ctx
= talloc_tos();
2114 START_PROFILE(SMBopen
);
2117 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2121 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2122 deny_mode
= SVAL(req
->vwv
+0, 0);
2123 dos_attr
= SVAL(req
->vwv
+1, 0);
2125 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2126 STR_TERMINATE
, &status
);
2127 if (!NT_STATUS_IS_OK(status
)) {
2128 reply_nterror(req
, status
);
2132 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2133 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2134 &share_mode
, &create_disposition
,
2135 &create_options
, &private_flags
)) {
2136 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2140 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2142 status
= filename_convert(ctx
,
2148 if (!NT_STATUS_IS_OK(status
)) {
2149 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2150 reply_botherror(req
,
2151 NT_STATUS_PATH_NOT_COVERED
,
2152 ERRSRV
, ERRbadpath
);
2155 reply_nterror(req
, status
);
2159 status
= SMB_VFS_CREATE_FILE(
2162 0, /* root_dir_fid */
2163 smb_fname
, /* fname */
2164 access_mask
, /* access_mask */
2165 share_mode
, /* share_access */
2166 create_disposition
, /* create_disposition*/
2167 create_options
, /* create_options */
2168 dos_attr
, /* file_attributes */
2169 oplock_request
, /* oplock_request */
2171 0, /* allocation_size */
2177 NULL
, NULL
); /* create context */
2179 if (!NT_STATUS_IS_OK(status
)) {
2180 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2181 /* We have re-scheduled this call. */
2184 reply_openerror(req
, status
);
2188 /* Ensure we're pointing at the correct stat struct. */
2189 TALLOC_FREE(smb_fname
);
2190 smb_fname
= fsp
->fsp_name
;
2192 size
= smb_fname
->st
.st_ex_size
;
2193 fattr
= dos_mode(conn
, smb_fname
);
2195 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2197 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2198 DEBUG(3,("attempt to open a directory %s\n",
2200 close_file(req
, fsp
, ERROR_CLOSE
);
2201 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2202 ERRDOS
, ERRnoaccess
);
2206 reply_outbuf(req
, 7, 0);
2207 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2208 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2209 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2210 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2212 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2214 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2215 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2217 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2218 SCVAL(req
->outbuf
,smb_flg
,
2219 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2222 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2223 SCVAL(req
->outbuf
,smb_flg
,
2224 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2227 END_PROFILE(SMBopen
);
2231 /****************************************************************************
2232 Reply to an open and X.
2233 ****************************************************************************/
2235 void reply_open_and_X(struct smb_request
*req
)
2237 connection_struct
*conn
= req
->conn
;
2238 struct smb_filename
*smb_fname
= NULL
;
2240 uint16_t open_flags
;
2243 /* Breakout the oplock request bits so we can set the
2244 reply bits separately. */
2245 int ex_oplock_request
;
2246 int core_oplock_request
;
2249 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2250 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2258 uint64_t allocation_size
;
2259 ssize_t retval
= -1;
2260 uint32_t access_mask
;
2261 uint32_t share_mode
;
2262 uint32_t create_disposition
;
2263 uint32_t create_options
= 0;
2264 uint32_t private_flags
= 0;
2266 TALLOC_CTX
*ctx
= talloc_tos();
2268 START_PROFILE(SMBopenX
);
2270 if (req
->wct
< 15) {
2271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2275 open_flags
= SVAL(req
->vwv
+2, 0);
2276 deny_mode
= SVAL(req
->vwv
+3, 0);
2277 smb_attr
= SVAL(req
->vwv
+5, 0);
2278 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2279 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2280 oplock_request
= ex_oplock_request
| core_oplock_request
;
2281 smb_ofun
= SVAL(req
->vwv
+8, 0);
2282 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2284 /* If it's an IPC, pass off the pipe handler. */
2286 if (lp_nt_pipe_support()) {
2287 reply_open_pipe_and_X(conn
, req
);
2289 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2294 /* XXXX we need to handle passed times, sattr and flags */
2295 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2296 STR_TERMINATE
, &status
);
2297 if (!NT_STATUS_IS_OK(status
)) {
2298 reply_nterror(req
, status
);
2302 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2304 &access_mask
, &share_mode
,
2305 &create_disposition
,
2308 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2312 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2314 status
= filename_convert(ctx
,
2320 if (!NT_STATUS_IS_OK(status
)) {
2321 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2322 reply_botherror(req
,
2323 NT_STATUS_PATH_NOT_COVERED
,
2324 ERRSRV
, ERRbadpath
);
2327 reply_nterror(req
, status
);
2331 status
= SMB_VFS_CREATE_FILE(
2334 0, /* root_dir_fid */
2335 smb_fname
, /* fname */
2336 access_mask
, /* access_mask */
2337 share_mode
, /* share_access */
2338 create_disposition
, /* create_disposition*/
2339 create_options
, /* create_options */
2340 smb_attr
, /* file_attributes */
2341 oplock_request
, /* oplock_request */
2343 0, /* allocation_size */
2348 &smb_action
, /* pinfo */
2349 NULL
, NULL
); /* create context */
2351 if (!NT_STATUS_IS_OK(status
)) {
2352 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2353 /* We have re-scheduled this call. */
2356 reply_openerror(req
, status
);
2360 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2361 if the file is truncated or created. */
2362 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2363 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2364 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2365 close_file(req
, fsp
, ERROR_CLOSE
);
2366 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2369 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2371 close_file(req
, fsp
, ERROR_CLOSE
);
2372 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2375 status
= vfs_stat_fsp(fsp
);
2376 if (!NT_STATUS_IS_OK(status
)) {
2377 close_file(req
, fsp
, ERROR_CLOSE
);
2378 reply_nterror(req
, status
);
2383 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2384 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2385 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2386 close_file(req
, fsp
, ERROR_CLOSE
);
2387 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2391 /* If the caller set the extended oplock request bit
2392 and we granted one (by whatever means) - set the
2393 correct bit for extended oplock reply.
2396 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2397 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2400 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2401 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2404 /* If the caller set the core oplock request bit
2405 and we granted one (by whatever means) - set the
2406 correct bit for core oplock reply.
2409 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2410 reply_outbuf(req
, 19, 0);
2412 reply_outbuf(req
, 15, 0);
2415 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2416 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2418 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2419 SCVAL(req
->outbuf
, smb_flg
,
2420 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2423 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2424 SCVAL(req
->outbuf
, smb_flg
,
2425 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2428 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2429 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2430 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2431 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2433 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2435 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2436 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2437 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2439 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2440 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2444 TALLOC_FREE(smb_fname
);
2445 END_PROFILE(SMBopenX
);
2449 /****************************************************************************
2450 Reply to a SMBulogoffX.
2451 ****************************************************************************/
2453 void reply_ulogoffX(struct smb_request
*req
)
2455 struct smbd_server_connection
*sconn
= req
->sconn
;
2456 struct user_struct
*vuser
;
2457 struct smbXsrv_session
*session
= NULL
;
2460 START_PROFILE(SMBulogoffX
);
2462 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2465 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2466 (unsigned long long)req
->vuid
));
2468 req
->vuid
= UID_FIELD_INVALID
;
2469 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2470 END_PROFILE(SMBulogoffX
);
2474 session
= vuser
->session
;
2478 * TODO: cancel all outstanding requests on the session
2480 status
= smbXsrv_session_logoff(session
);
2481 if (!NT_STATUS_IS_OK(status
)) {
2482 DEBUG(0, ("reply_ulogoff: "
2483 "smbXsrv_session_logoff() failed: %s\n",
2484 nt_errstr(status
)));
2486 * If we hit this case, there is something completely
2487 * wrong, so we better disconnect the transport connection.
2489 END_PROFILE(SMBulogoffX
);
2490 exit_server(__location__
": smbXsrv_session_logoff failed");
2494 TALLOC_FREE(session
);
2496 reply_outbuf(req
, 2, 0);
2497 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2498 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2500 DEBUG(3, ("ulogoffX vuid=%llu\n",
2501 (unsigned long long)req
->vuid
));
2503 END_PROFILE(SMBulogoffX
);
2504 req
->vuid
= UID_FIELD_INVALID
;
2507 /****************************************************************************
2508 Reply to a mknew or a create.
2509 ****************************************************************************/
2511 void reply_mknew(struct smb_request
*req
)
2513 connection_struct
*conn
= req
->conn
;
2514 struct smb_filename
*smb_fname
= NULL
;
2517 struct smb_file_time ft
;
2519 int oplock_request
= 0;
2521 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2522 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2523 uint32_t create_disposition
;
2524 uint32_t create_options
= 0;
2526 TALLOC_CTX
*ctx
= talloc_tos();
2528 START_PROFILE(SMBcreate
);
2532 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2536 fattr
= SVAL(req
->vwv
+0, 0);
2537 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2539 if (req
->cmd
== SMBmknew
) {
2540 /* We should fail if file exists. */
2541 create_disposition
= FILE_CREATE
;
2543 /* Create if file doesn't exist, truncate if it does. */
2544 create_disposition
= FILE_OVERWRITE_IF
;
2548 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2550 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2551 STR_TERMINATE
, &status
);
2552 if (!NT_STATUS_IS_OK(status
)) {
2553 reply_nterror(req
, status
);
2557 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2558 status
= filename_convert(ctx
,
2564 if (!NT_STATUS_IS_OK(status
)) {
2565 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2566 reply_botherror(req
,
2567 NT_STATUS_PATH_NOT_COVERED
,
2568 ERRSRV
, ERRbadpath
);
2571 reply_nterror(req
, status
);
2575 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2576 DEBUG(0,("Attempt to create file (%s) with volid set - "
2577 "please report this\n",
2578 smb_fname_str_dbg(smb_fname
)));
2581 status
= SMB_VFS_CREATE_FILE(
2584 0, /* root_dir_fid */
2585 smb_fname
, /* fname */
2586 access_mask
, /* access_mask */
2587 share_mode
, /* share_access */
2588 create_disposition
, /* create_disposition*/
2589 create_options
, /* create_options */
2590 fattr
, /* file_attributes */
2591 oplock_request
, /* oplock_request */
2593 0, /* allocation_size */
2594 0, /* private_flags */
2599 NULL
, NULL
); /* create context */
2601 if (!NT_STATUS_IS_OK(status
)) {
2602 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2603 /* We have re-scheduled this call. */
2606 reply_openerror(req
, status
);
2610 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2611 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2612 if (!NT_STATUS_IS_OK(status
)) {
2613 END_PROFILE(SMBcreate
);
2617 reply_outbuf(req
, 1, 0);
2618 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2620 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2621 SCVAL(req
->outbuf
,smb_flg
,
2622 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2625 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2626 SCVAL(req
->outbuf
,smb_flg
,
2627 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2630 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2631 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2632 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2633 (unsigned int)fattr
));
2636 TALLOC_FREE(smb_fname
);
2637 END_PROFILE(SMBcreate
);
2641 /****************************************************************************
2642 Reply to a create temporary file.
2643 ****************************************************************************/
2645 void reply_ctemp(struct smb_request
*req
)
2647 connection_struct
*conn
= req
->conn
;
2648 struct smb_filename
*smb_fname
= NULL
;
2649 char *wire_name
= NULL
;
2658 TALLOC_CTX
*ctx
= talloc_tos();
2660 START_PROFILE(SMBctemp
);
2663 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2667 fattr
= SVAL(req
->vwv
+0, 0);
2668 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2670 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2671 STR_TERMINATE
, &status
);
2672 if (!NT_STATUS_IS_OK(status
)) {
2673 reply_nterror(req
, status
);
2677 for (i
= 0; i
< 10; i
++) {
2679 fname
= talloc_asprintf(ctx
,
2682 generate_random_str_list(ctx
, 5, "0123456789"));
2684 fname
= talloc_asprintf(ctx
,
2686 generate_random_str_list(ctx
, 5, "0123456789"));
2690 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2694 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2695 status
= filename_convert(ctx
, conn
,
2700 if (!NT_STATUS_IS_OK(status
)) {
2701 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2702 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2703 ERRSRV
, ERRbadpath
);
2706 reply_nterror(req
, status
);
2710 /* Create the file. */
2711 status
= SMB_VFS_CREATE_FILE(
2714 0, /* root_dir_fid */
2715 smb_fname
, /* fname */
2716 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2717 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2718 FILE_CREATE
, /* create_disposition*/
2719 0, /* create_options */
2720 fattr
, /* file_attributes */
2721 oplock_request
, /* oplock_request */
2723 0, /* allocation_size */
2724 0, /* private_flags */
2729 NULL
, NULL
); /* create context */
2731 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2733 TALLOC_FREE(smb_fname
);
2737 if (!NT_STATUS_IS_OK(status
)) {
2738 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2739 /* We have re-scheduled this call. */
2742 reply_openerror(req
, status
);
2750 /* Collision after 10 times... */
2751 reply_nterror(req
, status
);
2755 reply_outbuf(req
, 1, 0);
2756 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2758 /* the returned filename is relative to the directory */
2759 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2761 s
= fsp
->fsp_name
->base_name
;
2767 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2768 thing in the byte section. JRA */
2769 SSVALS(p
, 0, -1); /* what is this? not in spec */
2771 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2773 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2777 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2778 SCVAL(req
->outbuf
, smb_flg
,
2779 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2782 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2783 SCVAL(req
->outbuf
, smb_flg
,
2784 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2787 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2788 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2789 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2791 TALLOC_FREE(smb_fname
);
2792 TALLOC_FREE(wire_name
);
2793 END_PROFILE(SMBctemp
);
2797 /*******************************************************************
2798 Check if a user is allowed to rename a file.
2799 ********************************************************************/
2801 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2804 if (!CAN_WRITE(conn
)) {
2805 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2808 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2809 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2810 /* Only bother to read the DOS attribute if we might deny the
2811 rename on the grounds of attribute mismatch. */
2812 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2813 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2814 return NT_STATUS_NO_SUCH_FILE
;
2818 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2819 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2820 return NT_STATUS_OK
;
2823 /* If no pathnames are open below this
2824 directory, allow the rename. */
2826 if (lp_strict_rename(SNUM(conn
))) {
2828 * Strict rename, check open file db.
2830 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2831 return NT_STATUS_ACCESS_DENIED
;
2833 } else if (file_find_subpath(fsp
)) {
2835 * No strict rename, just look in local process.
2837 return NT_STATUS_ACCESS_DENIED
;
2839 return NT_STATUS_OK
;
2842 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2843 return NT_STATUS_OK
;
2846 return NT_STATUS_ACCESS_DENIED
;
2849 /*******************************************************************
2850 * unlink a file with all relevant access checks
2851 *******************************************************************/
2853 static NTSTATUS
do_unlink(connection_struct
*conn
,
2854 struct smb_request
*req
,
2855 struct smb_filename
*smb_fname
,
2860 uint32_t dirtype_orig
= dirtype
;
2863 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2865 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2866 smb_fname_str_dbg(smb_fname
),
2869 if (!CAN_WRITE(conn
)) {
2870 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2874 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2876 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2879 return map_nt_error_from_unix(errno
);
2882 fattr
= dos_mode(conn
, smb_fname
);
2884 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2885 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2888 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2890 return NT_STATUS_NO_SUCH_FILE
;
2893 if (!dir_check_ftype(fattr
, dirtype
)) {
2894 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2895 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2897 return NT_STATUS_NO_SUCH_FILE
;
2900 if (dirtype_orig
& 0x8000) {
2901 /* These will never be set for POSIX. */
2902 return NT_STATUS_NO_SUCH_FILE
;
2906 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2907 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2910 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2911 return NT_STATUS_NO_SUCH_FILE
;
2914 if (dirtype
& 0xFF00) {
2915 /* These will never be set for POSIX. */
2916 return NT_STATUS_NO_SUCH_FILE
;
2921 return NT_STATUS_NO_SUCH_FILE
;
2924 /* Can't delete a directory. */
2925 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2926 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2931 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2932 return NT_STATUS_OBJECT_NAME_INVALID
;
2933 #endif /* JRATEST */
2935 /* On open checks the open itself will check the share mode, so
2936 don't do it here as we'll get it wrong. */
2938 status
= SMB_VFS_CREATE_FILE
2941 0, /* root_dir_fid */
2942 smb_fname
, /* fname */
2943 DELETE_ACCESS
, /* access_mask */
2944 FILE_SHARE_NONE
, /* share_access */
2945 FILE_OPEN
, /* create_disposition*/
2946 FILE_NON_DIRECTORY_FILE
, /* create_options */
2947 /* file_attributes */
2948 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2949 FILE_ATTRIBUTE_NORMAL
,
2950 0, /* oplock_request */
2952 0, /* allocation_size */
2953 0, /* private_flags */
2958 NULL
, NULL
); /* create context */
2960 if (!NT_STATUS_IS_OK(status
)) {
2961 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2962 nt_errstr(status
)));
2966 status
= can_set_delete_on_close(fsp
, fattr
);
2967 if (!NT_STATUS_IS_OK(status
)) {
2968 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2970 smb_fname_str_dbg(smb_fname
),
2971 nt_errstr(status
)));
2972 close_file(req
, fsp
, NORMAL_CLOSE
);
2976 /* The set is across all open files on this dev/inode pair. */
2977 if (!set_delete_on_close(fsp
, True
,
2978 conn
->session_info
->security_token
,
2979 conn
->session_info
->unix_token
)) {
2980 close_file(req
, fsp
, NORMAL_CLOSE
);
2981 return NT_STATUS_ACCESS_DENIED
;
2984 return close_file(req
, fsp
, NORMAL_CLOSE
);
2987 /****************************************************************************
2988 The guts of the unlink command, split out so it may be called by the NT SMB
2990 ****************************************************************************/
2992 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2993 uint32_t dirtype
, struct smb_filename
*smb_fname
,
2996 char *fname_dir
= NULL
;
2997 char *fname_mask
= NULL
;
2999 NTSTATUS status
= NT_STATUS_OK
;
3000 struct smb_filename
*smb_fname_dir
= NULL
;
3001 TALLOC_CTX
*ctx
= talloc_tos();
3003 /* Split up the directory from the filename/mask. */
3004 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3005 &fname_dir
, &fname_mask
);
3006 if (!NT_STATUS_IS_OK(status
)) {
3011 * We should only check the mangled cache
3012 * here if unix_convert failed. This means
3013 * that the path in 'mask' doesn't exist
3014 * on the file system and so we need to look
3015 * for a possible mangle. This patch from
3016 * Tine Smukavec <valentin.smukavec@hermes.si>.
3019 if (!VALID_STAT(smb_fname
->st
) &&
3020 mangle_is_mangled(fname_mask
, conn
->params
)) {
3021 char *new_mask
= NULL
;
3022 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3023 &new_mask
, conn
->params
);
3025 TALLOC_FREE(fname_mask
);
3026 fname_mask
= new_mask
;
3033 * Only one file needs to be unlinked. Append the mask back
3034 * onto the directory.
3036 TALLOC_FREE(smb_fname
->base_name
);
3037 if (ISDOT(fname_dir
)) {
3038 /* Ensure we use canonical names on open. */
3039 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3043 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3048 if (!smb_fname
->base_name
) {
3049 status
= NT_STATUS_NO_MEMORY
;
3053 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3056 status
= check_name(conn
, smb_fname
);
3057 if (!NT_STATUS_IS_OK(status
)) {
3061 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3062 if (!NT_STATUS_IS_OK(status
)) {
3068 struct smb_Dir
*dir_hnd
= NULL
;
3070 const char *dname
= NULL
;
3071 char *talloced
= NULL
;
3073 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3074 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3078 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3081 if (strequal(fname_mask
,"????????.???")) {
3082 TALLOC_FREE(fname_mask
);
3083 fname_mask
= talloc_strdup(ctx
, "*");
3085 status
= NT_STATUS_NO_MEMORY
;
3090 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3095 if (smb_fname_dir
== NULL
) {
3096 status
= NT_STATUS_NO_MEMORY
;
3100 status
= check_name(conn
, smb_fname_dir
);
3101 if (!NT_STATUS_IS_OK(status
)) {
3105 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3107 if (dir_hnd
== NULL
) {
3108 status
= map_nt_error_from_unix(errno
);
3112 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3113 the pattern matches against the long name, otherwise the short name
3114 We don't implement this yet XXXX
3117 status
= NT_STATUS_NO_SUCH_FILE
;
3119 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3120 &smb_fname
->st
, &talloced
))) {
3121 TALLOC_CTX
*frame
= talloc_stackframe();
3123 if (!is_visible_file(conn
, fname_dir
, dname
,
3124 &smb_fname
->st
, true)) {
3126 TALLOC_FREE(talloced
);
3130 /* Quick check for "." and ".." */
3131 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3133 TALLOC_FREE(talloced
);
3137 if(!mask_match(dname
, fname_mask
,
3138 conn
->case_sensitive
)) {
3140 TALLOC_FREE(talloced
);
3144 TALLOC_FREE(smb_fname
->base_name
);
3145 if (ISDOT(fname_dir
)) {
3146 /* Ensure we use canonical names on open. */
3147 smb_fname
->base_name
=
3148 talloc_asprintf(smb_fname
, "%s",
3151 smb_fname
->base_name
=
3152 talloc_asprintf(smb_fname
, "%s/%s",
3156 if (!smb_fname
->base_name
) {
3157 TALLOC_FREE(dir_hnd
);
3158 status
= NT_STATUS_NO_MEMORY
;
3160 TALLOC_FREE(talloced
);
3164 status
= check_name(conn
, smb_fname
);
3165 if (!NT_STATUS_IS_OK(status
)) {
3166 TALLOC_FREE(dir_hnd
);
3168 TALLOC_FREE(talloced
);
3172 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3173 if (!NT_STATUS_IS_OK(status
)) {
3174 TALLOC_FREE(dir_hnd
);
3176 TALLOC_FREE(talloced
);
3181 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3182 smb_fname
->base_name
));
3185 TALLOC_FREE(talloced
);
3187 TALLOC_FREE(dir_hnd
);
3190 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3191 status
= map_nt_error_from_unix(errno
);
3195 TALLOC_FREE(smb_fname_dir
);
3196 TALLOC_FREE(fname_dir
);
3197 TALLOC_FREE(fname_mask
);
3201 /****************************************************************************
3203 ****************************************************************************/
3205 void reply_unlink(struct smb_request
*req
)
3207 connection_struct
*conn
= req
->conn
;
3209 struct smb_filename
*smb_fname
= NULL
;
3212 bool path_contains_wcard
= False
;
3213 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3214 ucf_flags_from_smb_request(req
);
3215 TALLOC_CTX
*ctx
= talloc_tos();
3217 START_PROFILE(SMBunlink
);
3220 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3224 dirtype
= SVAL(req
->vwv
+0, 0);
3226 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3227 STR_TERMINATE
, &status
,
3228 &path_contains_wcard
);
3229 if (!NT_STATUS_IS_OK(status
)) {
3230 reply_nterror(req
, status
);
3234 status
= filename_convert(ctx
, conn
,
3237 &path_contains_wcard
,
3239 if (!NT_STATUS_IS_OK(status
)) {
3240 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3241 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3242 ERRSRV
, ERRbadpath
);
3245 reply_nterror(req
, status
);
3249 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3251 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3252 path_contains_wcard
);
3253 if (!NT_STATUS_IS_OK(status
)) {
3254 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3255 /* We have re-scheduled this call. */
3258 reply_nterror(req
, status
);
3262 reply_outbuf(req
, 0, 0);
3264 TALLOC_FREE(smb_fname
);
3265 END_PROFILE(SMBunlink
);
3269 /****************************************************************************
3271 ****************************************************************************/
3273 static void fail_readraw(void)
3275 const char *errstr
= talloc_asprintf(talloc_tos(),
3276 "FAIL ! reply_readbraw: socket write fail (%s)",
3281 exit_server_cleanly(errstr
);
3284 /****************************************************************************
3285 Fake (read/write) sendfile. Returns -1 on read or write fail.
3286 ****************************************************************************/
3288 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3289 off_t startpos
, size_t nread
)
3292 size_t tosend
= nread
;
3299 bufsize
= MIN(nread
, 65536);
3301 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3305 while (tosend
> 0) {
3309 cur_read
= MIN(tosend
, bufsize
);
3310 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3316 /* If we had a short read, fill with zeros. */
3317 if (ret
< cur_read
) {
3318 memset(buf
+ ret
, '\0', cur_read
- ret
);
3321 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3322 if (ret
!= cur_read
) {
3323 int saved_errno
= errno
;
3325 * Try and give an error message saying what
3328 DEBUG(0, ("write_data failed for client %s. "
3330 smbXsrv_connection_dbg(xconn
),
3331 strerror(saved_errno
)));
3333 errno
= saved_errno
;
3337 startpos
+= cur_read
;
3341 return (ssize_t
)nread
;
3344 /****************************************************************************
3345 Deal with the case of sendfile reading less bytes from the file than
3346 requested. Fill with zeros (all we can do). Returns 0 on success
3347 ****************************************************************************/
3349 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3355 #define SHORT_SEND_BUFSIZE 1024
3356 if (nread
< headersize
) {
3357 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3358 "header for file %s (%s). Terminating\n",
3359 fsp_str_dbg(fsp
), strerror(errno
)));
3363 nread
-= headersize
;
3365 if (nread
< smb_maxcnt
) {
3366 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3368 DEBUG(0,("sendfile_short_send: malloc failed "
3369 "for file %s (%s). Terminating\n",
3370 fsp_str_dbg(fsp
), strerror(errno
)));
3374 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3375 "with zeros !\n", fsp_str_dbg(fsp
)));
3377 while (nread
< smb_maxcnt
) {
3379 * We asked for the real file size and told sendfile
3380 * to not go beyond the end of the file. But it can
3381 * happen that in between our fstat call and the
3382 * sendfile call the file was truncated. This is very
3383 * bad because we have already announced the larger
3384 * number of bytes to the client.
3386 * The best we can do now is to send 0-bytes, just as
3387 * a read from a hole in a sparse file would do.
3389 * This should happen rarely enough that I don't care
3390 * about efficiency here :-)
3395 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3396 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3397 if (ret
!= to_write
) {
3398 int saved_errno
= errno
;
3400 * Try and give an error message saying what
3403 DEBUG(0, ("write_data failed for client %s. "
3405 smbXsrv_connection_dbg(xconn
),
3406 strerror(saved_errno
)));
3407 errno
= saved_errno
;
3418 /****************************************************************************
3419 Return a readbraw error (4 bytes of zero).
3420 ****************************************************************************/
3422 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3428 smbd_lock_socket(xconn
);
3429 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3430 int saved_errno
= errno
;
3432 * Try and give an error message saying what
3435 DEBUG(0, ("write_data failed for client %s. "
3437 smbXsrv_connection_dbg(xconn
),
3438 strerror(saved_errno
)));
3439 errno
= saved_errno
;
3443 smbd_unlock_socket(xconn
);
3446 /****************************************************************************
3447 Use sendfile in readbraw.
3448 ****************************************************************************/
3450 static void send_file_readbraw(connection_struct
*conn
,
3451 struct smb_request
*req
,
3457 struct smbXsrv_connection
*xconn
= req
->xconn
;
3458 char *outbuf
= NULL
;
3462 * We can only use sendfile on a non-chained packet
3463 * but we can use on a non-oplocked file. tridge proved this
3464 * on a train in Germany :-). JRA.
3465 * reply_readbraw has already checked the length.
3468 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3469 (fsp
->wcp
== NULL
) &&
3470 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3471 ssize_t sendfile_read
= -1;
3473 DATA_BLOB header_blob
;
3475 _smb_setlen(header
,nread
);
3476 header_blob
= data_blob_const(header
, 4);
3478 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3479 &header_blob
, startpos
,
3481 if (sendfile_read
== -1) {
3482 /* Returning ENOSYS means no data at all was sent.
3483 * Do this as a normal read. */
3484 if (errno
== ENOSYS
) {
3485 goto normal_readbraw
;
3489 * Special hack for broken Linux with no working sendfile. If we
3490 * return EINTR we sent the header but not the rest of the data.
3491 * Fake this up by doing read/write calls.
3493 if (errno
== EINTR
) {
3494 /* Ensure we don't do this again. */
3495 set_use_sendfile(SNUM(conn
), False
);
3496 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3498 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3499 DEBUG(0,("send_file_readbraw: "
3500 "fake_sendfile failed for "
3504 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3509 DEBUG(0,("send_file_readbraw: sendfile failed for "
3510 "file %s (%s). Terminating\n",
3511 fsp_str_dbg(fsp
), strerror(errno
)));
3512 exit_server_cleanly("send_file_readbraw sendfile failed");
3513 } else if (sendfile_read
== 0) {
3515 * Some sendfile implementations return 0 to indicate
3516 * that there was a short read, but nothing was
3517 * actually written to the socket. In this case,
3518 * fallback to the normal read path so the header gets
3519 * the correct byte count.
3521 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3522 "bytes falling back to the normal read: "
3523 "%s\n", fsp_str_dbg(fsp
)));
3524 goto normal_readbraw
;
3527 /* Deal with possible short send. */
3528 if (sendfile_read
!= 4+nread
) {
3529 ret
= sendfile_short_send(xconn
, fsp
,
3530 sendfile_read
, 4, nread
);
3540 outbuf
= talloc_array(NULL
, char, nread
+4);
3542 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3543 (unsigned)(nread
+4)));
3544 reply_readbraw_error(xconn
);
3549 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3550 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3559 _smb_setlen(outbuf
,ret
);
3560 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3561 int saved_errno
= errno
;
3563 * Try and give an error message saying what
3566 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3567 smbXsrv_connection_dbg(xconn
),
3568 strerror(saved_errno
)));
3569 errno
= saved_errno
;
3574 TALLOC_FREE(outbuf
);
3577 /****************************************************************************
3578 Reply to a readbraw (core+ protocol).
3579 ****************************************************************************/
3581 void reply_readbraw(struct smb_request
*req
)
3583 connection_struct
*conn
= req
->conn
;
3584 struct smbXsrv_connection
*xconn
= req
->xconn
;
3585 ssize_t maxcount
,mincount
;
3589 struct lock_struct lock
;
3592 START_PROFILE(SMBreadbraw
);
3594 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3595 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3596 "raw reads/writes are disallowed.");
3600 reply_readbraw_error(xconn
);
3601 END_PROFILE(SMBreadbraw
);
3605 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3606 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3607 "'async smb echo handler = yes'\n"));
3608 reply_readbraw_error(xconn
);
3609 END_PROFILE(SMBreadbraw
);
3614 * Special check if an oplock break has been issued
3615 * and the readraw request croses on the wire, we must
3616 * return a zero length response here.
3619 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3622 * We have to do a check_fsp by hand here, as
3623 * we must always return 4 zero bytes on error,
3627 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3628 req
->vuid
!= fsp
->vuid
||
3629 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3631 * fsp could be NULL here so use the value from the packet. JRA.
3633 DEBUG(3,("reply_readbraw: fnum %d not valid "
3635 (int)SVAL(req
->vwv
+0, 0)));
3636 reply_readbraw_error(xconn
);
3637 END_PROFILE(SMBreadbraw
);
3641 /* Do a "by hand" version of CHECK_READ. */
3642 if (!(fsp
->can_read
||
3643 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3644 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3645 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3646 (int)SVAL(req
->vwv
+0, 0)));
3647 reply_readbraw_error(xconn
);
3648 END_PROFILE(SMBreadbraw
);
3652 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3654 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3655 if(req
->wct
== 10) {
3657 * This is a large offset (64 bit) read.
3660 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3663 DEBUG(0,("reply_readbraw: negative 64 bit "
3664 "readraw offset (%.0f) !\n",
3665 (double)startpos
));
3666 reply_readbraw_error(xconn
);
3667 END_PROFILE(SMBreadbraw
);
3672 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3673 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3675 /* ensure we don't overrun the packet size */
3676 maxcount
= MIN(65535,maxcount
);
3678 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3679 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3682 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3683 reply_readbraw_error(xconn
);
3684 END_PROFILE(SMBreadbraw
);
3688 if (fsp_stat(fsp
) == 0) {
3689 size
= fsp
->fsp_name
->st
.st_ex_size
;
3692 if (startpos
>= size
) {
3695 nread
= MIN(maxcount
,(size
- startpos
));
3698 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3699 if (nread
< mincount
)
3703 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3704 "min=%lu nread=%lu\n",
3705 fsp_fnum_dbg(fsp
), (double)startpos
,
3706 (unsigned long)maxcount
,
3707 (unsigned long)mincount
,
3708 (unsigned long)nread
) );
3710 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3712 DEBUG(5,("reply_readbraw finished\n"));
3714 END_PROFILE(SMBreadbraw
);
3719 #define DBGC_CLASS DBGC_LOCKING
3721 /****************************************************************************
3722 Reply to a lockread (core+ protocol).
3723 ****************************************************************************/
3725 void reply_lockread(struct smb_request
*req
)
3727 connection_struct
*conn
= req
->conn
;
3735 struct byte_range_lock
*br_lck
= NULL
;
3737 struct smbXsrv_connection
*xconn
= req
->xconn
;
3739 START_PROFILE(SMBlockread
);
3742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3743 END_PROFILE(SMBlockread
);
3747 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3749 if (!check_fsp(conn
, req
, fsp
)) {
3750 END_PROFILE(SMBlockread
);
3754 if (!CHECK_READ(fsp
,req
)) {
3755 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3756 END_PROFILE(SMBlockread
);
3760 numtoread
= SVAL(req
->vwv
+1, 0);
3761 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3764 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3765 * protocol request that predates the read/write lock concept.
3766 * Thus instead of asking for a read lock here we need to ask
3767 * for a write lock. JRA.
3768 * Note that the requested lock size is unaffected by max_send.
3771 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3773 (uint64_t)req
->smbpid
,
3774 (uint64_t)numtoread
,
3778 False
, /* Non-blocking lock. */
3781 TALLOC_FREE(br_lck
);
3783 if (NT_STATUS_V(status
)) {
3784 reply_nterror(req
, status
);
3785 END_PROFILE(SMBlockread
);
3790 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3792 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3794 if (numtoread
> maxtoread
) {
3795 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3796 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3797 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3798 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3799 numtoread
= maxtoread
;
3802 reply_outbuf(req
, 5, numtoread
+ 3);
3804 data
= smb_buf(req
->outbuf
) + 3;
3806 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3809 reply_nterror(req
, map_nt_error_from_unix(errno
));
3810 END_PROFILE(SMBlockread
);
3814 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3816 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3817 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3818 p
= smb_buf(req
->outbuf
);
3819 SCVAL(p
,0,0); /* pad byte. */
3822 DEBUG(3,("lockread %s num=%d nread=%d\n",
3823 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3825 END_PROFILE(SMBlockread
);
3830 #define DBGC_CLASS DBGC_ALL
3832 /****************************************************************************
3834 ****************************************************************************/
3836 void reply_read(struct smb_request
*req
)
3838 connection_struct
*conn
= req
->conn
;
3845 struct lock_struct lock
;
3846 struct smbXsrv_connection
*xconn
= req
->xconn
;
3848 START_PROFILE(SMBread
);
3851 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3852 END_PROFILE(SMBread
);
3856 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3858 if (!check_fsp(conn
, req
, fsp
)) {
3859 END_PROFILE(SMBread
);
3863 if (!CHECK_READ(fsp
,req
)) {
3864 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3865 END_PROFILE(SMBread
);
3869 numtoread
= SVAL(req
->vwv
+1, 0);
3870 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3873 * The requested read size cannot be greater than max_send. JRA.
3875 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3877 if (numtoread
> maxtoread
) {
3878 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3879 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3880 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3881 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3882 numtoread
= maxtoread
;
3885 reply_outbuf(req
, 5, numtoread
+3);
3887 data
= smb_buf(req
->outbuf
) + 3;
3889 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3890 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3893 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3894 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3895 END_PROFILE(SMBread
);
3900 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3903 reply_nterror(req
, map_nt_error_from_unix(errno
));
3907 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3909 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3910 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3911 SCVAL(smb_buf(req
->outbuf
),0,1);
3912 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3914 DEBUG(3, ("read %s num=%d nread=%d\n",
3915 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3918 END_PROFILE(SMBread
);
3922 /****************************************************************************
3924 ****************************************************************************/
3926 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3930 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3933 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3935 SCVAL(outbuf
,smb_vwv0
,0xFF);
3936 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3937 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3938 SSVAL(outbuf
,smb_vwv6
,
3939 (smb_wct
- 4) /* offset from smb header to wct */
3940 + 1 /* the wct field */
3941 + 12 * sizeof(uint16_t) /* vwv */
3942 + 2 /* the buflen field */
3943 + 1); /* padding byte */
3944 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3945 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3946 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3947 _smb_setlen_large(outbuf
,
3948 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3952 /****************************************************************************
3953 Reply to a read and X - possibly using sendfile.
3954 ****************************************************************************/
3956 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3957 files_struct
*fsp
, off_t startpos
,
3960 struct smbXsrv_connection
*xconn
= req
->xconn
;
3962 struct lock_struct lock
;
3963 int saved_errno
= 0;
3965 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3966 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3969 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3970 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3975 * We can only use sendfile on a non-chained packet
3976 * but we can use on a non-oplocked file. tridge proved this
3977 * on a train in Germany :-). JRA.
3980 if (!req_is_in_chain(req
) &&
3982 (fsp
->base_fsp
== NULL
) &&
3983 (fsp
->wcp
== NULL
) &&
3984 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3985 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3988 if(fsp_stat(fsp
) == -1) {
3989 reply_nterror(req
, map_nt_error_from_unix(errno
));
3993 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3994 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3995 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3997 * We already know that we would do a short read, so don't
3998 * try the sendfile() path.
4000 goto nosendfile_read
;
4004 * Set up the packet header before send. We
4005 * assume here the sendfile will work (get the
4006 * correct amount of data).
4009 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4011 construct_reply_common_req(req
, (char *)headerbuf
);
4012 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4014 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4015 startpos
, smb_maxcnt
);
4017 saved_errno
= errno
;
4019 /* Returning ENOSYS means no data at all was sent.
4020 Do this as a normal read. */
4021 if (errno
== ENOSYS
) {
4026 * Special hack for broken Linux with no working sendfile. If we
4027 * return EINTR we sent the header but not the rest of the data.
4028 * Fake this up by doing read/write calls.
4031 if (errno
== EINTR
) {
4032 /* Ensure we don't do this again. */
4033 set_use_sendfile(SNUM(conn
), False
);
4034 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4035 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4038 saved_errno
= errno
;
4039 DEBUG(0,("send_file_readX: "
4040 "fake_sendfile failed for "
4041 "file %s (%s) for client %s. "
4044 smbXsrv_connection_dbg(xconn
),
4045 strerror(saved_errno
)));
4046 errno
= saved_errno
;
4047 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4049 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4050 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4051 /* No outbuf here means successful sendfile. */
4055 DEBUG(0,("send_file_readX: sendfile failed for file "
4056 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4058 exit_server_cleanly("send_file_readX sendfile failed");
4059 } else if (nread
== 0) {
4061 * Some sendfile implementations return 0 to indicate
4062 * that there was a short read, but nothing was
4063 * actually written to the socket. In this case,
4064 * fallback to the normal read path so the header gets
4065 * the correct byte count.
4067 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4068 "falling back to the normal read: %s\n",
4073 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4074 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4076 /* Deal with possible short send. */
4077 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4080 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4081 sizeof(headerbuf
), smb_maxcnt
);
4084 r
= "send_file_readX: sendfile_short_send failed";
4085 DEBUG(0,("%s for file %s (%s).\n",
4086 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4087 exit_server_cleanly(r
);
4090 /* No outbuf here means successful sendfile. */
4091 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4092 SMB_PERFCOUNT_END(&req
->pcd
);
4098 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4099 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4102 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4103 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4104 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4106 * We already know that we would do a short
4107 * read, so don't try the sendfile() path.
4109 goto nosendfile_read
;
4112 construct_reply_common_req(req
, (char *)headerbuf
);
4113 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4115 /* Send out the header. */
4116 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4118 if (ret
!= sizeof(headerbuf
)) {
4119 saved_errno
= errno
;
4121 * Try and give an error message saying what
4124 DEBUG(0,("send_file_readX: write_data failed for file "
4125 "%s (%s) for client %s. Terminating\n",
4127 smbXsrv_connection_dbg(xconn
),
4128 strerror(saved_errno
)));
4129 errno
= saved_errno
;
4130 exit_server_cleanly("send_file_readX sendfile failed");
4132 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4134 saved_errno
= errno
;
4135 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4136 "%s (%s) for client %s. Terminating\n",
4138 smbXsrv_connection_dbg(xconn
),
4139 strerror(saved_errno
)));
4140 errno
= saved_errno
;
4141 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4148 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4149 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4150 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4152 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4153 startpos
, smb_maxcnt
);
4154 saved_errno
= errno
;
4157 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4161 setup_readX_header((char *)req
->outbuf
, nread
);
4163 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4164 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4168 TALLOC_FREE(req
->outbuf
);
4172 /****************************************************************************
4173 Work out how much space we have for a read return.
4174 ****************************************************************************/
4176 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4178 struct smbXsrv_connection
*xconn
= req
->xconn
;
4180 if (xconn
->protocol
< PROTOCOL_NT1
) {
4181 return xconn
->smb1
.sessions
.max_send
;
4184 if (!lp_large_readwrite()) {
4185 return xconn
->smb1
.sessions
.max_send
;
4188 if (req_is_in_chain(req
)) {
4189 return xconn
->smb1
.sessions
.max_send
;
4192 if (req
->encrypted
) {
4194 * Don't take encrypted traffic up to the
4195 * limit. There are padding considerations
4196 * that make that tricky.
4198 return xconn
->smb1
.sessions
.max_send
;
4201 if (srv_is_signing_active(xconn
)) {
4205 if (!lp_unix_extensions()) {
4210 * We can do ultra-large POSIX reads.
4215 /****************************************************************************
4216 Calculate how big a read can be. Copes with all clients. It's always
4217 safe to return a short read - Windows does this.
4218 ****************************************************************************/
4220 static size_t calc_read_size(const struct smb_request
*req
,
4224 struct smbXsrv_connection
*xconn
= req
->xconn
;
4225 size_t max_pdu
= calc_max_read_pdu(req
);
4226 size_t total_size
= 0;
4227 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4228 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4231 * Windows explicitly ignores upper size of 0xFFFF.
4232 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4233 * We must do the same as these will never fit even in
4234 * an extended size NetBIOS packet.
4236 if (upper_size
== 0xFFFF) {
4240 if (xconn
->protocol
< PROTOCOL_NT1
) {
4244 total_size
= ((upper_size
<<16) | lower_size
);
4247 * LARGE_READX test shows it's always safe to return
4248 * a short read. Windows does so.
4250 return MIN(total_size
, max_len
);
4253 /****************************************************************************
4254 Reply to a read and X.
4255 ****************************************************************************/
4257 void reply_read_and_X(struct smb_request
*req
)
4259 connection_struct
*conn
= req
->conn
;
4264 bool big_readX
= False
;
4266 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4269 START_PROFILE(SMBreadX
);
4271 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4272 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4276 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4277 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4278 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4280 /* If it's an IPC, pass off the pipe handler. */
4282 reply_pipe_read_and_X(req
);
4283 END_PROFILE(SMBreadX
);
4287 if (!check_fsp(conn
, req
, fsp
)) {
4288 END_PROFILE(SMBreadX
);
4292 if (!CHECK_READ(fsp
,req
)) {
4293 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4294 END_PROFILE(SMBreadX
);
4298 upper_size
= SVAL(req
->vwv
+7, 0);
4299 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4300 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4302 * This is a heuristic to avoid keeping large
4303 * outgoing buffers around over long-lived aio
4309 if (req
->wct
== 12) {
4311 * This is a large offset (64 bit) read.
4313 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4318 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4323 if (NT_STATUS_IS_OK(status
)) {
4324 /* Read scheduled - we're done. */
4327 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4328 /* Real error - report to client. */
4329 END_PROFILE(SMBreadX
);
4330 reply_nterror(req
, status
);
4333 /* NT_STATUS_RETRY - fall back to sync read. */
4336 smbd_lock_socket(req
->xconn
);
4337 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4338 smbd_unlock_socket(req
->xconn
);
4341 END_PROFILE(SMBreadX
);
4345 /****************************************************************************
4346 Error replies to writebraw must have smb_wct == 1. Fix this up.
4347 ****************************************************************************/
4349 void error_to_writebrawerr(struct smb_request
*req
)
4351 uint8_t *old_outbuf
= req
->outbuf
;
4353 reply_outbuf(req
, 1, 0);
4355 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4356 TALLOC_FREE(old_outbuf
);
4359 /****************************************************************************
4360 Read 4 bytes of a smb packet and return the smb length of the packet.
4361 Store the result in the buffer. This version of the function will
4362 never return a session keepalive (length of zero).
4363 Timeout is in milliseconds.
4364 ****************************************************************************/
4366 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4369 uint8_t msgtype
= NBSSkeepalive
;
4371 while (msgtype
== NBSSkeepalive
) {
4374 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4376 if (!NT_STATUS_IS_OK(status
)) {
4377 char addr
[INET6_ADDRSTRLEN
];
4378 /* Try and give an error message
4379 * saying what client failed. */
4380 DEBUG(0, ("read_fd_with_timeout failed for "
4381 "client %s read error = %s.\n",
4382 get_peer_addr(fd
,addr
,sizeof(addr
)),
4383 nt_errstr(status
)));
4387 msgtype
= CVAL(inbuf
, 0);
4390 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4391 (unsigned long)len
));
4393 return NT_STATUS_OK
;
4396 /****************************************************************************
4397 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4398 ****************************************************************************/
4400 void reply_writebraw(struct smb_request
*req
)
4402 connection_struct
*conn
= req
->conn
;
4403 struct smbXsrv_connection
*xconn
= req
->xconn
;
4406 ssize_t total_written
=0;
4407 size_t numtowrite
=0;
4410 const char *data
=NULL
;
4413 struct lock_struct lock
;
4416 START_PROFILE(SMBwritebraw
);
4419 * If we ever reply with an error, it must have the SMB command
4420 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4423 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4425 if (srv_is_signing_active(xconn
)) {
4426 END_PROFILE(SMBwritebraw
);
4427 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4428 "raw reads/writes are disallowed.");
4431 if (req
->wct
< 12) {
4432 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4433 error_to_writebrawerr(req
);
4434 END_PROFILE(SMBwritebraw
);
4438 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4439 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4440 "'async smb echo handler = yes'\n"));
4441 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4442 error_to_writebrawerr(req
);
4443 END_PROFILE(SMBwritebraw
);
4447 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4448 if (!check_fsp(conn
, req
, fsp
)) {
4449 error_to_writebrawerr(req
);
4450 END_PROFILE(SMBwritebraw
);
4454 if (!CHECK_WRITE(fsp
)) {
4455 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4456 error_to_writebrawerr(req
);
4457 END_PROFILE(SMBwritebraw
);
4461 tcount
= IVAL(req
->vwv
+1, 0);
4462 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4463 write_through
= BITSETW(req
->vwv
+7,0);
4465 /* We have to deal with slightly different formats depending
4466 on whether we are using the core+ or lanman1.0 protocol */
4468 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4469 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4470 data
= smb_buf_const(req
->inbuf
);
4472 numtowrite
= SVAL(req
->vwv
+10, 0);
4473 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4476 /* Ensure we don't write bytes past the end of this packet. */
4477 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4478 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4479 error_to_writebrawerr(req
);
4480 END_PROFILE(SMBwritebraw
);
4484 if (!fsp
->print_file
) {
4485 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4486 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4489 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4490 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4491 error_to_writebrawerr(req
);
4492 END_PROFILE(SMBwritebraw
);
4498 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4501 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4502 "wrote=%d sync=%d\n",
4503 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4504 (int)nwritten
, (int)write_through
));
4506 if (nwritten
< (ssize_t
)numtowrite
) {
4507 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4508 error_to_writebrawerr(req
);
4512 total_written
= nwritten
;
4514 /* Allocate a buffer of 64k + length. */
4515 buf
= talloc_array(NULL
, char, 65540);
4517 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4518 error_to_writebrawerr(req
);
4522 /* Return a SMBwritebraw message to the redirector to tell
4523 * it to send more bytes */
4525 memcpy(buf
, req
->inbuf
, smb_size
);
4526 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4527 SCVAL(buf
,smb_com
,SMBwritebraw
);
4528 SSVALS(buf
,smb_vwv0
,0xFFFF);
4530 if (!srv_send_smb(req
->xconn
,
4532 false, 0, /* no signing */
4533 IS_CONN_ENCRYPTED(conn
),
4535 exit_server_cleanly("reply_writebraw: srv_send_smb "
4539 /* Now read the raw data into the buffer and write it */
4540 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4542 if (!NT_STATUS_IS_OK(status
)) {
4543 exit_server_cleanly("secondary writebraw failed");
4546 /* Set up outbuf to return the correct size */
4547 reply_outbuf(req
, 1, 0);
4549 if (numtowrite
!= 0) {
4551 if (numtowrite
> 0xFFFF) {
4552 DEBUG(0,("reply_writebraw: Oversize secondary write "
4553 "raw requested (%u). Terminating\n",
4554 (unsigned int)numtowrite
));
4555 exit_server_cleanly("secondary writebraw failed");
4558 if (tcount
> nwritten
+numtowrite
) {
4559 DEBUG(3,("reply_writebraw: Client overestimated the "
4561 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4564 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4567 if (!NT_STATUS_IS_OK(status
)) {
4568 /* Try and give an error message
4569 * saying what client failed. */
4570 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4571 "raw read failed (%s) for client %s. "
4572 "Terminating\n", nt_errstr(status
),
4573 smbXsrv_connection_dbg(xconn
)));
4574 exit_server_cleanly("secondary writebraw failed");
4577 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4578 if (nwritten
== -1) {
4580 reply_nterror(req
, map_nt_error_from_unix(errno
));
4581 error_to_writebrawerr(req
);
4585 if (nwritten
< (ssize_t
)numtowrite
) {
4586 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4587 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4591 total_written
+= nwritten
;
4596 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4598 status
= sync_file(conn
, fsp
, write_through
);
4599 if (!NT_STATUS_IS_OK(status
)) {
4600 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4601 fsp_str_dbg(fsp
), nt_errstr(status
)));
4602 reply_nterror(req
, status
);
4603 error_to_writebrawerr(req
);
4607 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4609 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4610 (int)total_written
));
4612 /* We won't return a status if write through is not selected - this
4613 * follows what WfWg does */
4614 END_PROFILE(SMBwritebraw
);
4616 if (!write_through
&& total_written
==tcount
) {
4618 #if RABBIT_PELLET_FIX
4620 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4621 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4624 if (!send_keepalive(xconn
->transport
.sock
)) {
4625 exit_server_cleanly("reply_writebraw: send of "
4626 "keepalive failed");
4629 TALLOC_FREE(req
->outbuf
);
4634 END_PROFILE(SMBwritebraw
);
4639 #define DBGC_CLASS DBGC_LOCKING
4641 /****************************************************************************
4642 Reply to a writeunlock (core+).
4643 ****************************************************************************/
4645 void reply_writeunlock(struct smb_request
*req
)
4647 connection_struct
*conn
= req
->conn
;
4648 ssize_t nwritten
= -1;
4652 NTSTATUS status
= NT_STATUS_OK
;
4654 struct lock_struct lock
;
4655 int saved_errno
= 0;
4657 START_PROFILE(SMBwriteunlock
);
4660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4661 END_PROFILE(SMBwriteunlock
);
4665 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4667 if (!check_fsp(conn
, req
, fsp
)) {
4668 END_PROFILE(SMBwriteunlock
);
4672 if (!CHECK_WRITE(fsp
)) {
4673 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4674 END_PROFILE(SMBwriteunlock
);
4678 numtowrite
= SVAL(req
->vwv
+1, 0);
4679 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4680 data
= (const char *)req
->buf
+ 3;
4682 if (!fsp
->print_file
&& numtowrite
> 0) {
4683 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4684 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4687 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4688 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4689 END_PROFILE(SMBwriteunlock
);
4694 /* The special X/Open SMB protocol handling of
4695 zero length writes is *NOT* done for
4697 if(numtowrite
== 0) {
4700 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4701 saved_errno
= errno
;
4704 status
= sync_file(conn
, fsp
, False
/* write through */);
4705 if (!NT_STATUS_IS_OK(status
)) {
4706 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4707 fsp_str_dbg(fsp
), nt_errstr(status
)));
4708 reply_nterror(req
, status
);
4713 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4717 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4718 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4722 if (numtowrite
&& !fsp
->print_file
) {
4723 status
= do_unlock(req
->sconn
->msg_ctx
,
4725 (uint64_t)req
->smbpid
,
4726 (uint64_t)numtowrite
,
4730 if (NT_STATUS_V(status
)) {
4731 reply_nterror(req
, status
);
4736 reply_outbuf(req
, 1, 0);
4738 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4740 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4741 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4744 END_PROFILE(SMBwriteunlock
);
4749 #define DBGC_CLASS DBGC_ALL
4751 /****************************************************************************
4753 ****************************************************************************/
4755 void reply_write(struct smb_request
*req
)
4757 connection_struct
*conn
= req
->conn
;
4759 ssize_t nwritten
= -1;
4763 struct lock_struct lock
;
4765 int saved_errno
= 0;
4767 START_PROFILE(SMBwrite
);
4770 END_PROFILE(SMBwrite
);
4771 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4775 /* If it's an IPC, pass off the pipe handler. */
4777 reply_pipe_write(req
);
4778 END_PROFILE(SMBwrite
);
4782 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4784 if (!check_fsp(conn
, req
, fsp
)) {
4785 END_PROFILE(SMBwrite
);
4789 if (!CHECK_WRITE(fsp
)) {
4790 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4791 END_PROFILE(SMBwrite
);
4795 numtowrite
= SVAL(req
->vwv
+1, 0);
4796 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4797 data
= (const char *)req
->buf
+ 3;
4799 if (!fsp
->print_file
) {
4800 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4801 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4804 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4805 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4806 END_PROFILE(SMBwrite
);
4812 * X/Open SMB protocol says that if smb_vwv1 is
4813 * zero then the file size should be extended or
4814 * truncated to the size given in smb_vwv[2-3].
4817 if(numtowrite
== 0) {
4819 * This is actually an allocate call, and set EOF. JRA.
4821 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4823 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4826 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4828 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4831 trigger_write_time_update_immediate(fsp
);
4833 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4836 status
= sync_file(conn
, fsp
, False
);
4837 if (!NT_STATUS_IS_OK(status
)) {
4838 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4839 fsp_str_dbg(fsp
), nt_errstr(status
)));
4840 reply_nterror(req
, status
);
4845 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4849 if((nwritten
== 0) && (numtowrite
!= 0)) {
4850 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4854 reply_outbuf(req
, 1, 0);
4856 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4858 if (nwritten
< (ssize_t
)numtowrite
) {
4859 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4860 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4863 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4866 END_PROFILE(SMBwrite
);
4870 /****************************************************************************
4871 Ensure a buffer is a valid writeX for recvfile purposes.
4872 ****************************************************************************/
4874 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4875 (2*14) + /* word count (including bcc) */ \
4878 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4879 const uint8_t *inbuf
)
4882 unsigned int doff
= 0;
4883 size_t len
= smb_len_large(inbuf
);
4885 struct smbXsrv_open
*op
= NULL
;
4886 struct files_struct
*fsp
= NULL
;
4889 if (is_encrypted_packet(inbuf
)) {
4890 /* Can't do this on encrypted
4895 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4899 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4900 CVAL(inbuf
,smb_wct
) != 14) {
4901 DEBUG(10,("is_valid_writeX_buffer: chained or "
4902 "invalid word length.\n"));
4906 fnum
= SVAL(inbuf
, smb_vwv2
);
4907 status
= smb1srv_open_lookup(xconn
,
4911 if (!NT_STATUS_IS_OK(status
)) {
4912 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4917 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4920 if (fsp
->conn
== NULL
) {
4921 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4925 if (IS_IPC(fsp
->conn
)) {
4926 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4929 if (IS_PRINT(fsp
->conn
)) {
4930 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4933 doff
= SVAL(inbuf
,smb_vwv11
);
4935 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4937 if (len
> doff
&& len
- doff
> 0xFFFF) {
4938 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4941 if (numtowrite
== 0) {
4942 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4946 /* Ensure the sizes match up. */
4947 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4948 /* no pad byte...old smbclient :-( */
4949 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4951 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4955 if (len
- doff
!= numtowrite
) {
4956 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4957 "len = %u, doff = %u, numtowrite = %u\n",
4960 (unsigned int)numtowrite
));
4964 DEBUG(10,("is_valid_writeX_buffer: true "
4965 "len = %u, doff = %u, numtowrite = %u\n",
4968 (unsigned int)numtowrite
));
4973 /****************************************************************************
4974 Reply to a write and X.
4975 ****************************************************************************/
4977 void reply_write_and_X(struct smb_request
*req
)
4979 connection_struct
*conn
= req
->conn
;
4980 struct smbXsrv_connection
*xconn
= req
->xconn
;
4982 struct lock_struct lock
;
4987 unsigned int smb_doff
;
4988 unsigned int smblen
;
4991 int saved_errno
= 0;
4993 START_PROFILE(SMBwriteX
);
4995 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4996 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5000 numtowrite
= SVAL(req
->vwv
+10, 0);
5001 smb_doff
= SVAL(req
->vwv
+11, 0);
5002 smblen
= smb_len(req
->inbuf
);
5004 if (req
->unread_bytes
> 0xFFFF ||
5005 (smblen
> smb_doff
&&
5006 smblen
- smb_doff
> 0xFFFF)) {
5007 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5010 if (req
->unread_bytes
) {
5011 /* Can't do a recvfile write on IPC$ */
5013 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5016 if (numtowrite
!= req
->unread_bytes
) {
5017 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5021 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5022 smb_doff
+ numtowrite
> smblen
) {
5023 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5028 /* If it's an IPC, pass off the pipe handler. */
5030 if (req
->unread_bytes
) {
5031 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5034 reply_pipe_write_and_X(req
);
5038 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5039 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5040 write_through
= BITSETW(req
->vwv
+7,0);
5042 if (!check_fsp(conn
, req
, fsp
)) {
5046 if (!CHECK_WRITE(fsp
)) {
5047 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5051 data
= smb_base(req
->inbuf
) + smb_doff
;
5053 if(req
->wct
== 14) {
5055 * This is a large offset (64 bit) write.
5057 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5061 /* X/Open SMB protocol says that, unlike SMBwrite
5062 if the length is zero then NO truncation is
5063 done, just a write of zero. To truncate a file,
5066 if(numtowrite
== 0) {
5069 if (req
->unread_bytes
== 0) {
5070 status
= schedule_aio_write_and_X(conn
,
5077 if (NT_STATUS_IS_OK(status
)) {
5078 /* write scheduled - we're done. */
5081 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5082 /* Real error - report to client. */
5083 reply_nterror(req
, status
);
5086 /* NT_STATUS_RETRY - fall through to sync write. */
5089 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5090 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5093 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5094 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5098 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5099 saved_errno
= errno
;
5103 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5107 if((nwritten
== 0) && (numtowrite
!= 0)) {
5108 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5112 reply_outbuf(req
, 6, 0);
5113 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5114 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5115 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5116 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5118 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5119 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5121 status
= sync_file(conn
, fsp
, write_through
);
5122 if (!NT_STATUS_IS_OK(status
)) {
5123 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5124 fsp_str_dbg(fsp
), nt_errstr(status
)));
5125 reply_nterror(req
, status
);
5129 END_PROFILE(SMBwriteX
);
5133 if (req
->unread_bytes
) {
5134 /* writeX failed. drain socket. */
5135 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5136 req
->unread_bytes
) {
5137 smb_panic("failed to drain pending bytes");
5139 req
->unread_bytes
= 0;
5142 END_PROFILE(SMBwriteX
);
5146 /****************************************************************************
5148 ****************************************************************************/
5150 void reply_lseek(struct smb_request
*req
)
5152 connection_struct
*conn
= req
->conn
;
5158 START_PROFILE(SMBlseek
);
5161 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5162 END_PROFILE(SMBlseek
);
5166 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5168 if (!check_fsp(conn
, req
, fsp
)) {
5172 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5174 mode
= SVAL(req
->vwv
+1, 0) & 3;
5175 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5176 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5185 res
= fsp
->fh
->pos
+ startpos
;
5196 if (umode
== SEEK_END
) {
5197 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5198 if(errno
== EINVAL
) {
5199 off_t current_pos
= startpos
;
5201 if(fsp_stat(fsp
) == -1) {
5203 map_nt_error_from_unix(errno
));
5204 END_PROFILE(SMBlseek
);
5208 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5210 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5215 reply_nterror(req
, map_nt_error_from_unix(errno
));
5216 END_PROFILE(SMBlseek
);
5223 reply_outbuf(req
, 2, 0);
5224 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5226 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5227 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5229 END_PROFILE(SMBlseek
);
5233 /****************************************************************************
5235 ****************************************************************************/
5237 void reply_flush(struct smb_request
*req
)
5239 connection_struct
*conn
= req
->conn
;
5243 START_PROFILE(SMBflush
);
5246 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5250 fnum
= SVAL(req
->vwv
+0, 0);
5251 fsp
= file_fsp(req
, fnum
);
5253 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5258 file_sync_all(conn
);
5260 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5261 if (!NT_STATUS_IS_OK(status
)) {
5262 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5263 fsp_str_dbg(fsp
), nt_errstr(status
)));
5264 reply_nterror(req
, status
);
5265 END_PROFILE(SMBflush
);
5270 reply_outbuf(req
, 0, 0);
5272 DEBUG(3,("flush\n"));
5273 END_PROFILE(SMBflush
);
5277 /****************************************************************************
5279 conn POINTER CAN BE NULL HERE !
5280 ****************************************************************************/
5282 void reply_exit(struct smb_request
*req
)
5284 START_PROFILE(SMBexit
);
5286 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5288 reply_outbuf(req
, 0, 0);
5290 DEBUG(3,("exit\n"));
5292 END_PROFILE(SMBexit
);
5296 struct reply_close_state
{
5298 struct smb_request
*smbreq
;
5301 static void do_smb1_close(struct tevent_req
*req
);
5303 void reply_close(struct smb_request
*req
)
5305 connection_struct
*conn
= req
->conn
;
5306 NTSTATUS status
= NT_STATUS_OK
;
5307 files_struct
*fsp
= NULL
;
5308 START_PROFILE(SMBclose
);
5311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5312 END_PROFILE(SMBclose
);
5316 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5319 * We can only use check_fsp if we know it's not a directory.
5322 if (!check_fsp_open(conn
, req
, fsp
)) {
5323 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5324 END_PROFILE(SMBclose
);
5328 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5329 fsp
->is_directory
? "directory" : "file",
5330 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5331 conn
->num_files_open
));
5333 if (!fsp
->is_directory
) {
5337 * Take care of any time sent in the close.
5340 t
= srv_make_unix_date3(req
->vwv
+1);
5341 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5344 if (fsp
->num_aio_requests
!= 0) {
5346 struct reply_close_state
*state
;
5348 DEBUG(10, ("closing with aio %u requests pending\n",
5349 fsp
->num_aio_requests
));
5352 * We depend on the aio_extra destructor to take care of this
5353 * close request once fsp->num_aio_request drops to 0.
5356 fsp
->deferred_close
= tevent_wait_send(
5357 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5358 if (fsp
->deferred_close
== NULL
) {
5359 status
= NT_STATUS_NO_MEMORY
;
5363 state
= talloc(fsp
, struct reply_close_state
);
5364 if (state
== NULL
) {
5365 TALLOC_FREE(fsp
->deferred_close
);
5366 status
= NT_STATUS_NO_MEMORY
;
5370 state
->smbreq
= talloc_move(fsp
, &req
);
5371 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5373 END_PROFILE(SMBclose
);
5378 * close_file() returns the unix errno if an error was detected on
5379 * close - normally this is due to a disk full error. If not then it
5380 * was probably an I/O error.
5383 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5385 if (!NT_STATUS_IS_OK(status
)) {
5386 reply_nterror(req
, status
);
5387 END_PROFILE(SMBclose
);
5391 reply_outbuf(req
, 0, 0);
5392 END_PROFILE(SMBclose
);
5396 static void do_smb1_close(struct tevent_req
*req
)
5398 struct reply_close_state
*state
= tevent_req_callback_data(
5399 req
, struct reply_close_state
);
5400 struct smb_request
*smbreq
;
5404 ret
= tevent_wait_recv(req
);
5407 DEBUG(10, ("tevent_wait_recv returned %s\n",
5410 * Continue anyway, this should never happen
5415 * fsp->smb2_close_request right now is a talloc grandchild of
5416 * fsp. When we close_file(fsp), it would go with it. No chance to
5419 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5421 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5422 if (NT_STATUS_IS_OK(status
)) {
5423 reply_outbuf(smbreq
, 0, 0);
5425 reply_nterror(smbreq
, status
);
5427 if (!srv_send_smb(smbreq
->xconn
,
5428 (char *)smbreq
->outbuf
,
5431 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5433 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5436 TALLOC_FREE(smbreq
);
5439 /****************************************************************************
5440 Reply to a writeclose (Core+ protocol).
5441 ****************************************************************************/
5443 void reply_writeclose(struct smb_request
*req
)
5445 connection_struct
*conn
= req
->conn
;
5447 ssize_t nwritten
= -1;
5448 NTSTATUS close_status
= NT_STATUS_OK
;
5451 struct timespec mtime
;
5453 struct lock_struct lock
;
5455 START_PROFILE(SMBwriteclose
);
5458 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5459 END_PROFILE(SMBwriteclose
);
5463 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5465 if (!check_fsp(conn
, req
, fsp
)) {
5466 END_PROFILE(SMBwriteclose
);
5469 if (!CHECK_WRITE(fsp
)) {
5470 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5471 END_PROFILE(SMBwriteclose
);
5475 numtowrite
= SVAL(req
->vwv
+1, 0);
5476 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5477 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5478 data
= (const char *)req
->buf
+ 1;
5480 if (fsp
->print_file
== NULL
) {
5481 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5482 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5485 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5486 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5487 END_PROFILE(SMBwriteclose
);
5492 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5494 set_close_write_time(fsp
, mtime
);
5497 * More insanity. W2K only closes the file if writelen > 0.
5501 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5502 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5503 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5506 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5507 "file %s\n", fsp_str_dbg(fsp
)));
5508 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5512 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5513 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5517 if(!NT_STATUS_IS_OK(close_status
)) {
5518 reply_nterror(req
, close_status
);
5522 reply_outbuf(req
, 1, 0);
5524 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5528 END_PROFILE(SMBwriteclose
);
5533 #define DBGC_CLASS DBGC_LOCKING
5535 /****************************************************************************
5537 ****************************************************************************/
5539 void reply_lock(struct smb_request
*req
)
5541 connection_struct
*conn
= req
->conn
;
5542 uint64_t count
,offset
;
5545 struct byte_range_lock
*br_lck
= NULL
;
5547 START_PROFILE(SMBlock
);
5550 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5551 END_PROFILE(SMBlock
);
5555 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5557 if (!check_fsp(conn
, req
, fsp
)) {
5558 END_PROFILE(SMBlock
);
5562 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5563 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5565 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5566 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5568 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5570 (uint64_t)req
->smbpid
,
5575 False
, /* Non-blocking lock. */
5579 TALLOC_FREE(br_lck
);
5581 if (NT_STATUS_V(status
)) {
5582 reply_nterror(req
, status
);
5583 END_PROFILE(SMBlock
);
5587 reply_outbuf(req
, 0, 0);
5589 END_PROFILE(SMBlock
);
5593 /****************************************************************************
5595 ****************************************************************************/
5597 void reply_unlock(struct smb_request
*req
)
5599 connection_struct
*conn
= req
->conn
;
5600 uint64_t count
,offset
;
5604 START_PROFILE(SMBunlock
);
5607 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5608 END_PROFILE(SMBunlock
);
5612 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5614 if (!check_fsp(conn
, req
, fsp
)) {
5615 END_PROFILE(SMBunlock
);
5619 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5620 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5622 status
= do_unlock(req
->sconn
->msg_ctx
,
5624 (uint64_t)req
->smbpid
,
5629 if (NT_STATUS_V(status
)) {
5630 reply_nterror(req
, status
);
5631 END_PROFILE(SMBunlock
);
5635 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5636 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5638 reply_outbuf(req
, 0, 0);
5640 END_PROFILE(SMBunlock
);
5645 #define DBGC_CLASS DBGC_ALL
5647 /****************************************************************************
5649 conn POINTER CAN BE NULL HERE !
5650 ****************************************************************************/
5652 void reply_tdis(struct smb_request
*req
)
5655 connection_struct
*conn
= req
->conn
;
5656 struct smbXsrv_tcon
*tcon
;
5658 START_PROFILE(SMBtdis
);
5661 DEBUG(4,("Invalid connection in tdis\n"));
5662 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5663 END_PROFILE(SMBtdis
);
5671 * TODO: cancel all outstanding requests on the tcon
5673 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5674 if (!NT_STATUS_IS_OK(status
)) {
5675 DEBUG(0, ("reply_tdis: "
5676 "smbXsrv_tcon_disconnect() failed: %s\n",
5677 nt_errstr(status
)));
5679 * If we hit this case, there is something completely
5680 * wrong, so we better disconnect the transport connection.
5682 END_PROFILE(SMBtdis
);
5683 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5689 reply_outbuf(req
, 0, 0);
5690 END_PROFILE(SMBtdis
);
5694 /****************************************************************************
5696 conn POINTER CAN BE NULL HERE !
5697 ****************************************************************************/
5699 void reply_echo(struct smb_request
*req
)
5701 connection_struct
*conn
= req
->conn
;
5702 struct smb_perfcount_data local_pcd
;
5703 struct smb_perfcount_data
*cur_pcd
;
5707 START_PROFILE(SMBecho
);
5709 smb_init_perfcount_data(&local_pcd
);
5712 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5713 END_PROFILE(SMBecho
);
5717 smb_reverb
= SVAL(req
->vwv
+0, 0);
5719 reply_outbuf(req
, 1, req
->buflen
);
5721 /* copy any incoming data back out */
5722 if (req
->buflen
> 0) {
5723 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5726 if (smb_reverb
> 100) {
5727 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5731 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5733 /* this makes sure we catch the request pcd */
5734 if (seq_num
== smb_reverb
) {
5735 cur_pcd
= &req
->pcd
;
5737 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5738 cur_pcd
= &local_pcd
;
5741 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5743 show_msg((char *)req
->outbuf
);
5744 if (!srv_send_smb(req
->xconn
,
5745 (char *)req
->outbuf
,
5746 true, req
->seqnum
+1,
5747 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5749 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5752 DEBUG(3,("echo %d times\n", smb_reverb
));
5754 TALLOC_FREE(req
->outbuf
);
5756 END_PROFILE(SMBecho
);
5760 /****************************************************************************
5761 Reply to a printopen.
5762 ****************************************************************************/
5764 void reply_printopen(struct smb_request
*req
)
5766 connection_struct
*conn
= req
->conn
;
5770 START_PROFILE(SMBsplopen
);
5773 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5774 END_PROFILE(SMBsplopen
);
5778 if (!CAN_PRINT(conn
)) {
5779 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5780 END_PROFILE(SMBsplopen
);
5784 status
= file_new(req
, conn
, &fsp
);
5785 if(!NT_STATUS_IS_OK(status
)) {
5786 reply_nterror(req
, status
);
5787 END_PROFILE(SMBsplopen
);
5791 /* Open for exclusive use, write only. */
5792 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5794 if (!NT_STATUS_IS_OK(status
)) {
5795 file_free(req
, fsp
);
5796 reply_nterror(req
, status
);
5797 END_PROFILE(SMBsplopen
);
5801 reply_outbuf(req
, 1, 0);
5802 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5804 DEBUG(3,("openprint fd=%d %s\n",
5805 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5807 END_PROFILE(SMBsplopen
);
5811 /****************************************************************************
5812 Reply to a printclose.
5813 ****************************************************************************/
5815 void reply_printclose(struct smb_request
*req
)
5817 connection_struct
*conn
= req
->conn
;
5821 START_PROFILE(SMBsplclose
);
5824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5825 END_PROFILE(SMBsplclose
);
5829 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5831 if (!check_fsp(conn
, req
, fsp
)) {
5832 END_PROFILE(SMBsplclose
);
5836 if (!CAN_PRINT(conn
)) {
5837 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5838 END_PROFILE(SMBsplclose
);
5842 DEBUG(3,("printclose fd=%d %s\n",
5843 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5845 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5847 if(!NT_STATUS_IS_OK(status
)) {
5848 reply_nterror(req
, status
);
5849 END_PROFILE(SMBsplclose
);
5853 reply_outbuf(req
, 0, 0);
5855 END_PROFILE(SMBsplclose
);
5859 /****************************************************************************
5860 Reply to a printqueue.
5861 ****************************************************************************/
5863 void reply_printqueue(struct smb_request
*req
)
5865 connection_struct
*conn
= req
->conn
;
5869 START_PROFILE(SMBsplretq
);
5872 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5873 END_PROFILE(SMBsplretq
);
5877 max_count
= SVAL(req
->vwv
+0, 0);
5878 start_index
= SVAL(req
->vwv
+1, 0);
5880 /* we used to allow the client to get the cnum wrong, but that
5881 is really quite gross and only worked when there was only
5882 one printer - I think we should now only accept it if they
5883 get it right (tridge) */
5884 if (!CAN_PRINT(conn
)) {
5885 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5886 END_PROFILE(SMBsplretq
);
5890 reply_outbuf(req
, 2, 3);
5891 SSVAL(req
->outbuf
,smb_vwv0
,0);
5892 SSVAL(req
->outbuf
,smb_vwv1
,0);
5893 SCVAL(smb_buf(req
->outbuf
),0,1);
5894 SSVAL(smb_buf(req
->outbuf
),1,0);
5896 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5897 start_index
, max_count
));
5900 TALLOC_CTX
*mem_ctx
= talloc_tos();
5903 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5904 struct rpc_pipe_client
*cli
= NULL
;
5905 struct dcerpc_binding_handle
*b
= NULL
;
5906 struct policy_handle handle
;
5907 struct spoolss_DevmodeContainer devmode_ctr
;
5908 union spoolss_JobInfo
*info
;
5910 uint32_t num_to_get
;
5914 ZERO_STRUCT(handle
);
5916 status
= rpc_pipe_open_interface(mem_ctx
,
5919 conn
->sconn
->remote_address
,
5920 conn
->sconn
->local_address
,
5921 conn
->sconn
->msg_ctx
,
5923 if (!NT_STATUS_IS_OK(status
)) {
5924 DEBUG(0, ("reply_printqueue: "
5925 "could not connect to spoolss: %s\n",
5926 nt_errstr(status
)));
5927 reply_nterror(req
, status
);
5930 b
= cli
->binding_handle
;
5932 ZERO_STRUCT(devmode_ctr
);
5934 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5937 SEC_FLAG_MAXIMUM_ALLOWED
,
5940 if (!NT_STATUS_IS_OK(status
)) {
5941 reply_nterror(req
, status
);
5944 if (!W_ERROR_IS_OK(werr
)) {
5945 reply_nterror(req
, werror_to_ntstatus(werr
));
5949 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5957 if (!W_ERROR_IS_OK(werr
)) {
5958 reply_nterror(req
, werror_to_ntstatus(werr
));
5962 if (max_count
> 0) {
5963 first
= start_index
;
5965 first
= start_index
+ max_count
+ 1;
5968 if (first
>= count
) {
5971 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5974 for (i
= first
; i
< num_to_get
; i
++) {
5977 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5980 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5981 info
[i
].info2
.job_id
);
5983 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5989 srv_put_dos_date2(p
, 0, qtime
);
5990 SCVAL(p
, 4, qstatus
);
5991 SSVAL(p
, 5, qrapjobid
);
5992 SIVAL(p
, 7, info
[i
].info2
.size
);
5994 status
= srvstr_push(blob
, req
->flags2
, p
+12,
5995 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
5996 if (!NT_STATUS_IS_OK(status
)) {
5997 reply_nterror(req
, status
);
6000 if (message_push_blob(
6003 blob
, sizeof(blob
))) == -1) {
6004 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6010 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6011 SSVAL(req
->outbuf
,smb_vwv1
,
6012 (max_count
>0?first
+count
:first
-1));
6013 SCVAL(smb_buf(req
->outbuf
),0,1);
6014 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6018 DEBUG(3, ("%u entries returned in queue\n",
6022 if (b
&& is_valid_policy_hnd(&handle
)) {
6023 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6028 END_PROFILE(SMBsplretq
);
6032 /****************************************************************************
6033 Reply to a printwrite.
6034 ****************************************************************************/
6036 void reply_printwrite(struct smb_request
*req
)
6038 connection_struct
*conn
= req
->conn
;
6043 START_PROFILE(SMBsplwr
);
6046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6047 END_PROFILE(SMBsplwr
);
6051 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6053 if (!check_fsp(conn
, req
, fsp
)) {
6054 END_PROFILE(SMBsplwr
);
6058 if (!fsp
->print_file
) {
6059 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6060 END_PROFILE(SMBsplwr
);
6064 if (!CHECK_WRITE(fsp
)) {
6065 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6066 END_PROFILE(SMBsplwr
);
6070 numtowrite
= SVAL(req
->buf
, 1);
6072 if (req
->buflen
< numtowrite
+ 3) {
6073 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6074 END_PROFILE(SMBsplwr
);
6078 data
= (const char *)req
->buf
+ 3;
6080 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6081 reply_nterror(req
, map_nt_error_from_unix(errno
));
6082 END_PROFILE(SMBsplwr
);
6086 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6088 END_PROFILE(SMBsplwr
);
6092 /****************************************************************************
6094 ****************************************************************************/
6096 void reply_mkdir(struct smb_request
*req
)
6098 connection_struct
*conn
= req
->conn
;
6099 struct smb_filename
*smb_dname
= NULL
;
6100 char *directory
= NULL
;
6103 TALLOC_CTX
*ctx
= talloc_tos();
6105 START_PROFILE(SMBmkdir
);
6107 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6108 STR_TERMINATE
, &status
);
6109 if (!NT_STATUS_IS_OK(status
)) {
6110 reply_nterror(req
, status
);
6114 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6115 status
= filename_convert(ctx
, conn
,
6120 if (!NT_STATUS_IS_OK(status
)) {
6121 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6122 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6123 ERRSRV
, ERRbadpath
);
6126 reply_nterror(req
, status
);
6130 status
= create_directory(conn
, req
, smb_dname
);
6132 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6134 if (!NT_STATUS_IS_OK(status
)) {
6136 if (!use_nt_status()
6137 && NT_STATUS_EQUAL(status
,
6138 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6140 * Yes, in the DOS error code case we get a
6141 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6142 * samba4 torture test.
6144 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6147 reply_nterror(req
, status
);
6151 reply_outbuf(req
, 0, 0);
6153 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6155 TALLOC_FREE(smb_dname
);
6156 END_PROFILE(SMBmkdir
);
6160 /****************************************************************************
6162 ****************************************************************************/
6164 void reply_rmdir(struct smb_request
*req
)
6166 connection_struct
*conn
= req
->conn
;
6167 struct smb_filename
*smb_dname
= NULL
;
6168 char *directory
= NULL
;
6170 TALLOC_CTX
*ctx
= talloc_tos();
6171 files_struct
*fsp
= NULL
;
6173 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6174 struct smbd_server_connection
*sconn
= req
->sconn
;
6176 START_PROFILE(SMBrmdir
);
6178 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6179 STR_TERMINATE
, &status
);
6180 if (!NT_STATUS_IS_OK(status
)) {
6181 reply_nterror(req
, status
);
6185 status
= filename_convert(ctx
, conn
,
6190 if (!NT_STATUS_IS_OK(status
)) {
6191 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6192 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6193 ERRSRV
, ERRbadpath
);
6196 reply_nterror(req
, status
);
6200 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6201 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6205 status
= SMB_VFS_CREATE_FILE(
6208 0, /* root_dir_fid */
6209 smb_dname
, /* fname */
6210 DELETE_ACCESS
, /* access_mask */
6211 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6213 FILE_OPEN
, /* create_disposition*/
6214 FILE_DIRECTORY_FILE
, /* create_options */
6215 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6216 0, /* oplock_request */
6218 0, /* allocation_size */
6219 0, /* private_flags */
6224 NULL
, NULL
); /* create context */
6226 if (!NT_STATUS_IS_OK(status
)) {
6227 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6228 /* We have re-scheduled this call. */
6231 reply_nterror(req
, status
);
6235 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6236 if (!NT_STATUS_IS_OK(status
)) {
6237 close_file(req
, fsp
, ERROR_CLOSE
);
6238 reply_nterror(req
, status
);
6242 if (!set_delete_on_close(fsp
, true,
6243 conn
->session_info
->security_token
,
6244 conn
->session_info
->unix_token
)) {
6245 close_file(req
, fsp
, ERROR_CLOSE
);
6246 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6250 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6251 if (!NT_STATUS_IS_OK(status
)) {
6252 reply_nterror(req
, status
);
6254 reply_outbuf(req
, 0, 0);
6257 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6259 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6261 TALLOC_FREE(smb_dname
);
6262 END_PROFILE(SMBrmdir
);
6266 /*******************************************************************
6267 Resolve wildcards in a filename rename.
6268 ********************************************************************/
6270 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6275 char *name2_copy
= NULL
;
6280 char *p
,*p2
, *pname1
, *pname2
;
6282 name2_copy
= talloc_strdup(ctx
, name2
);
6287 pname1
= strrchr_m(name1
,'/');
6288 pname2
= strrchr_m(name2_copy
,'/');
6290 if (!pname1
|| !pname2
) {
6294 /* Truncate the copy of name2 at the last '/' */
6297 /* Now go past the '/' */
6301 root1
= talloc_strdup(ctx
, pname1
);
6302 root2
= talloc_strdup(ctx
, pname2
);
6304 if (!root1
|| !root2
) {
6308 p
= strrchr_m(root1
,'.');
6311 ext1
= talloc_strdup(ctx
, p
+1);
6313 ext1
= talloc_strdup(ctx
, "");
6315 p
= strrchr_m(root2
,'.');
6318 ext2
= talloc_strdup(ctx
, p
+1);
6320 ext2
= talloc_strdup(ctx
, "");
6323 if (!ext1
|| !ext2
) {
6331 /* Hmmm. Should this be mb-aware ? */
6334 } else if (*p2
== '*') {
6336 root2
= talloc_asprintf(ctx
, "%s%s",
6355 /* Hmmm. Should this be mb-aware ? */
6358 } else if (*p2
== '*') {
6360 ext2
= talloc_asprintf(ctx
, "%s%s",
6376 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6381 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6393 /****************************************************************************
6394 Ensure open files have their names updated. Updated to notify other smbd's
6396 ****************************************************************************/
6398 static void rename_open_files(connection_struct
*conn
,
6399 struct share_mode_lock
*lck
,
6401 uint32_t orig_name_hash
,
6402 const struct smb_filename
*smb_fname_dst
)
6405 bool did_rename
= False
;
6407 uint32_t new_name_hash
= 0;
6409 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6410 fsp
= file_find_di_next(fsp
)) {
6411 /* fsp_name is a relative path under the fsp. To change this for other
6412 sharepaths we need to manipulate relative paths. */
6413 /* TODO - create the absolute path and manipulate the newname
6414 relative to the sharepath. */
6415 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6418 if (fsp
->name_hash
!= orig_name_hash
) {
6421 DEBUG(10, ("rename_open_files: renaming file %s "
6422 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6423 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6424 smb_fname_str_dbg(smb_fname_dst
)));
6426 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6427 if (NT_STATUS_IS_OK(status
)) {
6429 new_name_hash
= fsp
->name_hash
;
6434 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6435 "for %s\n", file_id_string_tos(&id
),
6436 smb_fname_str_dbg(smb_fname_dst
)));
6439 /* Send messages to all smbd's (not ourself) that the name has changed. */
6440 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6441 orig_name_hash
, new_name_hash
,
6446 /****************************************************************************
6447 We need to check if the source path is a parent directory of the destination
6448 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6449 refuse the rename with a sharing violation. Under UNIX the above call can
6450 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6451 probably need to check that the client is a Windows one before disallowing
6452 this as a UNIX client (one with UNIX extensions) can know the source is a
6453 symlink and make this decision intelligently. Found by an excellent bug
6454 report from <AndyLiebman@aol.com>.
6455 ****************************************************************************/
6457 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6458 const struct smb_filename
*smb_fname_dst
)
6460 const char *psrc
= smb_fname_src
->base_name
;
6461 const char *pdst
= smb_fname_dst
->base_name
;
6464 if (psrc
[0] == '.' && psrc
[1] == '/') {
6467 if (pdst
[0] == '.' && pdst
[1] == '/') {
6470 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6473 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6477 * Do the notify calls from a rename
6480 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6481 const struct smb_filename
*smb_fname_src
,
6482 const struct smb_filename
*smb_fname_dst
)
6484 char *parent_dir_src
= NULL
;
6485 char *parent_dir_dst
= NULL
;
6488 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6489 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6491 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6492 &parent_dir_src
, NULL
) ||
6493 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6494 &parent_dir_dst
, NULL
)) {
6498 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6499 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6500 smb_fname_src
->base_name
);
6501 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6502 smb_fname_dst
->base_name
);
6505 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6506 smb_fname_src
->base_name
);
6507 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6508 smb_fname_dst
->base_name
);
6511 /* this is a strange one. w2k3 gives an additional event for
6512 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6513 files, but not directories */
6515 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6516 FILE_NOTIFY_CHANGE_ATTRIBUTES
6517 |FILE_NOTIFY_CHANGE_CREATION
,
6518 smb_fname_dst
->base_name
);
6521 TALLOC_FREE(parent_dir_src
);
6522 TALLOC_FREE(parent_dir_dst
);
6525 /****************************************************************************
6526 Returns an error if the parent directory for a filename is open in an
6528 ****************************************************************************/
6530 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6531 const struct smb_filename
*smb_fname_dst_in
)
6533 char *parent_dir
= NULL
;
6534 struct smb_filename smb_fname_parent
;
6536 files_struct
*fsp
= NULL
;
6539 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6540 &parent_dir
, NULL
)) {
6541 return NT_STATUS_NO_MEMORY
;
6543 ZERO_STRUCT(smb_fname_parent
);
6544 smb_fname_parent
.base_name
= parent_dir
;
6546 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6548 return map_nt_error_from_unix(errno
);
6552 * We're only checking on this smbd here, mostly good
6553 * enough.. and will pass tests.
6556 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6557 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6558 fsp
= file_find_di_next(fsp
)) {
6559 if (fsp
->access_mask
& DELETE_ACCESS
) {
6560 return NT_STATUS_SHARING_VIOLATION
;
6563 return NT_STATUS_OK
;
6566 /****************************************************************************
6567 Rename an open file - given an fsp.
6568 ****************************************************************************/
6570 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6572 const struct smb_filename
*smb_fname_dst_in
,
6574 bool replace_if_exists
)
6576 TALLOC_CTX
*ctx
= talloc_tos();
6577 struct smb_filename
*smb_fname_dst
= NULL
;
6578 NTSTATUS status
= NT_STATUS_OK
;
6579 struct share_mode_lock
*lck
= NULL
;
6580 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6581 bool dst_exists
, old_is_stream
, new_is_stream
;
6583 status
= check_name(conn
, smb_fname_dst_in
);
6584 if (!NT_STATUS_IS_OK(status
)) {
6588 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6589 if (!NT_STATUS_IS_OK(status
)) {
6593 /* Make a copy of the dst smb_fname structs */
6595 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6596 if (smb_fname_dst
== NULL
) {
6597 status
= NT_STATUS_NO_MEMORY
;
6602 * Check for special case with case preserving and not
6603 * case sensitive. If the new last component differs from the original
6604 * last component only by case, then we should allow
6605 * the rename (user is trying to change the case of the
6608 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6609 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6610 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6611 char *fname_dst_parent
= NULL
;
6612 const char *fname_dst_lcomp
= NULL
;
6613 char *orig_lcomp_path
= NULL
;
6614 char *orig_lcomp_stream
= NULL
;
6618 * Split off the last component of the processed
6619 * destination name. We will compare this to
6620 * the split components of smb_fname_dst->original_lcomp.
6622 if (!parent_dirname(ctx
,
6623 smb_fname_dst
->base_name
,
6625 &fname_dst_lcomp
)) {
6626 status
= NT_STATUS_NO_MEMORY
;
6631 * The original_lcomp component contains
6632 * the last_component of the path + stream
6633 * name (if a stream exists).
6635 * Split off the stream name so we
6636 * can check them separately.
6639 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6640 /* POSIX - no stream component. */
6641 orig_lcomp_path
= talloc_strdup(ctx
,
6642 smb_fname_dst
->original_lcomp
);
6643 if (orig_lcomp_path
== NULL
) {
6647 ok
= split_stream_filename(ctx
,
6648 smb_fname_dst
->original_lcomp
,
6650 &orig_lcomp_stream
);
6654 TALLOC_FREE(fname_dst_parent
);
6655 status
= NT_STATUS_NO_MEMORY
;
6659 /* If the base names only differ by case, use original. */
6660 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6663 * Replace the modified last component with the
6666 if (!ISDOT(fname_dst_parent
)) {
6667 tmp
= talloc_asprintf(smb_fname_dst
,
6672 tmp
= talloc_strdup(smb_fname_dst
,
6676 status
= NT_STATUS_NO_MEMORY
;
6677 TALLOC_FREE(fname_dst_parent
);
6678 TALLOC_FREE(orig_lcomp_path
);
6679 TALLOC_FREE(orig_lcomp_stream
);
6682 TALLOC_FREE(smb_fname_dst
->base_name
);
6683 smb_fname_dst
->base_name
= tmp
;
6686 /* If the stream_names only differ by case, use original. */
6687 if(!strcsequal(smb_fname_dst
->stream_name
,
6688 orig_lcomp_stream
)) {
6689 /* Use the original stream. */
6690 char *tmp
= talloc_strdup(smb_fname_dst
,
6693 status
= NT_STATUS_NO_MEMORY
;
6694 TALLOC_FREE(fname_dst_parent
);
6695 TALLOC_FREE(orig_lcomp_path
);
6696 TALLOC_FREE(orig_lcomp_stream
);
6699 TALLOC_FREE(smb_fname_dst
->stream_name
);
6700 smb_fname_dst
->stream_name
= tmp
;
6702 TALLOC_FREE(fname_dst_parent
);
6703 TALLOC_FREE(orig_lcomp_path
);
6704 TALLOC_FREE(orig_lcomp_stream
);
6708 * If the src and dest names are identical - including case,
6709 * don't do the rename, just return success.
6712 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6713 strcsequal(fsp
->fsp_name
->stream_name
,
6714 smb_fname_dst
->stream_name
)) {
6715 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6716 "- returning success\n",
6717 smb_fname_str_dbg(smb_fname_dst
)));
6718 status
= NT_STATUS_OK
;
6722 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6723 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6725 /* Return the correct error code if both names aren't streams. */
6726 if (!old_is_stream
&& new_is_stream
) {
6727 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6731 if (old_is_stream
&& !new_is_stream
) {
6732 status
= NT_STATUS_INVALID_PARAMETER
;
6736 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6738 if(!replace_if_exists
&& dst_exists
) {
6739 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6740 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6741 smb_fname_str_dbg(smb_fname_dst
)));
6742 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6747 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6748 &smb_fname_dst
->st
);
6749 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6751 /* The file can be open when renaming a stream */
6752 if (dst_fsp
&& !new_is_stream
) {
6753 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6754 status
= NT_STATUS_ACCESS_DENIED
;
6759 /* Ensure we have a valid stat struct for the source. */
6760 status
= vfs_stat_fsp(fsp
);
6761 if (!NT_STATUS_IS_OK(status
)) {
6765 status
= can_rename(conn
, fsp
, attrs
);
6767 if (!NT_STATUS_IS_OK(status
)) {
6768 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6769 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6770 smb_fname_str_dbg(smb_fname_dst
)));
6771 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6772 status
= NT_STATUS_ACCESS_DENIED
;
6776 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6777 status
= NT_STATUS_ACCESS_DENIED
;
6781 /* Do we have rights to move into the destination ? */
6782 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6783 /* We're moving a directory. */
6784 access_mask
= SEC_DIR_ADD_SUBDIR
;
6786 status
= check_parent_access(conn
,
6789 if (!NT_STATUS_IS_OK(status
)) {
6790 DBG_INFO("check_parent_access on "
6791 "dst %s returned %s\n",
6792 smb_fname_str_dbg(smb_fname_dst
),
6797 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6800 * We have the file open ourselves, so not being able to get the
6801 * corresponding share mode lock is a fatal error.
6804 SMB_ASSERT(lck
!= NULL
);
6806 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6807 uint32_t create_options
= fsp
->fh
->private_options
;
6809 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6810 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6811 smb_fname_str_dbg(smb_fname_dst
)));
6813 if (!fsp
->is_directory
&&
6814 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6815 (lp_map_archive(SNUM(conn
)) ||
6816 lp_store_dos_attributes(SNUM(conn
)))) {
6817 /* We must set the archive bit on the newly
6819 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6820 uint32_t old_dosmode
= dos_mode(conn
,
6822 file_set_dosmode(conn
,
6824 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6830 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6833 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6837 * A rename acts as a new file create w.r.t. allowing an initial delete
6838 * on close, probably because in Windows there is a new handle to the
6839 * new file. If initial delete on close was requested but not
6840 * originally set, we need to set it here. This is probably not 100% correct,
6841 * but will work for the CIFSFS client which in non-posix mode
6842 * depends on these semantics. JRA.
6845 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6846 status
= can_set_delete_on_close(fsp
, 0);
6848 if (NT_STATUS_IS_OK(status
)) {
6849 /* Note that here we set the *inital* delete on close flag,
6850 * not the regular one. The magic gets handled in close. */
6851 fsp
->initial_delete_on_close
= True
;
6855 status
= NT_STATUS_OK
;
6861 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6862 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6864 status
= map_nt_error_from_unix(errno
);
6867 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6868 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6869 smb_fname_str_dbg(smb_fname_dst
)));
6872 TALLOC_FREE(smb_fname_dst
);
6877 /****************************************************************************
6878 The guts of the rename command, split out so it may be called by the NT SMB
6880 ****************************************************************************/
6882 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6883 connection_struct
*conn
,
6884 struct smb_request
*req
,
6885 struct smb_filename
*smb_fname_src
,
6886 struct smb_filename
*smb_fname_dst
,
6888 bool replace_if_exists
,
6891 uint32_t access_mask
)
6893 char *fname_src_dir
= NULL
;
6894 struct smb_filename
*smb_fname_src_dir
= NULL
;
6895 char *fname_src_mask
= NULL
;
6897 NTSTATUS status
= NT_STATUS_OK
;
6898 struct smb_Dir
*dir_hnd
= NULL
;
6899 const char *dname
= NULL
;
6900 char *talloced
= NULL
;
6902 int create_options
= 0;
6903 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6907 * Split the old name into directory and last component
6908 * strings. Note that unix_convert may have stripped off a
6909 * leading ./ from both name and newname if the rename is
6910 * at the root of the share. We need to make sure either both
6911 * name and newname contain a / character or neither of them do
6912 * as this is checked in resolve_wildcards().
6915 /* Split up the directory from the filename/mask. */
6916 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6917 &fname_src_dir
, &fname_src_mask
);
6918 if (!NT_STATUS_IS_OK(status
)) {
6919 status
= NT_STATUS_NO_MEMORY
;
6924 * We should only check the mangled cache
6925 * here if unix_convert failed. This means
6926 * that the path in 'mask' doesn't exist
6927 * on the file system and so we need to look
6928 * for a possible mangle. This patch from
6929 * Tine Smukavec <valentin.smukavec@hermes.si>.
6932 if (!VALID_STAT(smb_fname_src
->st
) &&
6933 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6934 char *new_mask
= NULL
;
6935 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6938 TALLOC_FREE(fname_src_mask
);
6939 fname_src_mask
= new_mask
;
6943 if (!src_has_wild
) {
6947 * Only one file needs to be renamed. Append the mask back
6948 * onto the directory.
6950 TALLOC_FREE(smb_fname_src
->base_name
);
6951 if (ISDOT(fname_src_dir
)) {
6952 /* Ensure we use canonical names on open. */
6953 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6957 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6962 if (!smb_fname_src
->base_name
) {
6963 status
= NT_STATUS_NO_MEMORY
;
6967 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6968 "case_preserve = %d, short case preserve = %d, "
6969 "directory = %s, newname = %s, "
6970 "last_component_dest = %s\n",
6971 conn
->case_sensitive
, conn
->case_preserve
,
6972 conn
->short_case_preserve
,
6973 smb_fname_str_dbg(smb_fname_src
),
6974 smb_fname_str_dbg(smb_fname_dst
),
6975 smb_fname_dst
->original_lcomp
));
6977 /* The dest name still may have wildcards. */
6978 if (dest_has_wild
) {
6979 char *fname_dst_mod
= NULL
;
6980 if (!resolve_wildcards(smb_fname_dst
,
6981 smb_fname_src
->base_name
,
6982 smb_fname_dst
->base_name
,
6984 DEBUG(6, ("rename_internals: resolve_wildcards "
6986 smb_fname_src
->base_name
,
6987 smb_fname_dst
->base_name
));
6988 status
= NT_STATUS_NO_MEMORY
;
6991 TALLOC_FREE(smb_fname_dst
->base_name
);
6992 smb_fname_dst
->base_name
= fname_dst_mod
;
6995 ZERO_STRUCT(smb_fname_src
->st
);
6996 if (posix_pathnames
) {
6997 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6999 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7002 status
= map_nt_error_from_unix_common(errno
);
7006 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7007 create_options
|= FILE_DIRECTORY_FILE
;
7010 status
= SMB_VFS_CREATE_FILE(
7013 0, /* root_dir_fid */
7014 smb_fname_src
, /* fname */
7015 access_mask
, /* access_mask */
7016 (FILE_SHARE_READ
| /* share_access */
7018 FILE_OPEN
, /* create_disposition*/
7019 create_options
, /* create_options */
7020 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7021 0, /* oplock_request */
7023 0, /* allocation_size */
7024 0, /* private_flags */
7029 NULL
, NULL
); /* create context */
7031 if (!NT_STATUS_IS_OK(status
)) {
7032 DEBUG(3, ("Could not open rename source %s: %s\n",
7033 smb_fname_str_dbg(smb_fname_src
),
7034 nt_errstr(status
)));
7038 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7039 attrs
, replace_if_exists
);
7041 close_file(req
, fsp
, NORMAL_CLOSE
);
7043 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7044 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7045 smb_fname_str_dbg(smb_fname_dst
)));
7051 * Wildcards - process each file that matches.
7053 if (strequal(fname_src_mask
, "????????.???")) {
7054 TALLOC_FREE(fname_src_mask
);
7055 fname_src_mask
= talloc_strdup(ctx
, "*");
7056 if (!fname_src_mask
) {
7057 status
= NT_STATUS_NO_MEMORY
;
7062 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7066 smb_fname_src
->flags
);
7067 if (smb_fname_src_dir
== NULL
) {
7068 status
= NT_STATUS_NO_MEMORY
;
7072 status
= check_name(conn
, smb_fname_src_dir
);
7073 if (!NT_STATUS_IS_OK(status
)) {
7077 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7079 if (dir_hnd
== NULL
) {
7080 status
= map_nt_error_from_unix(errno
);
7084 status
= NT_STATUS_NO_SUCH_FILE
;
7086 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7087 * - gentest fix. JRA
7090 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7092 files_struct
*fsp
= NULL
;
7093 char *destname
= NULL
;
7094 bool sysdir_entry
= False
;
7096 /* Quick check for "." and ".." */
7097 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7098 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7099 sysdir_entry
= True
;
7101 TALLOC_FREE(talloced
);
7106 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7107 &smb_fname_src
->st
, false)) {
7108 TALLOC_FREE(talloced
);
7112 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7113 TALLOC_FREE(talloced
);
7118 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7122 TALLOC_FREE(smb_fname_src
->base_name
);
7123 if (ISDOT(fname_src_dir
)) {
7124 /* Ensure we use canonical names on open. */
7125 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7129 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7134 if (!smb_fname_src
->base_name
) {
7135 status
= NT_STATUS_NO_MEMORY
;
7139 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7140 smb_fname_dst
->base_name
,
7142 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7143 smb_fname_src
->base_name
, destname
));
7144 TALLOC_FREE(talloced
);
7148 status
= NT_STATUS_NO_MEMORY
;
7152 TALLOC_FREE(smb_fname_dst
->base_name
);
7153 smb_fname_dst
->base_name
= destname
;
7155 ZERO_STRUCT(smb_fname_src
->st
);
7156 if (posix_pathnames
) {
7157 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7159 SMB_VFS_STAT(conn
, smb_fname_src
);
7164 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7165 create_options
|= FILE_DIRECTORY_FILE
;
7168 status
= SMB_VFS_CREATE_FILE(
7171 0, /* root_dir_fid */
7172 smb_fname_src
, /* fname */
7173 access_mask
, /* access_mask */
7174 (FILE_SHARE_READ
| /* share_access */
7176 FILE_OPEN
, /* create_disposition*/
7177 create_options
, /* create_options */
7178 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7179 0, /* oplock_request */
7181 0, /* allocation_size */
7182 0, /* private_flags */
7187 NULL
, NULL
); /* create context */
7189 if (!NT_STATUS_IS_OK(status
)) {
7190 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7191 "returned %s rename %s -> %s\n",
7193 smb_fname_str_dbg(smb_fname_src
),
7194 smb_fname_str_dbg(smb_fname_dst
)));
7198 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7200 if (!smb_fname_dst
->original_lcomp
) {
7201 status
= NT_STATUS_NO_MEMORY
;
7205 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7206 attrs
, replace_if_exists
);
7208 close_file(req
, fsp
, NORMAL_CLOSE
);
7210 if (!NT_STATUS_IS_OK(status
)) {
7211 DEBUG(3, ("rename_internals_fsp returned %s for "
7212 "rename %s -> %s\n", nt_errstr(status
),
7213 smb_fname_str_dbg(smb_fname_src
),
7214 smb_fname_str_dbg(smb_fname_dst
)));
7220 DEBUG(3,("rename_internals: doing rename on %s -> "
7221 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7222 smb_fname_str_dbg(smb_fname_src
)));
7223 TALLOC_FREE(talloced
);
7225 TALLOC_FREE(dir_hnd
);
7227 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7228 status
= map_nt_error_from_unix(errno
);
7232 TALLOC_FREE(talloced
);
7233 TALLOC_FREE(smb_fname_src_dir
);
7234 TALLOC_FREE(fname_src_dir
);
7235 TALLOC_FREE(fname_src_mask
);
7239 /****************************************************************************
7241 ****************************************************************************/
7243 void reply_mv(struct smb_request
*req
)
7245 connection_struct
*conn
= req
->conn
;
7247 char *newname
= NULL
;
7251 bool src_has_wcard
= False
;
7252 bool dest_has_wcard
= False
;
7253 TALLOC_CTX
*ctx
= talloc_tos();
7254 struct smb_filename
*smb_fname_src
= NULL
;
7255 struct smb_filename
*smb_fname_dst
= NULL
;
7256 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7257 (req
->posix_pathnames
?
7258 UCF_UNIX_NAME_LOOKUP
:
7259 UCF_COND_ALLOW_WCARD_LCOMP
);
7260 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7262 (req
->posix_pathnames
?
7264 UCF_COND_ALLOW_WCARD_LCOMP
);
7265 bool stream_rename
= false;
7267 START_PROFILE(SMBmv
);
7270 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7274 attrs
= SVAL(req
->vwv
+0, 0);
7276 p
= (const char *)req
->buf
+ 1;
7277 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7278 &status
, &src_has_wcard
);
7279 if (!NT_STATUS_IS_OK(status
)) {
7280 reply_nterror(req
, status
);
7284 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7285 &status
, &dest_has_wcard
);
7286 if (!NT_STATUS_IS_OK(status
)) {
7287 reply_nterror(req
, status
);
7291 if (!req
->posix_pathnames
) {
7292 /* The newname must begin with a ':' if the
7293 name contains a ':'. */
7294 if (strchr_m(name
, ':')) {
7295 if (newname
[0] != ':') {
7296 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7299 stream_rename
= true;
7303 status
= filename_convert(ctx
,
7310 if (!NT_STATUS_IS_OK(status
)) {
7311 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7312 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7313 ERRSRV
, ERRbadpath
);
7316 reply_nterror(req
, status
);
7320 status
= filename_convert(ctx
,
7327 if (!NT_STATUS_IS_OK(status
)) {
7328 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7329 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7330 ERRSRV
, ERRbadpath
);
7333 reply_nterror(req
, status
);
7337 if (stream_rename
) {
7338 /* smb_fname_dst->base_name must be the same as
7339 smb_fname_src->base_name. */
7340 TALLOC_FREE(smb_fname_dst
->base_name
);
7341 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7342 smb_fname_src
->base_name
);
7343 if (!smb_fname_dst
->base_name
) {
7344 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7349 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7350 smb_fname_str_dbg(smb_fname_dst
)));
7352 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7353 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7355 if (!NT_STATUS_IS_OK(status
)) {
7356 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7357 /* We have re-scheduled this call. */
7360 reply_nterror(req
, status
);
7364 reply_outbuf(req
, 0, 0);
7366 TALLOC_FREE(smb_fname_src
);
7367 TALLOC_FREE(smb_fname_dst
);
7372 /*******************************************************************
7373 Copy a file as part of a reply_copy.
7374 ******************************************************************/
7377 * TODO: check error codes on all callers
7380 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7381 connection_struct
*conn
,
7382 struct smb_filename
*smb_fname_src
,
7383 struct smb_filename
*smb_fname_dst
,
7386 bool target_is_directory
)
7388 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7390 files_struct
*fsp1
,*fsp2
;
7392 uint32_t new_create_disposition
;
7396 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7397 if (smb_fname_dst_tmp
== NULL
) {
7398 return NT_STATUS_NO_MEMORY
;
7402 * If the target is a directory, extract the last component from the
7403 * src filename and append it to the dst filename
7405 if (target_is_directory
) {
7408 /* dest/target can't be a stream if it's a directory. */
7409 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7411 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7415 p
= smb_fname_src
->base_name
;
7417 smb_fname_dst_tmp
->base_name
=
7418 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7420 if (!smb_fname_dst_tmp
->base_name
) {
7421 status
= NT_STATUS_NO_MEMORY
;
7426 status
= vfs_file_exist(conn
, smb_fname_src
);
7427 if (!NT_STATUS_IS_OK(status
)) {
7431 if (!target_is_directory
&& count
) {
7432 new_create_disposition
= FILE_OPEN
;
7434 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7437 &new_create_disposition
,
7440 status
= NT_STATUS_INVALID_PARAMETER
;
7445 /* Open the src file for reading. */
7446 status
= SMB_VFS_CREATE_FILE(
7449 0, /* root_dir_fid */
7450 smb_fname_src
, /* fname */
7451 FILE_GENERIC_READ
, /* access_mask */
7452 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7453 FILE_OPEN
, /* create_disposition*/
7454 0, /* create_options */
7455 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7456 INTERNAL_OPEN_ONLY
, /* oplock_request */
7458 0, /* allocation_size */
7459 0, /* private_flags */
7464 NULL
, NULL
); /* create context */
7466 if (!NT_STATUS_IS_OK(status
)) {
7470 dosattrs
= dos_mode(conn
, smb_fname_src
);
7472 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7473 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7476 /* Open the dst file for writing. */
7477 status
= SMB_VFS_CREATE_FILE(
7480 0, /* root_dir_fid */
7481 smb_fname_dst
, /* fname */
7482 FILE_GENERIC_WRITE
, /* access_mask */
7483 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7484 new_create_disposition
, /* create_disposition*/
7485 0, /* create_options */
7486 dosattrs
, /* file_attributes */
7487 INTERNAL_OPEN_ONLY
, /* oplock_request */
7489 0, /* allocation_size */
7490 0, /* private_flags */
7495 NULL
, NULL
); /* create context */
7497 if (!NT_STATUS_IS_OK(status
)) {
7498 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7502 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7503 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7505 DEBUG(0, ("error - vfs lseek returned error %s\n",
7507 status
= map_nt_error_from_unix(errno
);
7508 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7509 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7514 /* Do the actual copy. */
7515 if (smb_fname_src
->st
.st_ex_size
) {
7516 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7521 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7523 /* Ensure the modtime is set correctly on the destination file. */
7524 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7527 * As we are opening fsp1 read-only we only expect
7528 * an error on close on fsp2 if we are out of space.
7529 * Thus we don't look at the error return from the
7532 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7534 if (!NT_STATUS_IS_OK(status
)) {
7538 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7539 status
= NT_STATUS_DISK_FULL
;
7543 status
= NT_STATUS_OK
;
7546 TALLOC_FREE(smb_fname_dst_tmp
);
7550 /****************************************************************************
7551 Reply to a file copy.
7552 ****************************************************************************/
7554 void reply_copy(struct smb_request
*req
)
7556 connection_struct
*conn
= req
->conn
;
7557 struct smb_filename
*smb_fname_src
= NULL
;
7558 struct smb_filename
*smb_fname_src_dir
= NULL
;
7559 struct smb_filename
*smb_fname_dst
= NULL
;
7560 char *fname_src
= NULL
;
7561 char *fname_dst
= NULL
;
7562 char *fname_src_mask
= NULL
;
7563 char *fname_src_dir
= NULL
;
7566 int error
= ERRnoaccess
;
7570 bool target_is_directory
=False
;
7571 bool source_has_wild
= False
;
7572 bool dest_has_wild
= False
;
7574 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7575 ucf_flags_from_smb_request(req
);
7576 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7577 ucf_flags_from_smb_request(req
);
7578 TALLOC_CTX
*ctx
= talloc_tos();
7580 START_PROFILE(SMBcopy
);
7583 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7587 tid2
= SVAL(req
->vwv
+0, 0);
7588 ofun
= SVAL(req
->vwv
+1, 0);
7589 flags
= SVAL(req
->vwv
+2, 0);
7591 p
= (const char *)req
->buf
;
7592 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7593 &status
, &source_has_wild
);
7594 if (!NT_STATUS_IS_OK(status
)) {
7595 reply_nterror(req
, status
);
7598 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7599 &status
, &dest_has_wild
);
7600 if (!NT_STATUS_IS_OK(status
)) {
7601 reply_nterror(req
, status
);
7605 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7607 if (tid2
!= conn
->cnum
) {
7608 /* can't currently handle inter share copies XXXX */
7609 DEBUG(3,("Rejecting inter-share copy\n"));
7610 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7614 status
= filename_convert(ctx
, conn
,
7619 if (!NT_STATUS_IS_OK(status
)) {
7620 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7621 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7622 ERRSRV
, ERRbadpath
);
7625 reply_nterror(req
, status
);
7629 status
= filename_convert(ctx
, conn
,
7634 if (!NT_STATUS_IS_OK(status
)) {
7635 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7636 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7637 ERRSRV
, ERRbadpath
);
7640 reply_nterror(req
, status
);
7644 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7646 if ((flags
&1) && target_is_directory
) {
7647 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7651 if ((flags
&2) && !target_is_directory
) {
7652 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7656 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7657 /* wants a tree copy! XXXX */
7658 DEBUG(3,("Rejecting tree copy\n"));
7659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7663 /* Split up the directory from the filename/mask. */
7664 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7665 &fname_src_dir
, &fname_src_mask
);
7666 if (!NT_STATUS_IS_OK(status
)) {
7667 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7672 * We should only check the mangled cache
7673 * here if unix_convert failed. This means
7674 * that the path in 'mask' doesn't exist
7675 * on the file system and so we need to look
7676 * for a possible mangle. This patch from
7677 * Tine Smukavec <valentin.smukavec@hermes.si>.
7679 if (!VALID_STAT(smb_fname_src
->st
) &&
7680 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7681 char *new_mask
= NULL
;
7682 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7683 &new_mask
, conn
->params
);
7685 /* Use demangled name if one was successfully found. */
7687 TALLOC_FREE(fname_src_mask
);
7688 fname_src_mask
= new_mask
;
7692 if (!source_has_wild
) {
7695 * Only one file needs to be copied. Append the mask back onto
7698 TALLOC_FREE(smb_fname_src
->base_name
);
7699 if (ISDOT(fname_src_dir
)) {
7700 /* Ensure we use canonical names on open. */
7701 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7705 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7710 if (!smb_fname_src
->base_name
) {
7711 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7715 if (dest_has_wild
) {
7716 char *fname_dst_mod
= NULL
;
7717 if (!resolve_wildcards(smb_fname_dst
,
7718 smb_fname_src
->base_name
,
7719 smb_fname_dst
->base_name
,
7721 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7724 TALLOC_FREE(smb_fname_dst
->base_name
);
7725 smb_fname_dst
->base_name
= fname_dst_mod
;
7728 status
= check_name(conn
, smb_fname_src
);
7729 if (!NT_STATUS_IS_OK(status
)) {
7730 reply_nterror(req
, status
);
7734 status
= check_name(conn
, smb_fname_dst
);
7735 if (!NT_STATUS_IS_OK(status
)) {
7736 reply_nterror(req
, status
);
7740 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7741 ofun
, count
, target_is_directory
);
7743 if(!NT_STATUS_IS_OK(status
)) {
7744 reply_nterror(req
, status
);
7750 struct smb_Dir
*dir_hnd
= NULL
;
7751 const char *dname
= NULL
;
7752 char *talloced
= NULL
;
7756 * There is a wildcard that requires us to actually read the
7757 * src dir and copy each file matching the mask to the dst.
7758 * Right now streams won't be copied, but this could
7759 * presumably be added with a nested loop for reach dir entry.
7761 SMB_ASSERT(!smb_fname_src
->stream_name
);
7762 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7764 smb_fname_src
->stream_name
= NULL
;
7765 smb_fname_dst
->stream_name
= NULL
;
7767 if (strequal(fname_src_mask
,"????????.???")) {
7768 TALLOC_FREE(fname_src_mask
);
7769 fname_src_mask
= talloc_strdup(ctx
, "*");
7770 if (!fname_src_mask
) {
7771 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7776 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7780 smb_fname_src
->flags
);
7781 if (smb_fname_src_dir
== NULL
) {
7782 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7786 status
= check_name(conn
, smb_fname_src_dir
);
7787 if (!NT_STATUS_IS_OK(status
)) {
7788 reply_nterror(req
, status
);
7792 dir_hnd
= OpenDir(ctx
,
7797 if (dir_hnd
== NULL
) {
7798 status
= map_nt_error_from_unix(errno
);
7799 reply_nterror(req
, status
);
7805 /* Iterate over the src dir copying each entry to the dst. */
7806 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7807 &smb_fname_src
->st
, &talloced
))) {
7808 char *destname
= NULL
;
7810 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7811 TALLOC_FREE(talloced
);
7815 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7816 &smb_fname_src
->st
, false)) {
7817 TALLOC_FREE(talloced
);
7821 if(!mask_match(dname
, fname_src_mask
,
7822 conn
->case_sensitive
)) {
7823 TALLOC_FREE(talloced
);
7827 error
= ERRnoaccess
;
7829 /* Get the src smb_fname struct setup. */
7830 TALLOC_FREE(smb_fname_src
->base_name
);
7831 if (ISDOT(fname_src_dir
)) {
7832 /* Ensure we use canonical names on open. */
7833 smb_fname_src
->base_name
=
7834 talloc_asprintf(smb_fname_src
, "%s",
7837 smb_fname_src
->base_name
=
7838 talloc_asprintf(smb_fname_src
, "%s/%s",
7839 fname_src_dir
, dname
);
7842 if (!smb_fname_src
->base_name
) {
7843 TALLOC_FREE(dir_hnd
);
7844 TALLOC_FREE(talloced
);
7845 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7849 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7850 smb_fname_dst
->base_name
,
7852 TALLOC_FREE(talloced
);
7856 TALLOC_FREE(dir_hnd
);
7857 TALLOC_FREE(talloced
);
7858 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7862 TALLOC_FREE(smb_fname_dst
->base_name
);
7863 smb_fname_dst
->base_name
= destname
;
7865 status
= check_name(conn
, smb_fname_src
);
7866 if (!NT_STATUS_IS_OK(status
)) {
7867 TALLOC_FREE(dir_hnd
);
7868 TALLOC_FREE(talloced
);
7869 reply_nterror(req
, status
);
7873 status
= check_name(conn
, smb_fname_dst
);
7874 if (!NT_STATUS_IS_OK(status
)) {
7875 TALLOC_FREE(dir_hnd
);
7876 TALLOC_FREE(talloced
);
7877 reply_nterror(req
, status
);
7881 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7882 smb_fname_src
->base_name
,
7883 smb_fname_dst
->base_name
));
7885 status
= copy_file(ctx
, conn
, smb_fname_src
,
7886 smb_fname_dst
, ofun
, count
,
7887 target_is_directory
);
7888 if (NT_STATUS_IS_OK(status
)) {
7892 TALLOC_FREE(talloced
);
7894 TALLOC_FREE(dir_hnd
);
7898 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7902 reply_outbuf(req
, 1, 0);
7903 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7905 TALLOC_FREE(smb_fname_src
);
7906 TALLOC_FREE(smb_fname_src_dir
);
7907 TALLOC_FREE(smb_fname_dst
);
7908 TALLOC_FREE(fname_src
);
7909 TALLOC_FREE(fname_dst
);
7910 TALLOC_FREE(fname_src_mask
);
7911 TALLOC_FREE(fname_src_dir
);
7913 END_PROFILE(SMBcopy
);
7918 #define DBGC_CLASS DBGC_LOCKING
7920 /****************************************************************************
7921 Get a lock pid, dealing with large count requests.
7922 ****************************************************************************/
7924 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7925 bool large_file_format
)
7927 if(!large_file_format
)
7928 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7930 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7933 /****************************************************************************
7934 Get a lock count, dealing with large count requests.
7935 ****************************************************************************/
7937 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7938 bool large_file_format
)
7942 if(!large_file_format
) {
7943 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7946 * No BVAL, this is reversed!
7948 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7949 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7955 /****************************************************************************
7956 Get a lock offset, dealing with large offset requests.
7957 ****************************************************************************/
7959 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7960 bool large_file_format
)
7962 uint64_t offset
= 0;
7964 if(!large_file_format
) {
7965 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7968 * No BVAL, this is reversed!
7970 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7971 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7977 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7982 struct smbd_lock_element
*locks
,
7985 connection_struct
*conn
= req
->conn
;
7987 NTSTATUS status
= NT_STATUS_OK
;
7991 /* Setup the timeout in seconds. */
7993 if (!lp_blocking_locks(SNUM(conn
))) {
7997 for(i
= 0; i
< (int)num_locks
; i
++) {
7998 struct smbd_lock_element
*e
= &locks
[i
];
8000 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8001 "%llu, file %s timeout = %d\n",
8004 (unsigned long long)e
->smblctx
,
8008 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8009 struct blocking_lock_record
*blr
= NULL
;
8011 if (num_locks
> 1) {
8013 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8014 * if the lock vector contains one entry. When given multiple cancel
8015 * requests in a single PDU we expect the server to return an
8016 * error. Windows servers seem to accept the request but only
8017 * cancel the first lock.
8018 * JRA - Do what Windows does (tm) :-).
8022 /* MS-CIFS (2.2.4.32.1) behavior. */
8023 return NT_STATUS_DOS(ERRDOS
,
8024 ERRcancelviolation
);
8026 /* Windows behavior. */
8028 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8029 "cancel request\n"));
8035 if (lp_blocking_locks(SNUM(conn
))) {
8037 /* Schedule a message to ourselves to
8038 remove the blocking lock record and
8039 return the right error. */
8041 blr
= blocking_lock_cancel_smb1(fsp
,
8047 NT_STATUS_FILE_LOCK_CONFLICT
);
8049 return NT_STATUS_DOS(
8051 ERRcancelviolation
);
8054 /* Remove a matching pending lock. */
8055 status
= do_lock_cancel(fsp
,
8061 bool blocking_lock
= timeout
? true : false;
8062 bool defer_lock
= false;
8063 struct byte_range_lock
*br_lck
;
8064 uint64_t block_smblctx
;
8066 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8077 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8078 /* Windows internal resolution for blocking locks seems
8079 to be about 200ms... Don't wait for less than that. JRA. */
8080 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8081 timeout
= lp_lock_spin_time();
8086 /* If a lock sent with timeout of zero would fail, and
8087 * this lock has been requested multiple times,
8088 * according to brl_lock_failed() we convert this
8089 * request to a blocking lock with a timeout of between
8090 * 150 - 300 milliseconds.
8092 * If lp_lock_spin_time() has been set to 0, we skip
8093 * this blocking retry and fail immediately.
8095 * Replacement for do_lock_spin(). JRA. */
8097 if (!req
->sconn
->using_smb2
&&
8098 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8099 lp_lock_spin_time() && !blocking_lock
&&
8100 NT_STATUS_EQUAL((status
),
8101 NT_STATUS_FILE_LOCK_CONFLICT
))
8104 timeout
= lp_lock_spin_time();
8107 if (br_lck
&& defer_lock
) {
8109 * A blocking lock was requested. Package up
8110 * this smb into a queued request and push it
8111 * onto the blocking lock queue.
8113 if(push_blocking_lock_request(br_lck
,
8124 TALLOC_FREE(br_lck
);
8126 return NT_STATUS_OK
;
8130 TALLOC_FREE(br_lck
);
8133 if (!NT_STATUS_IS_OK(status
)) {
8138 /* If any of the above locks failed, then we must unlock
8139 all of the previous locks (X/Open spec). */
8141 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8143 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8144 i
= -1; /* we want to skip the for loop */
8148 * Ensure we don't do a remove on the lock that just failed,
8149 * as under POSIX rules, if we have a lock already there, we
8150 * will delete it (and we shouldn't) .....
8152 for(i
--; i
>= 0; i
--) {
8153 struct smbd_lock_element
*e
= &locks
[i
];
8155 do_unlock(req
->sconn
->msg_ctx
,
8165 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8166 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8168 return NT_STATUS_OK
;
8171 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8173 uint16_t num_ulocks
,
8174 struct smbd_lock_element
*ulocks
)
8178 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8179 struct smbd_lock_element
*e
= &ulocks
[i
];
8182 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8183 "pid %u, file %s\n", __func__
,
8186 (unsigned int)e
->smblctx
,
8189 if (e
->brltype
!= UNLOCK_LOCK
) {
8190 /* this can only happen with SMB2 */
8191 return NT_STATUS_INVALID_PARAMETER
;
8194 status
= do_unlock(req
->sconn
->msg_ctx
,
8201 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8202 nt_errstr(status
)));
8204 if (!NT_STATUS_IS_OK(status
)) {
8209 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8212 return NT_STATUS_OK
;
8215 /****************************************************************************
8216 Reply to a lockingX request.
8217 ****************************************************************************/
8219 void reply_lockingX(struct smb_request
*req
)
8221 connection_struct
*conn
= req
->conn
;
8223 unsigned char locktype
;
8224 unsigned char oplocklevel
;
8225 uint16_t num_ulocks
;
8227 int32_t lock_timeout
;
8229 const uint8_t *data
;
8230 bool large_file_format
;
8231 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8232 struct smbd_lock_element
*ulocks
;
8233 struct smbd_lock_element
*locks
;
8236 START_PROFILE(SMBlockingX
);
8239 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8240 END_PROFILE(SMBlockingX
);
8244 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8245 locktype
= CVAL(req
->vwv
+3, 0);
8246 oplocklevel
= CVAL(req
->vwv
+3, 1);
8247 num_ulocks
= SVAL(req
->vwv
+6, 0);
8248 num_locks
= SVAL(req
->vwv
+7, 0);
8249 lock_timeout
= IVAL(req
->vwv
+4, 0);
8250 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8252 if (!check_fsp(conn
, req
, fsp
)) {
8253 END_PROFILE(SMBlockingX
);
8259 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8260 /* we don't support these - and CANCEL_LOCK makes w2k
8261 and XP reboot so I don't really want to be
8262 compatible! (tridge) */
8263 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8264 END_PROFILE(SMBlockingX
);
8268 /* Check if this is an oplock break on a file
8269 we have granted an oplock on.
8271 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8272 /* Client can insist on breaking to none. */
8273 bool break_to_none
= (oplocklevel
== 0);
8276 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8277 "for %s\n", (unsigned int)oplocklevel
,
8278 fsp_fnum_dbg(fsp
)));
8281 * Make sure we have granted an exclusive or batch oplock on
8285 if (fsp
->oplock_type
== 0) {
8287 /* The Samba4 nbench simulator doesn't understand
8288 the difference between break to level2 and break
8289 to none from level2 - it sends oplock break
8290 replies in both cases. Don't keep logging an error
8291 message here - just ignore it. JRA. */
8293 DEBUG(5,("reply_lockingX: Error : oplock break from "
8294 "client for %s (oplock=%d) and no "
8295 "oplock granted on this file (%s).\n",
8296 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8299 /* if this is a pure oplock break request then don't
8301 if (num_locks
== 0 && num_ulocks
== 0) {
8302 END_PROFILE(SMBlockingX
);
8305 END_PROFILE(SMBlockingX
);
8306 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8311 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8313 result
= remove_oplock(fsp
);
8315 result
= downgrade_oplock(fsp
);
8319 DEBUG(0, ("reply_lockingX: error in removing "
8320 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8321 /* Hmmm. Is this panic justified? */
8322 smb_panic("internal tdb error");
8325 /* if this is a pure oplock break request then don't send a
8327 if (num_locks
== 0 && num_ulocks
== 0) {
8328 /* Sanity check - ensure a pure oplock break is not a
8330 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8331 DEBUG(0,("reply_lockingX: Error : pure oplock "
8332 "break is a chained %d request !\n",
8333 (unsigned int)CVAL(req
->vwv
+0, 0)));
8335 END_PROFILE(SMBlockingX
);
8341 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8343 END_PROFILE(SMBlockingX
);
8347 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8348 if (ulocks
== NULL
) {
8349 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8350 END_PROFILE(SMBlockingX
);
8354 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8355 if (locks
== NULL
) {
8356 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8357 END_PROFILE(SMBlockingX
);
8361 /* Data now points at the beginning of the list
8362 of smb_unlkrng structs */
8363 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8364 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8365 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8366 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8367 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8370 /* Now do any requested locks */
8371 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8373 /* Data now points at the beginning of the list
8374 of smb_lkrng structs */
8376 for(i
= 0; i
< (int)num_locks
; i
++) {
8377 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8378 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8379 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8381 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8382 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8383 locks
[i
].brltype
= PENDING_READ_LOCK
;
8385 locks
[i
].brltype
= READ_LOCK
;
8388 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8389 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8391 locks
[i
].brltype
= WRITE_LOCK
;
8396 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8397 if (!NT_STATUS_IS_OK(status
)) {
8398 END_PROFILE(SMBlockingX
);
8399 reply_nterror(req
, status
);
8403 status
= smbd_do_locking(req
, fsp
,
8404 locktype
, lock_timeout
,
8407 if (!NT_STATUS_IS_OK(status
)) {
8408 END_PROFILE(SMBlockingX
);
8409 reply_nterror(req
, status
);
8413 END_PROFILE(SMBlockingX
);
8417 reply_outbuf(req
, 2, 0);
8418 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8419 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8421 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8422 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8424 END_PROFILE(SMBlockingX
);
8428 #define DBGC_CLASS DBGC_ALL
8430 /****************************************************************************
8431 Reply to a SMBreadbmpx (read block multiplex) request.
8432 Always reply with an error, if someone has a platform really needs this,
8433 please contact vl@samba.org
8434 ****************************************************************************/
8436 void reply_readbmpx(struct smb_request
*req
)
8438 START_PROFILE(SMBreadBmpx
);
8439 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8440 END_PROFILE(SMBreadBmpx
);
8444 /****************************************************************************
8445 Reply to a SMBreadbs (read block multiplex secondary) request.
8446 Always reply with an error, if someone has a platform really needs this,
8447 please contact vl@samba.org
8448 ****************************************************************************/
8450 void reply_readbs(struct smb_request
*req
)
8452 START_PROFILE(SMBreadBs
);
8453 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8454 END_PROFILE(SMBreadBs
);
8458 /****************************************************************************
8459 Reply to a SMBsetattrE.
8460 ****************************************************************************/
8462 void reply_setattrE(struct smb_request
*req
)
8464 connection_struct
*conn
= req
->conn
;
8465 struct smb_file_time ft
;
8469 START_PROFILE(SMBsetattrE
);
8473 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8477 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8479 if(!fsp
|| (fsp
->conn
!= conn
)) {
8480 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8485 * Convert the DOS times into unix times.
8488 ft
.atime
= convert_time_t_to_timespec(
8489 srv_make_unix_date2(req
->vwv
+3));
8490 ft
.mtime
= convert_time_t_to_timespec(
8491 srv_make_unix_date2(req
->vwv
+5));
8492 ft
.create_time
= convert_time_t_to_timespec(
8493 srv_make_unix_date2(req
->vwv
+1));
8495 reply_outbuf(req
, 0, 0);
8498 * Patch from Ray Frush <frush@engr.colostate.edu>
8499 * Sometimes times are sent as zero - ignore them.
8502 /* Ensure we have a valid stat struct for the source. */
8503 status
= vfs_stat_fsp(fsp
);
8504 if (!NT_STATUS_IS_OK(status
)) {
8505 reply_nterror(req
, status
);
8509 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8510 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8514 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8515 if (!NT_STATUS_IS_OK(status
)) {
8516 reply_nterror(req
, status
);
8520 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8523 (unsigned int)ft
.atime
.tv_sec
,
8524 (unsigned int)ft
.mtime
.tv_sec
,
8525 (unsigned int)ft
.create_time
.tv_sec
8528 END_PROFILE(SMBsetattrE
);
8533 /* Back from the dead for OS/2..... JRA. */
8535 /****************************************************************************
8536 Reply to a SMBwritebmpx (write block multiplex primary) request.
8537 Always reply with an error, if someone has a platform really needs this,
8538 please contact vl@samba.org
8539 ****************************************************************************/
8541 void reply_writebmpx(struct smb_request
*req
)
8543 START_PROFILE(SMBwriteBmpx
);
8544 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8545 END_PROFILE(SMBwriteBmpx
);
8549 /****************************************************************************
8550 Reply to a SMBwritebs (write block multiplex secondary) request.
8551 Always reply with an error, if someone has a platform really needs this,
8552 please contact vl@samba.org
8553 ****************************************************************************/
8555 void reply_writebs(struct smb_request
*req
)
8557 START_PROFILE(SMBwriteBs
);
8558 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8559 END_PROFILE(SMBwriteBs
);
8563 /****************************************************************************
8564 Reply to a SMBgetattrE.
8565 ****************************************************************************/
8567 void reply_getattrE(struct smb_request
*req
)
8569 connection_struct
*conn
= req
->conn
;
8572 struct timespec create_ts
;
8574 START_PROFILE(SMBgetattrE
);
8577 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8578 END_PROFILE(SMBgetattrE
);
8582 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8584 if(!fsp
|| (fsp
->conn
!= conn
)) {
8585 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8586 END_PROFILE(SMBgetattrE
);
8590 /* Do an fstat on this file */
8592 reply_nterror(req
, map_nt_error_from_unix(errno
));
8593 END_PROFILE(SMBgetattrE
);
8597 mode
= dos_mode(conn
, fsp
->fsp_name
);
8600 * Convert the times into dos times. Set create
8601 * date to be last modify date as UNIX doesn't save
8605 reply_outbuf(req
, 11, 0);
8607 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8608 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8609 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8610 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8611 /* Should we check pending modtime here ? JRA */
8612 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8613 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8615 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8616 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8617 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8619 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8620 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8621 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8623 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8625 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8627 END_PROFILE(SMBgetattrE
);