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(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 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3716 END_PROFILE(SMBreadbraw
);
3721 #define DBGC_CLASS DBGC_LOCKING
3723 /****************************************************************************
3724 Reply to a lockread (core+ protocol).
3725 ****************************************************************************/
3727 void reply_lockread(struct smb_request
*req
)
3729 connection_struct
*conn
= req
->conn
;
3737 struct byte_range_lock
*br_lck
= NULL
;
3739 struct smbXsrv_connection
*xconn
= req
->xconn
;
3741 START_PROFILE(SMBlockread
);
3744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3745 END_PROFILE(SMBlockread
);
3749 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3751 if (!check_fsp(conn
, req
, fsp
)) {
3752 END_PROFILE(SMBlockread
);
3756 if (!CHECK_READ(fsp
,req
)) {
3757 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3758 END_PROFILE(SMBlockread
);
3762 numtoread
= SVAL(req
->vwv
+1, 0);
3763 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3766 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3767 * protocol request that predates the read/write lock concept.
3768 * Thus instead of asking for a read lock here we need to ask
3769 * for a write lock. JRA.
3770 * Note that the requested lock size is unaffected by max_send.
3773 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3775 (uint64_t)req
->smbpid
,
3776 (uint64_t)numtoread
,
3780 False
, /* Non-blocking lock. */
3783 TALLOC_FREE(br_lck
);
3785 if (NT_STATUS_V(status
)) {
3786 reply_nterror(req
, status
);
3787 END_PROFILE(SMBlockread
);
3792 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3794 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3796 if (numtoread
> maxtoread
) {
3797 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3798 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3799 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3800 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3801 numtoread
= maxtoread
;
3804 reply_outbuf(req
, 5, numtoread
+ 3);
3806 data
= smb_buf(req
->outbuf
) + 3;
3808 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3811 reply_nterror(req
, map_nt_error_from_unix(errno
));
3812 END_PROFILE(SMBlockread
);
3816 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3818 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3819 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3820 p
= smb_buf(req
->outbuf
);
3821 SCVAL(p
,0,0); /* pad byte. */
3824 DEBUG(3,("lockread %s num=%d nread=%d\n",
3825 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3827 END_PROFILE(SMBlockread
);
3832 #define DBGC_CLASS DBGC_ALL
3834 /****************************************************************************
3836 ****************************************************************************/
3838 void reply_read(struct smb_request
*req
)
3840 connection_struct
*conn
= req
->conn
;
3847 struct lock_struct lock
;
3848 struct smbXsrv_connection
*xconn
= req
->xconn
;
3850 START_PROFILE(SMBread
);
3853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3854 END_PROFILE(SMBread
);
3858 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3860 if (!check_fsp(conn
, req
, fsp
)) {
3861 END_PROFILE(SMBread
);
3865 if (!CHECK_READ(fsp
,req
)) {
3866 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3867 END_PROFILE(SMBread
);
3871 numtoread
= SVAL(req
->vwv
+1, 0);
3872 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3875 * The requested read size cannot be greater than max_send. JRA.
3877 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3879 if (numtoread
> maxtoread
) {
3880 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3881 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3882 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3883 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3884 numtoread
= maxtoread
;
3887 reply_outbuf(req
, 5, numtoread
+3);
3889 data
= smb_buf(req
->outbuf
) + 3;
3891 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3892 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3895 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3896 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3897 END_PROFILE(SMBread
);
3902 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3905 reply_nterror(req
, map_nt_error_from_unix(errno
));
3909 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3911 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3912 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3913 SCVAL(smb_buf(req
->outbuf
),0,1);
3914 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3916 DEBUG(3, ("read %s num=%d nread=%d\n",
3917 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3920 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3922 END_PROFILE(SMBread
);
3926 /****************************************************************************
3928 ****************************************************************************/
3930 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3934 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3937 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3939 SCVAL(outbuf
,smb_vwv0
,0xFF);
3940 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3941 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3942 SSVAL(outbuf
,smb_vwv6
,
3943 (smb_wct
- 4) /* offset from smb header to wct */
3944 + 1 /* the wct field */
3945 + 12 * sizeof(uint16_t) /* vwv */
3946 + 2 /* the buflen field */
3947 + 1); /* padding byte */
3948 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3949 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3950 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3951 _smb_setlen_large(outbuf
,
3952 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3956 /****************************************************************************
3957 Reply to a read and X - possibly using sendfile.
3958 ****************************************************************************/
3960 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3961 files_struct
*fsp
, off_t startpos
,
3964 struct smbXsrv_connection
*xconn
= req
->xconn
;
3966 struct lock_struct lock
;
3967 int saved_errno
= 0;
3969 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3970 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3973 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3974 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3979 * We can only use sendfile on a non-chained packet
3980 * but we can use on a non-oplocked file. tridge proved this
3981 * on a train in Germany :-). JRA.
3984 if (!req_is_in_chain(req
) &&
3986 (fsp
->base_fsp
== NULL
) &&
3987 (fsp
->wcp
== NULL
) &&
3988 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3989 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3992 if(fsp_stat(fsp
) == -1) {
3993 reply_nterror(req
, map_nt_error_from_unix(errno
));
3997 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3998 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3999 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4001 * We already know that we would do a short read, so don't
4002 * try the sendfile() path.
4004 goto nosendfile_read
;
4008 * Set up the packet header before send. We
4009 * assume here the sendfile will work (get the
4010 * correct amount of data).
4013 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4015 construct_reply_common_req(req
, (char *)headerbuf
);
4016 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4018 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4019 startpos
, smb_maxcnt
);
4021 saved_errno
= errno
;
4023 /* Returning ENOSYS means no data at all was sent.
4024 Do this as a normal read. */
4025 if (errno
== ENOSYS
) {
4030 * Special hack for broken Linux with no working sendfile. If we
4031 * return EINTR we sent the header but not the rest of the data.
4032 * Fake this up by doing read/write calls.
4035 if (errno
== EINTR
) {
4036 /* Ensure we don't do this again. */
4037 set_use_sendfile(SNUM(conn
), False
);
4038 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4039 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4042 saved_errno
= errno
;
4043 DEBUG(0,("send_file_readX: "
4044 "fake_sendfile failed for "
4045 "file %s (%s) for client %s. "
4048 smbXsrv_connection_dbg(xconn
),
4049 strerror(saved_errno
)));
4050 errno
= saved_errno
;
4051 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4053 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4054 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4055 /* No outbuf here means successful sendfile. */
4059 DEBUG(0,("send_file_readX: sendfile failed for file "
4060 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4062 exit_server_cleanly("send_file_readX sendfile failed");
4063 } else if (nread
== 0) {
4065 * Some sendfile implementations return 0 to indicate
4066 * that there was a short read, but nothing was
4067 * actually written to the socket. In this case,
4068 * fallback to the normal read path so the header gets
4069 * the correct byte count.
4071 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4072 "falling back to the normal read: %s\n",
4077 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4078 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4080 /* Deal with possible short send. */
4081 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4084 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4085 sizeof(headerbuf
), smb_maxcnt
);
4088 r
= "send_file_readX: sendfile_short_send failed";
4089 DEBUG(0,("%s for file %s (%s).\n",
4090 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4091 exit_server_cleanly(r
);
4094 /* No outbuf here means successful sendfile. */
4095 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4096 SMB_PERFCOUNT_END(&req
->pcd
);
4102 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4103 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4106 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4107 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4108 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4110 * We already know that we would do a short
4111 * read, so don't try the sendfile() path.
4113 goto nosendfile_read
;
4116 construct_reply_common_req(req
, (char *)headerbuf
);
4117 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4119 /* Send out the header. */
4120 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4122 if (ret
!= sizeof(headerbuf
)) {
4123 saved_errno
= errno
;
4125 * Try and give an error message saying what
4128 DEBUG(0,("send_file_readX: write_data failed for file "
4129 "%s (%s) for client %s. Terminating\n",
4131 smbXsrv_connection_dbg(xconn
),
4132 strerror(saved_errno
)));
4133 errno
= saved_errno
;
4134 exit_server_cleanly("send_file_readX sendfile failed");
4136 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4138 saved_errno
= errno
;
4139 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4140 "%s (%s) for client %s. Terminating\n",
4142 smbXsrv_connection_dbg(xconn
),
4143 strerror(saved_errno
)));
4144 errno
= saved_errno
;
4145 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4152 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4153 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4154 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4156 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4157 startpos
, smb_maxcnt
);
4158 saved_errno
= errno
;
4160 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4163 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4167 setup_readX_header((char *)req
->outbuf
, nread
);
4169 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4170 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4174 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4175 TALLOC_FREE(req
->outbuf
);
4179 /****************************************************************************
4180 Work out how much space we have for a read return.
4181 ****************************************************************************/
4183 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4185 struct smbXsrv_connection
*xconn
= req
->xconn
;
4187 if (xconn
->protocol
< PROTOCOL_NT1
) {
4188 return xconn
->smb1
.sessions
.max_send
;
4191 if (!lp_large_readwrite()) {
4192 return xconn
->smb1
.sessions
.max_send
;
4195 if (req_is_in_chain(req
)) {
4196 return xconn
->smb1
.sessions
.max_send
;
4199 if (req
->encrypted
) {
4201 * Don't take encrypted traffic up to the
4202 * limit. There are padding considerations
4203 * that make that tricky.
4205 return xconn
->smb1
.sessions
.max_send
;
4208 if (srv_is_signing_active(xconn
)) {
4212 if (!lp_unix_extensions()) {
4217 * We can do ultra-large POSIX reads.
4222 /****************************************************************************
4223 Calculate how big a read can be. Copes with all clients. It's always
4224 safe to return a short read - Windows does this.
4225 ****************************************************************************/
4227 static size_t calc_read_size(const struct smb_request
*req
,
4231 struct smbXsrv_connection
*xconn
= req
->xconn
;
4232 size_t max_pdu
= calc_max_read_pdu(req
);
4233 size_t total_size
= 0;
4234 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4235 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4238 * Windows explicitly ignores upper size of 0xFFFF.
4239 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4240 * We must do the same as these will never fit even in
4241 * an extended size NetBIOS packet.
4243 if (upper_size
== 0xFFFF) {
4247 if (xconn
->protocol
< PROTOCOL_NT1
) {
4251 total_size
= ((upper_size
<<16) | lower_size
);
4254 * LARGE_READX test shows it's always safe to return
4255 * a short read. Windows does so.
4257 return MIN(total_size
, max_len
);
4260 /****************************************************************************
4261 Reply to a read and X.
4262 ****************************************************************************/
4264 void reply_read_and_X(struct smb_request
*req
)
4266 connection_struct
*conn
= req
->conn
;
4271 bool big_readX
= False
;
4273 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4276 START_PROFILE(SMBreadX
);
4278 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4279 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4283 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4284 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4285 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4287 /* If it's an IPC, pass off the pipe handler. */
4289 reply_pipe_read_and_X(req
);
4290 END_PROFILE(SMBreadX
);
4294 if (!check_fsp(conn
, req
, fsp
)) {
4295 END_PROFILE(SMBreadX
);
4299 if (!CHECK_READ(fsp
,req
)) {
4300 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4301 END_PROFILE(SMBreadX
);
4305 upper_size
= SVAL(req
->vwv
+7, 0);
4306 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4307 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4309 * This is a heuristic to avoid keeping large
4310 * outgoing buffers around over long-lived aio
4316 if (req
->wct
== 12) {
4318 * This is a large offset (64 bit) read.
4320 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4325 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4330 if (NT_STATUS_IS_OK(status
)) {
4331 /* Read scheduled - we're done. */
4334 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4335 /* Real error - report to client. */
4336 END_PROFILE(SMBreadX
);
4337 reply_nterror(req
, status
);
4340 /* NT_STATUS_RETRY - fall back to sync read. */
4343 smbd_lock_socket(req
->xconn
);
4344 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4345 smbd_unlock_socket(req
->xconn
);
4348 END_PROFILE(SMBreadX
);
4352 /****************************************************************************
4353 Error replies to writebraw must have smb_wct == 1. Fix this up.
4354 ****************************************************************************/
4356 void error_to_writebrawerr(struct smb_request
*req
)
4358 uint8_t *old_outbuf
= req
->outbuf
;
4360 reply_outbuf(req
, 1, 0);
4362 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4363 TALLOC_FREE(old_outbuf
);
4366 /****************************************************************************
4367 Read 4 bytes of a smb packet and return the smb length of the packet.
4368 Store the result in the buffer. This version of the function will
4369 never return a session keepalive (length of zero).
4370 Timeout is in milliseconds.
4371 ****************************************************************************/
4373 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4376 uint8_t msgtype
= NBSSkeepalive
;
4378 while (msgtype
== NBSSkeepalive
) {
4381 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4383 if (!NT_STATUS_IS_OK(status
)) {
4384 char addr
[INET6_ADDRSTRLEN
];
4385 /* Try and give an error message
4386 * saying what client failed. */
4387 DEBUG(0, ("read_fd_with_timeout failed for "
4388 "client %s read error = %s.\n",
4389 get_peer_addr(fd
,addr
,sizeof(addr
)),
4390 nt_errstr(status
)));
4394 msgtype
= CVAL(inbuf
, 0);
4397 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4398 (unsigned long)len
));
4400 return NT_STATUS_OK
;
4403 /****************************************************************************
4404 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4405 ****************************************************************************/
4407 void reply_writebraw(struct smb_request
*req
)
4409 connection_struct
*conn
= req
->conn
;
4410 struct smbXsrv_connection
*xconn
= req
->xconn
;
4413 ssize_t total_written
=0;
4414 size_t numtowrite
=0;
4417 const char *data
=NULL
;
4420 struct lock_struct lock
;
4423 START_PROFILE(SMBwritebraw
);
4426 * If we ever reply with an error, it must have the SMB command
4427 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4430 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4432 if (srv_is_signing_active(xconn
)) {
4433 END_PROFILE(SMBwritebraw
);
4434 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4435 "raw reads/writes are disallowed.");
4438 if (req
->wct
< 12) {
4439 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4440 error_to_writebrawerr(req
);
4441 END_PROFILE(SMBwritebraw
);
4445 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4446 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4447 "'async smb echo handler = yes'\n"));
4448 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4449 error_to_writebrawerr(req
);
4450 END_PROFILE(SMBwritebraw
);
4454 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4455 if (!check_fsp(conn
, req
, fsp
)) {
4456 error_to_writebrawerr(req
);
4457 END_PROFILE(SMBwritebraw
);
4461 if (!CHECK_WRITE(fsp
)) {
4462 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4463 error_to_writebrawerr(req
);
4464 END_PROFILE(SMBwritebraw
);
4468 tcount
= IVAL(req
->vwv
+1, 0);
4469 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4470 write_through
= BITSETW(req
->vwv
+7,0);
4472 /* We have to deal with slightly different formats depending
4473 on whether we are using the core+ or lanman1.0 protocol */
4475 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4476 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4477 data
= smb_buf_const(req
->inbuf
);
4479 numtowrite
= SVAL(req
->vwv
+10, 0);
4480 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4483 /* Ensure we don't write bytes past the end of this packet. */
4484 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4486 error_to_writebrawerr(req
);
4487 END_PROFILE(SMBwritebraw
);
4491 if (!fsp
->print_file
) {
4492 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4493 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4496 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4497 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4498 error_to_writebrawerr(req
);
4499 END_PROFILE(SMBwritebraw
);
4505 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4508 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4509 "wrote=%d sync=%d\n",
4510 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4511 (int)nwritten
, (int)write_through
));
4513 if (nwritten
< (ssize_t
)numtowrite
) {
4514 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4515 error_to_writebrawerr(req
);
4519 total_written
= nwritten
;
4521 /* Allocate a buffer of 64k + length. */
4522 buf
= talloc_array(NULL
, char, 65540);
4524 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4525 error_to_writebrawerr(req
);
4529 /* Return a SMBwritebraw message to the redirector to tell
4530 * it to send more bytes */
4532 memcpy(buf
, req
->inbuf
, smb_size
);
4533 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4534 SCVAL(buf
,smb_com
,SMBwritebraw
);
4535 SSVALS(buf
,smb_vwv0
,0xFFFF);
4537 if (!srv_send_smb(req
->xconn
,
4539 false, 0, /* no signing */
4540 IS_CONN_ENCRYPTED(conn
),
4542 exit_server_cleanly("reply_writebraw: srv_send_smb "
4546 /* Now read the raw data into the buffer and write it */
4547 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4549 if (!NT_STATUS_IS_OK(status
)) {
4550 exit_server_cleanly("secondary writebraw failed");
4553 /* Set up outbuf to return the correct size */
4554 reply_outbuf(req
, 1, 0);
4556 if (numtowrite
!= 0) {
4558 if (numtowrite
> 0xFFFF) {
4559 DEBUG(0,("reply_writebraw: Oversize secondary write "
4560 "raw requested (%u). Terminating\n",
4561 (unsigned int)numtowrite
));
4562 exit_server_cleanly("secondary writebraw failed");
4565 if (tcount
> nwritten
+numtowrite
) {
4566 DEBUG(3,("reply_writebraw: Client overestimated the "
4568 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4571 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4574 if (!NT_STATUS_IS_OK(status
)) {
4575 /* Try and give an error message
4576 * saying what client failed. */
4577 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4578 "raw read failed (%s) for client %s. "
4579 "Terminating\n", nt_errstr(status
),
4580 smbXsrv_connection_dbg(xconn
)));
4581 exit_server_cleanly("secondary writebraw failed");
4584 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4585 if (nwritten
== -1) {
4587 reply_nterror(req
, map_nt_error_from_unix(errno
));
4588 error_to_writebrawerr(req
);
4592 if (nwritten
< (ssize_t
)numtowrite
) {
4593 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4594 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4598 total_written
+= nwritten
;
4603 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4605 status
= sync_file(conn
, fsp
, write_through
);
4606 if (!NT_STATUS_IS_OK(status
)) {
4607 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4608 fsp_str_dbg(fsp
), nt_errstr(status
)));
4609 reply_nterror(req
, status
);
4610 error_to_writebrawerr(req
);
4614 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4616 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4617 (int)total_written
));
4619 if (!fsp
->print_file
) {
4620 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4623 /* We won't return a status if write through is not selected - this
4624 * follows what WfWg does */
4625 END_PROFILE(SMBwritebraw
);
4627 if (!write_through
&& total_written
==tcount
) {
4629 #if RABBIT_PELLET_FIX
4631 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4632 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4635 if (!send_keepalive(xconn
->transport
.sock
)) {
4636 exit_server_cleanly("reply_writebraw: send of "
4637 "keepalive failed");
4640 TALLOC_FREE(req
->outbuf
);
4645 if (!fsp
->print_file
) {
4646 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4649 END_PROFILE(SMBwritebraw
);
4654 #define DBGC_CLASS DBGC_LOCKING
4656 /****************************************************************************
4657 Reply to a writeunlock (core+).
4658 ****************************************************************************/
4660 void reply_writeunlock(struct smb_request
*req
)
4662 connection_struct
*conn
= req
->conn
;
4663 ssize_t nwritten
= -1;
4667 NTSTATUS status
= NT_STATUS_OK
;
4669 struct lock_struct lock
;
4670 int saved_errno
= 0;
4672 START_PROFILE(SMBwriteunlock
);
4675 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4676 END_PROFILE(SMBwriteunlock
);
4680 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4682 if (!check_fsp(conn
, req
, fsp
)) {
4683 END_PROFILE(SMBwriteunlock
);
4687 if (!CHECK_WRITE(fsp
)) {
4688 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4689 END_PROFILE(SMBwriteunlock
);
4693 numtowrite
= SVAL(req
->vwv
+1, 0);
4694 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4695 data
= (const char *)req
->buf
+ 3;
4697 if (!fsp
->print_file
&& numtowrite
> 0) {
4698 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4699 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4702 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4703 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4704 END_PROFILE(SMBwriteunlock
);
4709 /* The special X/Open SMB protocol handling of
4710 zero length writes is *NOT* done for
4712 if(numtowrite
== 0) {
4715 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4716 saved_errno
= errno
;
4719 status
= sync_file(conn
, fsp
, False
/* write through */);
4720 if (!NT_STATUS_IS_OK(status
)) {
4721 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4722 fsp_str_dbg(fsp
), nt_errstr(status
)));
4723 reply_nterror(req
, status
);
4728 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4732 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4733 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4737 if (numtowrite
&& !fsp
->print_file
) {
4738 status
= do_unlock(req
->sconn
->msg_ctx
,
4740 (uint64_t)req
->smbpid
,
4741 (uint64_t)numtowrite
,
4745 if (NT_STATUS_V(status
)) {
4746 reply_nterror(req
, status
);
4751 reply_outbuf(req
, 1, 0);
4753 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4755 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4756 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4759 if (numtowrite
&& !fsp
->print_file
) {
4760 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4763 END_PROFILE(SMBwriteunlock
);
4768 #define DBGC_CLASS DBGC_ALL
4770 /****************************************************************************
4772 ****************************************************************************/
4774 void reply_write(struct smb_request
*req
)
4776 connection_struct
*conn
= req
->conn
;
4778 ssize_t nwritten
= -1;
4782 struct lock_struct lock
;
4784 int saved_errno
= 0;
4786 START_PROFILE(SMBwrite
);
4789 END_PROFILE(SMBwrite
);
4790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4794 /* If it's an IPC, pass off the pipe handler. */
4796 reply_pipe_write(req
);
4797 END_PROFILE(SMBwrite
);
4801 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4803 if (!check_fsp(conn
, req
, fsp
)) {
4804 END_PROFILE(SMBwrite
);
4808 if (!CHECK_WRITE(fsp
)) {
4809 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4810 END_PROFILE(SMBwrite
);
4814 numtowrite
= SVAL(req
->vwv
+1, 0);
4815 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4816 data
= (const char *)req
->buf
+ 3;
4818 if (!fsp
->print_file
) {
4819 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4820 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4823 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4824 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4825 END_PROFILE(SMBwrite
);
4831 * X/Open SMB protocol says that if smb_vwv1 is
4832 * zero then the file size should be extended or
4833 * truncated to the size given in smb_vwv[2-3].
4836 if(numtowrite
== 0) {
4838 * This is actually an allocate call, and set EOF. JRA.
4840 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4842 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4845 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4847 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4850 trigger_write_time_update_immediate(fsp
);
4852 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4855 status
= sync_file(conn
, fsp
, False
);
4856 if (!NT_STATUS_IS_OK(status
)) {
4857 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4858 fsp_str_dbg(fsp
), nt_errstr(status
)));
4859 reply_nterror(req
, status
);
4864 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4868 if((nwritten
== 0) && (numtowrite
!= 0)) {
4869 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4873 reply_outbuf(req
, 1, 0);
4875 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4877 if (nwritten
< (ssize_t
)numtowrite
) {
4878 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4879 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4882 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4885 if (!fsp
->print_file
) {
4886 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4889 END_PROFILE(SMBwrite
);
4893 /****************************************************************************
4894 Ensure a buffer is a valid writeX for recvfile purposes.
4895 ****************************************************************************/
4897 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4898 (2*14) + /* word count (including bcc) */ \
4901 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4902 const uint8_t *inbuf
)
4905 unsigned int doff
= 0;
4906 size_t len
= smb_len_large(inbuf
);
4908 struct smbXsrv_open
*op
= NULL
;
4909 struct files_struct
*fsp
= NULL
;
4912 if (is_encrypted_packet(inbuf
)) {
4913 /* Can't do this on encrypted
4918 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4922 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4923 CVAL(inbuf
,smb_wct
) != 14) {
4924 DEBUG(10,("is_valid_writeX_buffer: chained or "
4925 "invalid word length.\n"));
4929 fnum
= SVAL(inbuf
, smb_vwv2
);
4930 status
= smb1srv_open_lookup(xconn
,
4934 if (!NT_STATUS_IS_OK(status
)) {
4935 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4940 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4943 if (fsp
->conn
== NULL
) {
4944 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4948 if (IS_IPC(fsp
->conn
)) {
4949 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4952 if (IS_PRINT(fsp
->conn
)) {
4953 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4956 doff
= SVAL(inbuf
,smb_vwv11
);
4958 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4960 if (len
> doff
&& len
- doff
> 0xFFFF) {
4961 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4964 if (numtowrite
== 0) {
4965 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4969 /* Ensure the sizes match up. */
4970 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4971 /* no pad byte...old smbclient :-( */
4972 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4974 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4978 if (len
- doff
!= numtowrite
) {
4979 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4980 "len = %u, doff = %u, numtowrite = %u\n",
4983 (unsigned int)numtowrite
));
4987 DEBUG(10,("is_valid_writeX_buffer: true "
4988 "len = %u, doff = %u, numtowrite = %u\n",
4991 (unsigned int)numtowrite
));
4996 /****************************************************************************
4997 Reply to a write and X.
4998 ****************************************************************************/
5000 void reply_write_and_X(struct smb_request
*req
)
5002 connection_struct
*conn
= req
->conn
;
5003 struct smbXsrv_connection
*xconn
= req
->xconn
;
5005 struct lock_struct lock
;
5010 unsigned int smb_doff
;
5011 unsigned int smblen
;
5014 int saved_errno
= 0;
5016 START_PROFILE(SMBwriteX
);
5018 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5019 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5023 numtowrite
= SVAL(req
->vwv
+10, 0);
5024 smb_doff
= SVAL(req
->vwv
+11, 0);
5025 smblen
= smb_len(req
->inbuf
);
5027 if (req
->unread_bytes
> 0xFFFF ||
5028 (smblen
> smb_doff
&&
5029 smblen
- smb_doff
> 0xFFFF)) {
5030 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5033 if (req
->unread_bytes
) {
5034 /* Can't do a recvfile write on IPC$ */
5036 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5039 if (numtowrite
!= req
->unread_bytes
) {
5040 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5044 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5045 smb_doff
+ numtowrite
> smblen
) {
5046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5051 /* If it's an IPC, pass off the pipe handler. */
5053 if (req
->unread_bytes
) {
5054 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5057 reply_pipe_write_and_X(req
);
5061 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5062 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5063 write_through
= BITSETW(req
->vwv
+7,0);
5065 if (!check_fsp(conn
, req
, fsp
)) {
5069 if (!CHECK_WRITE(fsp
)) {
5070 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5074 data
= smb_base(req
->inbuf
) + smb_doff
;
5076 if(req
->wct
== 14) {
5078 * This is a large offset (64 bit) write.
5080 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5084 /* X/Open SMB protocol says that, unlike SMBwrite
5085 if the length is zero then NO truncation is
5086 done, just a write of zero. To truncate a file,
5089 if(numtowrite
== 0) {
5092 if (req
->unread_bytes
== 0) {
5093 status
= schedule_aio_write_and_X(conn
,
5100 if (NT_STATUS_IS_OK(status
)) {
5101 /* write scheduled - we're done. */
5104 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5105 /* Real error - report to client. */
5106 reply_nterror(req
, status
);
5109 /* NT_STATUS_RETRY - fall through to sync write. */
5112 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5113 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5116 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5117 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5121 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5122 saved_errno
= errno
;
5124 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5128 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5132 if((nwritten
== 0) && (numtowrite
!= 0)) {
5133 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5137 reply_outbuf(req
, 6, 0);
5138 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5139 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5140 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5141 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5143 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5144 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5146 status
= sync_file(conn
, fsp
, write_through
);
5147 if (!NT_STATUS_IS_OK(status
)) {
5148 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5149 fsp_str_dbg(fsp
), nt_errstr(status
)));
5150 reply_nterror(req
, status
);
5154 END_PROFILE(SMBwriteX
);
5158 if (req
->unread_bytes
) {
5159 /* writeX failed. drain socket. */
5160 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5161 req
->unread_bytes
) {
5162 smb_panic("failed to drain pending bytes");
5164 req
->unread_bytes
= 0;
5167 END_PROFILE(SMBwriteX
);
5171 /****************************************************************************
5173 ****************************************************************************/
5175 void reply_lseek(struct smb_request
*req
)
5177 connection_struct
*conn
= req
->conn
;
5183 START_PROFILE(SMBlseek
);
5186 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5187 END_PROFILE(SMBlseek
);
5191 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5193 if (!check_fsp(conn
, req
, fsp
)) {
5197 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5199 mode
= SVAL(req
->vwv
+1, 0) & 3;
5200 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5201 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5210 res
= fsp
->fh
->pos
+ startpos
;
5221 if (umode
== SEEK_END
) {
5222 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5223 if(errno
== EINVAL
) {
5224 off_t current_pos
= startpos
;
5226 if(fsp_stat(fsp
) == -1) {
5228 map_nt_error_from_unix(errno
));
5229 END_PROFILE(SMBlseek
);
5233 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5235 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5240 reply_nterror(req
, map_nt_error_from_unix(errno
));
5241 END_PROFILE(SMBlseek
);
5248 reply_outbuf(req
, 2, 0);
5249 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5251 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5252 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5254 END_PROFILE(SMBlseek
);
5258 /****************************************************************************
5260 ****************************************************************************/
5262 void reply_flush(struct smb_request
*req
)
5264 connection_struct
*conn
= req
->conn
;
5268 START_PROFILE(SMBflush
);
5271 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5275 fnum
= SVAL(req
->vwv
+0, 0);
5276 fsp
= file_fsp(req
, fnum
);
5278 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5283 file_sync_all(conn
);
5285 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5286 if (!NT_STATUS_IS_OK(status
)) {
5287 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5288 fsp_str_dbg(fsp
), nt_errstr(status
)));
5289 reply_nterror(req
, status
);
5290 END_PROFILE(SMBflush
);
5295 reply_outbuf(req
, 0, 0);
5297 DEBUG(3,("flush\n"));
5298 END_PROFILE(SMBflush
);
5302 /****************************************************************************
5304 conn POINTER CAN BE NULL HERE !
5305 ****************************************************************************/
5307 void reply_exit(struct smb_request
*req
)
5309 START_PROFILE(SMBexit
);
5311 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5313 reply_outbuf(req
, 0, 0);
5315 DEBUG(3,("exit\n"));
5317 END_PROFILE(SMBexit
);
5321 struct reply_close_state
{
5323 struct smb_request
*smbreq
;
5326 static void do_smb1_close(struct tevent_req
*req
);
5328 void reply_close(struct smb_request
*req
)
5330 connection_struct
*conn
= req
->conn
;
5331 NTSTATUS status
= NT_STATUS_OK
;
5332 files_struct
*fsp
= NULL
;
5333 START_PROFILE(SMBclose
);
5336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5337 END_PROFILE(SMBclose
);
5341 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5344 * We can only use check_fsp if we know it's not a directory.
5347 if (!check_fsp_open(conn
, req
, fsp
)) {
5348 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5349 END_PROFILE(SMBclose
);
5353 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5354 fsp
->is_directory
? "directory" : "file",
5355 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5356 conn
->num_files_open
));
5358 if (!fsp
->is_directory
) {
5362 * Take care of any time sent in the close.
5365 t
= srv_make_unix_date3(req
->vwv
+1);
5366 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5369 if (fsp
->num_aio_requests
!= 0) {
5371 struct reply_close_state
*state
;
5373 DEBUG(10, ("closing with aio %u requests pending\n",
5374 fsp
->num_aio_requests
));
5377 * We depend on the aio_extra destructor to take care of this
5378 * close request once fsp->num_aio_request drops to 0.
5381 fsp
->deferred_close
= tevent_wait_send(
5382 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5383 if (fsp
->deferred_close
== NULL
) {
5384 status
= NT_STATUS_NO_MEMORY
;
5388 state
= talloc(fsp
, struct reply_close_state
);
5389 if (state
== NULL
) {
5390 TALLOC_FREE(fsp
->deferred_close
);
5391 status
= NT_STATUS_NO_MEMORY
;
5395 state
->smbreq
= talloc_move(fsp
, &req
);
5396 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5398 END_PROFILE(SMBclose
);
5403 * close_file() returns the unix errno if an error was detected on
5404 * close - normally this is due to a disk full error. If not then it
5405 * was probably an I/O error.
5408 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5410 if (!NT_STATUS_IS_OK(status
)) {
5411 reply_nterror(req
, status
);
5412 END_PROFILE(SMBclose
);
5416 reply_outbuf(req
, 0, 0);
5417 END_PROFILE(SMBclose
);
5421 static void do_smb1_close(struct tevent_req
*req
)
5423 struct reply_close_state
*state
= tevent_req_callback_data(
5424 req
, struct reply_close_state
);
5425 struct smb_request
*smbreq
;
5429 ret
= tevent_wait_recv(req
);
5432 DEBUG(10, ("tevent_wait_recv returned %s\n",
5435 * Continue anyway, this should never happen
5440 * fsp->smb2_close_request right now is a talloc grandchild of
5441 * fsp. When we close_file(fsp), it would go with it. No chance to
5444 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5446 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5447 if (NT_STATUS_IS_OK(status
)) {
5448 reply_outbuf(smbreq
, 0, 0);
5450 reply_nterror(smbreq
, status
);
5452 if (!srv_send_smb(smbreq
->xconn
,
5453 (char *)smbreq
->outbuf
,
5456 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5458 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5461 TALLOC_FREE(smbreq
);
5464 /****************************************************************************
5465 Reply to a writeclose (Core+ protocol).
5466 ****************************************************************************/
5468 void reply_writeclose(struct smb_request
*req
)
5470 connection_struct
*conn
= req
->conn
;
5472 ssize_t nwritten
= -1;
5473 NTSTATUS close_status
= NT_STATUS_OK
;
5476 struct timespec mtime
;
5478 struct lock_struct lock
;
5480 START_PROFILE(SMBwriteclose
);
5483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5484 END_PROFILE(SMBwriteclose
);
5488 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5490 if (!check_fsp(conn
, req
, fsp
)) {
5491 END_PROFILE(SMBwriteclose
);
5494 if (!CHECK_WRITE(fsp
)) {
5495 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5496 END_PROFILE(SMBwriteclose
);
5500 numtowrite
= SVAL(req
->vwv
+1, 0);
5501 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5502 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5503 data
= (const char *)req
->buf
+ 1;
5505 if (fsp
->print_file
== NULL
) {
5506 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5507 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5510 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5511 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5512 END_PROFILE(SMBwriteclose
);
5517 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5519 if (fsp
->print_file
== NULL
) {
5520 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5523 set_close_write_time(fsp
, mtime
);
5526 * More insanity. W2K only closes the file if writelen > 0.
5530 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5531 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5532 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5535 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5536 "file %s\n", fsp_str_dbg(fsp
)));
5537 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5541 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5542 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5546 if(!NT_STATUS_IS_OK(close_status
)) {
5547 reply_nterror(req
, close_status
);
5551 reply_outbuf(req
, 1, 0);
5553 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5557 END_PROFILE(SMBwriteclose
);
5562 #define DBGC_CLASS DBGC_LOCKING
5564 /****************************************************************************
5566 ****************************************************************************/
5568 void reply_lock(struct smb_request
*req
)
5570 connection_struct
*conn
= req
->conn
;
5571 uint64_t count
,offset
;
5574 struct byte_range_lock
*br_lck
= NULL
;
5576 START_PROFILE(SMBlock
);
5579 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5580 END_PROFILE(SMBlock
);
5584 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5586 if (!check_fsp(conn
, req
, fsp
)) {
5587 END_PROFILE(SMBlock
);
5591 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5592 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5594 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5595 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5597 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5599 (uint64_t)req
->smbpid
,
5604 False
, /* Non-blocking lock. */
5608 TALLOC_FREE(br_lck
);
5610 if (NT_STATUS_V(status
)) {
5611 reply_nterror(req
, status
);
5612 END_PROFILE(SMBlock
);
5616 reply_outbuf(req
, 0, 0);
5618 END_PROFILE(SMBlock
);
5622 /****************************************************************************
5624 ****************************************************************************/
5626 void reply_unlock(struct smb_request
*req
)
5628 connection_struct
*conn
= req
->conn
;
5629 uint64_t count
,offset
;
5633 START_PROFILE(SMBunlock
);
5636 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5637 END_PROFILE(SMBunlock
);
5641 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5643 if (!check_fsp(conn
, req
, fsp
)) {
5644 END_PROFILE(SMBunlock
);
5648 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5649 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5651 status
= do_unlock(req
->sconn
->msg_ctx
,
5653 (uint64_t)req
->smbpid
,
5658 if (NT_STATUS_V(status
)) {
5659 reply_nterror(req
, status
);
5660 END_PROFILE(SMBunlock
);
5664 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5665 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5667 reply_outbuf(req
, 0, 0);
5669 END_PROFILE(SMBunlock
);
5674 #define DBGC_CLASS DBGC_ALL
5676 /****************************************************************************
5678 conn POINTER CAN BE NULL HERE !
5679 ****************************************************************************/
5681 void reply_tdis(struct smb_request
*req
)
5684 connection_struct
*conn
= req
->conn
;
5685 struct smbXsrv_tcon
*tcon
;
5687 START_PROFILE(SMBtdis
);
5690 DEBUG(4,("Invalid connection in tdis\n"));
5691 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5692 END_PROFILE(SMBtdis
);
5700 * TODO: cancel all outstanding requests on the tcon
5702 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5703 if (!NT_STATUS_IS_OK(status
)) {
5704 DEBUG(0, ("reply_tdis: "
5705 "smbXsrv_tcon_disconnect() failed: %s\n",
5706 nt_errstr(status
)));
5708 * If we hit this case, there is something completely
5709 * wrong, so we better disconnect the transport connection.
5711 END_PROFILE(SMBtdis
);
5712 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5718 reply_outbuf(req
, 0, 0);
5719 END_PROFILE(SMBtdis
);
5723 /****************************************************************************
5725 conn POINTER CAN BE NULL HERE !
5726 ****************************************************************************/
5728 void reply_echo(struct smb_request
*req
)
5730 connection_struct
*conn
= req
->conn
;
5731 struct smb_perfcount_data local_pcd
;
5732 struct smb_perfcount_data
*cur_pcd
;
5736 START_PROFILE(SMBecho
);
5738 smb_init_perfcount_data(&local_pcd
);
5741 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5742 END_PROFILE(SMBecho
);
5746 smb_reverb
= SVAL(req
->vwv
+0, 0);
5748 reply_outbuf(req
, 1, req
->buflen
);
5750 /* copy any incoming data back out */
5751 if (req
->buflen
> 0) {
5752 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5755 if (smb_reverb
> 100) {
5756 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5760 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5762 /* this makes sure we catch the request pcd */
5763 if (seq_num
== smb_reverb
) {
5764 cur_pcd
= &req
->pcd
;
5766 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5767 cur_pcd
= &local_pcd
;
5770 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5772 show_msg((char *)req
->outbuf
);
5773 if (!srv_send_smb(req
->xconn
,
5774 (char *)req
->outbuf
,
5775 true, req
->seqnum
+1,
5776 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5778 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5781 DEBUG(3,("echo %d times\n", smb_reverb
));
5783 TALLOC_FREE(req
->outbuf
);
5785 END_PROFILE(SMBecho
);
5789 /****************************************************************************
5790 Reply to a printopen.
5791 ****************************************************************************/
5793 void reply_printopen(struct smb_request
*req
)
5795 connection_struct
*conn
= req
->conn
;
5799 START_PROFILE(SMBsplopen
);
5802 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5803 END_PROFILE(SMBsplopen
);
5807 if (!CAN_PRINT(conn
)) {
5808 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5809 END_PROFILE(SMBsplopen
);
5813 status
= file_new(req
, conn
, &fsp
);
5814 if(!NT_STATUS_IS_OK(status
)) {
5815 reply_nterror(req
, status
);
5816 END_PROFILE(SMBsplopen
);
5820 /* Open for exclusive use, write only. */
5821 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5823 if (!NT_STATUS_IS_OK(status
)) {
5824 file_free(req
, fsp
);
5825 reply_nterror(req
, status
);
5826 END_PROFILE(SMBsplopen
);
5830 reply_outbuf(req
, 1, 0);
5831 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5833 DEBUG(3,("openprint fd=%d %s\n",
5834 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5836 END_PROFILE(SMBsplopen
);
5840 /****************************************************************************
5841 Reply to a printclose.
5842 ****************************************************************************/
5844 void reply_printclose(struct smb_request
*req
)
5846 connection_struct
*conn
= req
->conn
;
5850 START_PROFILE(SMBsplclose
);
5853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5854 END_PROFILE(SMBsplclose
);
5858 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5860 if (!check_fsp(conn
, req
, fsp
)) {
5861 END_PROFILE(SMBsplclose
);
5865 if (!CAN_PRINT(conn
)) {
5866 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5867 END_PROFILE(SMBsplclose
);
5871 DEBUG(3,("printclose fd=%d %s\n",
5872 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5874 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5876 if(!NT_STATUS_IS_OK(status
)) {
5877 reply_nterror(req
, status
);
5878 END_PROFILE(SMBsplclose
);
5882 reply_outbuf(req
, 0, 0);
5884 END_PROFILE(SMBsplclose
);
5888 /****************************************************************************
5889 Reply to a printqueue.
5890 ****************************************************************************/
5892 void reply_printqueue(struct smb_request
*req
)
5894 connection_struct
*conn
= req
->conn
;
5898 START_PROFILE(SMBsplretq
);
5901 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5902 END_PROFILE(SMBsplretq
);
5906 max_count
= SVAL(req
->vwv
+0, 0);
5907 start_index
= SVAL(req
->vwv
+1, 0);
5909 /* we used to allow the client to get the cnum wrong, but that
5910 is really quite gross and only worked when there was only
5911 one printer - I think we should now only accept it if they
5912 get it right (tridge) */
5913 if (!CAN_PRINT(conn
)) {
5914 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5915 END_PROFILE(SMBsplretq
);
5919 reply_outbuf(req
, 2, 3);
5920 SSVAL(req
->outbuf
,smb_vwv0
,0);
5921 SSVAL(req
->outbuf
,smb_vwv1
,0);
5922 SCVAL(smb_buf(req
->outbuf
),0,1);
5923 SSVAL(smb_buf(req
->outbuf
),1,0);
5925 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5926 start_index
, max_count
));
5929 TALLOC_CTX
*mem_ctx
= talloc_tos();
5932 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5933 struct rpc_pipe_client
*cli
= NULL
;
5934 struct dcerpc_binding_handle
*b
= NULL
;
5935 struct policy_handle handle
;
5936 struct spoolss_DevmodeContainer devmode_ctr
;
5937 union spoolss_JobInfo
*info
;
5939 uint32_t num_to_get
;
5943 ZERO_STRUCT(handle
);
5945 status
= rpc_pipe_open_interface(conn
,
5948 conn
->sconn
->remote_address
,
5949 conn
->sconn
->local_address
,
5950 conn
->sconn
->msg_ctx
,
5952 if (!NT_STATUS_IS_OK(status
)) {
5953 DEBUG(0, ("reply_printqueue: "
5954 "could not connect to spoolss: %s\n",
5955 nt_errstr(status
)));
5956 reply_nterror(req
, status
);
5959 b
= cli
->binding_handle
;
5961 ZERO_STRUCT(devmode_ctr
);
5963 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5966 SEC_FLAG_MAXIMUM_ALLOWED
,
5969 if (!NT_STATUS_IS_OK(status
)) {
5970 reply_nterror(req
, status
);
5973 if (!W_ERROR_IS_OK(werr
)) {
5974 reply_nterror(req
, werror_to_ntstatus(werr
));
5978 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5986 if (!W_ERROR_IS_OK(werr
)) {
5987 reply_nterror(req
, werror_to_ntstatus(werr
));
5991 if (max_count
> 0) {
5992 first
= start_index
;
5994 first
= start_index
+ max_count
+ 1;
5997 if (first
>= count
) {
6000 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6003 for (i
= first
; i
< num_to_get
; i
++) {
6006 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6009 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6010 info
[i
].info2
.job_id
);
6012 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6018 srv_put_dos_date2(p
, 0, qtime
);
6019 SCVAL(p
, 4, qstatus
);
6020 SSVAL(p
, 5, qrapjobid
);
6021 SIVAL(p
, 7, info
[i
].info2
.size
);
6023 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6024 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6025 if (!NT_STATUS_IS_OK(status
)) {
6026 reply_nterror(req
, status
);
6029 if (message_push_blob(
6032 blob
, sizeof(blob
))) == -1) {
6033 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6039 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6040 SSVAL(req
->outbuf
,smb_vwv1
,
6041 (max_count
>0?first
+count
:first
-1));
6042 SCVAL(smb_buf(req
->outbuf
),0,1);
6043 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6047 DEBUG(3, ("%u entries returned in queue\n",
6051 if (b
&& is_valid_policy_hnd(&handle
)) {
6052 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6057 END_PROFILE(SMBsplretq
);
6061 /****************************************************************************
6062 Reply to a printwrite.
6063 ****************************************************************************/
6065 void reply_printwrite(struct smb_request
*req
)
6067 connection_struct
*conn
= req
->conn
;
6072 START_PROFILE(SMBsplwr
);
6075 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6076 END_PROFILE(SMBsplwr
);
6080 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6082 if (!check_fsp(conn
, req
, fsp
)) {
6083 END_PROFILE(SMBsplwr
);
6087 if (!fsp
->print_file
) {
6088 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6089 END_PROFILE(SMBsplwr
);
6093 if (!CHECK_WRITE(fsp
)) {
6094 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6095 END_PROFILE(SMBsplwr
);
6099 numtowrite
= SVAL(req
->buf
, 1);
6101 if (req
->buflen
< numtowrite
+ 3) {
6102 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6103 END_PROFILE(SMBsplwr
);
6107 data
= (const char *)req
->buf
+ 3;
6109 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6110 reply_nterror(req
, map_nt_error_from_unix(errno
));
6111 END_PROFILE(SMBsplwr
);
6115 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6117 END_PROFILE(SMBsplwr
);
6121 /****************************************************************************
6123 ****************************************************************************/
6125 void reply_mkdir(struct smb_request
*req
)
6127 connection_struct
*conn
= req
->conn
;
6128 struct smb_filename
*smb_dname
= NULL
;
6129 char *directory
= NULL
;
6132 TALLOC_CTX
*ctx
= talloc_tos();
6134 START_PROFILE(SMBmkdir
);
6136 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6137 STR_TERMINATE
, &status
);
6138 if (!NT_STATUS_IS_OK(status
)) {
6139 reply_nterror(req
, status
);
6143 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6144 status
= filename_convert(ctx
, conn
,
6149 if (!NT_STATUS_IS_OK(status
)) {
6150 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6151 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6152 ERRSRV
, ERRbadpath
);
6155 reply_nterror(req
, status
);
6159 status
= create_directory(conn
, req
, smb_dname
);
6161 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6163 if (!NT_STATUS_IS_OK(status
)) {
6165 if (!use_nt_status()
6166 && NT_STATUS_EQUAL(status
,
6167 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6169 * Yes, in the DOS error code case we get a
6170 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6171 * samba4 torture test.
6173 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6176 reply_nterror(req
, status
);
6180 reply_outbuf(req
, 0, 0);
6182 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6184 TALLOC_FREE(smb_dname
);
6185 END_PROFILE(SMBmkdir
);
6189 /****************************************************************************
6191 ****************************************************************************/
6193 void reply_rmdir(struct smb_request
*req
)
6195 connection_struct
*conn
= req
->conn
;
6196 struct smb_filename
*smb_dname
= NULL
;
6197 char *directory
= NULL
;
6199 TALLOC_CTX
*ctx
= talloc_tos();
6200 files_struct
*fsp
= NULL
;
6202 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6203 struct smbd_server_connection
*sconn
= req
->sconn
;
6205 START_PROFILE(SMBrmdir
);
6207 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6208 STR_TERMINATE
, &status
);
6209 if (!NT_STATUS_IS_OK(status
)) {
6210 reply_nterror(req
, status
);
6214 status
= filename_convert(ctx
, conn
,
6219 if (!NT_STATUS_IS_OK(status
)) {
6220 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6221 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6222 ERRSRV
, ERRbadpath
);
6225 reply_nterror(req
, status
);
6229 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6230 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6234 status
= SMB_VFS_CREATE_FILE(
6237 0, /* root_dir_fid */
6238 smb_dname
, /* fname */
6239 DELETE_ACCESS
, /* access_mask */
6240 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6242 FILE_OPEN
, /* create_disposition*/
6243 FILE_DIRECTORY_FILE
, /* create_options */
6244 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6245 0, /* oplock_request */
6247 0, /* allocation_size */
6248 0, /* private_flags */
6253 NULL
, NULL
); /* create context */
6255 if (!NT_STATUS_IS_OK(status
)) {
6256 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6257 /* We have re-scheduled this call. */
6260 reply_nterror(req
, status
);
6264 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6265 if (!NT_STATUS_IS_OK(status
)) {
6266 close_file(req
, fsp
, ERROR_CLOSE
);
6267 reply_nterror(req
, status
);
6271 if (!set_delete_on_close(fsp
, true,
6272 conn
->session_info
->security_token
,
6273 conn
->session_info
->unix_token
)) {
6274 close_file(req
, fsp
, ERROR_CLOSE
);
6275 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6279 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6280 if (!NT_STATUS_IS_OK(status
)) {
6281 reply_nterror(req
, status
);
6283 reply_outbuf(req
, 0, 0);
6286 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6288 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6290 TALLOC_FREE(smb_dname
);
6291 END_PROFILE(SMBrmdir
);
6295 /*******************************************************************
6296 Resolve wildcards in a filename rename.
6297 ********************************************************************/
6299 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6304 char *name2_copy
= NULL
;
6309 char *p
,*p2
, *pname1
, *pname2
;
6311 name2_copy
= talloc_strdup(ctx
, name2
);
6316 pname1
= strrchr_m(name1
,'/');
6317 pname2
= strrchr_m(name2_copy
,'/');
6319 if (!pname1
|| !pname2
) {
6323 /* Truncate the copy of name2 at the last '/' */
6326 /* Now go past the '/' */
6330 root1
= talloc_strdup(ctx
, pname1
);
6331 root2
= talloc_strdup(ctx
, pname2
);
6333 if (!root1
|| !root2
) {
6337 p
= strrchr_m(root1
,'.');
6340 ext1
= talloc_strdup(ctx
, p
+1);
6342 ext1
= talloc_strdup(ctx
, "");
6344 p
= strrchr_m(root2
,'.');
6347 ext2
= talloc_strdup(ctx
, p
+1);
6349 ext2
= talloc_strdup(ctx
, "");
6352 if (!ext1
|| !ext2
) {
6360 /* Hmmm. Should this be mb-aware ? */
6363 } else if (*p2
== '*') {
6365 root2
= talloc_asprintf(ctx
, "%s%s",
6384 /* Hmmm. Should this be mb-aware ? */
6387 } else if (*p2
== '*') {
6389 ext2
= talloc_asprintf(ctx
, "%s%s",
6405 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6410 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6422 /****************************************************************************
6423 Ensure open files have their names updated. Updated to notify other smbd's
6425 ****************************************************************************/
6427 static void rename_open_files(connection_struct
*conn
,
6428 struct share_mode_lock
*lck
,
6430 uint32_t orig_name_hash
,
6431 const struct smb_filename
*smb_fname_dst
)
6434 bool did_rename
= False
;
6436 uint32_t new_name_hash
= 0;
6438 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6439 fsp
= file_find_di_next(fsp
)) {
6440 /* fsp_name is a relative path under the fsp. To change this for other
6441 sharepaths we need to manipulate relative paths. */
6442 /* TODO - create the absolute path and manipulate the newname
6443 relative to the sharepath. */
6444 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6447 if (fsp
->name_hash
!= orig_name_hash
) {
6450 DEBUG(10, ("rename_open_files: renaming file %s "
6451 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6452 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6453 smb_fname_str_dbg(smb_fname_dst
)));
6455 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6456 if (NT_STATUS_IS_OK(status
)) {
6458 new_name_hash
= fsp
->name_hash
;
6463 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6464 "for %s\n", file_id_string_tos(&id
),
6465 smb_fname_str_dbg(smb_fname_dst
)));
6468 /* Send messages to all smbd's (not ourself) that the name has changed. */
6469 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6470 orig_name_hash
, new_name_hash
,
6475 /****************************************************************************
6476 We need to check if the source path is a parent directory of the destination
6477 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6478 refuse the rename with a sharing violation. Under UNIX the above call can
6479 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6480 probably need to check that the client is a Windows one before disallowing
6481 this as a UNIX client (one with UNIX extensions) can know the source is a
6482 symlink and make this decision intelligently. Found by an excellent bug
6483 report from <AndyLiebman@aol.com>.
6484 ****************************************************************************/
6486 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6487 const struct smb_filename
*smb_fname_dst
)
6489 const char *psrc
= smb_fname_src
->base_name
;
6490 const char *pdst
= smb_fname_dst
->base_name
;
6493 if (psrc
[0] == '.' && psrc
[1] == '/') {
6496 if (pdst
[0] == '.' && pdst
[1] == '/') {
6499 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6502 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6506 * Do the notify calls from a rename
6509 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6510 const struct smb_filename
*smb_fname_src
,
6511 const struct smb_filename
*smb_fname_dst
)
6513 char *parent_dir_src
= NULL
;
6514 char *parent_dir_dst
= NULL
;
6517 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6518 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6520 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6521 &parent_dir_src
, NULL
) ||
6522 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6523 &parent_dir_dst
, NULL
)) {
6527 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6528 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6529 smb_fname_src
->base_name
);
6530 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6531 smb_fname_dst
->base_name
);
6534 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6535 smb_fname_src
->base_name
);
6536 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6537 smb_fname_dst
->base_name
);
6540 /* this is a strange one. w2k3 gives an additional event for
6541 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6542 files, but not directories */
6544 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6545 FILE_NOTIFY_CHANGE_ATTRIBUTES
6546 |FILE_NOTIFY_CHANGE_CREATION
,
6547 smb_fname_dst
->base_name
);
6550 TALLOC_FREE(parent_dir_src
);
6551 TALLOC_FREE(parent_dir_dst
);
6554 /****************************************************************************
6555 Returns an error if the parent directory for a filename is open in an
6557 ****************************************************************************/
6559 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6560 const struct smb_filename
*smb_fname_dst_in
)
6562 char *parent_dir
= NULL
;
6563 struct smb_filename smb_fname_parent
;
6565 files_struct
*fsp
= NULL
;
6568 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6569 &parent_dir
, NULL
)) {
6570 return NT_STATUS_NO_MEMORY
;
6572 ZERO_STRUCT(smb_fname_parent
);
6573 smb_fname_parent
.base_name
= parent_dir
;
6575 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6577 return map_nt_error_from_unix(errno
);
6581 * We're only checking on this smbd here, mostly good
6582 * enough.. and will pass tests.
6585 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6586 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6587 fsp
= file_find_di_next(fsp
)) {
6588 if (fsp
->access_mask
& DELETE_ACCESS
) {
6589 return NT_STATUS_SHARING_VIOLATION
;
6592 return NT_STATUS_OK
;
6595 /****************************************************************************
6596 Rename an open file - given an fsp.
6597 ****************************************************************************/
6599 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6601 const struct smb_filename
*smb_fname_dst_in
,
6603 bool replace_if_exists
)
6605 TALLOC_CTX
*ctx
= talloc_tos();
6606 struct smb_filename
*smb_fname_dst
= NULL
;
6607 NTSTATUS status
= NT_STATUS_OK
;
6608 struct share_mode_lock
*lck
= NULL
;
6609 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6610 bool dst_exists
, old_is_stream
, new_is_stream
;
6612 status
= check_name(conn
, smb_fname_dst_in
);
6613 if (!NT_STATUS_IS_OK(status
)) {
6617 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6618 if (!NT_STATUS_IS_OK(status
)) {
6622 /* Make a copy of the dst smb_fname structs */
6624 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6625 if (smb_fname_dst
== NULL
) {
6626 status
= NT_STATUS_NO_MEMORY
;
6631 * Check for special case with case preserving and not
6632 * case sensitive. If the new last component differs from the original
6633 * last component only by case, then we should allow
6634 * the rename (user is trying to change the case of the
6637 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6638 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6639 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6640 char *fname_dst_parent
= NULL
;
6641 const char *fname_dst_lcomp
= NULL
;
6642 char *orig_lcomp_path
= NULL
;
6643 char *orig_lcomp_stream
= NULL
;
6647 * Split off the last component of the processed
6648 * destination name. We will compare this to
6649 * the split components of smb_fname_dst->original_lcomp.
6651 if (!parent_dirname(ctx
,
6652 smb_fname_dst
->base_name
,
6654 &fname_dst_lcomp
)) {
6655 status
= NT_STATUS_NO_MEMORY
;
6660 * The original_lcomp component contains
6661 * the last_component of the path + stream
6662 * name (if a stream exists).
6664 * Split off the stream name so we
6665 * can check them separately.
6668 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6669 /* POSIX - no stream component. */
6670 orig_lcomp_path
= talloc_strdup(ctx
,
6671 smb_fname_dst
->original_lcomp
);
6672 if (orig_lcomp_path
== NULL
) {
6676 ok
= split_stream_filename(ctx
,
6677 smb_fname_dst
->original_lcomp
,
6679 &orig_lcomp_stream
);
6683 TALLOC_FREE(fname_dst_parent
);
6684 status
= NT_STATUS_NO_MEMORY
;
6688 /* If the base names only differ by case, use original. */
6689 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6692 * Replace the modified last component with the
6695 if (!ISDOT(fname_dst_parent
)) {
6696 tmp
= talloc_asprintf(smb_fname_dst
,
6701 tmp
= talloc_strdup(smb_fname_dst
,
6705 status
= NT_STATUS_NO_MEMORY
;
6706 TALLOC_FREE(fname_dst_parent
);
6707 TALLOC_FREE(orig_lcomp_path
);
6708 TALLOC_FREE(orig_lcomp_stream
);
6711 TALLOC_FREE(smb_fname_dst
->base_name
);
6712 smb_fname_dst
->base_name
= tmp
;
6715 /* If the stream_names only differ by case, use original. */
6716 if(!strcsequal(smb_fname_dst
->stream_name
,
6717 orig_lcomp_stream
)) {
6718 /* Use the original stream. */
6719 char *tmp
= talloc_strdup(smb_fname_dst
,
6722 status
= NT_STATUS_NO_MEMORY
;
6723 TALLOC_FREE(fname_dst_parent
);
6724 TALLOC_FREE(orig_lcomp_path
);
6725 TALLOC_FREE(orig_lcomp_stream
);
6728 TALLOC_FREE(smb_fname_dst
->stream_name
);
6729 smb_fname_dst
->stream_name
= tmp
;
6731 TALLOC_FREE(fname_dst_parent
);
6732 TALLOC_FREE(orig_lcomp_path
);
6733 TALLOC_FREE(orig_lcomp_stream
);
6737 * If the src and dest names are identical - including case,
6738 * don't do the rename, just return success.
6741 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6742 strcsequal(fsp
->fsp_name
->stream_name
,
6743 smb_fname_dst
->stream_name
)) {
6744 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6745 "- returning success\n",
6746 smb_fname_str_dbg(smb_fname_dst
)));
6747 status
= NT_STATUS_OK
;
6751 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6752 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6754 /* Return the correct error code if both names aren't streams. */
6755 if (!old_is_stream
&& new_is_stream
) {
6756 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6760 if (old_is_stream
&& !new_is_stream
) {
6761 status
= NT_STATUS_INVALID_PARAMETER
;
6765 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6767 if(!replace_if_exists
&& dst_exists
) {
6768 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6769 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6770 smb_fname_str_dbg(smb_fname_dst
)));
6771 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6776 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6777 &smb_fname_dst
->st
);
6778 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6780 /* The file can be open when renaming a stream */
6781 if (dst_fsp
&& !new_is_stream
) {
6782 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6783 status
= NT_STATUS_ACCESS_DENIED
;
6788 /* Ensure we have a valid stat struct for the source. */
6789 status
= vfs_stat_fsp(fsp
);
6790 if (!NT_STATUS_IS_OK(status
)) {
6794 status
= can_rename(conn
, fsp
, attrs
);
6796 if (!NT_STATUS_IS_OK(status
)) {
6797 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6798 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6799 smb_fname_str_dbg(smb_fname_dst
)));
6800 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6801 status
= NT_STATUS_ACCESS_DENIED
;
6805 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6806 status
= NT_STATUS_ACCESS_DENIED
;
6810 /* Do we have rights to move into the destination ? */
6811 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6812 /* We're moving a directory. */
6813 access_mask
= SEC_DIR_ADD_SUBDIR
;
6815 status
= check_parent_access(conn
,
6818 if (!NT_STATUS_IS_OK(status
)) {
6819 DBG_INFO("check_parent_access on "
6820 "dst %s returned %s\n",
6821 smb_fname_str_dbg(smb_fname_dst
),
6826 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6829 * We have the file open ourselves, so not being able to get the
6830 * corresponding share mode lock is a fatal error.
6833 SMB_ASSERT(lck
!= NULL
);
6835 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6836 uint32_t create_options
= fsp
->fh
->private_options
;
6838 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6839 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6840 smb_fname_str_dbg(smb_fname_dst
)));
6842 if (!fsp
->is_directory
&&
6843 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6844 (lp_map_archive(SNUM(conn
)) ||
6845 lp_store_dos_attributes(SNUM(conn
)))) {
6846 /* We must set the archive bit on the newly
6848 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6849 uint32_t old_dosmode
= dos_mode(conn
,
6851 file_set_dosmode(conn
,
6853 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6859 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6862 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6866 * A rename acts as a new file create w.r.t. allowing an initial delete
6867 * on close, probably because in Windows there is a new handle to the
6868 * new file. If initial delete on close was requested but not
6869 * originally set, we need to set it here. This is probably not 100% correct,
6870 * but will work for the CIFSFS client which in non-posix mode
6871 * depends on these semantics. JRA.
6874 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6875 status
= can_set_delete_on_close(fsp
, 0);
6877 if (NT_STATUS_IS_OK(status
)) {
6878 /* Note that here we set the *inital* delete on close flag,
6879 * not the regular one. The magic gets handled in close. */
6880 fsp
->initial_delete_on_close
= True
;
6884 status
= NT_STATUS_OK
;
6890 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6891 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6893 status
= map_nt_error_from_unix(errno
);
6896 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6897 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6898 smb_fname_str_dbg(smb_fname_dst
)));
6901 TALLOC_FREE(smb_fname_dst
);
6906 /****************************************************************************
6907 The guts of the rename command, split out so it may be called by the NT SMB
6909 ****************************************************************************/
6911 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6912 connection_struct
*conn
,
6913 struct smb_request
*req
,
6914 struct smb_filename
*smb_fname_src
,
6915 struct smb_filename
*smb_fname_dst
,
6917 bool replace_if_exists
,
6920 uint32_t access_mask
)
6922 char *fname_src_dir
= NULL
;
6923 struct smb_filename
*smb_fname_src_dir
= NULL
;
6924 char *fname_src_mask
= NULL
;
6926 NTSTATUS status
= NT_STATUS_OK
;
6927 struct smb_Dir
*dir_hnd
= NULL
;
6928 const char *dname
= NULL
;
6929 char *talloced
= NULL
;
6931 int create_options
= 0;
6932 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6936 * Split the old name into directory and last component
6937 * strings. Note that unix_convert may have stripped off a
6938 * leading ./ from both name and newname if the rename is
6939 * at the root of the share. We need to make sure either both
6940 * name and newname contain a / character or neither of them do
6941 * as this is checked in resolve_wildcards().
6944 /* Split up the directory from the filename/mask. */
6945 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6946 &fname_src_dir
, &fname_src_mask
);
6947 if (!NT_STATUS_IS_OK(status
)) {
6948 status
= NT_STATUS_NO_MEMORY
;
6953 * We should only check the mangled cache
6954 * here if unix_convert failed. This means
6955 * that the path in 'mask' doesn't exist
6956 * on the file system and so we need to look
6957 * for a possible mangle. This patch from
6958 * Tine Smukavec <valentin.smukavec@hermes.si>.
6961 if (!VALID_STAT(smb_fname_src
->st
) &&
6962 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6963 char *new_mask
= NULL
;
6964 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6967 TALLOC_FREE(fname_src_mask
);
6968 fname_src_mask
= new_mask
;
6972 if (!src_has_wild
) {
6976 * Only one file needs to be renamed. Append the mask back
6977 * onto the directory.
6979 TALLOC_FREE(smb_fname_src
->base_name
);
6980 if (ISDOT(fname_src_dir
)) {
6981 /* Ensure we use canonical names on open. */
6982 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6986 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6991 if (!smb_fname_src
->base_name
) {
6992 status
= NT_STATUS_NO_MEMORY
;
6996 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6997 "case_preserve = %d, short case preserve = %d, "
6998 "directory = %s, newname = %s, "
6999 "last_component_dest = %s\n",
7000 conn
->case_sensitive
, conn
->case_preserve
,
7001 conn
->short_case_preserve
,
7002 smb_fname_str_dbg(smb_fname_src
),
7003 smb_fname_str_dbg(smb_fname_dst
),
7004 smb_fname_dst
->original_lcomp
));
7006 /* The dest name still may have wildcards. */
7007 if (dest_has_wild
) {
7008 char *fname_dst_mod
= NULL
;
7009 if (!resolve_wildcards(smb_fname_dst
,
7010 smb_fname_src
->base_name
,
7011 smb_fname_dst
->base_name
,
7013 DEBUG(6, ("rename_internals: resolve_wildcards "
7015 smb_fname_src
->base_name
,
7016 smb_fname_dst
->base_name
));
7017 status
= NT_STATUS_NO_MEMORY
;
7020 TALLOC_FREE(smb_fname_dst
->base_name
);
7021 smb_fname_dst
->base_name
= fname_dst_mod
;
7024 ZERO_STRUCT(smb_fname_src
->st
);
7025 if (posix_pathnames
) {
7026 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7028 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7031 status
= map_nt_error_from_unix_common(errno
);
7035 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7036 create_options
|= FILE_DIRECTORY_FILE
;
7039 status
= SMB_VFS_CREATE_FILE(
7042 0, /* root_dir_fid */
7043 smb_fname_src
, /* fname */
7044 access_mask
, /* access_mask */
7045 (FILE_SHARE_READ
| /* share_access */
7047 FILE_OPEN
, /* create_disposition*/
7048 create_options
, /* create_options */
7049 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7050 0, /* oplock_request */
7052 0, /* allocation_size */
7053 0, /* private_flags */
7058 NULL
, NULL
); /* create context */
7060 if (!NT_STATUS_IS_OK(status
)) {
7061 DEBUG(3, ("Could not open rename source %s: %s\n",
7062 smb_fname_str_dbg(smb_fname_src
),
7063 nt_errstr(status
)));
7067 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7068 attrs
, replace_if_exists
);
7070 close_file(req
, fsp
, NORMAL_CLOSE
);
7072 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7073 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7074 smb_fname_str_dbg(smb_fname_dst
)));
7080 * Wildcards - process each file that matches.
7082 if (strequal(fname_src_mask
, "????????.???")) {
7083 TALLOC_FREE(fname_src_mask
);
7084 fname_src_mask
= talloc_strdup(ctx
, "*");
7085 if (!fname_src_mask
) {
7086 status
= NT_STATUS_NO_MEMORY
;
7091 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7095 smb_fname_src
->flags
);
7096 if (smb_fname_src_dir
== NULL
) {
7097 status
= NT_STATUS_NO_MEMORY
;
7101 status
= check_name(conn
, smb_fname_src_dir
);
7102 if (!NT_STATUS_IS_OK(status
)) {
7106 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7108 if (dir_hnd
== NULL
) {
7109 status
= map_nt_error_from_unix(errno
);
7113 status
= NT_STATUS_NO_SUCH_FILE
;
7115 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7116 * - gentest fix. JRA
7119 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7121 files_struct
*fsp
= NULL
;
7122 char *destname
= NULL
;
7123 bool sysdir_entry
= False
;
7125 /* Quick check for "." and ".." */
7126 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7127 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7128 sysdir_entry
= True
;
7130 TALLOC_FREE(talloced
);
7135 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7136 &smb_fname_src
->st
, false)) {
7137 TALLOC_FREE(talloced
);
7141 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7142 TALLOC_FREE(talloced
);
7147 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7151 TALLOC_FREE(smb_fname_src
->base_name
);
7152 if (ISDOT(fname_src_dir
)) {
7153 /* Ensure we use canonical names on open. */
7154 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7158 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7163 if (!smb_fname_src
->base_name
) {
7164 status
= NT_STATUS_NO_MEMORY
;
7168 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7169 smb_fname_dst
->base_name
,
7171 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7172 smb_fname_src
->base_name
, destname
));
7173 TALLOC_FREE(talloced
);
7177 status
= NT_STATUS_NO_MEMORY
;
7181 TALLOC_FREE(smb_fname_dst
->base_name
);
7182 smb_fname_dst
->base_name
= destname
;
7184 ZERO_STRUCT(smb_fname_src
->st
);
7185 if (posix_pathnames
) {
7186 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7188 SMB_VFS_STAT(conn
, smb_fname_src
);
7193 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7194 create_options
|= FILE_DIRECTORY_FILE
;
7197 status
= SMB_VFS_CREATE_FILE(
7200 0, /* root_dir_fid */
7201 smb_fname_src
, /* fname */
7202 access_mask
, /* access_mask */
7203 (FILE_SHARE_READ
| /* share_access */
7205 FILE_OPEN
, /* create_disposition*/
7206 create_options
, /* create_options */
7207 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7208 0, /* oplock_request */
7210 0, /* allocation_size */
7211 0, /* private_flags */
7216 NULL
, NULL
); /* create context */
7218 if (!NT_STATUS_IS_OK(status
)) {
7219 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7220 "returned %s rename %s -> %s\n",
7222 smb_fname_str_dbg(smb_fname_src
),
7223 smb_fname_str_dbg(smb_fname_dst
)));
7227 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7229 if (!smb_fname_dst
->original_lcomp
) {
7230 status
= NT_STATUS_NO_MEMORY
;
7234 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7235 attrs
, replace_if_exists
);
7237 close_file(req
, fsp
, NORMAL_CLOSE
);
7239 if (!NT_STATUS_IS_OK(status
)) {
7240 DEBUG(3, ("rename_internals_fsp returned %s for "
7241 "rename %s -> %s\n", nt_errstr(status
),
7242 smb_fname_str_dbg(smb_fname_src
),
7243 smb_fname_str_dbg(smb_fname_dst
)));
7249 DEBUG(3,("rename_internals: doing rename on %s -> "
7250 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7251 smb_fname_str_dbg(smb_fname_src
)));
7252 TALLOC_FREE(talloced
);
7254 TALLOC_FREE(dir_hnd
);
7256 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7257 status
= map_nt_error_from_unix(errno
);
7261 TALLOC_FREE(talloced
);
7262 TALLOC_FREE(smb_fname_src_dir
);
7263 TALLOC_FREE(fname_src_dir
);
7264 TALLOC_FREE(fname_src_mask
);
7268 /****************************************************************************
7270 ****************************************************************************/
7272 void reply_mv(struct smb_request
*req
)
7274 connection_struct
*conn
= req
->conn
;
7276 char *newname
= NULL
;
7280 bool src_has_wcard
= False
;
7281 bool dest_has_wcard
= False
;
7282 TALLOC_CTX
*ctx
= talloc_tos();
7283 struct smb_filename
*smb_fname_src
= NULL
;
7284 struct smb_filename
*smb_fname_dst
= NULL
;
7285 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
) |
7286 (req
->posix_pathnames
?
7287 UCF_UNIX_NAME_LOOKUP
:
7288 UCF_COND_ALLOW_WCARD_LCOMP
);
7289 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
) |
7291 (req
->posix_pathnames
?
7293 UCF_COND_ALLOW_WCARD_LCOMP
);
7294 bool stream_rename
= false;
7296 START_PROFILE(SMBmv
);
7299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7303 attrs
= SVAL(req
->vwv
+0, 0);
7305 p
= (const char *)req
->buf
+ 1;
7306 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7307 &status
, &src_has_wcard
);
7308 if (!NT_STATUS_IS_OK(status
)) {
7309 reply_nterror(req
, status
);
7313 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7314 &status
, &dest_has_wcard
);
7315 if (!NT_STATUS_IS_OK(status
)) {
7316 reply_nterror(req
, status
);
7320 if (!req
->posix_pathnames
) {
7321 /* The newname must begin with a ':' if the
7322 name contains a ':'. */
7323 if (strchr_m(name
, ':')) {
7324 if (newname
[0] != ':') {
7325 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7328 stream_rename
= true;
7332 status
= filename_convert(ctx
,
7339 if (!NT_STATUS_IS_OK(status
)) {
7340 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7341 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7342 ERRSRV
, ERRbadpath
);
7345 reply_nterror(req
, status
);
7349 status
= filename_convert(ctx
,
7356 if (!NT_STATUS_IS_OK(status
)) {
7357 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7358 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7359 ERRSRV
, ERRbadpath
);
7362 reply_nterror(req
, status
);
7366 if (stream_rename
) {
7367 /* smb_fname_dst->base_name must be the same as
7368 smb_fname_src->base_name. */
7369 TALLOC_FREE(smb_fname_dst
->base_name
);
7370 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7371 smb_fname_src
->base_name
);
7372 if (!smb_fname_dst
->base_name
) {
7373 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7378 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7379 smb_fname_str_dbg(smb_fname_dst
)));
7381 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7382 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7384 if (!NT_STATUS_IS_OK(status
)) {
7385 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7386 /* We have re-scheduled this call. */
7389 reply_nterror(req
, status
);
7393 reply_outbuf(req
, 0, 0);
7395 TALLOC_FREE(smb_fname_src
);
7396 TALLOC_FREE(smb_fname_dst
);
7401 /*******************************************************************
7402 Copy a file as part of a reply_copy.
7403 ******************************************************************/
7406 * TODO: check error codes on all callers
7409 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7410 connection_struct
*conn
,
7411 struct smb_filename
*smb_fname_src
,
7412 struct smb_filename
*smb_fname_dst
,
7415 bool target_is_directory
)
7417 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7419 files_struct
*fsp1
,*fsp2
;
7421 uint32_t new_create_disposition
;
7425 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7426 if (smb_fname_dst_tmp
== NULL
) {
7427 return NT_STATUS_NO_MEMORY
;
7431 * If the target is a directory, extract the last component from the
7432 * src filename and append it to the dst filename
7434 if (target_is_directory
) {
7437 /* dest/target can't be a stream if it's a directory. */
7438 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7440 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7444 p
= smb_fname_src
->base_name
;
7446 smb_fname_dst_tmp
->base_name
=
7447 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7449 if (!smb_fname_dst_tmp
->base_name
) {
7450 status
= NT_STATUS_NO_MEMORY
;
7455 status
= vfs_file_exist(conn
, smb_fname_src
);
7456 if (!NT_STATUS_IS_OK(status
)) {
7460 if (!target_is_directory
&& count
) {
7461 new_create_disposition
= FILE_OPEN
;
7463 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7466 &new_create_disposition
,
7469 status
= NT_STATUS_INVALID_PARAMETER
;
7474 /* Open the src file for reading. */
7475 status
= SMB_VFS_CREATE_FILE(
7478 0, /* root_dir_fid */
7479 smb_fname_src
, /* fname */
7480 FILE_GENERIC_READ
, /* access_mask */
7481 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7482 FILE_OPEN
, /* create_disposition*/
7483 0, /* create_options */
7484 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7485 INTERNAL_OPEN_ONLY
, /* oplock_request */
7487 0, /* allocation_size */
7488 0, /* private_flags */
7493 NULL
, NULL
); /* create context */
7495 if (!NT_STATUS_IS_OK(status
)) {
7499 dosattrs
= dos_mode(conn
, smb_fname_src
);
7501 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7502 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7505 /* Open the dst file for writing. */
7506 status
= SMB_VFS_CREATE_FILE(
7509 0, /* root_dir_fid */
7510 smb_fname_dst
, /* fname */
7511 FILE_GENERIC_WRITE
, /* access_mask */
7512 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7513 new_create_disposition
, /* create_disposition*/
7514 0, /* create_options */
7515 dosattrs
, /* file_attributes */
7516 INTERNAL_OPEN_ONLY
, /* oplock_request */
7518 0, /* allocation_size */
7519 0, /* private_flags */
7524 NULL
, NULL
); /* create context */
7526 if (!NT_STATUS_IS_OK(status
)) {
7527 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7531 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7532 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7534 DEBUG(0, ("error - vfs lseek returned error %s\n",
7536 status
= map_nt_error_from_unix(errno
);
7537 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7538 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7543 /* Do the actual copy. */
7544 if (smb_fname_src
->st
.st_ex_size
) {
7545 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7550 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7552 /* Ensure the modtime is set correctly on the destination file. */
7553 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7556 * As we are opening fsp1 read-only we only expect
7557 * an error on close on fsp2 if we are out of space.
7558 * Thus we don't look at the error return from the
7561 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7563 if (!NT_STATUS_IS_OK(status
)) {
7567 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7568 status
= NT_STATUS_DISK_FULL
;
7572 status
= NT_STATUS_OK
;
7575 TALLOC_FREE(smb_fname_dst_tmp
);
7579 /****************************************************************************
7580 Reply to a file copy.
7581 ****************************************************************************/
7583 void reply_copy(struct smb_request
*req
)
7585 connection_struct
*conn
= req
->conn
;
7586 struct smb_filename
*smb_fname_src
= NULL
;
7587 struct smb_filename
*smb_fname_src_dir
= NULL
;
7588 struct smb_filename
*smb_fname_dst
= NULL
;
7589 char *fname_src
= NULL
;
7590 char *fname_dst
= NULL
;
7591 char *fname_src_mask
= NULL
;
7592 char *fname_src_dir
= NULL
;
7595 int error
= ERRnoaccess
;
7599 bool target_is_directory
=False
;
7600 bool source_has_wild
= False
;
7601 bool dest_has_wild
= False
;
7603 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7604 ucf_flags_from_smb_request(req
);
7605 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7606 ucf_flags_from_smb_request(req
);
7607 TALLOC_CTX
*ctx
= talloc_tos();
7609 START_PROFILE(SMBcopy
);
7612 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7616 tid2
= SVAL(req
->vwv
+0, 0);
7617 ofun
= SVAL(req
->vwv
+1, 0);
7618 flags
= SVAL(req
->vwv
+2, 0);
7620 p
= (const char *)req
->buf
;
7621 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7622 &status
, &source_has_wild
);
7623 if (!NT_STATUS_IS_OK(status
)) {
7624 reply_nterror(req
, status
);
7627 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7628 &status
, &dest_has_wild
);
7629 if (!NT_STATUS_IS_OK(status
)) {
7630 reply_nterror(req
, status
);
7634 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7636 if (tid2
!= conn
->cnum
) {
7637 /* can't currently handle inter share copies XXXX */
7638 DEBUG(3,("Rejecting inter-share copy\n"));
7639 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7643 status
= filename_convert(ctx
, conn
,
7648 if (!NT_STATUS_IS_OK(status
)) {
7649 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7650 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7651 ERRSRV
, ERRbadpath
);
7654 reply_nterror(req
, status
);
7658 status
= filename_convert(ctx
, conn
,
7663 if (!NT_STATUS_IS_OK(status
)) {
7664 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7665 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7666 ERRSRV
, ERRbadpath
);
7669 reply_nterror(req
, status
);
7673 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7675 if ((flags
&1) && target_is_directory
) {
7676 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7680 if ((flags
&2) && !target_is_directory
) {
7681 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7685 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7686 /* wants a tree copy! XXXX */
7687 DEBUG(3,("Rejecting tree copy\n"));
7688 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7692 /* Split up the directory from the filename/mask. */
7693 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7694 &fname_src_dir
, &fname_src_mask
);
7695 if (!NT_STATUS_IS_OK(status
)) {
7696 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7701 * We should only check the mangled cache
7702 * here if unix_convert failed. This means
7703 * that the path in 'mask' doesn't exist
7704 * on the file system and so we need to look
7705 * for a possible mangle. This patch from
7706 * Tine Smukavec <valentin.smukavec@hermes.si>.
7708 if (!VALID_STAT(smb_fname_src
->st
) &&
7709 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7710 char *new_mask
= NULL
;
7711 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7712 &new_mask
, conn
->params
);
7714 /* Use demangled name if one was successfully found. */
7716 TALLOC_FREE(fname_src_mask
);
7717 fname_src_mask
= new_mask
;
7721 if (!source_has_wild
) {
7724 * Only one file needs to be copied. Append the mask back onto
7727 TALLOC_FREE(smb_fname_src
->base_name
);
7728 if (ISDOT(fname_src_dir
)) {
7729 /* Ensure we use canonical names on open. */
7730 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7734 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7739 if (!smb_fname_src
->base_name
) {
7740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7744 if (dest_has_wild
) {
7745 char *fname_dst_mod
= NULL
;
7746 if (!resolve_wildcards(smb_fname_dst
,
7747 smb_fname_src
->base_name
,
7748 smb_fname_dst
->base_name
,
7750 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7753 TALLOC_FREE(smb_fname_dst
->base_name
);
7754 smb_fname_dst
->base_name
= fname_dst_mod
;
7757 status
= check_name(conn
, smb_fname_src
);
7758 if (!NT_STATUS_IS_OK(status
)) {
7759 reply_nterror(req
, status
);
7763 status
= check_name(conn
, smb_fname_dst
);
7764 if (!NT_STATUS_IS_OK(status
)) {
7765 reply_nterror(req
, status
);
7769 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7770 ofun
, count
, target_is_directory
);
7772 if(!NT_STATUS_IS_OK(status
)) {
7773 reply_nterror(req
, status
);
7779 struct smb_Dir
*dir_hnd
= NULL
;
7780 const char *dname
= NULL
;
7781 char *talloced
= NULL
;
7785 * There is a wildcard that requires us to actually read the
7786 * src dir and copy each file matching the mask to the dst.
7787 * Right now streams won't be copied, but this could
7788 * presumably be added with a nested loop for reach dir entry.
7790 SMB_ASSERT(!smb_fname_src
->stream_name
);
7791 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7793 smb_fname_src
->stream_name
= NULL
;
7794 smb_fname_dst
->stream_name
= NULL
;
7796 if (strequal(fname_src_mask
,"????????.???")) {
7797 TALLOC_FREE(fname_src_mask
);
7798 fname_src_mask
= talloc_strdup(ctx
, "*");
7799 if (!fname_src_mask
) {
7800 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7805 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7809 smb_fname_src
->flags
);
7810 if (smb_fname_src_dir
== NULL
) {
7811 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7815 status
= check_name(conn
, smb_fname_src_dir
);
7816 if (!NT_STATUS_IS_OK(status
)) {
7817 reply_nterror(req
, status
);
7821 dir_hnd
= OpenDir(ctx
,
7826 if (dir_hnd
== NULL
) {
7827 status
= map_nt_error_from_unix(errno
);
7828 reply_nterror(req
, status
);
7834 /* Iterate over the src dir copying each entry to the dst. */
7835 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7836 &smb_fname_src
->st
, &talloced
))) {
7837 char *destname
= NULL
;
7839 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7840 TALLOC_FREE(talloced
);
7844 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7845 &smb_fname_src
->st
, false)) {
7846 TALLOC_FREE(talloced
);
7850 if(!mask_match(dname
, fname_src_mask
,
7851 conn
->case_sensitive
)) {
7852 TALLOC_FREE(talloced
);
7856 error
= ERRnoaccess
;
7858 /* Get the src smb_fname struct setup. */
7859 TALLOC_FREE(smb_fname_src
->base_name
);
7860 if (ISDOT(fname_src_dir
)) {
7861 /* Ensure we use canonical names on open. */
7862 smb_fname_src
->base_name
=
7863 talloc_asprintf(smb_fname_src
, "%s",
7866 smb_fname_src
->base_name
=
7867 talloc_asprintf(smb_fname_src
, "%s/%s",
7868 fname_src_dir
, dname
);
7871 if (!smb_fname_src
->base_name
) {
7872 TALLOC_FREE(dir_hnd
);
7873 TALLOC_FREE(talloced
);
7874 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7878 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7879 smb_fname_dst
->base_name
,
7881 TALLOC_FREE(talloced
);
7885 TALLOC_FREE(dir_hnd
);
7886 TALLOC_FREE(talloced
);
7887 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7891 TALLOC_FREE(smb_fname_dst
->base_name
);
7892 smb_fname_dst
->base_name
= destname
;
7894 status
= check_name(conn
, smb_fname_src
);
7895 if (!NT_STATUS_IS_OK(status
)) {
7896 TALLOC_FREE(dir_hnd
);
7897 TALLOC_FREE(talloced
);
7898 reply_nterror(req
, status
);
7902 status
= check_name(conn
, smb_fname_dst
);
7903 if (!NT_STATUS_IS_OK(status
)) {
7904 TALLOC_FREE(dir_hnd
);
7905 TALLOC_FREE(talloced
);
7906 reply_nterror(req
, status
);
7910 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7911 smb_fname_src
->base_name
,
7912 smb_fname_dst
->base_name
));
7914 status
= copy_file(ctx
, conn
, smb_fname_src
,
7915 smb_fname_dst
, ofun
, count
,
7916 target_is_directory
);
7917 if (NT_STATUS_IS_OK(status
)) {
7921 TALLOC_FREE(talloced
);
7923 TALLOC_FREE(dir_hnd
);
7927 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7931 reply_outbuf(req
, 1, 0);
7932 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7934 TALLOC_FREE(smb_fname_src
);
7935 TALLOC_FREE(smb_fname_src_dir
);
7936 TALLOC_FREE(smb_fname_dst
);
7937 TALLOC_FREE(fname_src
);
7938 TALLOC_FREE(fname_dst
);
7939 TALLOC_FREE(fname_src_mask
);
7940 TALLOC_FREE(fname_src_dir
);
7942 END_PROFILE(SMBcopy
);
7947 #define DBGC_CLASS DBGC_LOCKING
7949 /****************************************************************************
7950 Get a lock pid, dealing with large count requests.
7951 ****************************************************************************/
7953 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7954 bool large_file_format
)
7956 if(!large_file_format
)
7957 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7959 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7962 /****************************************************************************
7963 Get a lock count, dealing with large count requests.
7964 ****************************************************************************/
7966 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7967 bool large_file_format
)
7971 if(!large_file_format
) {
7972 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7975 * No BVAL, this is reversed!
7977 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7978 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7984 /****************************************************************************
7985 Get a lock offset, dealing with large offset requests.
7986 ****************************************************************************/
7988 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7989 bool large_file_format
)
7991 uint64_t offset
= 0;
7993 if(!large_file_format
) {
7994 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7997 * No BVAL, this is reversed!
7999 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8000 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8006 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8011 struct smbd_lock_element
*locks
,
8014 connection_struct
*conn
= req
->conn
;
8016 NTSTATUS status
= NT_STATUS_OK
;
8020 /* Setup the timeout in seconds. */
8022 if (!lp_blocking_locks(SNUM(conn
))) {
8026 for(i
= 0; i
< (int)num_locks
; i
++) {
8027 struct smbd_lock_element
*e
= &locks
[i
];
8029 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8030 "%llu, file %s timeout = %d\n",
8033 (unsigned long long)e
->smblctx
,
8037 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8038 struct blocking_lock_record
*blr
= NULL
;
8040 if (num_locks
> 1) {
8042 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8043 * if the lock vector contains one entry. When given multiple cancel
8044 * requests in a single PDU we expect the server to return an
8045 * error. Windows servers seem to accept the request but only
8046 * cancel the first lock.
8047 * JRA - Do what Windows does (tm) :-).
8051 /* MS-CIFS (2.2.4.32.1) behavior. */
8052 return NT_STATUS_DOS(ERRDOS
,
8053 ERRcancelviolation
);
8055 /* Windows behavior. */
8057 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8058 "cancel request\n"));
8064 if (lp_blocking_locks(SNUM(conn
))) {
8066 /* Schedule a message to ourselves to
8067 remove the blocking lock record and
8068 return the right error. */
8070 blr
= blocking_lock_cancel_smb1(fsp
,
8076 NT_STATUS_FILE_LOCK_CONFLICT
);
8078 return NT_STATUS_DOS(
8080 ERRcancelviolation
);
8083 /* Remove a matching pending lock. */
8084 status
= do_lock_cancel(fsp
,
8090 bool blocking_lock
= timeout
? true : false;
8091 bool defer_lock
= false;
8092 struct byte_range_lock
*br_lck
;
8093 uint64_t block_smblctx
;
8095 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8106 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8107 /* Windows internal resolution for blocking locks seems
8108 to be about 200ms... Don't wait for less than that. JRA. */
8109 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8110 timeout
= lp_lock_spin_time();
8115 /* If a lock sent with timeout of zero would fail, and
8116 * this lock has been requested multiple times,
8117 * according to brl_lock_failed() we convert this
8118 * request to a blocking lock with a timeout of between
8119 * 150 - 300 milliseconds.
8121 * If lp_lock_spin_time() has been set to 0, we skip
8122 * this blocking retry and fail immediately.
8124 * Replacement for do_lock_spin(). JRA. */
8126 if (!req
->sconn
->using_smb2
&&
8127 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8128 lp_lock_spin_time() && !blocking_lock
&&
8129 NT_STATUS_EQUAL((status
),
8130 NT_STATUS_FILE_LOCK_CONFLICT
))
8133 timeout
= lp_lock_spin_time();
8136 if (br_lck
&& defer_lock
) {
8138 * A blocking lock was requested. Package up
8139 * this smb into a queued request and push it
8140 * onto the blocking lock queue.
8142 if(push_blocking_lock_request(br_lck
,
8153 TALLOC_FREE(br_lck
);
8155 return NT_STATUS_OK
;
8159 TALLOC_FREE(br_lck
);
8162 if (!NT_STATUS_IS_OK(status
)) {
8167 /* If any of the above locks failed, then we must unlock
8168 all of the previous locks (X/Open spec). */
8170 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8172 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8173 i
= -1; /* we want to skip the for loop */
8177 * Ensure we don't do a remove on the lock that just failed,
8178 * as under POSIX rules, if we have a lock already there, we
8179 * will delete it (and we shouldn't) .....
8181 for(i
--; i
>= 0; i
--) {
8182 struct smbd_lock_element
*e
= &locks
[i
];
8184 do_unlock(req
->sconn
->msg_ctx
,
8194 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8195 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8197 return NT_STATUS_OK
;
8200 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8202 uint16_t num_ulocks
,
8203 struct smbd_lock_element
*ulocks
)
8207 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8208 struct smbd_lock_element
*e
= &ulocks
[i
];
8211 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8212 "pid %u, file %s\n", __func__
,
8215 (unsigned int)e
->smblctx
,
8218 if (e
->brltype
!= UNLOCK_LOCK
) {
8219 /* this can only happen with SMB2 */
8220 return NT_STATUS_INVALID_PARAMETER
;
8223 status
= do_unlock(req
->sconn
->msg_ctx
,
8230 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8231 nt_errstr(status
)));
8233 if (!NT_STATUS_IS_OK(status
)) {
8238 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8241 return NT_STATUS_OK
;
8244 /****************************************************************************
8245 Reply to a lockingX request.
8246 ****************************************************************************/
8248 void reply_lockingX(struct smb_request
*req
)
8250 connection_struct
*conn
= req
->conn
;
8252 unsigned char locktype
;
8253 unsigned char oplocklevel
;
8254 uint16_t num_ulocks
;
8256 int32_t lock_timeout
;
8258 const uint8_t *data
;
8259 bool large_file_format
;
8260 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8261 struct smbd_lock_element
*ulocks
;
8262 struct smbd_lock_element
*locks
;
8265 START_PROFILE(SMBlockingX
);
8268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8269 END_PROFILE(SMBlockingX
);
8273 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8274 locktype
= CVAL(req
->vwv
+3, 0);
8275 oplocklevel
= CVAL(req
->vwv
+3, 1);
8276 num_ulocks
= SVAL(req
->vwv
+6, 0);
8277 num_locks
= SVAL(req
->vwv
+7, 0);
8278 lock_timeout
= IVAL(req
->vwv
+4, 0);
8279 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8281 if (!check_fsp(conn
, req
, fsp
)) {
8282 END_PROFILE(SMBlockingX
);
8288 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8289 /* we don't support these - and CANCEL_LOCK makes w2k
8290 and XP reboot so I don't really want to be
8291 compatible! (tridge) */
8292 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8293 END_PROFILE(SMBlockingX
);
8297 /* Check if this is an oplock break on a file
8298 we have granted an oplock on.
8300 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8301 /* Client can insist on breaking to none. */
8302 bool break_to_none
= (oplocklevel
== 0);
8305 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8306 "for %s\n", (unsigned int)oplocklevel
,
8307 fsp_fnum_dbg(fsp
)));
8310 * Make sure we have granted an exclusive or batch oplock on
8314 if (fsp
->oplock_type
== 0) {
8316 /* The Samba4 nbench simulator doesn't understand
8317 the difference between break to level2 and break
8318 to none from level2 - it sends oplock break
8319 replies in both cases. Don't keep logging an error
8320 message here - just ignore it. JRA. */
8322 DEBUG(5,("reply_lockingX: Error : oplock break from "
8323 "client for %s (oplock=%d) and no "
8324 "oplock granted on this file (%s).\n",
8325 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8328 /* if this is a pure oplock break request then don't
8330 if (num_locks
== 0 && num_ulocks
== 0) {
8331 END_PROFILE(SMBlockingX
);
8334 END_PROFILE(SMBlockingX
);
8335 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8340 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8342 result
= remove_oplock(fsp
);
8344 result
= downgrade_oplock(fsp
);
8348 DEBUG(0, ("reply_lockingX: error in removing "
8349 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8350 /* Hmmm. Is this panic justified? */
8351 smb_panic("internal tdb error");
8354 /* if this is a pure oplock break request then don't send a
8356 if (num_locks
== 0 && num_ulocks
== 0) {
8357 /* Sanity check - ensure a pure oplock break is not a
8359 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8360 DEBUG(0,("reply_lockingX: Error : pure oplock "
8361 "break is a chained %d request !\n",
8362 (unsigned int)CVAL(req
->vwv
+0, 0)));
8364 END_PROFILE(SMBlockingX
);
8370 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8371 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8372 END_PROFILE(SMBlockingX
);
8376 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8377 if (ulocks
== NULL
) {
8378 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8379 END_PROFILE(SMBlockingX
);
8383 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8384 if (locks
== NULL
) {
8385 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8386 END_PROFILE(SMBlockingX
);
8390 /* Data now points at the beginning of the list
8391 of smb_unlkrng structs */
8392 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8393 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8394 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8395 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8396 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8399 /* Now do any requested locks */
8400 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8402 /* Data now points at the beginning of the list
8403 of smb_lkrng structs */
8405 for(i
= 0; i
< (int)num_locks
; i
++) {
8406 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8407 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8408 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8410 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8411 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8412 locks
[i
].brltype
= PENDING_READ_LOCK
;
8414 locks
[i
].brltype
= READ_LOCK
;
8417 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8418 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8420 locks
[i
].brltype
= WRITE_LOCK
;
8425 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8426 if (!NT_STATUS_IS_OK(status
)) {
8427 END_PROFILE(SMBlockingX
);
8428 reply_nterror(req
, status
);
8432 status
= smbd_do_locking(req
, fsp
,
8433 locktype
, lock_timeout
,
8436 if (!NT_STATUS_IS_OK(status
)) {
8437 END_PROFILE(SMBlockingX
);
8438 reply_nterror(req
, status
);
8442 END_PROFILE(SMBlockingX
);
8446 reply_outbuf(req
, 2, 0);
8447 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8448 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8450 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8451 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8453 END_PROFILE(SMBlockingX
);
8457 #define DBGC_CLASS DBGC_ALL
8459 /****************************************************************************
8460 Reply to a SMBreadbmpx (read block multiplex) request.
8461 Always reply with an error, if someone has a platform really needs this,
8462 please contact vl@samba.org
8463 ****************************************************************************/
8465 void reply_readbmpx(struct smb_request
*req
)
8467 START_PROFILE(SMBreadBmpx
);
8468 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8469 END_PROFILE(SMBreadBmpx
);
8473 /****************************************************************************
8474 Reply to a SMBreadbs (read block multiplex secondary) request.
8475 Always reply with an error, if someone has a platform really needs this,
8476 please contact vl@samba.org
8477 ****************************************************************************/
8479 void reply_readbs(struct smb_request
*req
)
8481 START_PROFILE(SMBreadBs
);
8482 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8483 END_PROFILE(SMBreadBs
);
8487 /****************************************************************************
8488 Reply to a SMBsetattrE.
8489 ****************************************************************************/
8491 void reply_setattrE(struct smb_request
*req
)
8493 connection_struct
*conn
= req
->conn
;
8494 struct smb_file_time ft
;
8498 START_PROFILE(SMBsetattrE
);
8502 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8506 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8508 if(!fsp
|| (fsp
->conn
!= conn
)) {
8509 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8514 * Convert the DOS times into unix times.
8517 ft
.atime
= convert_time_t_to_timespec(
8518 srv_make_unix_date2(req
->vwv
+3));
8519 ft
.mtime
= convert_time_t_to_timespec(
8520 srv_make_unix_date2(req
->vwv
+5));
8521 ft
.create_time
= convert_time_t_to_timespec(
8522 srv_make_unix_date2(req
->vwv
+1));
8524 reply_outbuf(req
, 0, 0);
8527 * Patch from Ray Frush <frush@engr.colostate.edu>
8528 * Sometimes times are sent as zero - ignore them.
8531 /* Ensure we have a valid stat struct for the source. */
8532 status
= vfs_stat_fsp(fsp
);
8533 if (!NT_STATUS_IS_OK(status
)) {
8534 reply_nterror(req
, status
);
8538 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8539 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8543 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8544 if (!NT_STATUS_IS_OK(status
)) {
8545 reply_nterror(req
, status
);
8549 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8552 (unsigned int)ft
.atime
.tv_sec
,
8553 (unsigned int)ft
.mtime
.tv_sec
,
8554 (unsigned int)ft
.create_time
.tv_sec
8557 END_PROFILE(SMBsetattrE
);
8562 /* Back from the dead for OS/2..... JRA. */
8564 /****************************************************************************
8565 Reply to a SMBwritebmpx (write block multiplex primary) request.
8566 Always reply with an error, if someone has a platform really needs this,
8567 please contact vl@samba.org
8568 ****************************************************************************/
8570 void reply_writebmpx(struct smb_request
*req
)
8572 START_PROFILE(SMBwriteBmpx
);
8573 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8574 END_PROFILE(SMBwriteBmpx
);
8578 /****************************************************************************
8579 Reply to a SMBwritebs (write block multiplex secondary) request.
8580 Always reply with an error, if someone has a platform really needs this,
8581 please contact vl@samba.org
8582 ****************************************************************************/
8584 void reply_writebs(struct smb_request
*req
)
8586 START_PROFILE(SMBwriteBs
);
8587 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8588 END_PROFILE(SMBwriteBs
);
8592 /****************************************************************************
8593 Reply to a SMBgetattrE.
8594 ****************************************************************************/
8596 void reply_getattrE(struct smb_request
*req
)
8598 connection_struct
*conn
= req
->conn
;
8601 struct timespec create_ts
;
8603 START_PROFILE(SMBgetattrE
);
8606 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8607 END_PROFILE(SMBgetattrE
);
8611 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8613 if(!fsp
|| (fsp
->conn
!= conn
)) {
8614 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8615 END_PROFILE(SMBgetattrE
);
8619 /* Do an fstat on this file */
8621 reply_nterror(req
, map_nt_error_from_unix(errno
));
8622 END_PROFILE(SMBgetattrE
);
8626 mode
= dos_mode(conn
, fsp
->fsp_name
);
8629 * Convert the times into dos times. Set create
8630 * date to be last modify date as UNIX doesn't save
8634 reply_outbuf(req
, 11, 0);
8636 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8637 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8638 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8639 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8640 /* Should we check pending modtime here ? JRA */
8641 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8642 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8644 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8645 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8646 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8648 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8649 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8650 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8652 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8654 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8656 END_PROFILE(SMBgetattrE
);