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
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
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
,
1300 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1306 if (!NT_STATUS_IS_OK(status
)) {
1307 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1308 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1309 ERRSRV
, ERRbadpath
);
1310 END_PROFILE(SMBcheckpath
);
1316 if (!VALID_STAT(smb_fname
->st
) &&
1317 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1318 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1319 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1320 status
= map_nt_error_from_unix(errno
);
1324 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1325 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1326 ERRDOS
, ERRbadpath
);
1330 reply_outbuf(req
, 0, 0);
1333 /* We special case this - as when a Windows machine
1334 is parsing a path is steps through the components
1335 one at a time - if a component fails it expects
1336 ERRbadpath, not ERRbadfile.
1338 status
= map_checkpath_error(req
->flags2
, status
);
1339 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1341 * Windows returns different error codes if
1342 * the parent directory is valid but not the
1343 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1344 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1345 * if the path is invalid.
1347 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1348 ERRDOS
, ERRbadpath
);
1352 reply_nterror(req
, status
);
1355 TALLOC_FREE(smb_fname
);
1356 END_PROFILE(SMBcheckpath
);
1360 /****************************************************************************
1362 ****************************************************************************/
1364 void reply_getatr(struct smb_request
*req
)
1366 connection_struct
*conn
= req
->conn
;
1367 struct smb_filename
*smb_fname
= NULL
;
1374 TALLOC_CTX
*ctx
= talloc_tos();
1375 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1377 START_PROFILE(SMBgetatr
);
1379 p
= (const char *)req
->buf
+ 1;
1380 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1381 if (!NT_STATUS_IS_OK(status
)) {
1382 reply_nterror(req
, status
);
1386 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1387 under WfWg - weird! */
1388 if (*fname
== '\0') {
1389 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1390 if (!CAN_WRITE(conn
)) {
1391 mode
|= FILE_ATTRIBUTE_READONLY
;
1396 uint32_t ucf_flags
= (req
->posix_pathnames
?
1397 UCF_POSIX_PATHNAMES
: 0);
1398 status
= filename_convert(ctx
,
1400 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1405 if (!NT_STATUS_IS_OK(status
)) {
1406 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1407 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1408 ERRSRV
, ERRbadpath
);
1411 reply_nterror(req
, status
);
1414 if (!VALID_STAT(smb_fname
->st
) &&
1415 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1416 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1417 smb_fname_str_dbg(smb_fname
),
1419 reply_nterror(req
, map_nt_error_from_unix(errno
));
1423 mode
= dos_mode(conn
, smb_fname
);
1424 size
= smb_fname
->st
.st_ex_size
;
1426 if (ask_sharemode
) {
1427 struct timespec write_time_ts
;
1428 struct file_id fileid
;
1430 ZERO_STRUCT(write_time_ts
);
1431 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1432 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1433 if (!null_timespec(write_time_ts
)) {
1434 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1438 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1439 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1444 reply_outbuf(req
, 10, 0);
1446 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1447 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1448 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1450 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1452 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1454 if (get_Protocol() >= PROTOCOL_NT1
) {
1455 SSVAL(req
->outbuf
, smb_flg2
,
1456 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1459 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1460 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1463 TALLOC_FREE(smb_fname
);
1465 END_PROFILE(SMBgetatr
);
1469 /****************************************************************************
1471 ****************************************************************************/
1473 void reply_setatr(struct smb_request
*req
)
1475 struct smb_file_time ft
;
1476 connection_struct
*conn
= req
->conn
;
1477 struct smb_filename
*smb_fname
= NULL
;
1483 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1484 TALLOC_CTX
*ctx
= talloc_tos();
1486 START_PROFILE(SMBsetatr
);
1491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1495 p
= (const char *)req
->buf
+ 1;
1496 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1497 if (!NT_STATUS_IS_OK(status
)) {
1498 reply_nterror(req
, status
);
1502 status
= filename_convert(ctx
,
1504 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1509 if (!NT_STATUS_IS_OK(status
)) {
1510 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1511 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1512 ERRSRV
, ERRbadpath
);
1515 reply_nterror(req
, status
);
1519 if (smb_fname
->base_name
[0] == '.' &&
1520 smb_fname
->base_name
[1] == '\0') {
1522 * Not sure here is the right place to catch this
1523 * condition. Might be moved to somewhere else later -- vl
1525 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1529 mode
= SVAL(req
->vwv
+0, 0);
1530 mtime
= srv_make_unix_date3(req
->vwv
+1);
1532 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1533 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1534 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1536 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1538 status
= check_access(conn
, NULL
, smb_fname
,
1539 FILE_WRITE_ATTRIBUTES
);
1540 if (!NT_STATUS_IS_OK(status
)) {
1541 reply_nterror(req
, status
);
1545 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1547 reply_nterror(req
, map_nt_error_from_unix(errno
));
1552 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1553 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1554 if (!NT_STATUS_IS_OK(status
)) {
1555 reply_nterror(req
, status
);
1559 reply_outbuf(req
, 0, 0);
1561 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1564 TALLOC_FREE(smb_fname
);
1565 END_PROFILE(SMBsetatr
);
1569 /****************************************************************************
1571 ****************************************************************************/
1573 void reply_dskattr(struct smb_request
*req
)
1575 connection_struct
*conn
= req
->conn
;
1577 uint64_t dfree
,dsize
,bsize
;
1578 struct smb_filename smb_fname
;
1579 START_PROFILE(SMBdskattr
);
1581 ZERO_STRUCT(smb_fname
);
1582 smb_fname
.base_name
= discard_const_p(char, ".");
1584 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1585 reply_nterror(req
, map_nt_error_from_unix(errno
));
1586 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1587 END_PROFILE(SMBdskattr
);
1591 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1592 if (ret
== (uint64_t)-1) {
1593 reply_nterror(req
, map_nt_error_from_unix(errno
));
1594 END_PROFILE(SMBdskattr
);
1599 * Force max to fit in 16 bit fields.
1601 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1605 if (bsize
> (WORDMAX
*512)) {
1606 bsize
= (WORDMAX
*512);
1607 if (dsize
> WORDMAX
)
1609 if (dfree
> WORDMAX
)
1615 reply_outbuf(req
, 5, 0);
1617 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1618 double total_space
, free_space
;
1619 /* we need to scale this to a number that DOS6 can handle. We
1620 use floating point so we can handle large drives on systems
1621 that don't have 64 bit integers
1623 we end up displaying a maximum of 2G to DOS systems
1625 total_space
= dsize
* (double)bsize
;
1626 free_space
= dfree
* (double)bsize
;
1628 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1629 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1631 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1632 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1634 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1635 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1636 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1637 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1639 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1640 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1641 SSVAL(req
->outbuf
,smb_vwv2
,512);
1642 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1645 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1647 END_PROFILE(SMBdskattr
);
1652 * Utility function to split the filename from the directory.
1654 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1655 char **fname_dir_out
,
1656 char **fname_mask_out
)
1658 const char *p
= NULL
;
1659 char *fname_dir
= NULL
;
1660 char *fname_mask
= NULL
;
1662 p
= strrchr_m(fname_in
, '/');
1664 fname_dir
= talloc_strdup(ctx
, ".");
1665 fname_mask
= talloc_strdup(ctx
, fname_in
);
1667 fname_dir
= talloc_strndup(ctx
, fname_in
,
1668 PTR_DIFF(p
, fname_in
));
1669 fname_mask
= talloc_strdup(ctx
, p
+1);
1672 if (!fname_dir
|| !fname_mask
) {
1673 TALLOC_FREE(fname_dir
);
1674 TALLOC_FREE(fname_mask
);
1675 return NT_STATUS_NO_MEMORY
;
1678 *fname_dir_out
= fname_dir
;
1679 *fname_mask_out
= fname_mask
;
1680 return NT_STATUS_OK
;
1683 /****************************************************************************
1685 ****************************************************************************/
1687 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1697 char *mask2
= talloc_strdup(ctx
, mask
);
1703 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1707 memset(buf
+1,' ',11);
1708 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1710 push_ascii(buf
+1,mask2
,8, 0);
1711 push_ascii(buf
+9,p
+1,3, 0);
1714 push_ascii(buf
+1,mask2
,11, 0);
1717 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1719 srv_put_dos_date(buf
,22,date
);
1720 SSVAL(buf
,26,size
& 0xFFFF);
1721 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1722 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1723 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1724 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1725 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1729 /****************************************************************************
1731 Can be called from SMBsearch, SMBffirst or SMBfunique.
1732 ****************************************************************************/
1734 void reply_search(struct smb_request
*req
)
1736 connection_struct
*conn
= req
->conn
;
1739 char *directory
= NULL
;
1740 struct smb_filename
*smb_fname
= NULL
;
1744 struct timespec date
;
1746 unsigned int numentries
= 0;
1747 unsigned int maxentries
= 0;
1748 bool finished
= False
;
1753 bool check_descend
= False
;
1754 bool expect_close
= False
;
1756 bool mask_contains_wcard
= False
;
1757 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1758 TALLOC_CTX
*ctx
= talloc_tos();
1759 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1760 struct dptr_struct
*dirptr
= NULL
;
1761 struct smbXsrv_connection
*xconn
= req
->xconn
;
1762 struct smbd_server_connection
*sconn
= req
->sconn
;
1764 START_PROFILE(SMBsearch
);
1767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1771 if (req
->posix_pathnames
) {
1772 reply_unknown_new(req
, req
->cmd
);
1776 /* If we were called as SMBffirst then we must expect close. */
1777 if(req
->cmd
== SMBffirst
) {
1778 expect_close
= True
;
1781 reply_outbuf(req
, 1, 3);
1782 maxentries
= SVAL(req
->vwv
+0, 0);
1783 dirtype
= SVAL(req
->vwv
+1, 0);
1784 p
= (const char *)req
->buf
+ 1;
1785 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1786 &nt_status
, &mask_contains_wcard
);
1787 if (!NT_STATUS_IS_OK(nt_status
)) {
1788 reply_nterror(req
, nt_status
);
1793 status_len
= SVAL(p
, 0);
1796 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1798 if (status_len
== 0) {
1799 struct smb_filename
*smb_dname
= NULL
;
1800 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1801 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1802 nt_status
= filename_convert(ctx
, conn
,
1803 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1806 &mask_contains_wcard
,
1808 if (!NT_STATUS_IS_OK(nt_status
)) {
1809 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1810 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1811 ERRSRV
, ERRbadpath
);
1814 reply_nterror(req
, nt_status
);
1818 directory
= smb_fname
->base_name
;
1820 p
= strrchr_m(directory
,'/');
1821 if ((p
!= NULL
) && (*directory
!= '/')) {
1822 mask
= talloc_strdup(ctx
, p
+ 1);
1823 directory
= talloc_strndup(ctx
, directory
,
1824 PTR_DIFF(p
, directory
));
1826 mask
= talloc_strdup(ctx
, directory
);
1827 directory
= talloc_strdup(ctx
,".");
1831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1835 memset((char *)status
,'\0',21);
1836 SCVAL(status
,0,(dirtype
& 0x1F));
1838 smb_dname
= synthetic_smb_fname(talloc_tos(),
1843 if (smb_dname
== NULL
) {
1844 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1848 nt_status
= dptr_create(conn
,
1856 mask_contains_wcard
,
1860 TALLOC_FREE(smb_dname
);
1862 if (!NT_STATUS_IS_OK(nt_status
)) {
1863 reply_nterror(req
, nt_status
);
1866 dptr_num
= dptr_dnum(dirptr
);
1869 const char *dirpath
;
1871 memcpy(status
,p
,21);
1872 status_dirtype
= CVAL(status
,0) & 0x1F;
1873 if (status_dirtype
!= (dirtype
& 0x1F)) {
1874 dirtype
= status_dirtype
;
1877 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1881 dirpath
= dptr_path(sconn
, dptr_num
);
1882 directory
= talloc_strdup(ctx
, dirpath
);
1884 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1888 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1893 * For a 'continue' search we have no string. So
1894 * check from the initial saved string.
1896 if (!req
->posix_pathnames
) {
1897 mask_contains_wcard
= ms_has_wild(mask
);
1899 dirtype
= dptr_attr(sconn
, dptr_num
);
1902 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1904 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1905 dptr_init_search_op(dirptr
);
1907 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1908 char buf
[DIR_STRUCT_SIZE
];
1909 memcpy(buf
,status
,21);
1910 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1911 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1912 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1915 dptr_fill(sconn
, buf
+12,dptr_num
);
1916 if (dptr_zero(buf
+12) && (status_len
==0)) {
1921 if (message_push_blob(&req
->outbuf
,
1922 data_blob_const(buf
, sizeof(buf
)))
1924 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1929 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1930 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1932 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1934 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1935 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1936 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1937 check_descend
= True
;
1940 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1941 finished
= !get_dir_entry(ctx
,
1952 char buf
[DIR_STRUCT_SIZE
];
1953 memcpy(buf
,status
,21);
1954 if (!make_dir_struct(ctx
,
1960 convert_timespec_to_time_t(date
),
1961 !allow_long_path_components
)) {
1962 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1965 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1968 if (message_push_blob(&req
->outbuf
,
1969 data_blob_const(buf
, sizeof(buf
)))
1971 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1981 /* If we were called as SMBffirst with smb_search_id == NULL
1982 and no entries were found then return error and close dirptr
1985 if (numentries
== 0) {
1986 dptr_close(sconn
, &dptr_num
);
1987 } else if(expect_close
&& status_len
== 0) {
1988 /* Close the dptr - we know it's gone */
1989 dptr_close(sconn
, &dptr_num
);
1992 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1993 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1994 dptr_close(sconn
, &dptr_num
);
1997 if ((numentries
== 0) && !mask_contains_wcard
) {
1998 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2002 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2003 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2004 SCVAL(smb_buf(req
->outbuf
),0,5);
2005 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2007 /* The replies here are never long name. */
2008 SSVAL(req
->outbuf
, smb_flg2
,
2009 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2010 if (!allow_long_path_components
) {
2011 SSVAL(req
->outbuf
, smb_flg2
,
2012 SVAL(req
->outbuf
, smb_flg2
)
2013 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2016 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2017 SSVAL(req
->outbuf
, smb_flg2
,
2018 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2020 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2021 smb_fn_name(req
->cmd
),
2028 TALLOC_FREE(directory
);
2030 TALLOC_FREE(smb_fname
);
2031 END_PROFILE(SMBsearch
);
2035 /****************************************************************************
2036 Reply to a fclose (stop directory search).
2037 ****************************************************************************/
2039 void reply_fclose(struct smb_request
*req
)
2047 bool path_contains_wcard
= False
;
2048 TALLOC_CTX
*ctx
= talloc_tos();
2049 struct smbd_server_connection
*sconn
= req
->sconn
;
2051 START_PROFILE(SMBfclose
);
2053 if (req
->posix_pathnames
) {
2054 reply_unknown_new(req
, req
->cmd
);
2055 END_PROFILE(SMBfclose
);
2059 p
= (const char *)req
->buf
+ 1;
2060 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2061 &err
, &path_contains_wcard
);
2062 if (!NT_STATUS_IS_OK(err
)) {
2063 reply_nterror(req
, err
);
2064 END_PROFILE(SMBfclose
);
2068 status_len
= SVAL(p
,0);
2071 if (status_len
== 0) {
2072 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2073 END_PROFILE(SMBfclose
);
2077 memcpy(status
,p
,21);
2079 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2080 /* Close the dptr - we know it's gone */
2081 dptr_close(sconn
, &dptr_num
);
2084 reply_outbuf(req
, 1, 0);
2085 SSVAL(req
->outbuf
,smb_vwv0
,0);
2087 DEBUG(3,("search close\n"));
2089 END_PROFILE(SMBfclose
);
2093 /****************************************************************************
2095 ****************************************************************************/
2097 void reply_open(struct smb_request
*req
)
2099 connection_struct
*conn
= req
->conn
;
2100 struct smb_filename
*smb_fname
= NULL
;
2110 uint32_t access_mask
;
2111 uint32_t share_mode
;
2112 uint32_t create_disposition
;
2113 uint32_t create_options
= 0;
2114 uint32_t private_flags
= 0;
2117 TALLOC_CTX
*ctx
= talloc_tos();
2119 START_PROFILE(SMBopen
);
2122 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2126 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2127 deny_mode
= SVAL(req
->vwv
+0, 0);
2128 dos_attr
= SVAL(req
->vwv
+1, 0);
2130 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2131 STR_TERMINATE
, &status
);
2132 if (!NT_STATUS_IS_OK(status
)) {
2133 reply_nterror(req
, status
);
2137 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2138 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2139 &share_mode
, &create_disposition
,
2140 &create_options
, &private_flags
)) {
2141 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2145 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2147 status
= filename_convert(ctx
,
2149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2154 if (!NT_STATUS_IS_OK(status
)) {
2155 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2156 reply_botherror(req
,
2157 NT_STATUS_PATH_NOT_COVERED
,
2158 ERRSRV
, ERRbadpath
);
2161 reply_nterror(req
, status
);
2165 status
= SMB_VFS_CREATE_FILE(
2168 0, /* root_dir_fid */
2169 smb_fname
, /* fname */
2170 access_mask
, /* access_mask */
2171 share_mode
, /* share_access */
2172 create_disposition
, /* create_disposition*/
2173 create_options
, /* create_options */
2174 dos_attr
, /* file_attributes */
2175 oplock_request
, /* oplock_request */
2177 0, /* allocation_size */
2183 NULL
, NULL
); /* create context */
2185 if (!NT_STATUS_IS_OK(status
)) {
2186 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2187 /* We have re-scheduled this call. */
2190 reply_openerror(req
, status
);
2194 /* Ensure we're pointing at the correct stat struct. */
2195 TALLOC_FREE(smb_fname
);
2196 smb_fname
= fsp
->fsp_name
;
2198 size
= smb_fname
->st
.st_ex_size
;
2199 fattr
= dos_mode(conn
, smb_fname
);
2201 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2203 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2204 DEBUG(3,("attempt to open a directory %s\n",
2206 close_file(req
, fsp
, ERROR_CLOSE
);
2207 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2208 ERRDOS
, ERRnoaccess
);
2212 reply_outbuf(req
, 7, 0);
2213 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2214 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2215 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2216 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2218 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2220 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2221 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2223 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2224 SCVAL(req
->outbuf
,smb_flg
,
2225 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2228 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2229 SCVAL(req
->outbuf
,smb_flg
,
2230 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2233 END_PROFILE(SMBopen
);
2237 /****************************************************************************
2238 Reply to an open and X.
2239 ****************************************************************************/
2241 void reply_open_and_X(struct smb_request
*req
)
2243 connection_struct
*conn
= req
->conn
;
2244 struct smb_filename
*smb_fname
= NULL
;
2246 uint16_t open_flags
;
2249 /* Breakout the oplock request bits so we can set the
2250 reply bits separately. */
2251 int ex_oplock_request
;
2252 int core_oplock_request
;
2255 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2256 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2264 uint64_t allocation_size
;
2265 ssize_t retval
= -1;
2266 uint32_t access_mask
;
2267 uint32_t share_mode
;
2268 uint32_t create_disposition
;
2269 uint32_t create_options
= 0;
2270 uint32_t private_flags
= 0;
2272 TALLOC_CTX
*ctx
= talloc_tos();
2274 START_PROFILE(SMBopenX
);
2276 if (req
->wct
< 15) {
2277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2281 open_flags
= SVAL(req
->vwv
+2, 0);
2282 deny_mode
= SVAL(req
->vwv
+3, 0);
2283 smb_attr
= SVAL(req
->vwv
+5, 0);
2284 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2285 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2286 oplock_request
= ex_oplock_request
| core_oplock_request
;
2287 smb_ofun
= SVAL(req
->vwv
+8, 0);
2288 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2290 /* If it's an IPC, pass off the pipe handler. */
2292 if (lp_nt_pipe_support()) {
2293 reply_open_pipe_and_X(conn
, req
);
2295 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2300 /* XXXX we need to handle passed times, sattr and flags */
2301 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2302 STR_TERMINATE
, &status
);
2303 if (!NT_STATUS_IS_OK(status
)) {
2304 reply_nterror(req
, status
);
2308 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2310 &access_mask
, &share_mode
,
2311 &create_disposition
,
2314 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2318 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2320 status
= filename_convert(ctx
,
2322 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2327 if (!NT_STATUS_IS_OK(status
)) {
2328 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2329 reply_botherror(req
,
2330 NT_STATUS_PATH_NOT_COVERED
,
2331 ERRSRV
, ERRbadpath
);
2334 reply_nterror(req
, status
);
2338 status
= SMB_VFS_CREATE_FILE(
2341 0, /* root_dir_fid */
2342 smb_fname
, /* fname */
2343 access_mask
, /* access_mask */
2344 share_mode
, /* share_access */
2345 create_disposition
, /* create_disposition*/
2346 create_options
, /* create_options */
2347 smb_attr
, /* file_attributes */
2348 oplock_request
, /* oplock_request */
2350 0, /* allocation_size */
2355 &smb_action
, /* pinfo */
2356 NULL
, NULL
); /* create context */
2358 if (!NT_STATUS_IS_OK(status
)) {
2359 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2360 /* We have re-scheduled this call. */
2363 reply_openerror(req
, status
);
2367 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2368 if the file is truncated or created. */
2369 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2370 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2371 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2372 close_file(req
, fsp
, ERROR_CLOSE
);
2373 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2376 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2378 close_file(req
, fsp
, ERROR_CLOSE
);
2379 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2382 status
= vfs_stat_fsp(fsp
);
2383 if (!NT_STATUS_IS_OK(status
)) {
2384 close_file(req
, fsp
, ERROR_CLOSE
);
2385 reply_nterror(req
, status
);
2390 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2391 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2392 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2393 close_file(req
, fsp
, ERROR_CLOSE
);
2394 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2398 /* If the caller set the extended oplock request bit
2399 and we granted one (by whatever means) - set the
2400 correct bit for extended oplock reply.
2403 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2404 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2407 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2408 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2411 /* If the caller set the core oplock request bit
2412 and we granted one (by whatever means) - set the
2413 correct bit for core oplock reply.
2416 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2417 reply_outbuf(req
, 19, 0);
2419 reply_outbuf(req
, 15, 0);
2422 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2423 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2425 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2426 SCVAL(req
->outbuf
, smb_flg
,
2427 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2430 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2431 SCVAL(req
->outbuf
, smb_flg
,
2432 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2435 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2436 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2437 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2438 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2440 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2442 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2443 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2444 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2446 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2447 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2451 TALLOC_FREE(smb_fname
);
2452 END_PROFILE(SMBopenX
);
2456 /****************************************************************************
2457 Reply to a SMBulogoffX.
2458 ****************************************************************************/
2460 void reply_ulogoffX(struct smb_request
*req
)
2462 struct smbd_server_connection
*sconn
= req
->sconn
;
2463 struct user_struct
*vuser
;
2464 struct smbXsrv_session
*session
= NULL
;
2467 START_PROFILE(SMBulogoffX
);
2469 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2472 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2473 (unsigned long long)req
->vuid
));
2475 req
->vuid
= UID_FIELD_INVALID
;
2476 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2477 END_PROFILE(SMBulogoffX
);
2481 session
= vuser
->session
;
2485 * TODO: cancel all outstanding requests on the session
2487 status
= smbXsrv_session_logoff(session
);
2488 if (!NT_STATUS_IS_OK(status
)) {
2489 DEBUG(0, ("reply_ulogoff: "
2490 "smbXsrv_session_logoff() failed: %s\n",
2491 nt_errstr(status
)));
2493 * If we hit this case, there is something completely
2494 * wrong, so we better disconnect the transport connection.
2496 END_PROFILE(SMBulogoffX
);
2497 exit_server(__location__
": smbXsrv_session_logoff failed");
2501 TALLOC_FREE(session
);
2503 reply_outbuf(req
, 2, 0);
2504 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2505 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2507 DEBUG(3, ("ulogoffX vuid=%llu\n",
2508 (unsigned long long)req
->vuid
));
2510 END_PROFILE(SMBulogoffX
);
2511 req
->vuid
= UID_FIELD_INVALID
;
2514 /****************************************************************************
2515 Reply to a mknew or a create.
2516 ****************************************************************************/
2518 void reply_mknew(struct smb_request
*req
)
2520 connection_struct
*conn
= req
->conn
;
2521 struct smb_filename
*smb_fname
= NULL
;
2524 struct smb_file_time ft
;
2526 int oplock_request
= 0;
2528 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2529 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2530 uint32_t create_disposition
;
2531 uint32_t create_options
= 0;
2533 TALLOC_CTX
*ctx
= talloc_tos();
2535 START_PROFILE(SMBcreate
);
2539 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2543 fattr
= SVAL(req
->vwv
+0, 0);
2544 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2546 if (req
->cmd
== SMBmknew
) {
2547 /* We should fail if file exists. */
2548 create_disposition
= FILE_CREATE
;
2550 /* Create if file doesn't exist, truncate if it does. */
2551 create_disposition
= FILE_OVERWRITE_IF
;
2555 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2557 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2558 STR_TERMINATE
, &status
);
2559 if (!NT_STATUS_IS_OK(status
)) {
2560 reply_nterror(req
, status
);
2564 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2565 status
= filename_convert(ctx
,
2567 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2574 reply_botherror(req
,
2575 NT_STATUS_PATH_NOT_COVERED
,
2576 ERRSRV
, ERRbadpath
);
2579 reply_nterror(req
, status
);
2583 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2584 DEBUG(0,("Attempt to create file (%s) with volid set - "
2585 "please report this\n",
2586 smb_fname_str_dbg(smb_fname
)));
2589 status
= SMB_VFS_CREATE_FILE(
2592 0, /* root_dir_fid */
2593 smb_fname
, /* fname */
2594 access_mask
, /* access_mask */
2595 share_mode
, /* share_access */
2596 create_disposition
, /* create_disposition*/
2597 create_options
, /* create_options */
2598 fattr
, /* file_attributes */
2599 oplock_request
, /* oplock_request */
2601 0, /* allocation_size */
2602 0, /* private_flags */
2607 NULL
, NULL
); /* create context */
2609 if (!NT_STATUS_IS_OK(status
)) {
2610 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2611 /* We have re-scheduled this call. */
2614 reply_openerror(req
, status
);
2618 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2619 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2620 if (!NT_STATUS_IS_OK(status
)) {
2621 END_PROFILE(SMBcreate
);
2625 reply_outbuf(req
, 1, 0);
2626 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2628 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2629 SCVAL(req
->outbuf
,smb_flg
,
2630 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2633 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2634 SCVAL(req
->outbuf
,smb_flg
,
2635 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2638 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2639 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2640 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2641 (unsigned int)fattr
));
2644 TALLOC_FREE(smb_fname
);
2645 END_PROFILE(SMBcreate
);
2649 /****************************************************************************
2650 Reply to a create temporary file.
2651 ****************************************************************************/
2653 void reply_ctemp(struct smb_request
*req
)
2655 connection_struct
*conn
= req
->conn
;
2656 struct smb_filename
*smb_fname
= NULL
;
2657 char *wire_name
= NULL
;
2666 TALLOC_CTX
*ctx
= talloc_tos();
2668 START_PROFILE(SMBctemp
);
2671 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2675 fattr
= SVAL(req
->vwv
+0, 0);
2676 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2678 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2679 STR_TERMINATE
, &status
);
2680 if (!NT_STATUS_IS_OK(status
)) {
2681 reply_nterror(req
, status
);
2685 for (i
= 0; i
< 10; i
++) {
2687 fname
= talloc_asprintf(ctx
,
2690 generate_random_str_list(ctx
, 5, "0123456789"));
2692 fname
= talloc_asprintf(ctx
,
2694 generate_random_str_list(ctx
, 5, "0123456789"));
2698 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2702 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2703 status
= filename_convert(ctx
, conn
,
2704 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2709 if (!NT_STATUS_IS_OK(status
)) {
2710 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2711 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2712 ERRSRV
, ERRbadpath
);
2715 reply_nterror(req
, status
);
2719 /* Create the file. */
2720 status
= SMB_VFS_CREATE_FILE(
2723 0, /* root_dir_fid */
2724 smb_fname
, /* fname */
2725 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2726 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2727 FILE_CREATE
, /* create_disposition*/
2728 0, /* create_options */
2729 fattr
, /* file_attributes */
2730 oplock_request
, /* oplock_request */
2732 0, /* allocation_size */
2733 0, /* private_flags */
2738 NULL
, NULL
); /* create context */
2740 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2742 TALLOC_FREE(smb_fname
);
2746 if (!NT_STATUS_IS_OK(status
)) {
2747 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2748 /* We have re-scheduled this call. */
2751 reply_openerror(req
, status
);
2759 /* Collision after 10 times... */
2760 reply_nterror(req
, status
);
2764 reply_outbuf(req
, 1, 0);
2765 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2767 /* the returned filename is relative to the directory */
2768 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2770 s
= fsp
->fsp_name
->base_name
;
2776 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2777 thing in the byte section. JRA */
2778 SSVALS(p
, 0, -1); /* what is this? not in spec */
2780 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2782 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2786 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2787 SCVAL(req
->outbuf
, smb_flg
,
2788 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2791 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2792 SCVAL(req
->outbuf
, smb_flg
,
2793 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2796 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2797 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2798 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2800 TALLOC_FREE(smb_fname
);
2801 TALLOC_FREE(wire_name
);
2802 END_PROFILE(SMBctemp
);
2806 /*******************************************************************
2807 Check if a user is allowed to rename a file.
2808 ********************************************************************/
2810 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2813 if (!CAN_WRITE(conn
)) {
2814 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2817 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2818 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2819 /* Only bother to read the DOS attribute if we might deny the
2820 rename on the grounds of attribute mismatch. */
2821 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2822 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2823 return NT_STATUS_NO_SUCH_FILE
;
2827 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2828 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2829 return NT_STATUS_OK
;
2832 /* If no pathnames are open below this
2833 directory, allow the rename. */
2835 if (lp_strict_rename(SNUM(conn
))) {
2837 * Strict rename, check open file db.
2839 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2840 return NT_STATUS_ACCESS_DENIED
;
2842 } else if (file_find_subpath(fsp
)) {
2844 * No strict rename, just look in local process.
2846 return NT_STATUS_ACCESS_DENIED
;
2848 return NT_STATUS_OK
;
2851 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2852 return NT_STATUS_OK
;
2855 return NT_STATUS_ACCESS_DENIED
;
2858 /*******************************************************************
2859 * unlink a file with all relevant access checks
2860 *******************************************************************/
2862 static NTSTATUS
do_unlink(connection_struct
*conn
,
2863 struct smb_request
*req
,
2864 struct smb_filename
*smb_fname
,
2869 uint32_t dirtype_orig
= dirtype
;
2872 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2874 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2875 smb_fname_str_dbg(smb_fname
),
2878 if (!CAN_WRITE(conn
)) {
2879 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2883 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2885 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2888 return map_nt_error_from_unix(errno
);
2891 fattr
= dos_mode(conn
, smb_fname
);
2893 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2894 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2897 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2899 return NT_STATUS_NO_SUCH_FILE
;
2902 if (!dir_check_ftype(fattr
, dirtype
)) {
2903 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2904 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2906 return NT_STATUS_NO_SUCH_FILE
;
2909 if (dirtype_orig
& 0x8000) {
2910 /* These will never be set for POSIX. */
2911 return NT_STATUS_NO_SUCH_FILE
;
2915 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2916 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2919 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2920 return NT_STATUS_NO_SUCH_FILE
;
2923 if (dirtype
& 0xFF00) {
2924 /* These will never be set for POSIX. */
2925 return NT_STATUS_NO_SUCH_FILE
;
2930 return NT_STATUS_NO_SUCH_FILE
;
2933 /* Can't delete a directory. */
2934 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2935 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2940 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2941 return NT_STATUS_OBJECT_NAME_INVALID
;
2942 #endif /* JRATEST */
2944 /* On open checks the open itself will check the share mode, so
2945 don't do it here as we'll get it wrong. */
2947 status
= SMB_VFS_CREATE_FILE
2950 0, /* root_dir_fid */
2951 smb_fname
, /* fname */
2952 DELETE_ACCESS
, /* access_mask */
2953 FILE_SHARE_NONE
, /* share_access */
2954 FILE_OPEN
, /* create_disposition*/
2955 FILE_NON_DIRECTORY_FILE
, /* create_options */
2956 /* file_attributes */
2957 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2958 FILE_ATTRIBUTE_NORMAL
,
2959 0, /* oplock_request */
2961 0, /* allocation_size */
2962 0, /* private_flags */
2967 NULL
, NULL
); /* create context */
2969 if (!NT_STATUS_IS_OK(status
)) {
2970 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2971 nt_errstr(status
)));
2975 status
= can_set_delete_on_close(fsp
, fattr
);
2976 if (!NT_STATUS_IS_OK(status
)) {
2977 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2979 smb_fname_str_dbg(smb_fname
),
2980 nt_errstr(status
)));
2981 close_file(req
, fsp
, NORMAL_CLOSE
);
2985 /* The set is across all open files on this dev/inode pair. */
2986 if (!set_delete_on_close(fsp
, True
,
2987 conn
->session_info
->security_token
,
2988 conn
->session_info
->unix_token
)) {
2989 close_file(req
, fsp
, NORMAL_CLOSE
);
2990 return NT_STATUS_ACCESS_DENIED
;
2993 return close_file(req
, fsp
, NORMAL_CLOSE
);
2996 /****************************************************************************
2997 The guts of the unlink command, split out so it may be called by the NT SMB
2999 ****************************************************************************/
3001 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
3002 uint32_t dirtype
, struct smb_filename
*smb_fname
,
3005 char *fname_dir
= NULL
;
3006 char *fname_mask
= NULL
;
3008 NTSTATUS status
= NT_STATUS_OK
;
3009 struct smb_filename
*smb_fname_dir
= NULL
;
3010 TALLOC_CTX
*ctx
= talloc_tos();
3012 /* Split up the directory from the filename/mask. */
3013 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3014 &fname_dir
, &fname_mask
);
3015 if (!NT_STATUS_IS_OK(status
)) {
3020 * We should only check the mangled cache
3021 * here if unix_convert failed. This means
3022 * that the path in 'mask' doesn't exist
3023 * on the file system and so we need to look
3024 * for a possible mangle. This patch from
3025 * Tine Smukavec <valentin.smukavec@hermes.si>.
3028 if (!VALID_STAT(smb_fname
->st
) &&
3029 mangle_is_mangled(fname_mask
, conn
->params
)) {
3030 char *new_mask
= NULL
;
3031 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3032 &new_mask
, conn
->params
);
3034 TALLOC_FREE(fname_mask
);
3035 fname_mask
= new_mask
;
3042 * Only one file needs to be unlinked. Append the mask back
3043 * onto the directory.
3045 TALLOC_FREE(smb_fname
->base_name
);
3046 if (ISDOT(fname_dir
)) {
3047 /* Ensure we use canonical names on open. */
3048 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3052 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3057 if (!smb_fname
->base_name
) {
3058 status
= NT_STATUS_NO_MEMORY
;
3062 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3065 status
= check_name(conn
, smb_fname
->base_name
);
3066 if (!NT_STATUS_IS_OK(status
)) {
3070 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3071 if (!NT_STATUS_IS_OK(status
)) {
3077 struct smb_Dir
*dir_hnd
= NULL
;
3079 const char *dname
= NULL
;
3080 char *talloced
= NULL
;
3082 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3083 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3087 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3090 if (strequal(fname_mask
,"????????.???")) {
3091 TALLOC_FREE(fname_mask
);
3092 fname_mask
= talloc_strdup(ctx
, "*");
3094 status
= NT_STATUS_NO_MEMORY
;
3099 status
= check_name(conn
, fname_dir
);
3100 if (!NT_STATUS_IS_OK(status
)) {
3104 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3109 if (smb_fname_dir
== NULL
) {
3110 status
= NT_STATUS_NO_MEMORY
;
3114 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3116 if (dir_hnd
== NULL
) {
3117 status
= map_nt_error_from_unix(errno
);
3121 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3122 the pattern matches against the long name, otherwise the short name
3123 We don't implement this yet XXXX
3126 status
= NT_STATUS_NO_SUCH_FILE
;
3128 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3129 &smb_fname
->st
, &talloced
))) {
3130 TALLOC_CTX
*frame
= talloc_stackframe();
3132 if (!is_visible_file(conn
, fname_dir
, dname
,
3133 &smb_fname
->st
, true)) {
3135 TALLOC_FREE(talloced
);
3139 /* Quick check for "." and ".." */
3140 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3142 TALLOC_FREE(talloced
);
3146 if(!mask_match(dname
, fname_mask
,
3147 conn
->case_sensitive
)) {
3149 TALLOC_FREE(talloced
);
3153 TALLOC_FREE(smb_fname
->base_name
);
3154 if (ISDOT(fname_dir
)) {
3155 /* Ensure we use canonical names on open. */
3156 smb_fname
->base_name
=
3157 talloc_asprintf(smb_fname
, "%s",
3160 smb_fname
->base_name
=
3161 talloc_asprintf(smb_fname
, "%s/%s",
3165 if (!smb_fname
->base_name
) {
3166 TALLOC_FREE(dir_hnd
);
3167 status
= NT_STATUS_NO_MEMORY
;
3169 TALLOC_FREE(talloced
);
3173 status
= check_name(conn
, smb_fname
->base_name
);
3174 if (!NT_STATUS_IS_OK(status
)) {
3175 TALLOC_FREE(dir_hnd
);
3177 TALLOC_FREE(talloced
);
3181 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3182 if (!NT_STATUS_IS_OK(status
)) {
3183 TALLOC_FREE(dir_hnd
);
3185 TALLOC_FREE(talloced
);
3190 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3191 smb_fname
->base_name
));
3194 TALLOC_FREE(talloced
);
3196 TALLOC_FREE(dir_hnd
);
3199 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3200 status
= map_nt_error_from_unix(errno
);
3204 TALLOC_FREE(smb_fname_dir
);
3205 TALLOC_FREE(fname_dir
);
3206 TALLOC_FREE(fname_mask
);
3210 /****************************************************************************
3212 ****************************************************************************/
3214 void reply_unlink(struct smb_request
*req
)
3216 connection_struct
*conn
= req
->conn
;
3218 struct smb_filename
*smb_fname
= NULL
;
3221 bool path_contains_wcard
= False
;
3222 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3223 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
3224 TALLOC_CTX
*ctx
= talloc_tos();
3226 START_PROFILE(SMBunlink
);
3229 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3233 dirtype
= SVAL(req
->vwv
+0, 0);
3235 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3236 STR_TERMINATE
, &status
,
3237 &path_contains_wcard
);
3238 if (!NT_STATUS_IS_OK(status
)) {
3239 reply_nterror(req
, status
);
3243 status
= filename_convert(ctx
, conn
,
3244 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3247 &path_contains_wcard
,
3249 if (!NT_STATUS_IS_OK(status
)) {
3250 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3251 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3252 ERRSRV
, ERRbadpath
);
3255 reply_nterror(req
, status
);
3259 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3261 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3262 path_contains_wcard
);
3263 if (!NT_STATUS_IS_OK(status
)) {
3264 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3265 /* We have re-scheduled this call. */
3268 reply_nterror(req
, status
);
3272 reply_outbuf(req
, 0, 0);
3274 TALLOC_FREE(smb_fname
);
3275 END_PROFILE(SMBunlink
);
3279 /****************************************************************************
3281 ****************************************************************************/
3283 static void fail_readraw(void)
3285 const char *errstr
= talloc_asprintf(talloc_tos(),
3286 "FAIL ! reply_readbraw: socket write fail (%s)",
3291 exit_server_cleanly(errstr
);
3294 /****************************************************************************
3295 Fake (read/write) sendfile. Returns -1 on read or write fail.
3296 ****************************************************************************/
3298 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3299 off_t startpos
, size_t nread
)
3302 size_t tosend
= nread
;
3309 bufsize
= MIN(nread
, 65536);
3311 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3315 while (tosend
> 0) {
3319 cur_read
= MIN(tosend
, bufsize
);
3320 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3326 /* If we had a short read, fill with zeros. */
3327 if (ret
< cur_read
) {
3328 memset(buf
+ ret
, '\0', cur_read
- ret
);
3331 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3332 if (ret
!= cur_read
) {
3333 int saved_errno
= errno
;
3335 * Try and give an error message saying what
3338 DEBUG(0, ("write_data failed for client %s. "
3340 smbXsrv_connection_dbg(xconn
),
3341 strerror(saved_errno
)));
3343 errno
= saved_errno
;
3347 startpos
+= cur_read
;
3351 return (ssize_t
)nread
;
3354 /****************************************************************************
3355 Deal with the case of sendfile reading less bytes from the file than
3356 requested. Fill with zeros (all we can do). Returns 0 on success
3357 ****************************************************************************/
3359 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3365 #define SHORT_SEND_BUFSIZE 1024
3366 if (nread
< headersize
) {
3367 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3368 "header for file %s (%s). Terminating\n",
3369 fsp_str_dbg(fsp
), strerror(errno
)));
3373 nread
-= headersize
;
3375 if (nread
< smb_maxcnt
) {
3376 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3378 DEBUG(0,("sendfile_short_send: malloc failed "
3379 "for file %s (%s). Terminating\n",
3380 fsp_str_dbg(fsp
), strerror(errno
)));
3384 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3385 "with zeros !\n", fsp_str_dbg(fsp
)));
3387 while (nread
< smb_maxcnt
) {
3389 * We asked for the real file size and told sendfile
3390 * to not go beyond the end of the file. But it can
3391 * happen that in between our fstat call and the
3392 * sendfile call the file was truncated. This is very
3393 * bad because we have already announced the larger
3394 * number of bytes to the client.
3396 * The best we can do now is to send 0-bytes, just as
3397 * a read from a hole in a sparse file would do.
3399 * This should happen rarely enough that I don't care
3400 * about efficiency here :-)
3405 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3406 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3407 if (ret
!= to_write
) {
3408 int saved_errno
= errno
;
3410 * Try and give an error message saying what
3413 DEBUG(0, ("write_data failed for client %s. "
3415 smbXsrv_connection_dbg(xconn
),
3416 strerror(saved_errno
)));
3417 errno
= saved_errno
;
3428 /****************************************************************************
3429 Return a readbraw error (4 bytes of zero).
3430 ****************************************************************************/
3432 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3438 smbd_lock_socket(xconn
);
3439 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3440 int saved_errno
= errno
;
3442 * Try and give an error message saying what
3445 DEBUG(0, ("write_data failed for client %s. "
3447 smbXsrv_connection_dbg(xconn
),
3448 strerror(saved_errno
)));
3449 errno
= saved_errno
;
3453 smbd_unlock_socket(xconn
);
3456 /****************************************************************************
3457 Use sendfile in readbraw.
3458 ****************************************************************************/
3460 static void send_file_readbraw(connection_struct
*conn
,
3461 struct smb_request
*req
,
3467 struct smbXsrv_connection
*xconn
= req
->xconn
;
3468 char *outbuf
= NULL
;
3472 * We can only use sendfile on a non-chained packet
3473 * but we can use on a non-oplocked file. tridge proved this
3474 * on a train in Germany :-). JRA.
3475 * reply_readbraw has already checked the length.
3478 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3479 (fsp
->wcp
== NULL
) &&
3480 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3481 ssize_t sendfile_read
= -1;
3483 DATA_BLOB header_blob
;
3485 _smb_setlen(header
,nread
);
3486 header_blob
= data_blob_const(header
, 4);
3488 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3489 &header_blob
, startpos
,
3491 if (sendfile_read
== -1) {
3492 /* Returning ENOSYS means no data at all was sent.
3493 * Do this as a normal read. */
3494 if (errno
== ENOSYS
) {
3495 goto normal_readbraw
;
3499 * Special hack for broken Linux with no working sendfile. If we
3500 * return EINTR we sent the header but not the rest of the data.
3501 * Fake this up by doing read/write calls.
3503 if (errno
== EINTR
) {
3504 /* Ensure we don't do this again. */
3505 set_use_sendfile(SNUM(conn
), False
);
3506 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3508 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3509 DEBUG(0,("send_file_readbraw: "
3510 "fake_sendfile failed for "
3514 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3519 DEBUG(0,("send_file_readbraw: sendfile failed for "
3520 "file %s (%s). Terminating\n",
3521 fsp_str_dbg(fsp
), strerror(errno
)));
3522 exit_server_cleanly("send_file_readbraw sendfile failed");
3523 } else if (sendfile_read
== 0) {
3525 * Some sendfile implementations return 0 to indicate
3526 * that there was a short read, but nothing was
3527 * actually written to the socket. In this case,
3528 * fallback to the normal read path so the header gets
3529 * the correct byte count.
3531 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3532 "bytes falling back to the normal read: "
3533 "%s\n", fsp_str_dbg(fsp
)));
3534 goto normal_readbraw
;
3537 /* Deal with possible short send. */
3538 if (sendfile_read
!= 4+nread
) {
3539 ret
= sendfile_short_send(xconn
, fsp
,
3540 sendfile_read
, 4, nread
);
3550 outbuf
= talloc_array(NULL
, char, nread
+4);
3552 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3553 (unsigned)(nread
+4)));
3554 reply_readbraw_error(xconn
);
3559 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3560 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3569 _smb_setlen(outbuf
,ret
);
3570 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3571 int saved_errno
= errno
;
3573 * Try and give an error message saying what
3576 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3577 smbXsrv_connection_dbg(xconn
),
3578 strerror(saved_errno
)));
3579 errno
= saved_errno
;
3584 TALLOC_FREE(outbuf
);
3587 /****************************************************************************
3588 Reply to a readbraw (core+ protocol).
3589 ****************************************************************************/
3591 void reply_readbraw(struct smb_request
*req
)
3593 connection_struct
*conn
= req
->conn
;
3594 struct smbXsrv_connection
*xconn
= req
->xconn
;
3595 ssize_t maxcount
,mincount
;
3599 struct lock_struct lock
;
3602 START_PROFILE(SMBreadbraw
);
3604 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3605 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3606 "raw reads/writes are disallowed.");
3610 reply_readbraw_error(xconn
);
3611 END_PROFILE(SMBreadbraw
);
3615 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3616 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3617 "'async smb echo handler = yes'\n"));
3618 reply_readbraw_error(xconn
);
3619 END_PROFILE(SMBreadbraw
);
3624 * Special check if an oplock break has been issued
3625 * and the readraw request croses on the wire, we must
3626 * return a zero length response here.
3629 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3632 * We have to do a check_fsp by hand here, as
3633 * we must always return 4 zero bytes on error,
3637 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3638 req
->vuid
!= fsp
->vuid
||
3639 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3641 * fsp could be NULL here so use the value from the packet. JRA.
3643 DEBUG(3,("reply_readbraw: fnum %d not valid "
3645 (int)SVAL(req
->vwv
+0, 0)));
3646 reply_readbraw_error(xconn
);
3647 END_PROFILE(SMBreadbraw
);
3651 /* Do a "by hand" version of CHECK_READ. */
3652 if (!(fsp
->can_read
||
3653 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3654 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3655 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3656 (int)SVAL(req
->vwv
+0, 0)));
3657 reply_readbraw_error(xconn
);
3658 END_PROFILE(SMBreadbraw
);
3662 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3664 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3665 if(req
->wct
== 10) {
3667 * This is a large offset (64 bit) read.
3670 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3673 DEBUG(0,("reply_readbraw: negative 64 bit "
3674 "readraw offset (%.0f) !\n",
3675 (double)startpos
));
3676 reply_readbraw_error(xconn
);
3677 END_PROFILE(SMBreadbraw
);
3682 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3683 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3685 /* ensure we don't overrun the packet size */
3686 maxcount
= MIN(65535,maxcount
);
3688 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3689 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3692 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3693 reply_readbraw_error(xconn
);
3694 END_PROFILE(SMBreadbraw
);
3698 if (fsp_stat(fsp
) == 0) {
3699 size
= fsp
->fsp_name
->st
.st_ex_size
;
3702 if (startpos
>= size
) {
3705 nread
= MIN(maxcount
,(size
- startpos
));
3708 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3709 if (nread
< mincount
)
3713 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3714 "min=%lu nread=%lu\n",
3715 fsp_fnum_dbg(fsp
), (double)startpos
,
3716 (unsigned long)maxcount
,
3717 (unsigned long)mincount
,
3718 (unsigned long)nread
) );
3720 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3722 DEBUG(5,("reply_readbraw finished\n"));
3724 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3726 END_PROFILE(SMBreadbraw
);
3731 #define DBGC_CLASS DBGC_LOCKING
3733 /****************************************************************************
3734 Reply to a lockread (core+ protocol).
3735 ****************************************************************************/
3737 void reply_lockread(struct smb_request
*req
)
3739 connection_struct
*conn
= req
->conn
;
3747 struct byte_range_lock
*br_lck
= NULL
;
3749 struct smbXsrv_connection
*xconn
= req
->xconn
;
3751 START_PROFILE(SMBlockread
);
3754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3755 END_PROFILE(SMBlockread
);
3759 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3761 if (!check_fsp(conn
, req
, fsp
)) {
3762 END_PROFILE(SMBlockread
);
3766 if (!CHECK_READ(fsp
,req
)) {
3767 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3768 END_PROFILE(SMBlockread
);
3772 numtoread
= SVAL(req
->vwv
+1, 0);
3773 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3776 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3777 * protocol request that predates the read/write lock concept.
3778 * Thus instead of asking for a read lock here we need to ask
3779 * for a write lock. JRA.
3780 * Note that the requested lock size is unaffected by max_send.
3783 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3785 (uint64_t)req
->smbpid
,
3786 (uint64_t)numtoread
,
3790 False
, /* Non-blocking lock. */
3793 TALLOC_FREE(br_lck
);
3795 if (NT_STATUS_V(status
)) {
3796 reply_nterror(req
, status
);
3797 END_PROFILE(SMBlockread
);
3802 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3804 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3806 if (numtoread
> maxtoread
) {
3807 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3808 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3809 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3810 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3811 numtoread
= maxtoread
;
3814 reply_outbuf(req
, 5, numtoread
+ 3);
3816 data
= smb_buf(req
->outbuf
) + 3;
3818 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3821 reply_nterror(req
, map_nt_error_from_unix(errno
));
3822 END_PROFILE(SMBlockread
);
3826 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3828 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3829 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3830 p
= smb_buf(req
->outbuf
);
3831 SCVAL(p
,0,0); /* pad byte. */
3834 DEBUG(3,("lockread %s num=%d nread=%d\n",
3835 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3837 END_PROFILE(SMBlockread
);
3842 #define DBGC_CLASS DBGC_ALL
3844 /****************************************************************************
3846 ****************************************************************************/
3848 void reply_read(struct smb_request
*req
)
3850 connection_struct
*conn
= req
->conn
;
3857 struct lock_struct lock
;
3858 struct smbXsrv_connection
*xconn
= req
->xconn
;
3860 START_PROFILE(SMBread
);
3863 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3864 END_PROFILE(SMBread
);
3868 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3870 if (!check_fsp(conn
, req
, fsp
)) {
3871 END_PROFILE(SMBread
);
3875 if (!CHECK_READ(fsp
,req
)) {
3876 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3877 END_PROFILE(SMBread
);
3881 numtoread
= SVAL(req
->vwv
+1, 0);
3882 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3885 * The requested read size cannot be greater than max_send. JRA.
3887 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3889 if (numtoread
> maxtoread
) {
3890 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3891 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3892 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3893 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3894 numtoread
= maxtoread
;
3897 reply_outbuf(req
, 5, numtoread
+3);
3899 data
= smb_buf(req
->outbuf
) + 3;
3901 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3902 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3905 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3906 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3907 END_PROFILE(SMBread
);
3912 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3915 reply_nterror(req
, map_nt_error_from_unix(errno
));
3919 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3921 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3922 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3923 SCVAL(smb_buf(req
->outbuf
),0,1);
3924 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3926 DEBUG(3, ("read %s num=%d nread=%d\n",
3927 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3930 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3932 END_PROFILE(SMBread
);
3936 /****************************************************************************
3938 ****************************************************************************/
3940 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3944 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3947 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3949 SCVAL(outbuf
,smb_vwv0
,0xFF);
3950 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3951 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3952 SSVAL(outbuf
,smb_vwv6
,
3953 (smb_wct
- 4) /* offset from smb header to wct */
3954 + 1 /* the wct field */
3955 + 12 * sizeof(uint16_t) /* vwv */
3956 + 2 /* the buflen field */
3957 + 1); /* padding byte */
3958 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3959 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3960 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3961 _smb_setlen_large(outbuf
,
3962 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3966 /****************************************************************************
3967 Reply to a read and X - possibly using sendfile.
3968 ****************************************************************************/
3970 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3971 files_struct
*fsp
, off_t startpos
,
3974 struct smbXsrv_connection
*xconn
= req
->xconn
;
3976 struct lock_struct lock
;
3977 int saved_errno
= 0;
3979 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3980 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3983 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3984 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3989 * We can only use sendfile on a non-chained packet
3990 * but we can use on a non-oplocked file. tridge proved this
3991 * on a train in Germany :-). JRA.
3994 if (!req_is_in_chain(req
) &&
3996 (fsp
->base_fsp
== NULL
) &&
3997 (fsp
->wcp
== NULL
) &&
3998 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3999 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
4002 if(fsp_stat(fsp
) == -1) {
4003 reply_nterror(req
, map_nt_error_from_unix(errno
));
4007 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4008 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4009 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4011 * We already know that we would do a short read, so don't
4012 * try the sendfile() path.
4014 goto nosendfile_read
;
4018 * Set up the packet header before send. We
4019 * assume here the sendfile will work (get the
4020 * correct amount of data).
4023 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4025 construct_reply_common_req(req
, (char *)headerbuf
);
4026 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4028 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4029 startpos
, smb_maxcnt
);
4031 saved_errno
= errno
;
4033 /* Returning ENOSYS means no data at all was sent.
4034 Do this as a normal read. */
4035 if (errno
== ENOSYS
) {
4040 * Special hack for broken Linux with no working sendfile. If we
4041 * return EINTR we sent the header but not the rest of the data.
4042 * Fake this up by doing read/write calls.
4045 if (errno
== EINTR
) {
4046 /* Ensure we don't do this again. */
4047 set_use_sendfile(SNUM(conn
), False
);
4048 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4049 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4052 saved_errno
= errno
;
4053 DEBUG(0,("send_file_readX: "
4054 "fake_sendfile failed for "
4055 "file %s (%s) for client %s. "
4058 smbXsrv_connection_dbg(xconn
),
4059 strerror(saved_errno
)));
4060 errno
= saved_errno
;
4061 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4063 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4064 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4065 /* No outbuf here means successful sendfile. */
4069 DEBUG(0,("send_file_readX: sendfile failed for file "
4070 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4072 exit_server_cleanly("send_file_readX sendfile failed");
4073 } else if (nread
== 0) {
4075 * Some sendfile implementations return 0 to indicate
4076 * that there was a short read, but nothing was
4077 * actually written to the socket. In this case,
4078 * fallback to the normal read path so the header gets
4079 * the correct byte count.
4081 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4082 "falling back to the normal read: %s\n",
4087 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4088 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4090 /* Deal with possible short send. */
4091 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4094 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4095 sizeof(headerbuf
), smb_maxcnt
);
4098 r
= "send_file_readX: sendfile_short_send failed";
4099 DEBUG(0,("%s for file %s (%s).\n",
4100 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4101 exit_server_cleanly(r
);
4104 /* No outbuf here means successful sendfile. */
4105 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4106 SMB_PERFCOUNT_END(&req
->pcd
);
4112 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4113 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4116 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4117 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4118 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4120 * We already know that we would do a short
4121 * read, so don't try the sendfile() path.
4123 goto nosendfile_read
;
4126 construct_reply_common_req(req
, (char *)headerbuf
);
4127 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4129 /* Send out the header. */
4130 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4132 if (ret
!= sizeof(headerbuf
)) {
4133 saved_errno
= errno
;
4135 * Try and give an error message saying what
4138 DEBUG(0,("send_file_readX: write_data failed for file "
4139 "%s (%s) for client %s. Terminating\n",
4141 smbXsrv_connection_dbg(xconn
),
4142 strerror(saved_errno
)));
4143 errno
= saved_errno
;
4144 exit_server_cleanly("send_file_readX sendfile failed");
4146 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4148 saved_errno
= errno
;
4149 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4150 "%s (%s) for client %s. Terminating\n",
4152 smbXsrv_connection_dbg(xconn
),
4153 strerror(saved_errno
)));
4154 errno
= saved_errno
;
4155 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4162 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4163 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4164 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4166 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4167 startpos
, smb_maxcnt
);
4168 saved_errno
= errno
;
4170 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4173 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4177 setup_readX_header((char *)req
->outbuf
, nread
);
4179 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4180 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4184 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4185 TALLOC_FREE(req
->outbuf
);
4189 /****************************************************************************
4190 Work out how much space we have for a read return.
4191 ****************************************************************************/
4193 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4195 struct smbXsrv_connection
*xconn
= req
->xconn
;
4197 if (xconn
->protocol
< PROTOCOL_NT1
) {
4198 return xconn
->smb1
.sessions
.max_send
;
4201 if (!lp_large_readwrite()) {
4202 return xconn
->smb1
.sessions
.max_send
;
4205 if (req_is_in_chain(req
)) {
4206 return xconn
->smb1
.sessions
.max_send
;
4209 if (req
->encrypted
) {
4211 * Don't take encrypted traffic up to the
4212 * limit. There are padding considerations
4213 * that make that tricky.
4215 return xconn
->smb1
.sessions
.max_send
;
4218 if (srv_is_signing_active(xconn
)) {
4222 if (!lp_unix_extensions()) {
4227 * We can do ultra-large POSIX reads.
4232 /****************************************************************************
4233 Calculate how big a read can be. Copes with all clients. It's always
4234 safe to return a short read - Windows does this.
4235 ****************************************************************************/
4237 static size_t calc_read_size(const struct smb_request
*req
,
4241 struct smbXsrv_connection
*xconn
= req
->xconn
;
4242 size_t max_pdu
= calc_max_read_pdu(req
);
4243 size_t total_size
= 0;
4244 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4245 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4248 * Windows explicitly ignores upper size of 0xFFFF.
4249 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4250 * We must do the same as these will never fit even in
4251 * an extended size NetBIOS packet.
4253 if (upper_size
== 0xFFFF) {
4257 if (xconn
->protocol
< PROTOCOL_NT1
) {
4261 total_size
= ((upper_size
<<16) | lower_size
);
4264 * LARGE_READX test shows it's always safe to return
4265 * a short read. Windows does so.
4267 return MIN(total_size
, max_len
);
4270 /****************************************************************************
4271 Reply to a read and X.
4272 ****************************************************************************/
4274 void reply_read_and_X(struct smb_request
*req
)
4276 connection_struct
*conn
= req
->conn
;
4281 bool big_readX
= False
;
4283 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4286 START_PROFILE(SMBreadX
);
4288 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4289 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4293 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4294 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4295 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4297 /* If it's an IPC, pass off the pipe handler. */
4299 reply_pipe_read_and_X(req
);
4300 END_PROFILE(SMBreadX
);
4304 if (!check_fsp(conn
, req
, fsp
)) {
4305 END_PROFILE(SMBreadX
);
4309 if (!CHECK_READ(fsp
,req
)) {
4310 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4311 END_PROFILE(SMBreadX
);
4315 upper_size
= SVAL(req
->vwv
+7, 0);
4316 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4317 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4319 * This is a heuristic to avoid keeping large
4320 * outgoing buffers around over long-lived aio
4326 if (req
->wct
== 12) {
4328 * This is a large offset (64 bit) read.
4330 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4335 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4340 if (NT_STATUS_IS_OK(status
)) {
4341 /* Read scheduled - we're done. */
4344 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4345 /* Real error - report to client. */
4346 END_PROFILE(SMBreadX
);
4347 reply_nterror(req
, status
);
4350 /* NT_STATUS_RETRY - fall back to sync read. */
4353 smbd_lock_socket(req
->xconn
);
4354 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4355 smbd_unlock_socket(req
->xconn
);
4358 END_PROFILE(SMBreadX
);
4362 /****************************************************************************
4363 Error replies to writebraw must have smb_wct == 1. Fix this up.
4364 ****************************************************************************/
4366 void error_to_writebrawerr(struct smb_request
*req
)
4368 uint8_t *old_outbuf
= req
->outbuf
;
4370 reply_outbuf(req
, 1, 0);
4372 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4373 TALLOC_FREE(old_outbuf
);
4376 /****************************************************************************
4377 Read 4 bytes of a smb packet and return the smb length of the packet.
4378 Store the result in the buffer. This version of the function will
4379 never return a session keepalive (length of zero).
4380 Timeout is in milliseconds.
4381 ****************************************************************************/
4383 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4386 uint8_t msgtype
= NBSSkeepalive
;
4388 while (msgtype
== NBSSkeepalive
) {
4391 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4393 if (!NT_STATUS_IS_OK(status
)) {
4394 char addr
[INET6_ADDRSTRLEN
];
4395 /* Try and give an error message
4396 * saying what client failed. */
4397 DEBUG(0, ("read_fd_with_timeout failed for "
4398 "client %s read error = %s.\n",
4399 get_peer_addr(fd
,addr
,sizeof(addr
)),
4400 nt_errstr(status
)));
4404 msgtype
= CVAL(inbuf
, 0);
4407 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4408 (unsigned long)len
));
4410 return NT_STATUS_OK
;
4413 /****************************************************************************
4414 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4415 ****************************************************************************/
4417 void reply_writebraw(struct smb_request
*req
)
4419 connection_struct
*conn
= req
->conn
;
4420 struct smbXsrv_connection
*xconn
= req
->xconn
;
4423 ssize_t total_written
=0;
4424 size_t numtowrite
=0;
4427 const char *data
=NULL
;
4430 struct lock_struct lock
;
4433 START_PROFILE(SMBwritebraw
);
4436 * If we ever reply with an error, it must have the SMB command
4437 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4440 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4442 if (srv_is_signing_active(xconn
)) {
4443 END_PROFILE(SMBwritebraw
);
4444 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4445 "raw reads/writes are disallowed.");
4448 if (req
->wct
< 12) {
4449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4450 error_to_writebrawerr(req
);
4451 END_PROFILE(SMBwritebraw
);
4455 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4456 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4457 "'async smb echo handler = yes'\n"));
4458 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4459 error_to_writebrawerr(req
);
4460 END_PROFILE(SMBwritebraw
);
4464 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4465 if (!check_fsp(conn
, req
, fsp
)) {
4466 error_to_writebrawerr(req
);
4467 END_PROFILE(SMBwritebraw
);
4471 if (!CHECK_WRITE(fsp
)) {
4472 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4473 error_to_writebrawerr(req
);
4474 END_PROFILE(SMBwritebraw
);
4478 tcount
= IVAL(req
->vwv
+1, 0);
4479 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4480 write_through
= BITSETW(req
->vwv
+7,0);
4482 /* We have to deal with slightly different formats depending
4483 on whether we are using the core+ or lanman1.0 protocol */
4485 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4486 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4487 data
= smb_buf_const(req
->inbuf
);
4489 numtowrite
= SVAL(req
->vwv
+10, 0);
4490 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4493 /* Ensure we don't write bytes past the end of this packet. */
4494 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4495 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4496 error_to_writebrawerr(req
);
4497 END_PROFILE(SMBwritebraw
);
4501 if (!fsp
->print_file
) {
4502 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4503 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4506 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4507 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4508 error_to_writebrawerr(req
);
4509 END_PROFILE(SMBwritebraw
);
4515 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4518 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4519 "wrote=%d sync=%d\n",
4520 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4521 (int)nwritten
, (int)write_through
));
4523 if (nwritten
< (ssize_t
)numtowrite
) {
4524 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4525 error_to_writebrawerr(req
);
4529 total_written
= nwritten
;
4531 /* Allocate a buffer of 64k + length. */
4532 buf
= talloc_array(NULL
, char, 65540);
4534 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4535 error_to_writebrawerr(req
);
4539 /* Return a SMBwritebraw message to the redirector to tell
4540 * it to send more bytes */
4542 memcpy(buf
, req
->inbuf
, smb_size
);
4543 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4544 SCVAL(buf
,smb_com
,SMBwritebraw
);
4545 SSVALS(buf
,smb_vwv0
,0xFFFF);
4547 if (!srv_send_smb(req
->xconn
,
4549 false, 0, /* no signing */
4550 IS_CONN_ENCRYPTED(conn
),
4552 exit_server_cleanly("reply_writebraw: srv_send_smb "
4556 /* Now read the raw data into the buffer and write it */
4557 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4559 if (!NT_STATUS_IS_OK(status
)) {
4560 exit_server_cleanly("secondary writebraw failed");
4563 /* Set up outbuf to return the correct size */
4564 reply_outbuf(req
, 1, 0);
4566 if (numtowrite
!= 0) {
4568 if (numtowrite
> 0xFFFF) {
4569 DEBUG(0,("reply_writebraw: Oversize secondary write "
4570 "raw requested (%u). Terminating\n",
4571 (unsigned int)numtowrite
));
4572 exit_server_cleanly("secondary writebraw failed");
4575 if (tcount
> nwritten
+numtowrite
) {
4576 DEBUG(3,("reply_writebraw: Client overestimated the "
4578 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4581 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4584 if (!NT_STATUS_IS_OK(status
)) {
4585 /* Try and give an error message
4586 * saying what client failed. */
4587 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4588 "raw read failed (%s) for client %s. "
4589 "Terminating\n", nt_errstr(status
),
4590 smbXsrv_connection_dbg(xconn
)));
4591 exit_server_cleanly("secondary writebraw failed");
4594 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4595 if (nwritten
== -1) {
4597 reply_nterror(req
, map_nt_error_from_unix(errno
));
4598 error_to_writebrawerr(req
);
4602 if (nwritten
< (ssize_t
)numtowrite
) {
4603 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4604 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4608 total_written
+= nwritten
;
4613 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4615 status
= sync_file(conn
, fsp
, write_through
);
4616 if (!NT_STATUS_IS_OK(status
)) {
4617 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4618 fsp_str_dbg(fsp
), nt_errstr(status
)));
4619 reply_nterror(req
, status
);
4620 error_to_writebrawerr(req
);
4624 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4626 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4627 (int)total_written
));
4629 if (!fsp
->print_file
) {
4630 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4633 /* We won't return a status if write through is not selected - this
4634 * follows what WfWg does */
4635 END_PROFILE(SMBwritebraw
);
4637 if (!write_through
&& total_written
==tcount
) {
4639 #if RABBIT_PELLET_FIX
4641 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4642 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4645 if (!send_keepalive(xconn
->transport
.sock
)) {
4646 exit_server_cleanly("reply_writebraw: send of "
4647 "keepalive failed");
4650 TALLOC_FREE(req
->outbuf
);
4655 if (!fsp
->print_file
) {
4656 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4659 END_PROFILE(SMBwritebraw
);
4664 #define DBGC_CLASS DBGC_LOCKING
4666 /****************************************************************************
4667 Reply to a writeunlock (core+).
4668 ****************************************************************************/
4670 void reply_writeunlock(struct smb_request
*req
)
4672 connection_struct
*conn
= req
->conn
;
4673 ssize_t nwritten
= -1;
4677 NTSTATUS status
= NT_STATUS_OK
;
4679 struct lock_struct lock
;
4680 int saved_errno
= 0;
4682 START_PROFILE(SMBwriteunlock
);
4685 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4686 END_PROFILE(SMBwriteunlock
);
4690 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4692 if (!check_fsp(conn
, req
, fsp
)) {
4693 END_PROFILE(SMBwriteunlock
);
4697 if (!CHECK_WRITE(fsp
)) {
4698 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4699 END_PROFILE(SMBwriteunlock
);
4703 numtowrite
= SVAL(req
->vwv
+1, 0);
4704 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4705 data
= (const char *)req
->buf
+ 3;
4707 if (!fsp
->print_file
&& numtowrite
> 0) {
4708 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4709 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4712 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4713 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4714 END_PROFILE(SMBwriteunlock
);
4719 /* The special X/Open SMB protocol handling of
4720 zero length writes is *NOT* done for
4722 if(numtowrite
== 0) {
4725 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4726 saved_errno
= errno
;
4729 status
= sync_file(conn
, fsp
, False
/* write through */);
4730 if (!NT_STATUS_IS_OK(status
)) {
4731 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4732 fsp_str_dbg(fsp
), nt_errstr(status
)));
4733 reply_nterror(req
, status
);
4738 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4742 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4743 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4747 if (numtowrite
&& !fsp
->print_file
) {
4748 status
= do_unlock(req
->sconn
->msg_ctx
,
4750 (uint64_t)req
->smbpid
,
4751 (uint64_t)numtowrite
,
4755 if (NT_STATUS_V(status
)) {
4756 reply_nterror(req
, status
);
4761 reply_outbuf(req
, 1, 0);
4763 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4765 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4766 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4769 if (numtowrite
&& !fsp
->print_file
) {
4770 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4773 END_PROFILE(SMBwriteunlock
);
4778 #define DBGC_CLASS DBGC_ALL
4780 /****************************************************************************
4782 ****************************************************************************/
4784 void reply_write(struct smb_request
*req
)
4786 connection_struct
*conn
= req
->conn
;
4788 ssize_t nwritten
= -1;
4792 struct lock_struct lock
;
4794 int saved_errno
= 0;
4796 START_PROFILE(SMBwrite
);
4799 END_PROFILE(SMBwrite
);
4800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4804 /* If it's an IPC, pass off the pipe handler. */
4806 reply_pipe_write(req
);
4807 END_PROFILE(SMBwrite
);
4811 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4813 if (!check_fsp(conn
, req
, fsp
)) {
4814 END_PROFILE(SMBwrite
);
4818 if (!CHECK_WRITE(fsp
)) {
4819 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4820 END_PROFILE(SMBwrite
);
4824 numtowrite
= SVAL(req
->vwv
+1, 0);
4825 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4826 data
= (const char *)req
->buf
+ 3;
4828 if (!fsp
->print_file
) {
4829 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4830 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4833 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4834 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4835 END_PROFILE(SMBwrite
);
4841 * X/Open SMB protocol says that if smb_vwv1 is
4842 * zero then the file size should be extended or
4843 * truncated to the size given in smb_vwv[2-3].
4846 if(numtowrite
== 0) {
4848 * This is actually an allocate call, and set EOF. JRA.
4850 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4852 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4855 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4857 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4860 trigger_write_time_update_immediate(fsp
);
4862 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4865 status
= sync_file(conn
, fsp
, False
);
4866 if (!NT_STATUS_IS_OK(status
)) {
4867 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4868 fsp_str_dbg(fsp
), nt_errstr(status
)));
4869 reply_nterror(req
, status
);
4874 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4878 if((nwritten
== 0) && (numtowrite
!= 0)) {
4879 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4883 reply_outbuf(req
, 1, 0);
4885 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4887 if (nwritten
< (ssize_t
)numtowrite
) {
4888 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4889 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4892 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4895 if (!fsp
->print_file
) {
4896 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4899 END_PROFILE(SMBwrite
);
4903 /****************************************************************************
4904 Ensure a buffer is a valid writeX for recvfile purposes.
4905 ****************************************************************************/
4907 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4908 (2*14) + /* word count (including bcc) */ \
4911 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4912 const uint8_t *inbuf
)
4915 unsigned int doff
= 0;
4916 size_t len
= smb_len_large(inbuf
);
4918 struct smbXsrv_open
*op
= NULL
;
4919 struct files_struct
*fsp
= NULL
;
4922 if (is_encrypted_packet(inbuf
)) {
4923 /* Can't do this on encrypted
4928 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4932 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4933 CVAL(inbuf
,smb_wct
) != 14) {
4934 DEBUG(10,("is_valid_writeX_buffer: chained or "
4935 "invalid word length.\n"));
4939 fnum
= SVAL(inbuf
, smb_vwv2
);
4940 status
= smb1srv_open_lookup(xconn
,
4944 if (!NT_STATUS_IS_OK(status
)) {
4945 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4950 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4953 if (fsp
->conn
== NULL
) {
4954 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4958 if (IS_IPC(fsp
->conn
)) {
4959 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4962 if (IS_PRINT(fsp
->conn
)) {
4963 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4966 doff
= SVAL(inbuf
,smb_vwv11
);
4968 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4970 if (len
> doff
&& len
- doff
> 0xFFFF) {
4971 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4974 if (numtowrite
== 0) {
4975 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4979 /* Ensure the sizes match up. */
4980 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4981 /* no pad byte...old smbclient :-( */
4982 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4984 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4988 if (len
- doff
!= numtowrite
) {
4989 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4990 "len = %u, doff = %u, numtowrite = %u\n",
4993 (unsigned int)numtowrite
));
4997 DEBUG(10,("is_valid_writeX_buffer: true "
4998 "len = %u, doff = %u, numtowrite = %u\n",
5001 (unsigned int)numtowrite
));
5006 /****************************************************************************
5007 Reply to a write and X.
5008 ****************************************************************************/
5010 void reply_write_and_X(struct smb_request
*req
)
5012 connection_struct
*conn
= req
->conn
;
5013 struct smbXsrv_connection
*xconn
= req
->xconn
;
5015 struct lock_struct lock
;
5020 unsigned int smb_doff
;
5021 unsigned int smblen
;
5024 int saved_errno
= 0;
5026 START_PROFILE(SMBwriteX
);
5028 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5033 numtowrite
= SVAL(req
->vwv
+10, 0);
5034 smb_doff
= SVAL(req
->vwv
+11, 0);
5035 smblen
= smb_len(req
->inbuf
);
5037 if (req
->unread_bytes
> 0xFFFF ||
5038 (smblen
> smb_doff
&&
5039 smblen
- smb_doff
> 0xFFFF)) {
5040 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5043 if (req
->unread_bytes
) {
5044 /* Can't do a recvfile write on IPC$ */
5046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5049 if (numtowrite
!= req
->unread_bytes
) {
5050 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5054 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5055 smb_doff
+ numtowrite
> smblen
) {
5056 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5061 /* If it's an IPC, pass off the pipe handler. */
5063 if (req
->unread_bytes
) {
5064 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5067 reply_pipe_write_and_X(req
);
5071 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5072 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5073 write_through
= BITSETW(req
->vwv
+7,0);
5075 if (!check_fsp(conn
, req
, fsp
)) {
5079 if (!CHECK_WRITE(fsp
)) {
5080 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5084 data
= smb_base(req
->inbuf
) + smb_doff
;
5086 if(req
->wct
== 14) {
5088 * This is a large offset (64 bit) write.
5090 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5094 /* X/Open SMB protocol says that, unlike SMBwrite
5095 if the length is zero then NO truncation is
5096 done, just a write of zero. To truncate a file,
5099 if(numtowrite
== 0) {
5102 if (req
->unread_bytes
== 0) {
5103 status
= schedule_aio_write_and_X(conn
,
5110 if (NT_STATUS_IS_OK(status
)) {
5111 /* write scheduled - we're done. */
5114 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5115 /* Real error - report to client. */
5116 reply_nterror(req
, status
);
5119 /* NT_STATUS_RETRY - fall through to sync write. */
5122 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5123 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5126 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5127 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5131 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5132 saved_errno
= errno
;
5134 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5138 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5142 if((nwritten
== 0) && (numtowrite
!= 0)) {
5143 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5147 reply_outbuf(req
, 6, 0);
5148 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5149 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5150 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5151 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5153 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5154 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5156 status
= sync_file(conn
, fsp
, write_through
);
5157 if (!NT_STATUS_IS_OK(status
)) {
5158 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5159 fsp_str_dbg(fsp
), nt_errstr(status
)));
5160 reply_nterror(req
, status
);
5164 END_PROFILE(SMBwriteX
);
5168 if (req
->unread_bytes
) {
5169 /* writeX failed. drain socket. */
5170 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5171 req
->unread_bytes
) {
5172 smb_panic("failed to drain pending bytes");
5174 req
->unread_bytes
= 0;
5177 END_PROFILE(SMBwriteX
);
5181 /****************************************************************************
5183 ****************************************************************************/
5185 void reply_lseek(struct smb_request
*req
)
5187 connection_struct
*conn
= req
->conn
;
5193 START_PROFILE(SMBlseek
);
5196 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5197 END_PROFILE(SMBlseek
);
5201 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5203 if (!check_fsp(conn
, req
, fsp
)) {
5207 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5209 mode
= SVAL(req
->vwv
+1, 0) & 3;
5210 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5211 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5220 res
= fsp
->fh
->pos
+ startpos
;
5231 if (umode
== SEEK_END
) {
5232 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5233 if(errno
== EINVAL
) {
5234 off_t current_pos
= startpos
;
5236 if(fsp_stat(fsp
) == -1) {
5238 map_nt_error_from_unix(errno
));
5239 END_PROFILE(SMBlseek
);
5243 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5245 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5250 reply_nterror(req
, map_nt_error_from_unix(errno
));
5251 END_PROFILE(SMBlseek
);
5258 reply_outbuf(req
, 2, 0);
5259 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5261 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5262 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5264 END_PROFILE(SMBlseek
);
5268 /****************************************************************************
5270 ****************************************************************************/
5272 void reply_flush(struct smb_request
*req
)
5274 connection_struct
*conn
= req
->conn
;
5278 START_PROFILE(SMBflush
);
5281 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5285 fnum
= SVAL(req
->vwv
+0, 0);
5286 fsp
= file_fsp(req
, fnum
);
5288 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5293 file_sync_all(conn
);
5295 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5296 if (!NT_STATUS_IS_OK(status
)) {
5297 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5298 fsp_str_dbg(fsp
), nt_errstr(status
)));
5299 reply_nterror(req
, status
);
5300 END_PROFILE(SMBflush
);
5305 reply_outbuf(req
, 0, 0);
5307 DEBUG(3,("flush\n"));
5308 END_PROFILE(SMBflush
);
5312 /****************************************************************************
5314 conn POINTER CAN BE NULL HERE !
5315 ****************************************************************************/
5317 void reply_exit(struct smb_request
*req
)
5319 START_PROFILE(SMBexit
);
5321 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5323 reply_outbuf(req
, 0, 0);
5325 DEBUG(3,("exit\n"));
5327 END_PROFILE(SMBexit
);
5331 struct reply_close_state
{
5333 struct smb_request
*smbreq
;
5336 static void do_smb1_close(struct tevent_req
*req
);
5338 void reply_close(struct smb_request
*req
)
5340 connection_struct
*conn
= req
->conn
;
5341 NTSTATUS status
= NT_STATUS_OK
;
5342 files_struct
*fsp
= NULL
;
5343 START_PROFILE(SMBclose
);
5346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5347 END_PROFILE(SMBclose
);
5351 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5354 * We can only use check_fsp if we know it's not a directory.
5357 if (!check_fsp_open(conn
, req
, fsp
)) {
5358 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5359 END_PROFILE(SMBclose
);
5363 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5364 fsp
->is_directory
? "directory" : "file",
5365 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5366 conn
->num_files_open
));
5368 if (!fsp
->is_directory
) {
5372 * Take care of any time sent in the close.
5375 t
= srv_make_unix_date3(req
->vwv
+1);
5376 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5379 if (fsp
->num_aio_requests
!= 0) {
5381 struct reply_close_state
*state
;
5383 DEBUG(10, ("closing with aio %u requests pending\n",
5384 fsp
->num_aio_requests
));
5387 * We depend on the aio_extra destructor to take care of this
5388 * close request once fsp->num_aio_request drops to 0.
5391 fsp
->deferred_close
= tevent_wait_send(
5392 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5393 if (fsp
->deferred_close
== NULL
) {
5394 status
= NT_STATUS_NO_MEMORY
;
5398 state
= talloc(fsp
, struct reply_close_state
);
5399 if (state
== NULL
) {
5400 TALLOC_FREE(fsp
->deferred_close
);
5401 status
= NT_STATUS_NO_MEMORY
;
5405 state
->smbreq
= talloc_move(fsp
, &req
);
5406 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5408 END_PROFILE(SMBclose
);
5413 * close_file() returns the unix errno if an error was detected on
5414 * close - normally this is due to a disk full error. If not then it
5415 * was probably an I/O error.
5418 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5420 if (!NT_STATUS_IS_OK(status
)) {
5421 reply_nterror(req
, status
);
5422 END_PROFILE(SMBclose
);
5426 reply_outbuf(req
, 0, 0);
5427 END_PROFILE(SMBclose
);
5431 static void do_smb1_close(struct tevent_req
*req
)
5433 struct reply_close_state
*state
= tevent_req_callback_data(
5434 req
, struct reply_close_state
);
5435 struct smb_request
*smbreq
;
5439 ret
= tevent_wait_recv(req
);
5442 DEBUG(10, ("tevent_wait_recv returned %s\n",
5445 * Continue anyway, this should never happen
5450 * fsp->smb2_close_request right now is a talloc grandchild of
5451 * fsp. When we close_file(fsp), it would go with it. No chance to
5454 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5456 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5457 if (NT_STATUS_IS_OK(status
)) {
5458 reply_outbuf(smbreq
, 0, 0);
5460 reply_nterror(smbreq
, status
);
5462 if (!srv_send_smb(smbreq
->xconn
,
5463 (char *)smbreq
->outbuf
,
5466 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5468 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5471 TALLOC_FREE(smbreq
);
5474 /****************************************************************************
5475 Reply to a writeclose (Core+ protocol).
5476 ****************************************************************************/
5478 void reply_writeclose(struct smb_request
*req
)
5480 connection_struct
*conn
= req
->conn
;
5482 ssize_t nwritten
= -1;
5483 NTSTATUS close_status
= NT_STATUS_OK
;
5486 struct timespec mtime
;
5488 struct lock_struct lock
;
5490 START_PROFILE(SMBwriteclose
);
5493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5494 END_PROFILE(SMBwriteclose
);
5498 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5500 if (!check_fsp(conn
, req
, fsp
)) {
5501 END_PROFILE(SMBwriteclose
);
5504 if (!CHECK_WRITE(fsp
)) {
5505 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5506 END_PROFILE(SMBwriteclose
);
5510 numtowrite
= SVAL(req
->vwv
+1, 0);
5511 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5512 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5513 data
= (const char *)req
->buf
+ 1;
5515 if (fsp
->print_file
== NULL
) {
5516 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5517 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5520 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5521 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5522 END_PROFILE(SMBwriteclose
);
5527 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5529 if (fsp
->print_file
== NULL
) {
5530 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5533 set_close_write_time(fsp
, mtime
);
5536 * More insanity. W2K only closes the file if writelen > 0.
5540 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5541 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5542 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5545 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5546 "file %s\n", fsp_str_dbg(fsp
)));
5547 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5551 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5552 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5556 if(!NT_STATUS_IS_OK(close_status
)) {
5557 reply_nterror(req
, close_status
);
5561 reply_outbuf(req
, 1, 0);
5563 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5567 END_PROFILE(SMBwriteclose
);
5572 #define DBGC_CLASS DBGC_LOCKING
5574 /****************************************************************************
5576 ****************************************************************************/
5578 void reply_lock(struct smb_request
*req
)
5580 connection_struct
*conn
= req
->conn
;
5581 uint64_t count
,offset
;
5584 struct byte_range_lock
*br_lck
= NULL
;
5586 START_PROFILE(SMBlock
);
5589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5590 END_PROFILE(SMBlock
);
5594 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5596 if (!check_fsp(conn
, req
, fsp
)) {
5597 END_PROFILE(SMBlock
);
5601 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5602 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5604 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5605 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5607 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5609 (uint64_t)req
->smbpid
,
5614 False
, /* Non-blocking lock. */
5618 TALLOC_FREE(br_lck
);
5620 if (NT_STATUS_V(status
)) {
5621 reply_nterror(req
, status
);
5622 END_PROFILE(SMBlock
);
5626 reply_outbuf(req
, 0, 0);
5628 END_PROFILE(SMBlock
);
5632 /****************************************************************************
5634 ****************************************************************************/
5636 void reply_unlock(struct smb_request
*req
)
5638 connection_struct
*conn
= req
->conn
;
5639 uint64_t count
,offset
;
5643 START_PROFILE(SMBunlock
);
5646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5647 END_PROFILE(SMBunlock
);
5651 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5653 if (!check_fsp(conn
, req
, fsp
)) {
5654 END_PROFILE(SMBunlock
);
5658 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5659 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5661 status
= do_unlock(req
->sconn
->msg_ctx
,
5663 (uint64_t)req
->smbpid
,
5668 if (NT_STATUS_V(status
)) {
5669 reply_nterror(req
, status
);
5670 END_PROFILE(SMBunlock
);
5674 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5675 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5677 reply_outbuf(req
, 0, 0);
5679 END_PROFILE(SMBunlock
);
5684 #define DBGC_CLASS DBGC_ALL
5686 /****************************************************************************
5688 conn POINTER CAN BE NULL HERE !
5689 ****************************************************************************/
5691 void reply_tdis(struct smb_request
*req
)
5694 connection_struct
*conn
= req
->conn
;
5695 struct smbXsrv_tcon
*tcon
;
5697 START_PROFILE(SMBtdis
);
5700 DEBUG(4,("Invalid connection in tdis\n"));
5701 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5702 END_PROFILE(SMBtdis
);
5710 * TODO: cancel all outstanding requests on the tcon
5712 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5713 if (!NT_STATUS_IS_OK(status
)) {
5714 DEBUG(0, ("reply_tdis: "
5715 "smbXsrv_tcon_disconnect() failed: %s\n",
5716 nt_errstr(status
)));
5718 * If we hit this case, there is something completely
5719 * wrong, so we better disconnect the transport connection.
5721 END_PROFILE(SMBtdis
);
5722 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5728 reply_outbuf(req
, 0, 0);
5729 END_PROFILE(SMBtdis
);
5733 /****************************************************************************
5735 conn POINTER CAN BE NULL HERE !
5736 ****************************************************************************/
5738 void reply_echo(struct smb_request
*req
)
5740 connection_struct
*conn
= req
->conn
;
5741 struct smb_perfcount_data local_pcd
;
5742 struct smb_perfcount_data
*cur_pcd
;
5746 START_PROFILE(SMBecho
);
5748 smb_init_perfcount_data(&local_pcd
);
5751 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5752 END_PROFILE(SMBecho
);
5756 smb_reverb
= SVAL(req
->vwv
+0, 0);
5758 reply_outbuf(req
, 1, req
->buflen
);
5760 /* copy any incoming data back out */
5761 if (req
->buflen
> 0) {
5762 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5765 if (smb_reverb
> 100) {
5766 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5770 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5772 /* this makes sure we catch the request pcd */
5773 if (seq_num
== smb_reverb
) {
5774 cur_pcd
= &req
->pcd
;
5776 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5777 cur_pcd
= &local_pcd
;
5780 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5782 show_msg((char *)req
->outbuf
);
5783 if (!srv_send_smb(req
->xconn
,
5784 (char *)req
->outbuf
,
5785 true, req
->seqnum
+1,
5786 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5788 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5791 DEBUG(3,("echo %d times\n", smb_reverb
));
5793 TALLOC_FREE(req
->outbuf
);
5795 END_PROFILE(SMBecho
);
5799 /****************************************************************************
5800 Reply to a printopen.
5801 ****************************************************************************/
5803 void reply_printopen(struct smb_request
*req
)
5805 connection_struct
*conn
= req
->conn
;
5809 START_PROFILE(SMBsplopen
);
5812 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5813 END_PROFILE(SMBsplopen
);
5817 if (!CAN_PRINT(conn
)) {
5818 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5819 END_PROFILE(SMBsplopen
);
5823 status
= file_new(req
, conn
, &fsp
);
5824 if(!NT_STATUS_IS_OK(status
)) {
5825 reply_nterror(req
, status
);
5826 END_PROFILE(SMBsplopen
);
5830 /* Open for exclusive use, write only. */
5831 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5833 if (!NT_STATUS_IS_OK(status
)) {
5834 file_free(req
, fsp
);
5835 reply_nterror(req
, status
);
5836 END_PROFILE(SMBsplopen
);
5840 reply_outbuf(req
, 1, 0);
5841 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5843 DEBUG(3,("openprint fd=%d %s\n",
5844 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5846 END_PROFILE(SMBsplopen
);
5850 /****************************************************************************
5851 Reply to a printclose.
5852 ****************************************************************************/
5854 void reply_printclose(struct smb_request
*req
)
5856 connection_struct
*conn
= req
->conn
;
5860 START_PROFILE(SMBsplclose
);
5863 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5864 END_PROFILE(SMBsplclose
);
5868 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5870 if (!check_fsp(conn
, req
, fsp
)) {
5871 END_PROFILE(SMBsplclose
);
5875 if (!CAN_PRINT(conn
)) {
5876 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5877 END_PROFILE(SMBsplclose
);
5881 DEBUG(3,("printclose fd=%d %s\n",
5882 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5884 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5886 if(!NT_STATUS_IS_OK(status
)) {
5887 reply_nterror(req
, status
);
5888 END_PROFILE(SMBsplclose
);
5892 reply_outbuf(req
, 0, 0);
5894 END_PROFILE(SMBsplclose
);
5898 /****************************************************************************
5899 Reply to a printqueue.
5900 ****************************************************************************/
5902 void reply_printqueue(struct smb_request
*req
)
5904 connection_struct
*conn
= req
->conn
;
5908 START_PROFILE(SMBsplretq
);
5911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5912 END_PROFILE(SMBsplretq
);
5916 max_count
= SVAL(req
->vwv
+0, 0);
5917 start_index
= SVAL(req
->vwv
+1, 0);
5919 /* we used to allow the client to get the cnum wrong, but that
5920 is really quite gross and only worked when there was only
5921 one printer - I think we should now only accept it if they
5922 get it right (tridge) */
5923 if (!CAN_PRINT(conn
)) {
5924 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5925 END_PROFILE(SMBsplretq
);
5929 reply_outbuf(req
, 2, 3);
5930 SSVAL(req
->outbuf
,smb_vwv0
,0);
5931 SSVAL(req
->outbuf
,smb_vwv1
,0);
5932 SCVAL(smb_buf(req
->outbuf
),0,1);
5933 SSVAL(smb_buf(req
->outbuf
),1,0);
5935 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5936 start_index
, max_count
));
5939 TALLOC_CTX
*mem_ctx
= talloc_tos();
5942 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5943 struct rpc_pipe_client
*cli
= NULL
;
5944 struct dcerpc_binding_handle
*b
= NULL
;
5945 struct policy_handle handle
;
5946 struct spoolss_DevmodeContainer devmode_ctr
;
5947 union spoolss_JobInfo
*info
;
5949 uint32_t num_to_get
;
5953 ZERO_STRUCT(handle
);
5955 status
= rpc_pipe_open_interface(conn
,
5958 conn
->sconn
->remote_address
,
5959 conn
->sconn
->local_address
,
5960 conn
->sconn
->msg_ctx
,
5962 if (!NT_STATUS_IS_OK(status
)) {
5963 DEBUG(0, ("reply_printqueue: "
5964 "could not connect to spoolss: %s\n",
5965 nt_errstr(status
)));
5966 reply_nterror(req
, status
);
5969 b
= cli
->binding_handle
;
5971 ZERO_STRUCT(devmode_ctr
);
5973 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5976 SEC_FLAG_MAXIMUM_ALLOWED
,
5979 if (!NT_STATUS_IS_OK(status
)) {
5980 reply_nterror(req
, status
);
5983 if (!W_ERROR_IS_OK(werr
)) {
5984 reply_nterror(req
, werror_to_ntstatus(werr
));
5988 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5996 if (!W_ERROR_IS_OK(werr
)) {
5997 reply_nterror(req
, werror_to_ntstatus(werr
));
6001 if (max_count
> 0) {
6002 first
= start_index
;
6004 first
= start_index
+ max_count
+ 1;
6007 if (first
>= count
) {
6010 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6013 for (i
= first
; i
< num_to_get
; i
++) {
6016 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6019 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6020 info
[i
].info2
.job_id
);
6022 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6028 srv_put_dos_date2(p
, 0, qtime
);
6029 SCVAL(p
, 4, qstatus
);
6030 SSVAL(p
, 5, qrapjobid
);
6031 SIVAL(p
, 7, info
[i
].info2
.size
);
6033 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6034 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6035 if (!NT_STATUS_IS_OK(status
)) {
6036 reply_nterror(req
, status
);
6039 if (message_push_blob(
6042 blob
, sizeof(blob
))) == -1) {
6043 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6049 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6050 SSVAL(req
->outbuf
,smb_vwv1
,
6051 (max_count
>0?first
+count
:first
-1));
6052 SCVAL(smb_buf(req
->outbuf
),0,1);
6053 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6057 DEBUG(3, ("%u entries returned in queue\n",
6061 if (b
&& is_valid_policy_hnd(&handle
)) {
6062 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6067 END_PROFILE(SMBsplretq
);
6071 /****************************************************************************
6072 Reply to a printwrite.
6073 ****************************************************************************/
6075 void reply_printwrite(struct smb_request
*req
)
6077 connection_struct
*conn
= req
->conn
;
6082 START_PROFILE(SMBsplwr
);
6085 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6086 END_PROFILE(SMBsplwr
);
6090 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6092 if (!check_fsp(conn
, req
, fsp
)) {
6093 END_PROFILE(SMBsplwr
);
6097 if (!fsp
->print_file
) {
6098 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6099 END_PROFILE(SMBsplwr
);
6103 if (!CHECK_WRITE(fsp
)) {
6104 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6105 END_PROFILE(SMBsplwr
);
6109 numtowrite
= SVAL(req
->buf
, 1);
6111 if (req
->buflen
< numtowrite
+ 3) {
6112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6113 END_PROFILE(SMBsplwr
);
6117 data
= (const char *)req
->buf
+ 3;
6119 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6120 reply_nterror(req
, map_nt_error_from_unix(errno
));
6121 END_PROFILE(SMBsplwr
);
6125 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6127 END_PROFILE(SMBsplwr
);
6131 /****************************************************************************
6133 ****************************************************************************/
6135 void reply_mkdir(struct smb_request
*req
)
6137 connection_struct
*conn
= req
->conn
;
6138 struct smb_filename
*smb_dname
= NULL
;
6139 char *directory
= NULL
;
6142 TALLOC_CTX
*ctx
= talloc_tos();
6144 START_PROFILE(SMBmkdir
);
6146 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6147 STR_TERMINATE
, &status
);
6148 if (!NT_STATUS_IS_OK(status
)) {
6149 reply_nterror(req
, status
);
6153 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6154 status
= filename_convert(ctx
, conn
,
6155 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6160 if (!NT_STATUS_IS_OK(status
)) {
6161 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6162 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6163 ERRSRV
, ERRbadpath
);
6166 reply_nterror(req
, status
);
6170 status
= create_directory(conn
, req
, smb_dname
);
6172 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6174 if (!NT_STATUS_IS_OK(status
)) {
6176 if (!use_nt_status()
6177 && NT_STATUS_EQUAL(status
,
6178 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6180 * Yes, in the DOS error code case we get a
6181 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6182 * samba4 torture test.
6184 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6187 reply_nterror(req
, status
);
6191 reply_outbuf(req
, 0, 0);
6193 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6195 TALLOC_FREE(smb_dname
);
6196 END_PROFILE(SMBmkdir
);
6200 /****************************************************************************
6202 ****************************************************************************/
6204 void reply_rmdir(struct smb_request
*req
)
6206 connection_struct
*conn
= req
->conn
;
6207 struct smb_filename
*smb_dname
= NULL
;
6208 char *directory
= NULL
;
6210 TALLOC_CTX
*ctx
= talloc_tos();
6211 files_struct
*fsp
= NULL
;
6213 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6214 struct smbd_server_connection
*sconn
= req
->sconn
;
6216 START_PROFILE(SMBrmdir
);
6218 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6219 STR_TERMINATE
, &status
);
6220 if (!NT_STATUS_IS_OK(status
)) {
6221 reply_nterror(req
, status
);
6225 status
= filename_convert(ctx
, conn
,
6226 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6231 if (!NT_STATUS_IS_OK(status
)) {
6232 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6233 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6234 ERRSRV
, ERRbadpath
);
6237 reply_nterror(req
, status
);
6241 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6242 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6246 status
= SMB_VFS_CREATE_FILE(
6249 0, /* root_dir_fid */
6250 smb_dname
, /* fname */
6251 DELETE_ACCESS
, /* access_mask */
6252 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6254 FILE_OPEN
, /* create_disposition*/
6255 FILE_DIRECTORY_FILE
, /* create_options */
6256 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6257 0, /* oplock_request */
6259 0, /* allocation_size */
6260 0, /* private_flags */
6265 NULL
, NULL
); /* create context */
6267 if (!NT_STATUS_IS_OK(status
)) {
6268 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6269 /* We have re-scheduled this call. */
6272 reply_nterror(req
, status
);
6276 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6277 if (!NT_STATUS_IS_OK(status
)) {
6278 close_file(req
, fsp
, ERROR_CLOSE
);
6279 reply_nterror(req
, status
);
6283 if (!set_delete_on_close(fsp
, true,
6284 conn
->session_info
->security_token
,
6285 conn
->session_info
->unix_token
)) {
6286 close_file(req
, fsp
, ERROR_CLOSE
);
6287 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6291 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6292 if (!NT_STATUS_IS_OK(status
)) {
6293 reply_nterror(req
, status
);
6295 reply_outbuf(req
, 0, 0);
6298 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6300 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6302 TALLOC_FREE(smb_dname
);
6303 END_PROFILE(SMBrmdir
);
6307 /*******************************************************************
6308 Resolve wildcards in a filename rename.
6309 ********************************************************************/
6311 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6316 char *name2_copy
= NULL
;
6321 char *p
,*p2
, *pname1
, *pname2
;
6323 name2_copy
= talloc_strdup(ctx
, name2
);
6328 pname1
= strrchr_m(name1
,'/');
6329 pname2
= strrchr_m(name2_copy
,'/');
6331 if (!pname1
|| !pname2
) {
6335 /* Truncate the copy of name2 at the last '/' */
6338 /* Now go past the '/' */
6342 root1
= talloc_strdup(ctx
, pname1
);
6343 root2
= talloc_strdup(ctx
, pname2
);
6345 if (!root1
|| !root2
) {
6349 p
= strrchr_m(root1
,'.');
6352 ext1
= talloc_strdup(ctx
, p
+1);
6354 ext1
= talloc_strdup(ctx
, "");
6356 p
= strrchr_m(root2
,'.');
6359 ext2
= talloc_strdup(ctx
, p
+1);
6361 ext2
= talloc_strdup(ctx
, "");
6364 if (!ext1
|| !ext2
) {
6372 /* Hmmm. Should this be mb-aware ? */
6375 } else if (*p2
== '*') {
6377 root2
= talloc_asprintf(ctx
, "%s%s",
6396 /* Hmmm. Should this be mb-aware ? */
6399 } else if (*p2
== '*') {
6401 ext2
= talloc_asprintf(ctx
, "%s%s",
6417 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6422 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6434 /****************************************************************************
6435 Ensure open files have their names updated. Updated to notify other smbd's
6437 ****************************************************************************/
6439 static void rename_open_files(connection_struct
*conn
,
6440 struct share_mode_lock
*lck
,
6442 uint32_t orig_name_hash
,
6443 const struct smb_filename
*smb_fname_dst
)
6446 bool did_rename
= False
;
6448 uint32_t new_name_hash
= 0;
6450 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6451 fsp
= file_find_di_next(fsp
)) {
6452 /* fsp_name is a relative path under the fsp. To change this for other
6453 sharepaths we need to manipulate relative paths. */
6454 /* TODO - create the absolute path and manipulate the newname
6455 relative to the sharepath. */
6456 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6459 if (fsp
->name_hash
!= orig_name_hash
) {
6462 DEBUG(10, ("rename_open_files: renaming file %s "
6463 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6464 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6465 smb_fname_str_dbg(smb_fname_dst
)));
6467 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6468 if (NT_STATUS_IS_OK(status
)) {
6470 new_name_hash
= fsp
->name_hash
;
6475 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6476 "for %s\n", file_id_string_tos(&id
),
6477 smb_fname_str_dbg(smb_fname_dst
)));
6480 /* Send messages to all smbd's (not ourself) that the name has changed. */
6481 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6482 orig_name_hash
, new_name_hash
,
6487 /****************************************************************************
6488 We need to check if the source path is a parent directory of the destination
6489 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6490 refuse the rename with a sharing violation. Under UNIX the above call can
6491 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6492 probably need to check that the client is a Windows one before disallowing
6493 this as a UNIX client (one with UNIX extensions) can know the source is a
6494 symlink and make this decision intelligently. Found by an excellent bug
6495 report from <AndyLiebman@aol.com>.
6496 ****************************************************************************/
6498 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6499 const struct smb_filename
*smb_fname_dst
)
6501 const char *psrc
= smb_fname_src
->base_name
;
6502 const char *pdst
= smb_fname_dst
->base_name
;
6505 if (psrc
[0] == '.' && psrc
[1] == '/') {
6508 if (pdst
[0] == '.' && pdst
[1] == '/') {
6511 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6514 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6518 * Do the notify calls from a rename
6521 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6522 const struct smb_filename
*smb_fname_src
,
6523 const struct smb_filename
*smb_fname_dst
)
6525 char *parent_dir_src
= NULL
;
6526 char *parent_dir_dst
= NULL
;
6529 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6530 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6532 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6533 &parent_dir_src
, NULL
) ||
6534 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6535 &parent_dir_dst
, NULL
)) {
6539 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6540 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6541 smb_fname_src
->base_name
);
6542 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6543 smb_fname_dst
->base_name
);
6546 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6547 smb_fname_src
->base_name
);
6548 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6549 smb_fname_dst
->base_name
);
6552 /* this is a strange one. w2k3 gives an additional event for
6553 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6554 files, but not directories */
6556 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6557 FILE_NOTIFY_CHANGE_ATTRIBUTES
6558 |FILE_NOTIFY_CHANGE_CREATION
,
6559 smb_fname_dst
->base_name
);
6562 TALLOC_FREE(parent_dir_src
);
6563 TALLOC_FREE(parent_dir_dst
);
6566 /****************************************************************************
6567 Returns an error if the parent directory for a filename is open in an
6569 ****************************************************************************/
6571 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6572 const struct smb_filename
*smb_fname_dst_in
)
6574 char *parent_dir
= NULL
;
6575 struct smb_filename smb_fname_parent
;
6577 files_struct
*fsp
= NULL
;
6580 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6581 &parent_dir
, NULL
)) {
6582 return NT_STATUS_NO_MEMORY
;
6584 ZERO_STRUCT(smb_fname_parent
);
6585 smb_fname_parent
.base_name
= parent_dir
;
6587 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6589 return map_nt_error_from_unix(errno
);
6593 * We're only checking on this smbd here, mostly good
6594 * enough.. and will pass tests.
6597 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6598 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6599 fsp
= file_find_di_next(fsp
)) {
6600 if (fsp
->access_mask
& DELETE_ACCESS
) {
6601 return NT_STATUS_SHARING_VIOLATION
;
6604 return NT_STATUS_OK
;
6607 /****************************************************************************
6608 Rename an open file - given an fsp.
6609 ****************************************************************************/
6611 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6613 const struct smb_filename
*smb_fname_dst_in
,
6615 bool replace_if_exists
)
6617 TALLOC_CTX
*ctx
= talloc_tos();
6618 struct smb_filename
*smb_fname_dst
= NULL
;
6619 NTSTATUS status
= NT_STATUS_OK
;
6620 struct share_mode_lock
*lck
= NULL
;
6621 uint32_t access_mask
= SEC_DIR_ADD_FILE
;
6622 bool dst_exists
, old_is_stream
, new_is_stream
;
6624 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6625 if (!NT_STATUS_IS_OK(status
)) {
6629 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6630 if (!NT_STATUS_IS_OK(status
)) {
6634 /* Make a copy of the dst smb_fname structs */
6636 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6637 if (smb_fname_dst
== NULL
) {
6638 status
= NT_STATUS_NO_MEMORY
;
6643 * Check for special case with case preserving and not
6644 * case sensitive. If the new last component differs from the original
6645 * last component only by case, then we should allow
6646 * the rename (user is trying to change the case of the
6649 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6650 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6651 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6652 char *fname_dst_parent
= NULL
;
6653 const char *fname_dst_lcomp
= NULL
;
6654 char *orig_lcomp_path
= NULL
;
6655 char *orig_lcomp_stream
= NULL
;
6659 * Split off the last component of the processed
6660 * destination name. We will compare this to
6661 * the split components of smb_fname_dst->original_lcomp.
6663 if (!parent_dirname(ctx
,
6664 smb_fname_dst
->base_name
,
6666 &fname_dst_lcomp
)) {
6667 status
= NT_STATUS_NO_MEMORY
;
6672 * The original_lcomp component contains
6673 * the last_component of the path + stream
6674 * name (if a stream exists).
6676 * Split off the stream name so we
6677 * can check them separately.
6680 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6681 /* POSIX - no stream component. */
6682 orig_lcomp_path
= talloc_strdup(ctx
,
6683 smb_fname_dst
->original_lcomp
);
6684 if (orig_lcomp_path
== NULL
) {
6688 ok
= split_stream_filename(ctx
,
6689 smb_fname_dst
->original_lcomp
,
6691 &orig_lcomp_stream
);
6695 TALLOC_FREE(fname_dst_parent
);
6696 status
= NT_STATUS_NO_MEMORY
;
6700 /* If the base names only differ by case, use original. */
6701 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6704 * Replace the modified last component with the
6707 if (!ISDOT(fname_dst_parent
)) {
6708 tmp
= talloc_asprintf(smb_fname_dst
,
6713 tmp
= talloc_strdup(smb_fname_dst
,
6717 status
= NT_STATUS_NO_MEMORY
;
6718 TALLOC_FREE(fname_dst_parent
);
6719 TALLOC_FREE(orig_lcomp_path
);
6720 TALLOC_FREE(orig_lcomp_stream
);
6723 TALLOC_FREE(smb_fname_dst
->base_name
);
6724 smb_fname_dst
->base_name
= tmp
;
6727 /* If the stream_names only differ by case, use original. */
6728 if(!strcsequal(smb_fname_dst
->stream_name
,
6729 orig_lcomp_stream
)) {
6730 /* Use the original stream. */
6731 char *tmp
= talloc_strdup(smb_fname_dst
,
6734 status
= NT_STATUS_NO_MEMORY
;
6735 TALLOC_FREE(fname_dst_parent
);
6736 TALLOC_FREE(orig_lcomp_path
);
6737 TALLOC_FREE(orig_lcomp_stream
);
6740 TALLOC_FREE(smb_fname_dst
->stream_name
);
6741 smb_fname_dst
->stream_name
= tmp
;
6743 TALLOC_FREE(fname_dst_parent
);
6744 TALLOC_FREE(orig_lcomp_path
);
6745 TALLOC_FREE(orig_lcomp_stream
);
6749 * If the src and dest names are identical - including case,
6750 * don't do the rename, just return success.
6753 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6754 strcsequal(fsp
->fsp_name
->stream_name
,
6755 smb_fname_dst
->stream_name
)) {
6756 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6757 "- returning success\n",
6758 smb_fname_str_dbg(smb_fname_dst
)));
6759 status
= NT_STATUS_OK
;
6763 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6764 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6766 /* Return the correct error code if both names aren't streams. */
6767 if (!old_is_stream
&& new_is_stream
) {
6768 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6772 if (old_is_stream
&& !new_is_stream
) {
6773 status
= NT_STATUS_INVALID_PARAMETER
;
6777 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6779 if(!replace_if_exists
&& dst_exists
) {
6780 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6781 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6782 smb_fname_str_dbg(smb_fname_dst
)));
6783 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6788 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6789 &smb_fname_dst
->st
);
6790 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6792 /* The file can be open when renaming a stream */
6793 if (dst_fsp
&& !new_is_stream
) {
6794 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6795 status
= NT_STATUS_ACCESS_DENIED
;
6800 /* Ensure we have a valid stat struct for the source. */
6801 status
= vfs_stat_fsp(fsp
);
6802 if (!NT_STATUS_IS_OK(status
)) {
6806 status
= can_rename(conn
, fsp
, attrs
);
6808 if (!NT_STATUS_IS_OK(status
)) {
6809 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6810 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6811 smb_fname_str_dbg(smb_fname_dst
)));
6812 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6813 status
= NT_STATUS_ACCESS_DENIED
;
6817 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6818 status
= NT_STATUS_ACCESS_DENIED
;
6822 /* Do we have rights to move into the destination ? */
6823 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
6824 /* We're moving a directory. */
6825 access_mask
= SEC_DIR_ADD_SUBDIR
;
6827 status
= check_parent_access(conn
,
6830 if (!NT_STATUS_IS_OK(status
)) {
6831 DBG_INFO("check_parent_access on "
6832 "dst %s returned %s\n",
6833 smb_fname_str_dbg(smb_fname_dst
),
6838 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6841 * We have the file open ourselves, so not being able to get the
6842 * corresponding share mode lock is a fatal error.
6845 SMB_ASSERT(lck
!= NULL
);
6847 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6848 uint32_t create_options
= fsp
->fh
->private_options
;
6850 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6851 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6852 smb_fname_str_dbg(smb_fname_dst
)));
6854 if (!fsp
->is_directory
&&
6855 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6856 (lp_map_archive(SNUM(conn
)) ||
6857 lp_store_dos_attributes(SNUM(conn
)))) {
6858 /* We must set the archive bit on the newly
6860 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6861 uint32_t old_dosmode
= dos_mode(conn
,
6863 file_set_dosmode(conn
,
6865 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6871 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6874 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6878 * A rename acts as a new file create w.r.t. allowing an initial delete
6879 * on close, probably because in Windows there is a new handle to the
6880 * new file. If initial delete on close was requested but not
6881 * originally set, we need to set it here. This is probably not 100% correct,
6882 * but will work for the CIFSFS client which in non-posix mode
6883 * depends on these semantics. JRA.
6886 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6887 status
= can_set_delete_on_close(fsp
, 0);
6889 if (NT_STATUS_IS_OK(status
)) {
6890 /* Note that here we set the *inital* delete on close flag,
6891 * not the regular one. The magic gets handled in close. */
6892 fsp
->initial_delete_on_close
= True
;
6896 status
= NT_STATUS_OK
;
6902 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6903 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6905 status
= map_nt_error_from_unix(errno
);
6908 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6909 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6910 smb_fname_str_dbg(smb_fname_dst
)));
6913 TALLOC_FREE(smb_fname_dst
);
6918 /****************************************************************************
6919 The guts of the rename command, split out so it may be called by the NT SMB
6921 ****************************************************************************/
6923 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6924 connection_struct
*conn
,
6925 struct smb_request
*req
,
6926 struct smb_filename
*smb_fname_src
,
6927 struct smb_filename
*smb_fname_dst
,
6929 bool replace_if_exists
,
6932 uint32_t access_mask
)
6934 char *fname_src_dir
= NULL
;
6935 struct smb_filename
*smb_fname_src_dir
= NULL
;
6936 char *fname_src_mask
= NULL
;
6938 NTSTATUS status
= NT_STATUS_OK
;
6939 struct smb_Dir
*dir_hnd
= NULL
;
6940 const char *dname
= NULL
;
6941 char *talloced
= NULL
;
6943 int create_options
= 0;
6944 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6948 * Split the old name into directory and last component
6949 * strings. Note that unix_convert may have stripped off a
6950 * leading ./ from both name and newname if the rename is
6951 * at the root of the share. We need to make sure either both
6952 * name and newname contain a / character or neither of them do
6953 * as this is checked in resolve_wildcards().
6956 /* Split up the directory from the filename/mask. */
6957 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6958 &fname_src_dir
, &fname_src_mask
);
6959 if (!NT_STATUS_IS_OK(status
)) {
6960 status
= NT_STATUS_NO_MEMORY
;
6965 * We should only check the mangled cache
6966 * here if unix_convert failed. This means
6967 * that the path in 'mask' doesn't exist
6968 * on the file system and so we need to look
6969 * for a possible mangle. This patch from
6970 * Tine Smukavec <valentin.smukavec@hermes.si>.
6973 if (!VALID_STAT(smb_fname_src
->st
) &&
6974 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6975 char *new_mask
= NULL
;
6976 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6979 TALLOC_FREE(fname_src_mask
);
6980 fname_src_mask
= new_mask
;
6984 if (!src_has_wild
) {
6988 * Only one file needs to be renamed. Append the mask back
6989 * onto the directory.
6991 TALLOC_FREE(smb_fname_src
->base_name
);
6992 if (ISDOT(fname_src_dir
)) {
6993 /* Ensure we use canonical names on open. */
6994 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6998 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7003 if (!smb_fname_src
->base_name
) {
7004 status
= NT_STATUS_NO_MEMORY
;
7008 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7009 "case_preserve = %d, short case preserve = %d, "
7010 "directory = %s, newname = %s, "
7011 "last_component_dest = %s\n",
7012 conn
->case_sensitive
, conn
->case_preserve
,
7013 conn
->short_case_preserve
,
7014 smb_fname_str_dbg(smb_fname_src
),
7015 smb_fname_str_dbg(smb_fname_dst
),
7016 smb_fname_dst
->original_lcomp
));
7018 /* The dest name still may have wildcards. */
7019 if (dest_has_wild
) {
7020 char *fname_dst_mod
= NULL
;
7021 if (!resolve_wildcards(smb_fname_dst
,
7022 smb_fname_src
->base_name
,
7023 smb_fname_dst
->base_name
,
7025 DEBUG(6, ("rename_internals: resolve_wildcards "
7027 smb_fname_src
->base_name
,
7028 smb_fname_dst
->base_name
));
7029 status
= NT_STATUS_NO_MEMORY
;
7032 TALLOC_FREE(smb_fname_dst
->base_name
);
7033 smb_fname_dst
->base_name
= fname_dst_mod
;
7036 ZERO_STRUCT(smb_fname_src
->st
);
7037 if (posix_pathnames
) {
7038 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7040 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7043 status
= map_nt_error_from_unix_common(errno
);
7047 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7048 create_options
|= FILE_DIRECTORY_FILE
;
7051 status
= SMB_VFS_CREATE_FILE(
7054 0, /* root_dir_fid */
7055 smb_fname_src
, /* fname */
7056 access_mask
, /* access_mask */
7057 (FILE_SHARE_READ
| /* share_access */
7059 FILE_OPEN
, /* create_disposition*/
7060 create_options
, /* create_options */
7061 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7062 0, /* oplock_request */
7064 0, /* allocation_size */
7065 0, /* private_flags */
7070 NULL
, NULL
); /* create context */
7072 if (!NT_STATUS_IS_OK(status
)) {
7073 DEBUG(3, ("Could not open rename source %s: %s\n",
7074 smb_fname_str_dbg(smb_fname_src
),
7075 nt_errstr(status
)));
7079 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7080 attrs
, replace_if_exists
);
7082 close_file(req
, fsp
, NORMAL_CLOSE
);
7084 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7085 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7086 smb_fname_str_dbg(smb_fname_dst
)));
7092 * Wildcards - process each file that matches.
7094 if (strequal(fname_src_mask
, "????????.???")) {
7095 TALLOC_FREE(fname_src_mask
);
7096 fname_src_mask
= talloc_strdup(ctx
, "*");
7097 if (!fname_src_mask
) {
7098 status
= NT_STATUS_NO_MEMORY
;
7103 status
= check_name(conn
, fname_src_dir
);
7104 if (!NT_STATUS_IS_OK(status
)) {
7108 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7112 smb_fname_src
->flags
);
7113 if (smb_fname_src_dir
== NULL
) {
7114 status
= NT_STATUS_NO_MEMORY
;
7118 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7120 if (dir_hnd
== NULL
) {
7121 status
= map_nt_error_from_unix(errno
);
7125 status
= NT_STATUS_NO_SUCH_FILE
;
7127 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7128 * - gentest fix. JRA
7131 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7133 files_struct
*fsp
= NULL
;
7134 char *destname
= NULL
;
7135 bool sysdir_entry
= False
;
7137 /* Quick check for "." and ".." */
7138 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7139 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7140 sysdir_entry
= True
;
7142 TALLOC_FREE(talloced
);
7147 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7148 &smb_fname_src
->st
, false)) {
7149 TALLOC_FREE(talloced
);
7153 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7154 TALLOC_FREE(talloced
);
7159 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7163 TALLOC_FREE(smb_fname_src
->base_name
);
7164 if (ISDOT(fname_src_dir
)) {
7165 /* Ensure we use canonical names on open. */
7166 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7170 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7175 if (!smb_fname_src
->base_name
) {
7176 status
= NT_STATUS_NO_MEMORY
;
7180 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7181 smb_fname_dst
->base_name
,
7183 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7184 smb_fname_src
->base_name
, destname
));
7185 TALLOC_FREE(talloced
);
7189 status
= NT_STATUS_NO_MEMORY
;
7193 TALLOC_FREE(smb_fname_dst
->base_name
);
7194 smb_fname_dst
->base_name
= destname
;
7196 ZERO_STRUCT(smb_fname_src
->st
);
7197 if (posix_pathnames
) {
7198 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7200 SMB_VFS_STAT(conn
, smb_fname_src
);
7205 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7206 create_options
|= FILE_DIRECTORY_FILE
;
7209 status
= SMB_VFS_CREATE_FILE(
7212 0, /* root_dir_fid */
7213 smb_fname_src
, /* fname */
7214 access_mask
, /* access_mask */
7215 (FILE_SHARE_READ
| /* share_access */
7217 FILE_OPEN
, /* create_disposition*/
7218 create_options
, /* create_options */
7219 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7220 0, /* oplock_request */
7222 0, /* allocation_size */
7223 0, /* private_flags */
7228 NULL
, NULL
); /* create context */
7230 if (!NT_STATUS_IS_OK(status
)) {
7231 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7232 "returned %s rename %s -> %s\n",
7234 smb_fname_str_dbg(smb_fname_src
),
7235 smb_fname_str_dbg(smb_fname_dst
)));
7239 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7241 if (!smb_fname_dst
->original_lcomp
) {
7242 status
= NT_STATUS_NO_MEMORY
;
7246 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7247 attrs
, replace_if_exists
);
7249 close_file(req
, fsp
, NORMAL_CLOSE
);
7251 if (!NT_STATUS_IS_OK(status
)) {
7252 DEBUG(3, ("rename_internals_fsp returned %s for "
7253 "rename %s -> %s\n", nt_errstr(status
),
7254 smb_fname_str_dbg(smb_fname_src
),
7255 smb_fname_str_dbg(smb_fname_dst
)));
7261 DEBUG(3,("rename_internals: doing rename on %s -> "
7262 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7263 smb_fname_str_dbg(smb_fname_src
)));
7264 TALLOC_FREE(talloced
);
7266 TALLOC_FREE(dir_hnd
);
7268 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7269 status
= map_nt_error_from_unix(errno
);
7273 TALLOC_FREE(talloced
);
7274 TALLOC_FREE(smb_fname_src_dir
);
7275 TALLOC_FREE(fname_src_dir
);
7276 TALLOC_FREE(fname_src_mask
);
7280 /****************************************************************************
7282 ****************************************************************************/
7284 void reply_mv(struct smb_request
*req
)
7286 connection_struct
*conn
= req
->conn
;
7288 char *newname
= NULL
;
7292 bool src_has_wcard
= False
;
7293 bool dest_has_wcard
= False
;
7294 TALLOC_CTX
*ctx
= talloc_tos();
7295 struct smb_filename
*smb_fname_src
= NULL
;
7296 struct smb_filename
*smb_fname_dst
= NULL
;
7297 uint32_t src_ucf_flags
= (req
->posix_pathnames
?
7298 (UCF_UNIX_NAME_LOOKUP
|UCF_POSIX_PATHNAMES
) :
7299 UCF_COND_ALLOW_WCARD_LCOMP
);
7300 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
|
7301 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
:
7302 UCF_COND_ALLOW_WCARD_LCOMP
);
7303 bool stream_rename
= false;
7305 START_PROFILE(SMBmv
);
7308 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7312 attrs
= SVAL(req
->vwv
+0, 0);
7314 p
= (const char *)req
->buf
+ 1;
7315 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7316 &status
, &src_has_wcard
);
7317 if (!NT_STATUS_IS_OK(status
)) {
7318 reply_nterror(req
, status
);
7322 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7323 &status
, &dest_has_wcard
);
7324 if (!NT_STATUS_IS_OK(status
)) {
7325 reply_nterror(req
, status
);
7329 if (!req
->posix_pathnames
) {
7330 /* The newname must begin with a ':' if the
7331 name contains a ':'. */
7332 if (strchr_m(name
, ':')) {
7333 if (newname
[0] != ':') {
7334 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7337 stream_rename
= true;
7341 status
= filename_convert(ctx
,
7343 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7349 if (!NT_STATUS_IS_OK(status
)) {
7350 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7351 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7352 ERRSRV
, ERRbadpath
);
7355 reply_nterror(req
, status
);
7359 status
= filename_convert(ctx
,
7361 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7367 if (!NT_STATUS_IS_OK(status
)) {
7368 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7369 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7370 ERRSRV
, ERRbadpath
);
7373 reply_nterror(req
, status
);
7377 if (stream_rename
) {
7378 /* smb_fname_dst->base_name must be the same as
7379 smb_fname_src->base_name. */
7380 TALLOC_FREE(smb_fname_dst
->base_name
);
7381 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7382 smb_fname_src
->base_name
);
7383 if (!smb_fname_dst
->base_name
) {
7384 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7389 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7390 smb_fname_str_dbg(smb_fname_dst
)));
7392 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7393 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7395 if (!NT_STATUS_IS_OK(status
)) {
7396 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7397 /* We have re-scheduled this call. */
7400 reply_nterror(req
, status
);
7404 reply_outbuf(req
, 0, 0);
7406 TALLOC_FREE(smb_fname_src
);
7407 TALLOC_FREE(smb_fname_dst
);
7412 /*******************************************************************
7413 Copy a file as part of a reply_copy.
7414 ******************************************************************/
7417 * TODO: check error codes on all callers
7420 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7421 connection_struct
*conn
,
7422 struct smb_filename
*smb_fname_src
,
7423 struct smb_filename
*smb_fname_dst
,
7426 bool target_is_directory
)
7428 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7430 files_struct
*fsp1
,*fsp2
;
7432 uint32_t new_create_disposition
;
7436 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7437 if (smb_fname_dst_tmp
== NULL
) {
7438 return NT_STATUS_NO_MEMORY
;
7442 * If the target is a directory, extract the last component from the
7443 * src filename and append it to the dst filename
7445 if (target_is_directory
) {
7448 /* dest/target can't be a stream if it's a directory. */
7449 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7451 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7455 p
= smb_fname_src
->base_name
;
7457 smb_fname_dst_tmp
->base_name
=
7458 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7460 if (!smb_fname_dst_tmp
->base_name
) {
7461 status
= NT_STATUS_NO_MEMORY
;
7466 status
= vfs_file_exist(conn
, smb_fname_src
);
7467 if (!NT_STATUS_IS_OK(status
)) {
7471 if (!target_is_directory
&& count
) {
7472 new_create_disposition
= FILE_OPEN
;
7474 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7477 &new_create_disposition
,
7480 status
= NT_STATUS_INVALID_PARAMETER
;
7485 /* Open the src file for reading. */
7486 status
= SMB_VFS_CREATE_FILE(
7489 0, /* root_dir_fid */
7490 smb_fname_src
, /* fname */
7491 FILE_GENERIC_READ
, /* access_mask */
7492 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7493 FILE_OPEN
, /* create_disposition*/
7494 0, /* create_options */
7495 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7496 INTERNAL_OPEN_ONLY
, /* oplock_request */
7498 0, /* allocation_size */
7499 0, /* private_flags */
7504 NULL
, NULL
); /* create context */
7506 if (!NT_STATUS_IS_OK(status
)) {
7510 dosattrs
= dos_mode(conn
, smb_fname_src
);
7512 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7513 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7516 /* Open the dst file for writing. */
7517 status
= SMB_VFS_CREATE_FILE(
7520 0, /* root_dir_fid */
7521 smb_fname_dst
, /* fname */
7522 FILE_GENERIC_WRITE
, /* access_mask */
7523 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7524 new_create_disposition
, /* create_disposition*/
7525 0, /* create_options */
7526 dosattrs
, /* file_attributes */
7527 INTERNAL_OPEN_ONLY
, /* oplock_request */
7529 0, /* allocation_size */
7530 0, /* private_flags */
7535 NULL
, NULL
); /* create context */
7537 if (!NT_STATUS_IS_OK(status
)) {
7538 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7542 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7543 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7545 DEBUG(0, ("error - vfs lseek returned error %s\n",
7547 status
= map_nt_error_from_unix(errno
);
7548 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7549 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7554 /* Do the actual copy. */
7555 if (smb_fname_src
->st
.st_ex_size
) {
7556 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7561 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7563 /* Ensure the modtime is set correctly on the destination file. */
7564 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7567 * As we are opening fsp1 read-only we only expect
7568 * an error on close on fsp2 if we are out of space.
7569 * Thus we don't look at the error return from the
7572 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7574 if (!NT_STATUS_IS_OK(status
)) {
7578 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7579 status
= NT_STATUS_DISK_FULL
;
7583 status
= NT_STATUS_OK
;
7586 TALLOC_FREE(smb_fname_dst_tmp
);
7590 /****************************************************************************
7591 Reply to a file copy.
7592 ****************************************************************************/
7594 void reply_copy(struct smb_request
*req
)
7596 connection_struct
*conn
= req
->conn
;
7597 struct smb_filename
*smb_fname_src
= NULL
;
7598 struct smb_filename
*smb_fname_src_dir
= NULL
;
7599 struct smb_filename
*smb_fname_dst
= NULL
;
7600 char *fname_src
= NULL
;
7601 char *fname_dst
= NULL
;
7602 char *fname_src_mask
= NULL
;
7603 char *fname_src_dir
= NULL
;
7606 int error
= ERRnoaccess
;
7610 bool target_is_directory
=False
;
7611 bool source_has_wild
= False
;
7612 bool dest_has_wild
= False
;
7614 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7615 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7616 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7617 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7618 TALLOC_CTX
*ctx
= talloc_tos();
7620 START_PROFILE(SMBcopy
);
7623 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7627 tid2
= SVAL(req
->vwv
+0, 0);
7628 ofun
= SVAL(req
->vwv
+1, 0);
7629 flags
= SVAL(req
->vwv
+2, 0);
7631 p
= (const char *)req
->buf
;
7632 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7633 &status
, &source_has_wild
);
7634 if (!NT_STATUS_IS_OK(status
)) {
7635 reply_nterror(req
, status
);
7638 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7639 &status
, &dest_has_wild
);
7640 if (!NT_STATUS_IS_OK(status
)) {
7641 reply_nterror(req
, status
);
7645 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7647 if (tid2
!= conn
->cnum
) {
7648 /* can't currently handle inter share copies XXXX */
7649 DEBUG(3,("Rejecting inter-share copy\n"));
7650 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7654 status
= filename_convert(ctx
, conn
,
7655 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7660 if (!NT_STATUS_IS_OK(status
)) {
7661 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7662 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7663 ERRSRV
, ERRbadpath
);
7666 reply_nterror(req
, status
);
7670 status
= filename_convert(ctx
, conn
,
7671 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7676 if (!NT_STATUS_IS_OK(status
)) {
7677 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7678 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7679 ERRSRV
, ERRbadpath
);
7682 reply_nterror(req
, status
);
7686 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7688 if ((flags
&1) && target_is_directory
) {
7689 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7693 if ((flags
&2) && !target_is_directory
) {
7694 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7698 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7699 /* wants a tree copy! XXXX */
7700 DEBUG(3,("Rejecting tree copy\n"));
7701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7705 /* Split up the directory from the filename/mask. */
7706 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7707 &fname_src_dir
, &fname_src_mask
);
7708 if (!NT_STATUS_IS_OK(status
)) {
7709 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7714 * We should only check the mangled cache
7715 * here if unix_convert failed. This means
7716 * that the path in 'mask' doesn't exist
7717 * on the file system and so we need to look
7718 * for a possible mangle. This patch from
7719 * Tine Smukavec <valentin.smukavec@hermes.si>.
7721 if (!VALID_STAT(smb_fname_src
->st
) &&
7722 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7723 char *new_mask
= NULL
;
7724 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7725 &new_mask
, conn
->params
);
7727 /* Use demangled name if one was successfully found. */
7729 TALLOC_FREE(fname_src_mask
);
7730 fname_src_mask
= new_mask
;
7734 if (!source_has_wild
) {
7737 * Only one file needs to be copied. Append the mask back onto
7740 TALLOC_FREE(smb_fname_src
->base_name
);
7741 if (ISDOT(fname_src_dir
)) {
7742 /* Ensure we use canonical names on open. */
7743 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7747 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7752 if (!smb_fname_src
->base_name
) {
7753 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7757 if (dest_has_wild
) {
7758 char *fname_dst_mod
= NULL
;
7759 if (!resolve_wildcards(smb_fname_dst
,
7760 smb_fname_src
->base_name
,
7761 smb_fname_dst
->base_name
,
7763 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7766 TALLOC_FREE(smb_fname_dst
->base_name
);
7767 smb_fname_dst
->base_name
= fname_dst_mod
;
7770 status
= check_name(conn
, smb_fname_src
->base_name
);
7771 if (!NT_STATUS_IS_OK(status
)) {
7772 reply_nterror(req
, status
);
7776 status
= check_name(conn
, smb_fname_dst
->base_name
);
7777 if (!NT_STATUS_IS_OK(status
)) {
7778 reply_nterror(req
, status
);
7782 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7783 ofun
, count
, target_is_directory
);
7785 if(!NT_STATUS_IS_OK(status
)) {
7786 reply_nterror(req
, status
);
7792 struct smb_Dir
*dir_hnd
= NULL
;
7793 const char *dname
= NULL
;
7794 char *talloced
= NULL
;
7798 * There is a wildcard that requires us to actually read the
7799 * src dir and copy each file matching the mask to the dst.
7800 * Right now streams won't be copied, but this could
7801 * presumably be added with a nested loop for reach dir entry.
7803 SMB_ASSERT(!smb_fname_src
->stream_name
);
7804 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7806 smb_fname_src
->stream_name
= NULL
;
7807 smb_fname_dst
->stream_name
= NULL
;
7809 if (strequal(fname_src_mask
,"????????.???")) {
7810 TALLOC_FREE(fname_src_mask
);
7811 fname_src_mask
= talloc_strdup(ctx
, "*");
7812 if (!fname_src_mask
) {
7813 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7818 status
= check_name(conn
, fname_src_dir
);
7819 if (!NT_STATUS_IS_OK(status
)) {
7820 reply_nterror(req
, status
);
7824 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7828 smb_fname_src
->flags
);
7829 if (smb_fname_src_dir
== NULL
) {
7830 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7834 dir_hnd
= OpenDir(ctx
,
7839 if (dir_hnd
== NULL
) {
7840 status
= map_nt_error_from_unix(errno
);
7841 reply_nterror(req
, status
);
7847 /* Iterate over the src dir copying each entry to the dst. */
7848 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7849 &smb_fname_src
->st
, &talloced
))) {
7850 char *destname
= NULL
;
7852 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7853 TALLOC_FREE(talloced
);
7857 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7858 &smb_fname_src
->st
, false)) {
7859 TALLOC_FREE(talloced
);
7863 if(!mask_match(dname
, fname_src_mask
,
7864 conn
->case_sensitive
)) {
7865 TALLOC_FREE(talloced
);
7869 error
= ERRnoaccess
;
7871 /* Get the src smb_fname struct setup. */
7872 TALLOC_FREE(smb_fname_src
->base_name
);
7873 if (ISDOT(fname_src_dir
)) {
7874 /* Ensure we use canonical names on open. */
7875 smb_fname_src
->base_name
=
7876 talloc_asprintf(smb_fname_src
, "%s",
7879 smb_fname_src
->base_name
=
7880 talloc_asprintf(smb_fname_src
, "%s/%s",
7881 fname_src_dir
, dname
);
7884 if (!smb_fname_src
->base_name
) {
7885 TALLOC_FREE(dir_hnd
);
7886 TALLOC_FREE(talloced
);
7887 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7891 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7892 smb_fname_dst
->base_name
,
7894 TALLOC_FREE(talloced
);
7898 TALLOC_FREE(dir_hnd
);
7899 TALLOC_FREE(talloced
);
7900 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7904 TALLOC_FREE(smb_fname_dst
->base_name
);
7905 smb_fname_dst
->base_name
= destname
;
7907 status
= check_name(conn
, smb_fname_src
->base_name
);
7908 if (!NT_STATUS_IS_OK(status
)) {
7909 TALLOC_FREE(dir_hnd
);
7910 TALLOC_FREE(talloced
);
7911 reply_nterror(req
, status
);
7915 status
= check_name(conn
, smb_fname_dst
->base_name
);
7916 if (!NT_STATUS_IS_OK(status
)) {
7917 TALLOC_FREE(dir_hnd
);
7918 TALLOC_FREE(talloced
);
7919 reply_nterror(req
, status
);
7923 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7924 smb_fname_src
->base_name
,
7925 smb_fname_dst
->base_name
));
7927 status
= copy_file(ctx
, conn
, smb_fname_src
,
7928 smb_fname_dst
, ofun
, count
,
7929 target_is_directory
);
7930 if (NT_STATUS_IS_OK(status
)) {
7934 TALLOC_FREE(talloced
);
7936 TALLOC_FREE(dir_hnd
);
7940 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7944 reply_outbuf(req
, 1, 0);
7945 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7947 TALLOC_FREE(smb_fname_src
);
7948 TALLOC_FREE(smb_fname_src_dir
);
7949 TALLOC_FREE(smb_fname_dst
);
7950 TALLOC_FREE(fname_src
);
7951 TALLOC_FREE(fname_dst
);
7952 TALLOC_FREE(fname_src_mask
);
7953 TALLOC_FREE(fname_src_dir
);
7955 END_PROFILE(SMBcopy
);
7960 #define DBGC_CLASS DBGC_LOCKING
7962 /****************************************************************************
7963 Get a lock pid, dealing with large count requests.
7964 ****************************************************************************/
7966 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7967 bool large_file_format
)
7969 if(!large_file_format
)
7970 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7972 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7975 /****************************************************************************
7976 Get a lock count, dealing with large count requests.
7977 ****************************************************************************/
7979 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7980 bool large_file_format
)
7984 if(!large_file_format
) {
7985 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7988 * No BVAL, this is reversed!
7990 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7991 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7997 /****************************************************************************
7998 Get a lock offset, dealing with large offset requests.
7999 ****************************************************************************/
8001 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
8002 bool large_file_format
)
8004 uint64_t offset
= 0;
8006 if(!large_file_format
) {
8007 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
8010 * No BVAL, this is reversed!
8012 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
8013 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
8019 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8024 struct smbd_lock_element
*locks
,
8027 connection_struct
*conn
= req
->conn
;
8029 NTSTATUS status
= NT_STATUS_OK
;
8033 /* Setup the timeout in seconds. */
8035 if (!lp_blocking_locks(SNUM(conn
))) {
8039 for(i
= 0; i
< (int)num_locks
; i
++) {
8040 struct smbd_lock_element
*e
= &locks
[i
];
8042 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8043 "%llu, file %s timeout = %d\n",
8046 (unsigned long long)e
->smblctx
,
8050 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8051 struct blocking_lock_record
*blr
= NULL
;
8053 if (num_locks
> 1) {
8055 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8056 * if the lock vector contains one entry. When given multiple cancel
8057 * requests in a single PDU we expect the server to return an
8058 * error. Windows servers seem to accept the request but only
8059 * cancel the first lock.
8060 * JRA - Do what Windows does (tm) :-).
8064 /* MS-CIFS (2.2.4.32.1) behavior. */
8065 return NT_STATUS_DOS(ERRDOS
,
8066 ERRcancelviolation
);
8068 /* Windows behavior. */
8070 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8071 "cancel request\n"));
8077 if (lp_blocking_locks(SNUM(conn
))) {
8079 /* Schedule a message to ourselves to
8080 remove the blocking lock record and
8081 return the right error. */
8083 blr
= blocking_lock_cancel_smb1(fsp
,
8089 NT_STATUS_FILE_LOCK_CONFLICT
);
8091 return NT_STATUS_DOS(
8093 ERRcancelviolation
);
8096 /* Remove a matching pending lock. */
8097 status
= do_lock_cancel(fsp
,
8103 bool blocking_lock
= timeout
? true : false;
8104 bool defer_lock
= false;
8105 struct byte_range_lock
*br_lck
;
8106 uint64_t block_smblctx
;
8108 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8119 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8120 /* Windows internal resolution for blocking locks seems
8121 to be about 200ms... Don't wait for less than that. JRA. */
8122 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8123 timeout
= lp_lock_spin_time();
8128 /* If a lock sent with timeout of zero would fail, and
8129 * this lock has been requested multiple times,
8130 * according to brl_lock_failed() we convert this
8131 * request to a blocking lock with a timeout of between
8132 * 150 - 300 milliseconds.
8134 * If lp_lock_spin_time() has been set to 0, we skip
8135 * this blocking retry and fail immediately.
8137 * Replacement for do_lock_spin(). JRA. */
8139 if (!req
->sconn
->using_smb2
&&
8140 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8141 lp_lock_spin_time() && !blocking_lock
&&
8142 NT_STATUS_EQUAL((status
),
8143 NT_STATUS_FILE_LOCK_CONFLICT
))
8146 timeout
= lp_lock_spin_time();
8149 if (br_lck
&& defer_lock
) {
8151 * A blocking lock was requested. Package up
8152 * this smb into a queued request and push it
8153 * onto the blocking lock queue.
8155 if(push_blocking_lock_request(br_lck
,
8166 TALLOC_FREE(br_lck
);
8168 return NT_STATUS_OK
;
8172 TALLOC_FREE(br_lck
);
8175 if (!NT_STATUS_IS_OK(status
)) {
8180 /* If any of the above locks failed, then we must unlock
8181 all of the previous locks (X/Open spec). */
8183 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8185 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8186 i
= -1; /* we want to skip the for loop */
8190 * Ensure we don't do a remove on the lock that just failed,
8191 * as under POSIX rules, if we have a lock already there, we
8192 * will delete it (and we shouldn't) .....
8194 for(i
--; i
>= 0; i
--) {
8195 struct smbd_lock_element
*e
= &locks
[i
];
8197 do_unlock(req
->sconn
->msg_ctx
,
8207 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8208 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8210 return NT_STATUS_OK
;
8213 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8215 uint16_t num_ulocks
,
8216 struct smbd_lock_element
*ulocks
)
8220 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8221 struct smbd_lock_element
*e
= &ulocks
[i
];
8224 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8225 "pid %u, file %s\n", __func__
,
8228 (unsigned int)e
->smblctx
,
8231 if (e
->brltype
!= UNLOCK_LOCK
) {
8232 /* this can only happen with SMB2 */
8233 return NT_STATUS_INVALID_PARAMETER
;
8236 status
= do_unlock(req
->sconn
->msg_ctx
,
8243 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8244 nt_errstr(status
)));
8246 if (!NT_STATUS_IS_OK(status
)) {
8251 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8254 return NT_STATUS_OK
;
8257 /****************************************************************************
8258 Reply to a lockingX request.
8259 ****************************************************************************/
8261 void reply_lockingX(struct smb_request
*req
)
8263 connection_struct
*conn
= req
->conn
;
8265 unsigned char locktype
;
8266 unsigned char oplocklevel
;
8267 uint16_t num_ulocks
;
8269 int32_t lock_timeout
;
8271 const uint8_t *data
;
8272 bool large_file_format
;
8273 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8274 struct smbd_lock_element
*ulocks
;
8275 struct smbd_lock_element
*locks
;
8278 START_PROFILE(SMBlockingX
);
8281 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8282 END_PROFILE(SMBlockingX
);
8286 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8287 locktype
= CVAL(req
->vwv
+3, 0);
8288 oplocklevel
= CVAL(req
->vwv
+3, 1);
8289 num_ulocks
= SVAL(req
->vwv
+6, 0);
8290 num_locks
= SVAL(req
->vwv
+7, 0);
8291 lock_timeout
= IVAL(req
->vwv
+4, 0);
8292 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8294 if (!check_fsp(conn
, req
, fsp
)) {
8295 END_PROFILE(SMBlockingX
);
8301 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8302 /* we don't support these - and CANCEL_LOCK makes w2k
8303 and XP reboot so I don't really want to be
8304 compatible! (tridge) */
8305 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8306 END_PROFILE(SMBlockingX
);
8310 /* Check if this is an oplock break on a file
8311 we have granted an oplock on.
8313 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8314 /* Client can insist on breaking to none. */
8315 bool break_to_none
= (oplocklevel
== 0);
8318 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8319 "for %s\n", (unsigned int)oplocklevel
,
8320 fsp_fnum_dbg(fsp
)));
8323 * Make sure we have granted an exclusive or batch oplock on
8327 if (fsp
->oplock_type
== 0) {
8329 /* The Samba4 nbench simulator doesn't understand
8330 the difference between break to level2 and break
8331 to none from level2 - it sends oplock break
8332 replies in both cases. Don't keep logging an error
8333 message here - just ignore it. JRA. */
8335 DEBUG(5,("reply_lockingX: Error : oplock break from "
8336 "client for %s (oplock=%d) and no "
8337 "oplock granted on this file (%s).\n",
8338 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8341 /* if this is a pure oplock break request then don't
8343 if (num_locks
== 0 && num_ulocks
== 0) {
8344 END_PROFILE(SMBlockingX
);
8347 END_PROFILE(SMBlockingX
);
8348 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8353 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8355 result
= remove_oplock(fsp
);
8357 result
= downgrade_oplock(fsp
);
8361 DEBUG(0, ("reply_lockingX: error in removing "
8362 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8363 /* Hmmm. Is this panic justified? */
8364 smb_panic("internal tdb error");
8367 /* if this is a pure oplock break request then don't send a
8369 if (num_locks
== 0 && num_ulocks
== 0) {
8370 /* Sanity check - ensure a pure oplock break is not a
8372 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8373 DEBUG(0,("reply_lockingX: Error : pure oplock "
8374 "break is a chained %d request !\n",
8375 (unsigned int)CVAL(req
->vwv
+0, 0)));
8377 END_PROFILE(SMBlockingX
);
8383 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8384 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8385 END_PROFILE(SMBlockingX
);
8389 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8390 if (ulocks
== NULL
) {
8391 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8392 END_PROFILE(SMBlockingX
);
8396 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8397 if (locks
== NULL
) {
8398 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8399 END_PROFILE(SMBlockingX
);
8403 /* Data now points at the beginning of the list
8404 of smb_unlkrng structs */
8405 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8406 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8407 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8408 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8409 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8412 /* Now do any requested locks */
8413 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8415 /* Data now points at the beginning of the list
8416 of smb_lkrng structs */
8418 for(i
= 0; i
< (int)num_locks
; i
++) {
8419 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8420 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8421 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8423 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8424 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8425 locks
[i
].brltype
= PENDING_READ_LOCK
;
8427 locks
[i
].brltype
= READ_LOCK
;
8430 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8431 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8433 locks
[i
].brltype
= WRITE_LOCK
;
8438 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8439 if (!NT_STATUS_IS_OK(status
)) {
8440 END_PROFILE(SMBlockingX
);
8441 reply_nterror(req
, status
);
8445 status
= smbd_do_locking(req
, fsp
,
8446 locktype
, lock_timeout
,
8449 if (!NT_STATUS_IS_OK(status
)) {
8450 END_PROFILE(SMBlockingX
);
8451 reply_nterror(req
, status
);
8455 END_PROFILE(SMBlockingX
);
8459 reply_outbuf(req
, 2, 0);
8460 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8461 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8463 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8464 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8466 END_PROFILE(SMBlockingX
);
8470 #define DBGC_CLASS DBGC_ALL
8472 /****************************************************************************
8473 Reply to a SMBreadbmpx (read block multiplex) request.
8474 Always reply with an error, if someone has a platform really needs this,
8475 please contact vl@samba.org
8476 ****************************************************************************/
8478 void reply_readbmpx(struct smb_request
*req
)
8480 START_PROFILE(SMBreadBmpx
);
8481 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8482 END_PROFILE(SMBreadBmpx
);
8486 /****************************************************************************
8487 Reply to a SMBreadbs (read block multiplex secondary) request.
8488 Always reply with an error, if someone has a platform really needs this,
8489 please contact vl@samba.org
8490 ****************************************************************************/
8492 void reply_readbs(struct smb_request
*req
)
8494 START_PROFILE(SMBreadBs
);
8495 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8496 END_PROFILE(SMBreadBs
);
8500 /****************************************************************************
8501 Reply to a SMBsetattrE.
8502 ****************************************************************************/
8504 void reply_setattrE(struct smb_request
*req
)
8506 connection_struct
*conn
= req
->conn
;
8507 struct smb_file_time ft
;
8511 START_PROFILE(SMBsetattrE
);
8515 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8519 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8521 if(!fsp
|| (fsp
->conn
!= conn
)) {
8522 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8527 * Convert the DOS times into unix times.
8530 ft
.atime
= convert_time_t_to_timespec(
8531 srv_make_unix_date2(req
->vwv
+3));
8532 ft
.mtime
= convert_time_t_to_timespec(
8533 srv_make_unix_date2(req
->vwv
+5));
8534 ft
.create_time
= convert_time_t_to_timespec(
8535 srv_make_unix_date2(req
->vwv
+1));
8537 reply_outbuf(req
, 0, 0);
8540 * Patch from Ray Frush <frush@engr.colostate.edu>
8541 * Sometimes times are sent as zero - ignore them.
8544 /* Ensure we have a valid stat struct for the source. */
8545 status
= vfs_stat_fsp(fsp
);
8546 if (!NT_STATUS_IS_OK(status
)) {
8547 reply_nterror(req
, status
);
8551 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8552 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8556 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8557 if (!NT_STATUS_IS_OK(status
)) {
8558 reply_nterror(req
, status
);
8562 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8565 (unsigned int)ft
.atime
.tv_sec
,
8566 (unsigned int)ft
.mtime
.tv_sec
,
8567 (unsigned int)ft
.create_time
.tv_sec
8570 END_PROFILE(SMBsetattrE
);
8575 /* Back from the dead for OS/2..... JRA. */
8577 /****************************************************************************
8578 Reply to a SMBwritebmpx (write block multiplex primary) request.
8579 Always reply with an error, if someone has a platform really needs this,
8580 please contact vl@samba.org
8581 ****************************************************************************/
8583 void reply_writebmpx(struct smb_request
*req
)
8585 START_PROFILE(SMBwriteBmpx
);
8586 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8587 END_PROFILE(SMBwriteBmpx
);
8591 /****************************************************************************
8592 Reply to a SMBwritebs (write block multiplex secondary) request.
8593 Always reply with an error, if someone has a platform really needs this,
8594 please contact vl@samba.org
8595 ****************************************************************************/
8597 void reply_writebs(struct smb_request
*req
)
8599 START_PROFILE(SMBwriteBs
);
8600 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8601 END_PROFILE(SMBwriteBs
);
8605 /****************************************************************************
8606 Reply to a SMBgetattrE.
8607 ****************************************************************************/
8609 void reply_getattrE(struct smb_request
*req
)
8611 connection_struct
*conn
= req
->conn
;
8614 struct timespec create_ts
;
8616 START_PROFILE(SMBgetattrE
);
8619 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8620 END_PROFILE(SMBgetattrE
);
8624 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8626 if(!fsp
|| (fsp
->conn
!= conn
)) {
8627 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8628 END_PROFILE(SMBgetattrE
);
8632 /* Do an fstat on this file */
8634 reply_nterror(req
, map_nt_error_from_unix(errno
));
8635 END_PROFILE(SMBgetattrE
);
8639 mode
= dos_mode(conn
, fsp
->fsp_name
);
8642 * Convert the times into dos times. Set create
8643 * date to be last modify date as UNIX doesn't save
8647 reply_outbuf(req
, 11, 0);
8649 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8650 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8651 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8652 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8653 /* Should we check pending modtime here ? JRA */
8654 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8655 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8657 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8658 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8659 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8661 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8662 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8663 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8665 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8667 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8669 END_PROFILE(SMBgetattrE
);