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 srv_send_smb(xconn
, outbuf
, false, 0, false, NULL
);
784 if (CVAL(outbuf
, 0) != 0x82) {
785 exit_server_cleanly("invalid netbios session");
790 /****************************************************************************
792 conn POINTER CAN BE NULL HERE !
793 ****************************************************************************/
795 void reply_tcon(struct smb_request
*req
)
797 connection_struct
*conn
= req
->conn
;
799 char *service_buf
= NULL
;
800 char *password
= NULL
;
806 TALLOC_CTX
*ctx
= talloc_tos();
807 struct smbXsrv_connection
*xconn
= req
->xconn
;
808 NTTIME now
= timeval_to_nttime(&req
->request_time
);
810 START_PROFILE(SMBtcon
);
812 if (req
->buflen
< 4) {
813 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
814 END_PROFILE(SMBtcon
);
819 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
821 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
823 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
826 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
828 END_PROFILE(SMBtcon
);
831 p2
= strrchr_m(service_buf
,'\\');
835 service
= service_buf
;
838 conn
= make_connection(req
, now
, service
, dev
,
839 req
->vuid
,&nt_status
);
843 reply_nterror(req
, nt_status
);
844 END_PROFILE(SMBtcon
);
848 reply_outbuf(req
, 2, 0);
849 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
850 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
851 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
853 DEBUG(3,("tcon service=%s cnum=%d\n",
854 service
, conn
->cnum
));
856 END_PROFILE(SMBtcon
);
860 /****************************************************************************
861 Reply to a tcon and X.
862 conn POINTER CAN BE NULL HERE !
863 ****************************************************************************/
865 void reply_tcon_and_X(struct smb_request
*req
)
867 connection_struct
*conn
= req
->conn
;
868 const char *service
= NULL
;
869 TALLOC_CTX
*ctx
= talloc_tos();
870 /* what the cleint thinks the device is */
871 char *client_devicetype
= NULL
;
872 /* what the server tells the client the share represents */
873 const char *server_devicetype
;
880 struct smbXsrv_session
*session
= NULL
;
881 NTTIME now
= timeval_to_nttime(&req
->request_time
);
882 bool session_key_updated
= false;
883 uint16_t optional_support
= 0;
884 struct smbXsrv_connection
*xconn
= req
->xconn
;
886 START_PROFILE(SMBtconX
);
889 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
890 END_PROFILE(SMBtconX
);
894 passlen
= SVAL(req
->vwv
+3, 0);
895 tcon_flags
= SVAL(req
->vwv
+2, 0);
897 /* we might have to close an old one */
898 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
899 struct smbXsrv_tcon
*tcon
;
907 * TODO: cancel all outstanding requests on the tcon
909 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
910 if (!NT_STATUS_IS_OK(status
)) {
911 DEBUG(0, ("reply_tcon_and_X: "
912 "smbXsrv_tcon_disconnect() failed: %s\n",
915 * If we hit this case, there is something completely
916 * wrong, so we better disconnect the transport connection.
918 END_PROFILE(SMBtconX
);
919 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
926 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
927 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
928 END_PROFILE(SMBtconX
);
932 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
933 p
= req
->buf
+ passlen
;
935 p
= req
->buf
+ passlen
+ 1;
938 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
941 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
942 END_PROFILE(SMBtconX
);
947 * the service name can be either: \\server\share
948 * or share directly like on the DELL PowerVault 705
951 q
= strchr_m(path
+2,'\\');
953 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
954 END_PROFILE(SMBtconX
);
962 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
963 &client_devicetype
, p
,
964 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
966 if (client_devicetype
== NULL
) {
967 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
968 END_PROFILE(SMBtconX
);
972 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
974 nt_status
= smb1srv_session_lookup(xconn
,
975 req
->vuid
, now
, &session
);
976 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
977 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
978 END_PROFILE(SMBtconX
);
981 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
982 reply_nterror(req
, nt_status
);
983 END_PROFILE(SMBtconX
);
986 if (!NT_STATUS_IS_OK(nt_status
)) {
987 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
988 END_PROFILE(SMBtconX
);
992 if (session
->global
->auth_session_info
== NULL
) {
993 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
994 END_PROFILE(SMBtconX
);
999 * If there is no application key defined yet
1002 * This means we setup the application key on the
1003 * first tcon that happens via the given session.
1005 * Once the application key is defined, it does not
1008 if (session
->global
->application_key
.length
== 0 &&
1009 session
->global
->signing_key
.length
> 0)
1011 struct smbXsrv_session
*x
= session
;
1012 struct auth_session_info
*session_info
=
1013 session
->global
->auth_session_info
;
1014 uint8_t session_key
[16];
1016 ZERO_STRUCT(session_key
);
1017 memcpy(session_key
, x
->global
->signing_key
.data
,
1018 MIN(x
->global
->signing_key
.length
, sizeof(session_key
)));
1021 * The application key is truncated/padded to 16 bytes
1023 x
->global
->application_key
= data_blob_talloc(x
->global
,
1025 sizeof(session_key
));
1026 ZERO_STRUCT(session_key
);
1027 if (x
->global
->application_key
.data
== NULL
) {
1028 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1029 END_PROFILE(SMBtconX
);
1033 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
1034 smb_key_derivation(x
->global
->application_key
.data
,
1035 x
->global
->application_key
.length
,
1036 x
->global
->application_key
.data
);
1037 optional_support
|= SMB_EXTENDED_SIGNATURES
;
1041 * Place the application key into the session_info
1043 data_blob_clear_free(&session_info
->session_key
);
1044 session_info
->session_key
= data_blob_dup_talloc(session_info
,
1045 x
->global
->application_key
);
1046 if (session_info
->session_key
.data
== NULL
) {
1047 data_blob_clear_free(&x
->global
->application_key
);
1048 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1049 END_PROFILE(SMBtconX
);
1052 session_key_updated
= true;
1055 conn
= make_connection(req
, now
, service
, client_devicetype
,
1056 req
->vuid
, &nt_status
);
1060 if (session_key_updated
) {
1061 struct smbXsrv_session
*x
= session
;
1062 struct auth_session_info
*session_info
=
1063 session
->global
->auth_session_info
;
1064 data_blob_clear_free(&x
->global
->application_key
);
1065 data_blob_clear_free(&session_info
->session_key
);
1067 reply_nterror(req
, nt_status
);
1068 END_PROFILE(SMBtconX
);
1073 server_devicetype
= "IPC";
1074 else if ( IS_PRINT(conn
) )
1075 server_devicetype
= "LPT1:";
1077 server_devicetype
= "A:";
1079 if (get_Protocol() < PROTOCOL_NT1
) {
1080 reply_outbuf(req
, 2, 0);
1081 if (message_push_string(&req
->outbuf
, server_devicetype
,
1082 STR_TERMINATE
|STR_ASCII
) == -1) {
1083 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1084 END_PROFILE(SMBtconX
);
1088 /* NT sets the fstype of IPC$ to the null string */
1089 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
1091 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
1092 /* Return permissions. */
1096 reply_outbuf(req
, 7, 0);
1099 perm1
= FILE_ALL_ACCESS
;
1100 perm2
= FILE_ALL_ACCESS
;
1102 perm1
= conn
->share_access
;
1105 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
1106 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
1108 reply_outbuf(req
, 3, 0);
1111 if ((message_push_string(&req
->outbuf
, server_devicetype
,
1112 STR_TERMINATE
|STR_ASCII
) == -1)
1113 || (message_push_string(&req
->outbuf
, fstype
,
1114 STR_TERMINATE
) == -1)) {
1115 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1116 END_PROFILE(SMBtconX
);
1120 /* what does setting this bit do? It is set by NT4 and
1121 may affect the ability to autorun mounted cdroms */
1122 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
1124 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
1126 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
1127 DEBUG(2,("Serving %s as a Dfs root\n",
1128 lp_servicename(ctx
, SNUM(conn
)) ));
1129 optional_support
|= SMB_SHARE_IN_DFS
;
1132 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
1135 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1136 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1138 DEBUG(3,("tconX service=%s \n",
1141 /* set the incoming and outgoing tid to the just created one */
1142 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
1143 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
1145 END_PROFILE(SMBtconX
);
1147 req
->tid
= conn
->cnum
;
1150 /****************************************************************************
1151 Reply to an unknown type.
1152 ****************************************************************************/
1154 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
1156 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1157 smb_fn_name(type
), type
, type
));
1158 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
1162 /****************************************************************************
1164 conn POINTER CAN BE NULL HERE !
1165 ****************************************************************************/
1167 void reply_ioctl(struct smb_request
*req
)
1169 connection_struct
*conn
= req
->conn
;
1172 uint32_t ioctl_code
;
1176 START_PROFILE(SMBioctl
);
1179 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1180 END_PROFILE(SMBioctl
);
1184 device
= SVAL(req
->vwv
+1, 0);
1185 function
= SVAL(req
->vwv
+2, 0);
1186 ioctl_code
= (device
<< 16) + function
;
1188 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
1190 switch (ioctl_code
) {
1191 case IOCTL_QUERY_JOB_INFO
:
1195 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
1196 END_PROFILE(SMBioctl
);
1200 reply_outbuf(req
, 8, replysize
+1);
1201 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
1202 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
1203 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
1204 p
= smb_buf(req
->outbuf
);
1205 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
1206 p
+= 1; /* Allow for alignment */
1208 switch (ioctl_code
) {
1209 case IOCTL_QUERY_JOB_INFO
:
1213 files_struct
*fsp
= file_fsp(
1214 req
, SVAL(req
->vwv
+0, 0));
1216 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
1217 END_PROFILE(SMBioctl
);
1221 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
1223 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
1224 lp_netbios_name(), 15,
1225 STR_TERMINATE
|STR_ASCII
, &len
);
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 reply_nterror(req
, status
);
1228 END_PROFILE(SMBioctl
);
1232 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
1234 lp_servicename(talloc_tos(),
1236 13, STR_TERMINATE
|STR_ASCII
, &len
);
1237 if (!NT_STATUS_IS_OK(status
)) {
1238 reply_nterror(req
, status
);
1239 END_PROFILE(SMBioctl
);
1243 memset(p
+18, 0, 13);
1249 END_PROFILE(SMBioctl
);
1253 /****************************************************************************
1254 Strange checkpath NTSTATUS mapping.
1255 ****************************************************************************/
1257 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
1259 /* Strange DOS error code semantics only for checkpath... */
1260 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
1261 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
1262 /* We need to map to ERRbadpath */
1263 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1269 /****************************************************************************
1270 Reply to a checkpath.
1271 ****************************************************************************/
1273 void reply_checkpath(struct smb_request
*req
)
1275 connection_struct
*conn
= req
->conn
;
1276 struct smb_filename
*smb_fname
= NULL
;
1279 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1280 TALLOC_CTX
*ctx
= talloc_tos();
1282 START_PROFILE(SMBcheckpath
);
1284 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
1285 STR_TERMINATE
, &status
);
1287 if (!NT_STATUS_IS_OK(status
)) {
1288 status
= map_checkpath_error(req
->flags2
, status
);
1289 reply_nterror(req
, status
);
1290 END_PROFILE(SMBcheckpath
);
1294 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
1296 status
= filename_convert(ctx
,
1298 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1304 if (!NT_STATUS_IS_OK(status
)) {
1305 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1306 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1307 ERRSRV
, ERRbadpath
);
1308 END_PROFILE(SMBcheckpath
);
1314 if (!VALID_STAT(smb_fname
->st
) &&
1315 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1316 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1317 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1318 status
= map_nt_error_from_unix(errno
);
1322 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1323 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1324 ERRDOS
, ERRbadpath
);
1328 reply_outbuf(req
, 0, 0);
1331 /* We special case this - as when a Windows machine
1332 is parsing a path is steps through the components
1333 one at a time - if a component fails it expects
1334 ERRbadpath, not ERRbadfile.
1336 status
= map_checkpath_error(req
->flags2
, status
);
1337 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1339 * Windows returns different error codes if
1340 * the parent directory is valid but not the
1341 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1342 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1343 * if the path is invalid.
1345 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1346 ERRDOS
, ERRbadpath
);
1350 reply_nterror(req
, status
);
1353 TALLOC_FREE(smb_fname
);
1354 END_PROFILE(SMBcheckpath
);
1358 /****************************************************************************
1360 ****************************************************************************/
1362 void reply_getatr(struct smb_request
*req
)
1364 connection_struct
*conn
= req
->conn
;
1365 struct smb_filename
*smb_fname
= NULL
;
1372 TALLOC_CTX
*ctx
= talloc_tos();
1373 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1375 START_PROFILE(SMBgetatr
);
1377 p
= (const char *)req
->buf
+ 1;
1378 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1379 if (!NT_STATUS_IS_OK(status
)) {
1380 reply_nterror(req
, status
);
1384 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1385 under WfWg - weird! */
1386 if (*fname
== '\0') {
1387 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
1388 if (!CAN_WRITE(conn
)) {
1389 mode
|= FILE_ATTRIBUTE_READONLY
;
1394 uint32_t ucf_flags
= (req
->posix_pathnames
?
1395 UCF_POSIX_PATHNAMES
: 0);
1396 status
= filename_convert(ctx
,
1398 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1403 if (!NT_STATUS_IS_OK(status
)) {
1404 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1405 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1406 ERRSRV
, ERRbadpath
);
1409 reply_nterror(req
, status
);
1412 if (!VALID_STAT(smb_fname
->st
) &&
1413 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1414 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1415 smb_fname_str_dbg(smb_fname
),
1417 reply_nterror(req
, map_nt_error_from_unix(errno
));
1421 mode
= dos_mode(conn
, smb_fname
);
1422 size
= smb_fname
->st
.st_ex_size
;
1424 if (ask_sharemode
) {
1425 struct timespec write_time_ts
;
1426 struct file_id fileid
;
1428 ZERO_STRUCT(write_time_ts
);
1429 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1430 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1431 if (!null_timespec(write_time_ts
)) {
1432 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1436 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1437 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
1442 reply_outbuf(req
, 10, 0);
1444 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1445 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1446 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1448 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1450 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
1452 if (get_Protocol() >= PROTOCOL_NT1
) {
1453 SSVAL(req
->outbuf
, smb_flg2
,
1454 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1457 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1458 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1461 TALLOC_FREE(smb_fname
);
1463 END_PROFILE(SMBgetatr
);
1467 /****************************************************************************
1469 ****************************************************************************/
1471 void reply_setatr(struct smb_request
*req
)
1473 struct smb_file_time ft
;
1474 connection_struct
*conn
= req
->conn
;
1475 struct smb_filename
*smb_fname
= NULL
;
1481 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1482 TALLOC_CTX
*ctx
= talloc_tos();
1484 START_PROFILE(SMBsetatr
);
1489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1493 p
= (const char *)req
->buf
+ 1;
1494 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1495 if (!NT_STATUS_IS_OK(status
)) {
1496 reply_nterror(req
, status
);
1500 status
= filename_convert(ctx
,
1502 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1507 if (!NT_STATUS_IS_OK(status
)) {
1508 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1509 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1510 ERRSRV
, ERRbadpath
);
1513 reply_nterror(req
, status
);
1517 if (smb_fname
->base_name
[0] == '.' &&
1518 smb_fname
->base_name
[1] == '\0') {
1520 * Not sure here is the right place to catch this
1521 * condition. Might be moved to somewhere else later -- vl
1523 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1527 mode
= SVAL(req
->vwv
+0, 0);
1528 mtime
= srv_make_unix_date3(req
->vwv
+1);
1530 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1531 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1532 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
1534 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
1536 status
= check_access(conn
, NULL
, smb_fname
,
1537 FILE_WRITE_ATTRIBUTES
);
1538 if (!NT_STATUS_IS_OK(status
)) {
1539 reply_nterror(req
, status
);
1543 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1545 reply_nterror(req
, map_nt_error_from_unix(errno
));
1550 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1551 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1552 if (!NT_STATUS_IS_OK(status
)) {
1553 reply_nterror(req
, status
);
1557 reply_outbuf(req
, 0, 0);
1559 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1562 TALLOC_FREE(smb_fname
);
1563 END_PROFILE(SMBsetatr
);
1567 /****************************************************************************
1569 ****************************************************************************/
1571 void reply_dskattr(struct smb_request
*req
)
1573 connection_struct
*conn
= req
->conn
;
1575 uint64_t dfree
,dsize
,bsize
;
1576 START_PROFILE(SMBdskattr
);
1578 ret
= get_dfree_info(conn
, ".", &bsize
, &dfree
, &dsize
);
1579 if (ret
== (uint64_t)-1) {
1580 reply_nterror(req
, map_nt_error_from_unix(errno
));
1581 END_PROFILE(SMBdskattr
);
1586 * Force max to fit in 16 bit fields.
1588 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1592 if (bsize
> (WORDMAX
*512)) {
1593 bsize
= (WORDMAX
*512);
1594 if (dsize
> WORDMAX
)
1596 if (dfree
> WORDMAX
)
1602 reply_outbuf(req
, 5, 0);
1604 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1605 double total_space
, free_space
;
1606 /* we need to scale this to a number that DOS6 can handle. We
1607 use floating point so we can handle large drives on systems
1608 that don't have 64 bit integers
1610 we end up displaying a maximum of 2G to DOS systems
1612 total_space
= dsize
* (double)bsize
;
1613 free_space
= dfree
* (double)bsize
;
1615 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1616 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1618 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1619 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1621 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1622 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1623 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1624 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1626 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1627 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1628 SSVAL(req
->outbuf
,smb_vwv2
,512);
1629 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1632 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1634 END_PROFILE(SMBdskattr
);
1639 * Utility function to split the filename from the directory.
1641 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1642 char **fname_dir_out
,
1643 char **fname_mask_out
)
1645 const char *p
= NULL
;
1646 char *fname_dir
= NULL
;
1647 char *fname_mask
= NULL
;
1649 p
= strrchr_m(fname_in
, '/');
1651 fname_dir
= talloc_strdup(ctx
, ".");
1652 fname_mask
= talloc_strdup(ctx
, fname_in
);
1654 fname_dir
= talloc_strndup(ctx
, fname_in
,
1655 PTR_DIFF(p
, fname_in
));
1656 fname_mask
= talloc_strdup(ctx
, p
+1);
1659 if (!fname_dir
|| !fname_mask
) {
1660 TALLOC_FREE(fname_dir
);
1661 TALLOC_FREE(fname_mask
);
1662 return NT_STATUS_NO_MEMORY
;
1665 *fname_dir_out
= fname_dir
;
1666 *fname_mask_out
= fname_mask
;
1667 return NT_STATUS_OK
;
1670 /****************************************************************************
1672 ****************************************************************************/
1674 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1684 char *mask2
= talloc_strdup(ctx
, mask
);
1690 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1694 memset(buf
+1,' ',11);
1695 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1697 push_ascii(buf
+1,mask2
,8, 0);
1698 push_ascii(buf
+9,p
+1,3, 0);
1701 push_ascii(buf
+1,mask2
,11, 0);
1704 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1706 srv_put_dos_date(buf
,22,date
);
1707 SSVAL(buf
,26,size
& 0xFFFF);
1708 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1709 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1710 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1711 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1712 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1716 /****************************************************************************
1718 Can be called from SMBsearch, SMBffirst or SMBfunique.
1719 ****************************************************************************/
1721 void reply_search(struct smb_request
*req
)
1723 connection_struct
*conn
= req
->conn
;
1726 char *directory
= NULL
;
1727 struct smb_filename
*smb_fname
= NULL
;
1731 struct timespec date
;
1733 unsigned int numentries
= 0;
1734 unsigned int maxentries
= 0;
1735 bool finished
= False
;
1740 bool check_descend
= False
;
1741 bool expect_close
= False
;
1743 bool mask_contains_wcard
= False
;
1744 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1745 TALLOC_CTX
*ctx
= talloc_tos();
1746 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1747 struct dptr_struct
*dirptr
= NULL
;
1748 struct smbXsrv_connection
*xconn
= req
->xconn
;
1749 struct smbd_server_connection
*sconn
= req
->sconn
;
1751 START_PROFILE(SMBsearch
);
1754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1758 if (req
->posix_pathnames
) {
1759 reply_unknown_new(req
, req
->cmd
);
1763 /* If we were called as SMBffirst then we must expect close. */
1764 if(req
->cmd
== SMBffirst
) {
1765 expect_close
= True
;
1768 reply_outbuf(req
, 1, 3);
1769 maxentries
= SVAL(req
->vwv
+0, 0);
1770 dirtype
= SVAL(req
->vwv
+1, 0);
1771 p
= (const char *)req
->buf
+ 1;
1772 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1773 &nt_status
, &mask_contains_wcard
);
1774 if (!NT_STATUS_IS_OK(nt_status
)) {
1775 reply_nterror(req
, nt_status
);
1780 status_len
= SVAL(p
, 0);
1783 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1785 if (status_len
== 0) {
1786 struct smb_filename
*smb_dname
= NULL
;
1787 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1788 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1789 nt_status
= filename_convert(ctx
, conn
,
1790 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1793 &mask_contains_wcard
,
1795 if (!NT_STATUS_IS_OK(nt_status
)) {
1796 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1797 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1798 ERRSRV
, ERRbadpath
);
1801 reply_nterror(req
, nt_status
);
1805 directory
= smb_fname
->base_name
;
1807 p
= strrchr_m(directory
,'/');
1808 if ((p
!= NULL
) && (*directory
!= '/')) {
1809 mask
= talloc_strdup(ctx
, p
+ 1);
1810 directory
= talloc_strndup(ctx
, directory
,
1811 PTR_DIFF(p
, directory
));
1813 mask
= talloc_strdup(ctx
, directory
);
1814 directory
= talloc_strdup(ctx
,".");
1818 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1822 memset((char *)status
,'\0',21);
1823 SCVAL(status
,0,(dirtype
& 0x1F));
1825 smb_dname
= synthetic_smb_fname(talloc_tos(),
1830 if (smb_dname
== NULL
) {
1831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1835 nt_status
= dptr_create(conn
,
1843 mask_contains_wcard
,
1847 TALLOC_FREE(smb_dname
);
1849 if (!NT_STATUS_IS_OK(nt_status
)) {
1850 reply_nterror(req
, nt_status
);
1853 dptr_num
= dptr_dnum(dirptr
);
1856 const char *dirpath
;
1858 memcpy(status
,p
,21);
1859 status_dirtype
= CVAL(status
,0) & 0x1F;
1860 if (status_dirtype
!= (dirtype
& 0x1F)) {
1861 dirtype
= status_dirtype
;
1864 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1868 dirpath
= dptr_path(sconn
, dptr_num
);
1869 directory
= talloc_strdup(ctx
, dirpath
);
1871 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1875 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1880 * For a 'continue' search we have no string. So
1881 * check from the initial saved string.
1883 if (!req
->posix_pathnames
) {
1884 mask_contains_wcard
= ms_has_wild(mask
);
1886 dirtype
= dptr_attr(sconn
, dptr_num
);
1889 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1891 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1892 dptr_init_search_op(dirptr
);
1894 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1895 char buf
[DIR_STRUCT_SIZE
];
1896 memcpy(buf
,status
,21);
1897 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1898 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1899 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1902 dptr_fill(sconn
, buf
+12,dptr_num
);
1903 if (dptr_zero(buf
+12) && (status_len
==0)) {
1908 if (message_push_blob(&req
->outbuf
,
1909 data_blob_const(buf
, sizeof(buf
)))
1911 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1916 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1917 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1919 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1921 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1922 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1923 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1924 check_descend
= True
;
1927 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1928 finished
= !get_dir_entry(ctx
,
1939 char buf
[DIR_STRUCT_SIZE
];
1940 memcpy(buf
,status
,21);
1941 if (!make_dir_struct(ctx
,
1947 convert_timespec_to_time_t(date
),
1948 !allow_long_path_components
)) {
1949 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1952 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1955 if (message_push_blob(&req
->outbuf
,
1956 data_blob_const(buf
, sizeof(buf
)))
1958 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1968 /* If we were called as SMBffirst with smb_search_id == NULL
1969 and no entries were found then return error and close dirptr
1972 if (numentries
== 0) {
1973 dptr_close(sconn
, &dptr_num
);
1974 } else if(expect_close
&& status_len
== 0) {
1975 /* Close the dptr - we know it's gone */
1976 dptr_close(sconn
, &dptr_num
);
1979 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1980 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1981 dptr_close(sconn
, &dptr_num
);
1984 if ((numentries
== 0) && !mask_contains_wcard
) {
1985 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1989 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1990 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1991 SCVAL(smb_buf(req
->outbuf
),0,5);
1992 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1994 /* The replies here are never long name. */
1995 SSVAL(req
->outbuf
, smb_flg2
,
1996 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1997 if (!allow_long_path_components
) {
1998 SSVAL(req
->outbuf
, smb_flg2
,
1999 SVAL(req
->outbuf
, smb_flg2
)
2000 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2003 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2004 SSVAL(req
->outbuf
, smb_flg2
,
2005 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2007 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2008 smb_fn_name(req
->cmd
),
2015 TALLOC_FREE(directory
);
2017 TALLOC_FREE(smb_fname
);
2018 END_PROFILE(SMBsearch
);
2022 /****************************************************************************
2023 Reply to a fclose (stop directory search).
2024 ****************************************************************************/
2026 void reply_fclose(struct smb_request
*req
)
2034 bool path_contains_wcard
= False
;
2035 TALLOC_CTX
*ctx
= talloc_tos();
2036 struct smbd_server_connection
*sconn
= req
->sconn
;
2038 START_PROFILE(SMBfclose
);
2040 if (req
->posix_pathnames
) {
2041 reply_unknown_new(req
, req
->cmd
);
2042 END_PROFILE(SMBfclose
);
2046 p
= (const char *)req
->buf
+ 1;
2047 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2048 &err
, &path_contains_wcard
);
2049 if (!NT_STATUS_IS_OK(err
)) {
2050 reply_nterror(req
, err
);
2051 END_PROFILE(SMBfclose
);
2055 status_len
= SVAL(p
,0);
2058 if (status_len
== 0) {
2059 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2060 END_PROFILE(SMBfclose
);
2064 memcpy(status
,p
,21);
2066 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2067 /* Close the dptr - we know it's gone */
2068 dptr_close(sconn
, &dptr_num
);
2071 reply_outbuf(req
, 1, 0);
2072 SSVAL(req
->outbuf
,smb_vwv0
,0);
2074 DEBUG(3,("search close\n"));
2076 END_PROFILE(SMBfclose
);
2080 /****************************************************************************
2082 ****************************************************************************/
2084 void reply_open(struct smb_request
*req
)
2086 connection_struct
*conn
= req
->conn
;
2087 struct smb_filename
*smb_fname
= NULL
;
2097 uint32_t access_mask
;
2098 uint32_t share_mode
;
2099 uint32_t create_disposition
;
2100 uint32_t create_options
= 0;
2101 uint32_t private_flags
= 0;
2103 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2104 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2105 TALLOC_CTX
*ctx
= talloc_tos();
2107 START_PROFILE(SMBopen
);
2110 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2114 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2115 deny_mode
= SVAL(req
->vwv
+0, 0);
2116 dos_attr
= SVAL(req
->vwv
+1, 0);
2118 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2119 STR_TERMINATE
, &status
);
2120 if (!NT_STATUS_IS_OK(status
)) {
2121 reply_nterror(req
, status
);
2125 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2126 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2127 &share_mode
, &create_disposition
,
2128 &create_options
, &private_flags
)) {
2129 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2133 status
= filename_convert(ctx
,
2135 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2140 if (!NT_STATUS_IS_OK(status
)) {
2141 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2142 reply_botherror(req
,
2143 NT_STATUS_PATH_NOT_COVERED
,
2144 ERRSRV
, ERRbadpath
);
2147 reply_nterror(req
, status
);
2151 status
= SMB_VFS_CREATE_FILE(
2154 0, /* root_dir_fid */
2155 smb_fname
, /* fname */
2156 access_mask
, /* access_mask */
2157 share_mode
, /* share_access */
2158 create_disposition
, /* create_disposition*/
2159 create_options
, /* create_options */
2160 dos_attr
, /* file_attributes */
2161 oplock_request
, /* oplock_request */
2163 0, /* allocation_size */
2169 NULL
, NULL
); /* create context */
2171 if (!NT_STATUS_IS_OK(status
)) {
2172 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2173 /* We have re-scheduled this call. */
2176 reply_openerror(req
, status
);
2180 /* Ensure we're pointing at the correct stat struct. */
2181 TALLOC_FREE(smb_fname
);
2182 smb_fname
= fsp
->fsp_name
;
2184 size
= smb_fname
->st
.st_ex_size
;
2185 fattr
= dos_mode(conn
, smb_fname
);
2187 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2189 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2190 DEBUG(3,("attempt to open a directory %s\n",
2192 close_file(req
, fsp
, ERROR_CLOSE
);
2193 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2194 ERRDOS
, ERRnoaccess
);
2198 reply_outbuf(req
, 7, 0);
2199 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2200 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2201 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2202 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2204 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2206 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2207 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2209 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2210 SCVAL(req
->outbuf
,smb_flg
,
2211 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2214 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2215 SCVAL(req
->outbuf
,smb_flg
,
2216 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2219 END_PROFILE(SMBopen
);
2223 /****************************************************************************
2224 Reply to an open and X.
2225 ****************************************************************************/
2227 void reply_open_and_X(struct smb_request
*req
)
2229 connection_struct
*conn
= req
->conn
;
2230 struct smb_filename
*smb_fname
= NULL
;
2232 uint16_t open_flags
;
2235 /* Breakout the oplock request bits so we can set the
2236 reply bits separately. */
2237 int ex_oplock_request
;
2238 int core_oplock_request
;
2241 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2242 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2250 uint64_t allocation_size
;
2251 ssize_t retval
= -1;
2252 uint32_t access_mask
;
2253 uint32_t share_mode
;
2254 uint32_t create_disposition
;
2255 uint32_t create_options
= 0;
2256 uint32_t private_flags
= 0;
2257 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2258 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2259 TALLOC_CTX
*ctx
= talloc_tos();
2261 START_PROFILE(SMBopenX
);
2263 if (req
->wct
< 15) {
2264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2268 open_flags
= SVAL(req
->vwv
+2, 0);
2269 deny_mode
= SVAL(req
->vwv
+3, 0);
2270 smb_attr
= SVAL(req
->vwv
+5, 0);
2271 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2272 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2273 oplock_request
= ex_oplock_request
| core_oplock_request
;
2274 smb_ofun
= SVAL(req
->vwv
+8, 0);
2275 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2277 /* If it's an IPC, pass off the pipe handler. */
2279 if (lp_nt_pipe_support()) {
2280 reply_open_pipe_and_X(conn
, req
);
2282 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2287 /* XXXX we need to handle passed times, sattr and flags */
2288 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2289 STR_TERMINATE
, &status
);
2290 if (!NT_STATUS_IS_OK(status
)) {
2291 reply_nterror(req
, status
);
2295 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2297 &access_mask
, &share_mode
,
2298 &create_disposition
,
2301 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2305 status
= filename_convert(ctx
,
2307 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2312 if (!NT_STATUS_IS_OK(status
)) {
2313 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2314 reply_botherror(req
,
2315 NT_STATUS_PATH_NOT_COVERED
,
2316 ERRSRV
, ERRbadpath
);
2319 reply_nterror(req
, status
);
2323 status
= SMB_VFS_CREATE_FILE(
2326 0, /* root_dir_fid */
2327 smb_fname
, /* fname */
2328 access_mask
, /* access_mask */
2329 share_mode
, /* share_access */
2330 create_disposition
, /* create_disposition*/
2331 create_options
, /* create_options */
2332 smb_attr
, /* file_attributes */
2333 oplock_request
, /* oplock_request */
2335 0, /* allocation_size */
2340 &smb_action
, /* pinfo */
2341 NULL
, NULL
); /* create context */
2343 if (!NT_STATUS_IS_OK(status
)) {
2344 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2345 /* We have re-scheduled this call. */
2348 reply_openerror(req
, status
);
2352 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2353 if the file is truncated or created. */
2354 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2355 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2356 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2357 close_file(req
, fsp
, ERROR_CLOSE
);
2358 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2361 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2363 close_file(req
, fsp
, ERROR_CLOSE
);
2364 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2367 status
= vfs_stat_fsp(fsp
);
2368 if (!NT_STATUS_IS_OK(status
)) {
2369 close_file(req
, fsp
, ERROR_CLOSE
);
2370 reply_nterror(req
, status
);
2375 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2376 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2377 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2378 close_file(req
, fsp
, ERROR_CLOSE
);
2379 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2383 /* If the caller set the extended oplock request bit
2384 and we granted one (by whatever means) - set the
2385 correct bit for extended oplock reply.
2388 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2389 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2392 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2393 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2396 /* If the caller set the core oplock request bit
2397 and we granted one (by whatever means) - set the
2398 correct bit for core oplock reply.
2401 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2402 reply_outbuf(req
, 19, 0);
2404 reply_outbuf(req
, 15, 0);
2407 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2408 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2410 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2411 SCVAL(req
->outbuf
, smb_flg
,
2412 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2415 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2416 SCVAL(req
->outbuf
, smb_flg
,
2417 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2420 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2421 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2422 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2423 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2425 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2427 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2428 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2429 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2431 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2432 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2436 TALLOC_FREE(smb_fname
);
2437 END_PROFILE(SMBopenX
);
2441 /****************************************************************************
2442 Reply to a SMBulogoffX.
2443 ****************************************************************************/
2445 void reply_ulogoffX(struct smb_request
*req
)
2447 struct smbd_server_connection
*sconn
= req
->sconn
;
2448 struct user_struct
*vuser
;
2449 struct smbXsrv_session
*session
= NULL
;
2452 START_PROFILE(SMBulogoffX
);
2454 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2457 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2458 (unsigned long long)req
->vuid
));
2460 req
->vuid
= UID_FIELD_INVALID
;
2461 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2462 END_PROFILE(SMBulogoffX
);
2466 session
= vuser
->session
;
2470 * TODO: cancel all outstanding requests on the session
2472 status
= smbXsrv_session_logoff(session
);
2473 if (!NT_STATUS_IS_OK(status
)) {
2474 DEBUG(0, ("reply_ulogoff: "
2475 "smbXsrv_session_logoff() failed: %s\n",
2476 nt_errstr(status
)));
2478 * If we hit this case, there is something completely
2479 * wrong, so we better disconnect the transport connection.
2481 END_PROFILE(SMBulogoffX
);
2482 exit_server(__location__
": smbXsrv_session_logoff failed");
2486 TALLOC_FREE(session
);
2488 reply_outbuf(req
, 2, 0);
2489 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2490 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2492 DEBUG(3, ("ulogoffX vuid=%llu\n",
2493 (unsigned long long)req
->vuid
));
2495 END_PROFILE(SMBulogoffX
);
2496 req
->vuid
= UID_FIELD_INVALID
;
2499 /****************************************************************************
2500 Reply to a mknew or a create.
2501 ****************************************************************************/
2503 void reply_mknew(struct smb_request
*req
)
2505 connection_struct
*conn
= req
->conn
;
2506 struct smb_filename
*smb_fname
= NULL
;
2509 struct smb_file_time ft
;
2511 int oplock_request
= 0;
2513 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2514 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2515 uint32_t create_disposition
;
2516 uint32_t create_options
= 0;
2517 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2518 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2519 TALLOC_CTX
*ctx
= talloc_tos();
2521 START_PROFILE(SMBcreate
);
2525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2529 fattr
= SVAL(req
->vwv
+0, 0);
2530 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2533 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2535 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2536 STR_TERMINATE
, &status
);
2537 if (!NT_STATUS_IS_OK(status
)) {
2538 reply_nterror(req
, status
);
2542 status
= filename_convert(ctx
,
2544 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2549 if (!NT_STATUS_IS_OK(status
)) {
2550 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2551 reply_botherror(req
,
2552 NT_STATUS_PATH_NOT_COVERED
,
2553 ERRSRV
, ERRbadpath
);
2556 reply_nterror(req
, status
);
2560 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2561 DEBUG(0,("Attempt to create file (%s) with volid set - "
2562 "please report this\n",
2563 smb_fname_str_dbg(smb_fname
)));
2566 if(req
->cmd
== SMBmknew
) {
2567 /* We should fail if file exists. */
2568 create_disposition
= FILE_CREATE
;
2570 /* Create if file doesn't exist, truncate if it does. */
2571 create_disposition
= FILE_OVERWRITE_IF
;
2574 status
= SMB_VFS_CREATE_FILE(
2577 0, /* root_dir_fid */
2578 smb_fname
, /* fname */
2579 access_mask
, /* access_mask */
2580 share_mode
, /* share_access */
2581 create_disposition
, /* create_disposition*/
2582 create_options
, /* create_options */
2583 fattr
, /* file_attributes */
2584 oplock_request
, /* oplock_request */
2586 0, /* allocation_size */
2587 0, /* private_flags */
2592 NULL
, NULL
); /* create context */
2594 if (!NT_STATUS_IS_OK(status
)) {
2595 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2596 /* We have re-scheduled this call. */
2599 reply_openerror(req
, status
);
2603 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2604 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2605 if (!NT_STATUS_IS_OK(status
)) {
2606 END_PROFILE(SMBcreate
);
2610 reply_outbuf(req
, 1, 0);
2611 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2613 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2614 SCVAL(req
->outbuf
,smb_flg
,
2615 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2618 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2619 SCVAL(req
->outbuf
,smb_flg
,
2620 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2623 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2624 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2625 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2626 (unsigned int)fattr
));
2629 TALLOC_FREE(smb_fname
);
2630 END_PROFILE(SMBcreate
);
2634 /****************************************************************************
2635 Reply to a create temporary file.
2636 ****************************************************************************/
2638 void reply_ctemp(struct smb_request
*req
)
2640 connection_struct
*conn
= req
->conn
;
2641 struct smb_filename
*smb_fname
= NULL
;
2642 char *wire_name
= NULL
;
2650 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2651 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2652 TALLOC_CTX
*ctx
= talloc_tos();
2654 START_PROFILE(SMBctemp
);
2657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2661 fattr
= SVAL(req
->vwv
+0, 0);
2662 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2664 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2665 STR_TERMINATE
, &status
);
2666 if (!NT_STATUS_IS_OK(status
)) {
2667 reply_nterror(req
, status
);
2671 for (i
= 0; i
< 10; i
++) {
2673 fname
= talloc_asprintf(ctx
,
2676 generate_random_str_list(ctx
, 5, "0123456789"));
2678 fname
= talloc_asprintf(ctx
,
2680 generate_random_str_list(ctx
, 5, "0123456789"));
2684 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2688 status
= filename_convert(ctx
, conn
,
2689 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2694 if (!NT_STATUS_IS_OK(status
)) {
2695 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2696 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2697 ERRSRV
, ERRbadpath
);
2700 reply_nterror(req
, status
);
2704 /* Create the file. */
2705 status
= SMB_VFS_CREATE_FILE(
2708 0, /* root_dir_fid */
2709 smb_fname
, /* fname */
2710 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2711 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2712 FILE_CREATE
, /* create_disposition*/
2713 0, /* create_options */
2714 fattr
, /* file_attributes */
2715 oplock_request
, /* oplock_request */
2717 0, /* allocation_size */
2718 0, /* private_flags */
2723 NULL
, NULL
); /* create context */
2725 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2727 TALLOC_FREE(smb_fname
);
2731 if (!NT_STATUS_IS_OK(status
)) {
2732 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2733 /* We have re-scheduled this call. */
2736 reply_openerror(req
, status
);
2744 /* Collision after 10 times... */
2745 reply_nterror(req
, status
);
2749 reply_outbuf(req
, 1, 0);
2750 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2752 /* the returned filename is relative to the directory */
2753 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2755 s
= fsp
->fsp_name
->base_name
;
2761 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2762 thing in the byte section. JRA */
2763 SSVALS(p
, 0, -1); /* what is this? not in spec */
2765 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2767 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2771 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2772 SCVAL(req
->outbuf
, smb_flg
,
2773 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2776 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2777 SCVAL(req
->outbuf
, smb_flg
,
2778 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2781 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2782 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2783 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2785 TALLOC_FREE(smb_fname
);
2786 TALLOC_FREE(wire_name
);
2787 END_PROFILE(SMBctemp
);
2791 /*******************************************************************
2792 Check if a user is allowed to rename a file.
2793 ********************************************************************/
2795 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2798 if (!CAN_WRITE(conn
)) {
2799 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2802 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2803 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2804 /* Only bother to read the DOS attribute if we might deny the
2805 rename on the grounds of attribute mismatch. */
2806 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2807 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2808 return NT_STATUS_NO_SUCH_FILE
;
2812 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2813 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2814 return NT_STATUS_OK
;
2817 /* If no pathnames are open below this
2818 directory, allow the rename. */
2820 if (lp_strict_rename(SNUM(conn
))) {
2822 * Strict rename, check open file db.
2824 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2825 return NT_STATUS_ACCESS_DENIED
;
2827 } else if (file_find_subpath(fsp
)) {
2829 * No strict rename, just look in local process.
2831 return NT_STATUS_ACCESS_DENIED
;
2833 return NT_STATUS_OK
;
2836 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2837 return NT_STATUS_OK
;
2840 return NT_STATUS_ACCESS_DENIED
;
2843 /*******************************************************************
2844 * unlink a file with all relevant access checks
2845 *******************************************************************/
2847 static NTSTATUS
do_unlink(connection_struct
*conn
,
2848 struct smb_request
*req
,
2849 struct smb_filename
*smb_fname
,
2854 uint32_t dirtype_orig
= dirtype
;
2857 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2859 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2860 smb_fname_str_dbg(smb_fname
),
2863 if (!CAN_WRITE(conn
)) {
2864 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2868 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2870 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2873 return map_nt_error_from_unix(errno
);
2876 fattr
= dos_mode(conn
, smb_fname
);
2878 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2879 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2882 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2884 return NT_STATUS_NO_SUCH_FILE
;
2887 if (!dir_check_ftype(fattr
, dirtype
)) {
2888 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2889 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2891 return NT_STATUS_NO_SUCH_FILE
;
2894 if (dirtype_orig
& 0x8000) {
2895 /* These will never be set for POSIX. */
2896 return NT_STATUS_NO_SUCH_FILE
;
2900 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2901 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2904 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2905 return NT_STATUS_NO_SUCH_FILE
;
2908 if (dirtype
& 0xFF00) {
2909 /* These will never be set for POSIX. */
2910 return NT_STATUS_NO_SUCH_FILE
;
2915 return NT_STATUS_NO_SUCH_FILE
;
2918 /* Can't delete a directory. */
2919 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2920 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2925 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2926 return NT_STATUS_OBJECT_NAME_INVALID
;
2927 #endif /* JRATEST */
2929 /* On open checks the open itself will check the share mode, so
2930 don't do it here as we'll get it wrong. */
2932 status
= SMB_VFS_CREATE_FILE
2935 0, /* root_dir_fid */
2936 smb_fname
, /* fname */
2937 DELETE_ACCESS
, /* access_mask */
2938 FILE_SHARE_NONE
, /* share_access */
2939 FILE_OPEN
, /* create_disposition*/
2940 FILE_NON_DIRECTORY_FILE
, /* create_options */
2941 /* file_attributes */
2942 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2943 FILE_ATTRIBUTE_NORMAL
,
2944 0, /* oplock_request */
2946 0, /* allocation_size */
2947 0, /* private_flags */
2952 NULL
, NULL
); /* create context */
2954 if (!NT_STATUS_IS_OK(status
)) {
2955 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2956 nt_errstr(status
)));
2960 status
= can_set_delete_on_close(fsp
, fattr
);
2961 if (!NT_STATUS_IS_OK(status
)) {
2962 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2964 smb_fname_str_dbg(smb_fname
),
2965 nt_errstr(status
)));
2966 close_file(req
, fsp
, NORMAL_CLOSE
);
2970 /* The set is across all open files on this dev/inode pair. */
2971 if (!set_delete_on_close(fsp
, True
,
2972 conn
->session_info
->security_token
,
2973 conn
->session_info
->unix_token
)) {
2974 close_file(req
, fsp
, NORMAL_CLOSE
);
2975 return NT_STATUS_ACCESS_DENIED
;
2978 return close_file(req
, fsp
, NORMAL_CLOSE
);
2981 /****************************************************************************
2982 The guts of the unlink command, split out so it may be called by the NT SMB
2984 ****************************************************************************/
2986 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2987 uint32_t dirtype
, struct smb_filename
*smb_fname
,
2990 char *fname_dir
= NULL
;
2991 char *fname_mask
= NULL
;
2993 NTSTATUS status
= NT_STATUS_OK
;
2994 struct smb_filename
*smb_fname_dir
= NULL
;
2995 TALLOC_CTX
*ctx
= talloc_tos();
2997 /* Split up the directory from the filename/mask. */
2998 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2999 &fname_dir
, &fname_mask
);
3000 if (!NT_STATUS_IS_OK(status
)) {
3005 * We should only check the mangled cache
3006 * here if unix_convert failed. This means
3007 * that the path in 'mask' doesn't exist
3008 * on the file system and so we need to look
3009 * for a possible mangle. This patch from
3010 * Tine Smukavec <valentin.smukavec@hermes.si>.
3013 if (!VALID_STAT(smb_fname
->st
) &&
3014 mangle_is_mangled(fname_mask
, conn
->params
)) {
3015 char *new_mask
= NULL
;
3016 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3017 &new_mask
, conn
->params
);
3019 TALLOC_FREE(fname_mask
);
3020 fname_mask
= new_mask
;
3027 * Only one file needs to be unlinked. Append the mask back
3028 * onto the directory.
3030 TALLOC_FREE(smb_fname
->base_name
);
3031 if (ISDOT(fname_dir
)) {
3032 /* Ensure we use canonical names on open. */
3033 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3037 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3042 if (!smb_fname
->base_name
) {
3043 status
= NT_STATUS_NO_MEMORY
;
3047 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3050 status
= check_name(conn
, smb_fname
->base_name
);
3051 if (!NT_STATUS_IS_OK(status
)) {
3055 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3056 if (!NT_STATUS_IS_OK(status
)) {
3062 struct smb_Dir
*dir_hnd
= NULL
;
3064 const char *dname
= NULL
;
3065 char *talloced
= NULL
;
3067 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3068 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3072 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3075 if (strequal(fname_mask
,"????????.???")) {
3076 TALLOC_FREE(fname_mask
);
3077 fname_mask
= talloc_strdup(ctx
, "*");
3079 status
= NT_STATUS_NO_MEMORY
;
3084 status
= check_name(conn
, fname_dir
);
3085 if (!NT_STATUS_IS_OK(status
)) {
3089 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3094 if (smb_fname_dir
== NULL
) {
3095 status
= NT_STATUS_NO_MEMORY
;
3099 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3101 if (dir_hnd
== NULL
) {
3102 status
= map_nt_error_from_unix(errno
);
3106 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3107 the pattern matches against the long name, otherwise the short name
3108 We don't implement this yet XXXX
3111 status
= NT_STATUS_NO_SUCH_FILE
;
3113 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3114 &smb_fname
->st
, &talloced
))) {
3115 TALLOC_CTX
*frame
= talloc_stackframe();
3117 if (!is_visible_file(conn
, fname_dir
, dname
,
3118 &smb_fname
->st
, true)) {
3120 TALLOC_FREE(talloced
);
3124 /* Quick check for "." and ".." */
3125 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3127 TALLOC_FREE(talloced
);
3131 if(!mask_match(dname
, fname_mask
,
3132 conn
->case_sensitive
)) {
3134 TALLOC_FREE(talloced
);
3138 TALLOC_FREE(smb_fname
->base_name
);
3139 if (ISDOT(fname_dir
)) {
3140 /* Ensure we use canonical names on open. */
3141 smb_fname
->base_name
=
3142 talloc_asprintf(smb_fname
, "%s",
3145 smb_fname
->base_name
=
3146 talloc_asprintf(smb_fname
, "%s/%s",
3150 if (!smb_fname
->base_name
) {
3151 TALLOC_FREE(dir_hnd
);
3152 status
= NT_STATUS_NO_MEMORY
;
3154 TALLOC_FREE(talloced
);
3158 status
= check_name(conn
, smb_fname
->base_name
);
3159 if (!NT_STATUS_IS_OK(status
)) {
3160 TALLOC_FREE(dir_hnd
);
3162 TALLOC_FREE(talloced
);
3166 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3167 if (!NT_STATUS_IS_OK(status
)) {
3168 TALLOC_FREE(dir_hnd
);
3170 TALLOC_FREE(talloced
);
3175 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3176 smb_fname
->base_name
));
3179 TALLOC_FREE(talloced
);
3181 TALLOC_FREE(dir_hnd
);
3184 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3185 status
= map_nt_error_from_unix(errno
);
3189 TALLOC_FREE(smb_fname_dir
);
3190 TALLOC_FREE(fname_dir
);
3191 TALLOC_FREE(fname_mask
);
3195 /****************************************************************************
3197 ****************************************************************************/
3199 void reply_unlink(struct smb_request
*req
)
3201 connection_struct
*conn
= req
->conn
;
3203 struct smb_filename
*smb_fname
= NULL
;
3206 bool path_contains_wcard
= False
;
3207 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3208 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
3209 TALLOC_CTX
*ctx
= talloc_tos();
3211 START_PROFILE(SMBunlink
);
3214 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3218 dirtype
= SVAL(req
->vwv
+0, 0);
3220 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3221 STR_TERMINATE
, &status
,
3222 &path_contains_wcard
);
3223 if (!NT_STATUS_IS_OK(status
)) {
3224 reply_nterror(req
, status
);
3228 status
= filename_convert(ctx
, conn
,
3229 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3232 &path_contains_wcard
,
3234 if (!NT_STATUS_IS_OK(status
)) {
3235 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3236 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3237 ERRSRV
, ERRbadpath
);
3240 reply_nterror(req
, status
);
3244 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3246 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3247 path_contains_wcard
);
3248 if (!NT_STATUS_IS_OK(status
)) {
3249 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3250 /* We have re-scheduled this call. */
3253 reply_nterror(req
, status
);
3257 reply_outbuf(req
, 0, 0);
3259 TALLOC_FREE(smb_fname
);
3260 END_PROFILE(SMBunlink
);
3264 /****************************************************************************
3266 ****************************************************************************/
3268 static void fail_readraw(void)
3270 const char *errstr
= talloc_asprintf(talloc_tos(),
3271 "FAIL ! reply_readbraw: socket write fail (%s)",
3276 exit_server_cleanly(errstr
);
3279 /****************************************************************************
3280 Fake (read/write) sendfile. Returns -1 on read or write fail.
3281 ****************************************************************************/
3283 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3284 off_t startpos
, size_t nread
)
3287 size_t tosend
= nread
;
3294 bufsize
= MIN(nread
, 65536);
3296 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3300 while (tosend
> 0) {
3304 cur_read
= MIN(tosend
, bufsize
);
3305 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3311 /* If we had a short read, fill with zeros. */
3312 if (ret
< cur_read
) {
3313 memset(buf
+ ret
, '\0', cur_read
- ret
);
3316 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3317 if (ret
!= cur_read
) {
3318 int saved_errno
= errno
;
3320 * Try and give an error message saying what
3323 DEBUG(0, ("write_data failed for client %s. "
3325 smbXsrv_connection_dbg(xconn
),
3326 strerror(saved_errno
)));
3328 errno
= saved_errno
;
3332 startpos
+= cur_read
;
3336 return (ssize_t
)nread
;
3339 /****************************************************************************
3340 Deal with the case of sendfile reading less bytes from the file than
3341 requested. Fill with zeros (all we can do). Returns 0 on success
3342 ****************************************************************************/
3344 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3350 #define SHORT_SEND_BUFSIZE 1024
3351 if (nread
< headersize
) {
3352 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3353 "header for file %s (%s). Terminating\n",
3354 fsp_str_dbg(fsp
), strerror(errno
)));
3358 nread
-= headersize
;
3360 if (nread
< smb_maxcnt
) {
3361 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3363 DEBUG(0,("sendfile_short_send: malloc failed "
3364 "for file %s (%s). Terminating\n",
3365 fsp_str_dbg(fsp
), strerror(errno
)));
3369 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3370 "with zeros !\n", fsp_str_dbg(fsp
)));
3372 while (nread
< smb_maxcnt
) {
3374 * We asked for the real file size and told sendfile
3375 * to not go beyond the end of the file. But it can
3376 * happen that in between our fstat call and the
3377 * sendfile call the file was truncated. This is very
3378 * bad because we have already announced the larger
3379 * number of bytes to the client.
3381 * The best we can do now is to send 0-bytes, just as
3382 * a read from a hole in a sparse file would do.
3384 * This should happen rarely enough that I don't care
3385 * about efficiency here :-)
3390 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3391 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3392 if (ret
!= to_write
) {
3393 int saved_errno
= errno
;
3395 * Try and give an error message saying what
3398 DEBUG(0, ("write_data failed for client %s. "
3400 smbXsrv_connection_dbg(xconn
),
3401 strerror(saved_errno
)));
3402 errno
= saved_errno
;
3413 /****************************************************************************
3414 Return a readbraw error (4 bytes of zero).
3415 ****************************************************************************/
3417 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3423 smbd_lock_socket(xconn
);
3424 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3425 int saved_errno
= errno
;
3427 * Try and give an error message saying what
3430 DEBUG(0, ("write_data failed for client %s. "
3432 smbXsrv_connection_dbg(xconn
),
3433 strerror(saved_errno
)));
3434 errno
= saved_errno
;
3438 smbd_unlock_socket(xconn
);
3441 /****************************************************************************
3442 Use sendfile in readbraw.
3443 ****************************************************************************/
3445 static void send_file_readbraw(connection_struct
*conn
,
3446 struct smb_request
*req
,
3452 struct smbXsrv_connection
*xconn
= req
->xconn
;
3453 char *outbuf
= NULL
;
3457 * We can only use sendfile on a non-chained packet
3458 * but we can use on a non-oplocked file. tridge proved this
3459 * on a train in Germany :-). JRA.
3460 * reply_readbraw has already checked the length.
3463 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3464 (fsp
->wcp
== NULL
) &&
3465 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3466 ssize_t sendfile_read
= -1;
3468 DATA_BLOB header_blob
;
3470 _smb_setlen(header
,nread
);
3471 header_blob
= data_blob_const(header
, 4);
3473 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3474 &header_blob
, startpos
,
3476 if (sendfile_read
== -1) {
3477 /* Returning ENOSYS means no data at all was sent.
3478 * Do this as a normal read. */
3479 if (errno
== ENOSYS
) {
3480 goto normal_readbraw
;
3484 * Special hack for broken Linux with no working sendfile. If we
3485 * return EINTR we sent the header but not the rest of the data.
3486 * Fake this up by doing read/write calls.
3488 if (errno
== EINTR
) {
3489 /* Ensure we don't do this again. */
3490 set_use_sendfile(SNUM(conn
), False
);
3491 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3493 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3494 DEBUG(0,("send_file_readbraw: "
3495 "fake_sendfile failed for "
3499 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3504 DEBUG(0,("send_file_readbraw: sendfile failed for "
3505 "file %s (%s). Terminating\n",
3506 fsp_str_dbg(fsp
), strerror(errno
)));
3507 exit_server_cleanly("send_file_readbraw sendfile failed");
3508 } else if (sendfile_read
== 0) {
3510 * Some sendfile implementations return 0 to indicate
3511 * that there was a short read, but nothing was
3512 * actually written to the socket. In this case,
3513 * fallback to the normal read path so the header gets
3514 * the correct byte count.
3516 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3517 "bytes falling back to the normal read: "
3518 "%s\n", fsp_str_dbg(fsp
)));
3519 goto normal_readbraw
;
3522 /* Deal with possible short send. */
3523 if (sendfile_read
!= 4+nread
) {
3524 ret
= sendfile_short_send(xconn
, fsp
,
3525 sendfile_read
, 4, nread
);
3535 outbuf
= talloc_array(NULL
, char, nread
+4);
3537 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3538 (unsigned)(nread
+4)));
3539 reply_readbraw_error(xconn
);
3544 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3545 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3554 _smb_setlen(outbuf
,ret
);
3555 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3556 int saved_errno
= errno
;
3558 * Try and give an error message saying what
3561 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3562 smbXsrv_connection_dbg(xconn
),
3563 strerror(saved_errno
)));
3564 errno
= saved_errno
;
3569 TALLOC_FREE(outbuf
);
3572 /****************************************************************************
3573 Reply to a readbraw (core+ protocol).
3574 ****************************************************************************/
3576 void reply_readbraw(struct smb_request
*req
)
3578 connection_struct
*conn
= req
->conn
;
3579 struct smbXsrv_connection
*xconn
= req
->xconn
;
3580 ssize_t maxcount
,mincount
;
3584 struct lock_struct lock
;
3587 START_PROFILE(SMBreadbraw
);
3589 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3590 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3591 "raw reads/writes are disallowed.");
3595 reply_readbraw_error(xconn
);
3596 END_PROFILE(SMBreadbraw
);
3600 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3601 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3602 "'async smb echo handler = yes'\n"));
3603 reply_readbraw_error(xconn
);
3604 END_PROFILE(SMBreadbraw
);
3609 * Special check if an oplock break has been issued
3610 * and the readraw request croses on the wire, we must
3611 * return a zero length response here.
3614 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3617 * We have to do a check_fsp by hand here, as
3618 * we must always return 4 zero bytes on error,
3622 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3623 req
->vuid
!= fsp
->vuid
||
3624 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3626 * fsp could be NULL here so use the value from the packet. JRA.
3628 DEBUG(3,("reply_readbraw: fnum %d not valid "
3630 (int)SVAL(req
->vwv
+0, 0)));
3631 reply_readbraw_error(xconn
);
3632 END_PROFILE(SMBreadbraw
);
3636 /* Do a "by hand" version of CHECK_READ. */
3637 if (!(fsp
->can_read
||
3638 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3639 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3640 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3641 (int)SVAL(req
->vwv
+0, 0)));
3642 reply_readbraw_error(xconn
);
3643 END_PROFILE(SMBreadbraw
);
3647 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3649 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3650 if(req
->wct
== 10) {
3652 * This is a large offset (64 bit) read.
3655 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3658 DEBUG(0,("reply_readbraw: negative 64 bit "
3659 "readraw offset (%.0f) !\n",
3660 (double)startpos
));
3661 reply_readbraw_error(xconn
);
3662 END_PROFILE(SMBreadbraw
);
3667 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3668 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3670 /* ensure we don't overrun the packet size */
3671 maxcount
= MIN(65535,maxcount
);
3673 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3674 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3677 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3678 reply_readbraw_error(xconn
);
3679 END_PROFILE(SMBreadbraw
);
3683 if (fsp_stat(fsp
) == 0) {
3684 size
= fsp
->fsp_name
->st
.st_ex_size
;
3687 if (startpos
>= size
) {
3690 nread
= MIN(maxcount
,(size
- startpos
));
3693 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3694 if (nread
< mincount
)
3698 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3699 "min=%lu nread=%lu\n",
3700 fsp_fnum_dbg(fsp
), (double)startpos
,
3701 (unsigned long)maxcount
,
3702 (unsigned long)mincount
,
3703 (unsigned long)nread
) );
3705 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3707 DEBUG(5,("reply_readbraw finished\n"));
3709 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3711 END_PROFILE(SMBreadbraw
);
3716 #define DBGC_CLASS DBGC_LOCKING
3718 /****************************************************************************
3719 Reply to a lockread (core+ protocol).
3720 ****************************************************************************/
3722 void reply_lockread(struct smb_request
*req
)
3724 connection_struct
*conn
= req
->conn
;
3732 struct byte_range_lock
*br_lck
= NULL
;
3734 struct smbXsrv_connection
*xconn
= req
->xconn
;
3736 START_PROFILE(SMBlockread
);
3739 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3740 END_PROFILE(SMBlockread
);
3744 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3746 if (!check_fsp(conn
, req
, fsp
)) {
3747 END_PROFILE(SMBlockread
);
3751 if (!CHECK_READ(fsp
,req
)) {
3752 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3753 END_PROFILE(SMBlockread
);
3757 numtoread
= SVAL(req
->vwv
+1, 0);
3758 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3761 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3762 * protocol request that predates the read/write lock concept.
3763 * Thus instead of asking for a read lock here we need to ask
3764 * for a write lock. JRA.
3765 * Note that the requested lock size is unaffected by max_send.
3768 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3770 (uint64_t)req
->smbpid
,
3771 (uint64_t)numtoread
,
3775 False
, /* Non-blocking lock. */
3778 TALLOC_FREE(br_lck
);
3780 if (NT_STATUS_V(status
)) {
3781 reply_nterror(req
, status
);
3782 END_PROFILE(SMBlockread
);
3787 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3789 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3791 if (numtoread
> maxtoread
) {
3792 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3793 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3794 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3795 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3796 numtoread
= maxtoread
;
3799 reply_outbuf(req
, 5, numtoread
+ 3);
3801 data
= smb_buf(req
->outbuf
) + 3;
3803 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3806 reply_nterror(req
, map_nt_error_from_unix(errno
));
3807 END_PROFILE(SMBlockread
);
3811 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3813 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3814 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3815 p
= smb_buf(req
->outbuf
);
3816 SCVAL(p
,0,0); /* pad byte. */
3819 DEBUG(3,("lockread %s num=%d nread=%d\n",
3820 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3822 END_PROFILE(SMBlockread
);
3827 #define DBGC_CLASS DBGC_ALL
3829 /****************************************************************************
3831 ****************************************************************************/
3833 void reply_read(struct smb_request
*req
)
3835 connection_struct
*conn
= req
->conn
;
3842 struct lock_struct lock
;
3843 struct smbXsrv_connection
*xconn
= req
->xconn
;
3845 START_PROFILE(SMBread
);
3848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3849 END_PROFILE(SMBread
);
3853 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3855 if (!check_fsp(conn
, req
, fsp
)) {
3856 END_PROFILE(SMBread
);
3860 if (!CHECK_READ(fsp
,req
)) {
3861 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3862 END_PROFILE(SMBread
);
3866 numtoread
= SVAL(req
->vwv
+1, 0);
3867 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3870 * The requested read size cannot be greater than max_send. JRA.
3872 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3874 if (numtoread
> maxtoread
) {
3875 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3876 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3877 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3878 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3879 numtoread
= maxtoread
;
3882 reply_outbuf(req
, 5, numtoread
+3);
3884 data
= smb_buf(req
->outbuf
) + 3;
3886 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3887 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3890 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3891 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3892 END_PROFILE(SMBread
);
3897 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3900 reply_nterror(req
, map_nt_error_from_unix(errno
));
3904 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3906 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3907 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3908 SCVAL(smb_buf(req
->outbuf
),0,1);
3909 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3911 DEBUG(3, ("read %s num=%d nread=%d\n",
3912 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3915 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3917 END_PROFILE(SMBread
);
3921 /****************************************************************************
3923 ****************************************************************************/
3925 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3929 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3932 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3934 SCVAL(outbuf
,smb_vwv0
,0xFF);
3935 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3936 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3937 SSVAL(outbuf
,smb_vwv6
,
3938 (smb_wct
- 4) /* offset from smb header to wct */
3939 + 1 /* the wct field */
3940 + 12 * sizeof(uint16_t) /* vwv */
3941 + 2 /* the buflen field */
3942 + 1); /* padding byte */
3943 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3944 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3945 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3946 _smb_setlen_large(outbuf
,
3947 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3951 /****************************************************************************
3952 Reply to a read and X - possibly using sendfile.
3953 ****************************************************************************/
3955 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3956 files_struct
*fsp
, off_t startpos
,
3959 struct smbXsrv_connection
*xconn
= req
->xconn
;
3961 struct lock_struct lock
;
3962 int saved_errno
= 0;
3964 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3965 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3968 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3969 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3974 * We can only use sendfile on a non-chained packet
3975 * but we can use on a non-oplocked file. tridge proved this
3976 * on a train in Germany :-). JRA.
3979 if (!req_is_in_chain(req
) &&
3981 (fsp
->base_fsp
== NULL
) &&
3982 (fsp
->wcp
== NULL
) &&
3983 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3984 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3987 if(fsp_stat(fsp
) == -1) {
3988 reply_nterror(req
, map_nt_error_from_unix(errno
));
3992 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3993 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3994 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3996 * We already know that we would do a short read, so don't
3997 * try the sendfile() path.
3999 goto nosendfile_read
;
4003 * Set up the packet header before send. We
4004 * assume here the sendfile will work (get the
4005 * correct amount of data).
4008 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4010 construct_reply_common_req(req
, (char *)headerbuf
);
4011 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4013 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4014 startpos
, smb_maxcnt
);
4016 saved_errno
= errno
;
4018 /* Returning ENOSYS means no data at all was sent.
4019 Do this as a normal read. */
4020 if (errno
== ENOSYS
) {
4025 * Special hack for broken Linux with no working sendfile. If we
4026 * return EINTR we sent the header but not the rest of the data.
4027 * Fake this up by doing read/write calls.
4030 if (errno
== EINTR
) {
4031 /* Ensure we don't do this again. */
4032 set_use_sendfile(SNUM(conn
), False
);
4033 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4034 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4037 saved_errno
= errno
;
4038 DEBUG(0,("send_file_readX: "
4039 "fake_sendfile failed for "
4040 "file %s (%s) for client %s. "
4043 smbXsrv_connection_dbg(xconn
),
4044 strerror(saved_errno
)));
4045 errno
= saved_errno
;
4046 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4048 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4049 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4050 /* No outbuf here means successful sendfile. */
4054 DEBUG(0,("send_file_readX: sendfile failed for file "
4055 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4057 exit_server_cleanly("send_file_readX sendfile failed");
4058 } else if (nread
== 0) {
4060 * Some sendfile implementations return 0 to indicate
4061 * that there was a short read, but nothing was
4062 * actually written to the socket. In this case,
4063 * fallback to the normal read path so the header gets
4064 * the correct byte count.
4066 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4067 "falling back to the normal read: %s\n",
4072 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4073 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4075 /* Deal with possible short send. */
4076 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4079 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4080 sizeof(headerbuf
), smb_maxcnt
);
4083 r
= "send_file_readX: sendfile_short_send failed";
4084 DEBUG(0,("%s for file %s (%s).\n",
4085 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4086 exit_server_cleanly(r
);
4089 /* No outbuf here means successful sendfile. */
4090 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4091 SMB_PERFCOUNT_END(&req
->pcd
);
4097 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4098 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4101 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4102 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4103 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4105 * We already know that we would do a short
4106 * read, so don't try the sendfile() path.
4108 goto nosendfile_read
;
4111 construct_reply_common_req(req
, (char *)headerbuf
);
4112 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4114 /* Send out the header. */
4115 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4117 if (ret
!= sizeof(headerbuf
)) {
4118 saved_errno
= errno
;
4120 * Try and give an error message saying what
4123 DEBUG(0,("send_file_readX: write_data failed for file "
4124 "%s (%s) for client %s. Terminating\n",
4126 smbXsrv_connection_dbg(xconn
),
4127 strerror(saved_errno
)));
4128 errno
= saved_errno
;
4129 exit_server_cleanly("send_file_readX sendfile failed");
4131 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4133 saved_errno
= errno
;
4134 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4135 "%s (%s) for client %s. Terminating\n",
4137 smbXsrv_connection_dbg(xconn
),
4138 strerror(saved_errno
)));
4139 errno
= saved_errno
;
4140 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4147 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4148 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4149 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4151 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4152 startpos
, smb_maxcnt
);
4153 saved_errno
= errno
;
4155 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4158 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4162 setup_readX_header((char *)req
->outbuf
, nread
);
4164 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4165 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4169 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4170 TALLOC_FREE(req
->outbuf
);
4174 /****************************************************************************
4175 Work out how much space we have for a read return.
4176 ****************************************************************************/
4178 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4180 struct smbXsrv_connection
*xconn
= req
->xconn
;
4182 if (xconn
->protocol
< PROTOCOL_NT1
) {
4183 return xconn
->smb1
.sessions
.max_send
;
4186 if (!lp_large_readwrite()) {
4187 return xconn
->smb1
.sessions
.max_send
;
4190 if (req_is_in_chain(req
)) {
4191 return xconn
->smb1
.sessions
.max_send
;
4194 if (req
->encrypted
) {
4196 * Don't take encrypted traffic up to the
4197 * limit. There are padding considerations
4198 * that make that tricky.
4200 return xconn
->smb1
.sessions
.max_send
;
4203 if (srv_is_signing_active(xconn
)) {
4207 if (!lp_unix_extensions()) {
4212 * We can do ultra-large POSIX reads.
4217 /****************************************************************************
4218 Calculate how big a read can be. Copes with all clients. It's always
4219 safe to return a short read - Windows does this.
4220 ****************************************************************************/
4222 static size_t calc_read_size(const struct smb_request
*req
,
4226 struct smbXsrv_connection
*xconn
= req
->xconn
;
4227 size_t max_pdu
= calc_max_read_pdu(req
);
4228 size_t total_size
= 0;
4229 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4230 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4233 * Windows explicitly ignores upper size of 0xFFFF.
4234 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4235 * We must do the same as these will never fit even in
4236 * an extended size NetBIOS packet.
4238 if (upper_size
== 0xFFFF) {
4242 if (xconn
->protocol
< PROTOCOL_NT1
) {
4246 total_size
= ((upper_size
<<16) | lower_size
);
4249 * LARGE_READX test shows it's always safe to return
4250 * a short read. Windows does so.
4252 return MIN(total_size
, max_len
);
4255 /****************************************************************************
4256 Reply to a read and X.
4257 ****************************************************************************/
4259 void reply_read_and_X(struct smb_request
*req
)
4261 connection_struct
*conn
= req
->conn
;
4266 bool big_readX
= False
;
4268 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4271 START_PROFILE(SMBreadX
);
4273 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4274 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4278 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4279 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4280 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4282 /* If it's an IPC, pass off the pipe handler. */
4284 reply_pipe_read_and_X(req
);
4285 END_PROFILE(SMBreadX
);
4289 if (!check_fsp(conn
, req
, fsp
)) {
4290 END_PROFILE(SMBreadX
);
4294 if (!CHECK_READ(fsp
,req
)) {
4295 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4296 END_PROFILE(SMBreadX
);
4300 upper_size
= SVAL(req
->vwv
+7, 0);
4301 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4302 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4304 * This is a heuristic to avoid keeping large
4305 * outgoing buffers around over long-lived aio
4311 if (req
->wct
== 12) {
4313 * This is a large offset (64 bit) read.
4315 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4320 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4325 if (NT_STATUS_IS_OK(status
)) {
4326 /* Read scheduled - we're done. */
4329 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4330 /* Real error - report to client. */
4331 END_PROFILE(SMBreadX
);
4332 reply_nterror(req
, status
);
4335 /* NT_STATUS_RETRY - fall back to sync read. */
4338 smbd_lock_socket(req
->xconn
);
4339 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4340 smbd_unlock_socket(req
->xconn
);
4343 END_PROFILE(SMBreadX
);
4347 /****************************************************************************
4348 Error replies to writebraw must have smb_wct == 1. Fix this up.
4349 ****************************************************************************/
4351 void error_to_writebrawerr(struct smb_request
*req
)
4353 uint8_t *old_outbuf
= req
->outbuf
;
4355 reply_outbuf(req
, 1, 0);
4357 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4358 TALLOC_FREE(old_outbuf
);
4361 /****************************************************************************
4362 Read 4 bytes of a smb packet and return the smb length of the packet.
4363 Store the result in the buffer. This version of the function will
4364 never return a session keepalive (length of zero).
4365 Timeout is in milliseconds.
4366 ****************************************************************************/
4368 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4371 uint8_t msgtype
= NBSSkeepalive
;
4373 while (msgtype
== NBSSkeepalive
) {
4376 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4378 if (!NT_STATUS_IS_OK(status
)) {
4379 char addr
[INET6_ADDRSTRLEN
];
4380 /* Try and give an error message
4381 * saying what client failed. */
4382 DEBUG(0, ("read_fd_with_timeout failed for "
4383 "client %s read error = %s.\n",
4384 get_peer_addr(fd
,addr
,sizeof(addr
)),
4385 nt_errstr(status
)));
4389 msgtype
= CVAL(inbuf
, 0);
4392 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4393 (unsigned long)len
));
4395 return NT_STATUS_OK
;
4398 /****************************************************************************
4399 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4400 ****************************************************************************/
4402 void reply_writebraw(struct smb_request
*req
)
4404 connection_struct
*conn
= req
->conn
;
4405 struct smbXsrv_connection
*xconn
= req
->xconn
;
4408 ssize_t total_written
=0;
4409 size_t numtowrite
=0;
4412 const char *data
=NULL
;
4415 struct lock_struct lock
;
4418 START_PROFILE(SMBwritebraw
);
4421 * If we ever reply with an error, it must have the SMB command
4422 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4425 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4427 if (srv_is_signing_active(xconn
)) {
4428 END_PROFILE(SMBwritebraw
);
4429 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4430 "raw reads/writes are disallowed.");
4433 if (req
->wct
< 12) {
4434 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4435 error_to_writebrawerr(req
);
4436 END_PROFILE(SMBwritebraw
);
4440 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4441 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4442 "'async smb echo handler = yes'\n"));
4443 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4444 error_to_writebrawerr(req
);
4445 END_PROFILE(SMBwritebraw
);
4449 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4450 if (!check_fsp(conn
, req
, fsp
)) {
4451 error_to_writebrawerr(req
);
4452 END_PROFILE(SMBwritebraw
);
4456 if (!CHECK_WRITE(fsp
)) {
4457 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4458 error_to_writebrawerr(req
);
4459 END_PROFILE(SMBwritebraw
);
4463 tcount
= IVAL(req
->vwv
+1, 0);
4464 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4465 write_through
= BITSETW(req
->vwv
+7,0);
4467 /* We have to deal with slightly different formats depending
4468 on whether we are using the core+ or lanman1.0 protocol */
4470 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4471 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4472 data
= smb_buf_const(req
->inbuf
);
4474 numtowrite
= SVAL(req
->vwv
+10, 0);
4475 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4478 /* Ensure we don't write bytes past the end of this packet. */
4479 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4481 error_to_writebrawerr(req
);
4482 END_PROFILE(SMBwritebraw
);
4486 if (!fsp
->print_file
) {
4487 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4488 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4491 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4492 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4493 error_to_writebrawerr(req
);
4494 END_PROFILE(SMBwritebraw
);
4500 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4503 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4504 "wrote=%d sync=%d\n",
4505 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4506 (int)nwritten
, (int)write_through
));
4508 if (nwritten
< (ssize_t
)numtowrite
) {
4509 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4510 error_to_writebrawerr(req
);
4514 total_written
= nwritten
;
4516 /* Allocate a buffer of 64k + length. */
4517 buf
= talloc_array(NULL
, char, 65540);
4519 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4520 error_to_writebrawerr(req
);
4524 /* Return a SMBwritebraw message to the redirector to tell
4525 * it to send more bytes */
4527 memcpy(buf
, req
->inbuf
, smb_size
);
4528 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4529 SCVAL(buf
,smb_com
,SMBwritebraw
);
4530 SSVALS(buf
,smb_vwv0
,0xFFFF);
4532 if (!srv_send_smb(req
->xconn
,
4534 false, 0, /* no signing */
4535 IS_CONN_ENCRYPTED(conn
),
4537 exit_server_cleanly("reply_writebraw: srv_send_smb "
4541 /* Now read the raw data into the buffer and write it */
4542 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4544 if (!NT_STATUS_IS_OK(status
)) {
4545 exit_server_cleanly("secondary writebraw failed");
4548 /* Set up outbuf to return the correct size */
4549 reply_outbuf(req
, 1, 0);
4551 if (numtowrite
!= 0) {
4553 if (numtowrite
> 0xFFFF) {
4554 DEBUG(0,("reply_writebraw: Oversize secondary write "
4555 "raw requested (%u). Terminating\n",
4556 (unsigned int)numtowrite
));
4557 exit_server_cleanly("secondary writebraw failed");
4560 if (tcount
> nwritten
+numtowrite
) {
4561 DEBUG(3,("reply_writebraw: Client overestimated the "
4563 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4566 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4569 if (!NT_STATUS_IS_OK(status
)) {
4570 /* Try and give an error message
4571 * saying what client failed. */
4572 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4573 "raw read failed (%s) for client %s. "
4574 "Terminating\n", nt_errstr(status
),
4575 smbXsrv_connection_dbg(xconn
)));
4576 exit_server_cleanly("secondary writebraw failed");
4579 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4580 if (nwritten
== -1) {
4582 reply_nterror(req
, map_nt_error_from_unix(errno
));
4583 error_to_writebrawerr(req
);
4587 if (nwritten
< (ssize_t
)numtowrite
) {
4588 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4589 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4593 total_written
+= nwritten
;
4598 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4600 status
= sync_file(conn
, fsp
, write_through
);
4601 if (!NT_STATUS_IS_OK(status
)) {
4602 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4603 fsp_str_dbg(fsp
), nt_errstr(status
)));
4604 reply_nterror(req
, status
);
4605 error_to_writebrawerr(req
);
4609 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4611 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4612 (int)total_written
));
4614 if (!fsp
->print_file
) {
4615 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4618 /* We won't return a status if write through is not selected - this
4619 * follows what WfWg does */
4620 END_PROFILE(SMBwritebraw
);
4622 if (!write_through
&& total_written
==tcount
) {
4624 #if RABBIT_PELLET_FIX
4626 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4627 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4630 if (!send_keepalive(xconn
->transport
.sock
)) {
4631 exit_server_cleanly("reply_writebraw: send of "
4632 "keepalive failed");
4635 TALLOC_FREE(req
->outbuf
);
4640 if (!fsp
->print_file
) {
4641 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4644 END_PROFILE(SMBwritebraw
);
4649 #define DBGC_CLASS DBGC_LOCKING
4651 /****************************************************************************
4652 Reply to a writeunlock (core+).
4653 ****************************************************************************/
4655 void reply_writeunlock(struct smb_request
*req
)
4657 connection_struct
*conn
= req
->conn
;
4658 ssize_t nwritten
= -1;
4662 NTSTATUS status
= NT_STATUS_OK
;
4664 struct lock_struct lock
;
4665 int saved_errno
= 0;
4667 START_PROFILE(SMBwriteunlock
);
4670 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4671 END_PROFILE(SMBwriteunlock
);
4675 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4677 if (!check_fsp(conn
, req
, fsp
)) {
4678 END_PROFILE(SMBwriteunlock
);
4682 if (!CHECK_WRITE(fsp
)) {
4683 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4684 END_PROFILE(SMBwriteunlock
);
4688 numtowrite
= SVAL(req
->vwv
+1, 0);
4689 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4690 data
= (const char *)req
->buf
+ 3;
4692 if (!fsp
->print_file
&& numtowrite
> 0) {
4693 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4694 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4697 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4698 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4699 END_PROFILE(SMBwriteunlock
);
4704 /* The special X/Open SMB protocol handling of
4705 zero length writes is *NOT* done for
4707 if(numtowrite
== 0) {
4710 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4711 saved_errno
= errno
;
4714 status
= sync_file(conn
, fsp
, False
/* write through */);
4715 if (!NT_STATUS_IS_OK(status
)) {
4716 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4717 fsp_str_dbg(fsp
), nt_errstr(status
)));
4718 reply_nterror(req
, status
);
4723 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4727 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4728 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4732 if (numtowrite
&& !fsp
->print_file
) {
4733 status
= do_unlock(req
->sconn
->msg_ctx
,
4735 (uint64_t)req
->smbpid
,
4736 (uint64_t)numtowrite
,
4740 if (NT_STATUS_V(status
)) {
4741 reply_nterror(req
, status
);
4746 reply_outbuf(req
, 1, 0);
4748 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4750 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4751 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4754 if (numtowrite
&& !fsp
->print_file
) {
4755 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4758 END_PROFILE(SMBwriteunlock
);
4763 #define DBGC_CLASS DBGC_ALL
4765 /****************************************************************************
4767 ****************************************************************************/
4769 void reply_write(struct smb_request
*req
)
4771 connection_struct
*conn
= req
->conn
;
4773 ssize_t nwritten
= -1;
4777 struct lock_struct lock
;
4779 int saved_errno
= 0;
4781 START_PROFILE(SMBwrite
);
4784 END_PROFILE(SMBwrite
);
4785 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4789 /* If it's an IPC, pass off the pipe handler. */
4791 reply_pipe_write(req
);
4792 END_PROFILE(SMBwrite
);
4796 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4798 if (!check_fsp(conn
, req
, fsp
)) {
4799 END_PROFILE(SMBwrite
);
4803 if (!CHECK_WRITE(fsp
)) {
4804 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4805 END_PROFILE(SMBwrite
);
4809 numtowrite
= SVAL(req
->vwv
+1, 0);
4810 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4811 data
= (const char *)req
->buf
+ 3;
4813 if (!fsp
->print_file
) {
4814 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4815 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4818 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4819 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4820 END_PROFILE(SMBwrite
);
4826 * X/Open SMB protocol says that if smb_vwv1 is
4827 * zero then the file size should be extended or
4828 * truncated to the size given in smb_vwv[2-3].
4831 if(numtowrite
== 0) {
4833 * This is actually an allocate call, and set EOF. JRA.
4835 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4837 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4840 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4842 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4845 trigger_write_time_update_immediate(fsp
);
4847 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4850 status
= sync_file(conn
, fsp
, False
);
4851 if (!NT_STATUS_IS_OK(status
)) {
4852 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4853 fsp_str_dbg(fsp
), nt_errstr(status
)));
4854 reply_nterror(req
, status
);
4859 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4863 if((nwritten
== 0) && (numtowrite
!= 0)) {
4864 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4868 reply_outbuf(req
, 1, 0);
4870 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4872 if (nwritten
< (ssize_t
)numtowrite
) {
4873 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4874 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4877 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4880 if (!fsp
->print_file
) {
4881 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4884 END_PROFILE(SMBwrite
);
4888 /****************************************************************************
4889 Ensure a buffer is a valid writeX for recvfile purposes.
4890 ****************************************************************************/
4892 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4893 (2*14) + /* word count (including bcc) */ \
4896 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4897 const uint8_t *inbuf
)
4900 unsigned int doff
= 0;
4901 size_t len
= smb_len_large(inbuf
);
4903 struct smbXsrv_open
*op
= NULL
;
4904 struct files_struct
*fsp
= NULL
;
4907 if (is_encrypted_packet(inbuf
)) {
4908 /* Can't do this on encrypted
4913 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4917 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4918 CVAL(inbuf
,smb_wct
) != 14) {
4919 DEBUG(10,("is_valid_writeX_buffer: chained or "
4920 "invalid word length.\n"));
4924 fnum
= SVAL(inbuf
, smb_vwv2
);
4925 status
= smb1srv_open_lookup(xconn
,
4929 if (!NT_STATUS_IS_OK(status
)) {
4930 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4935 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4938 if (fsp
->conn
== NULL
) {
4939 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4943 if (IS_IPC(fsp
->conn
)) {
4944 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4947 if (IS_PRINT(fsp
->conn
)) {
4948 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4951 doff
= SVAL(inbuf
,smb_vwv11
);
4953 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4955 if (len
> doff
&& len
- doff
> 0xFFFF) {
4956 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4959 if (numtowrite
== 0) {
4960 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4964 /* Ensure the sizes match up. */
4965 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4966 /* no pad byte...old smbclient :-( */
4967 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4969 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4973 if (len
- doff
!= numtowrite
) {
4974 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4975 "len = %u, doff = %u, numtowrite = %u\n",
4978 (unsigned int)numtowrite
));
4982 DEBUG(10,("is_valid_writeX_buffer: true "
4983 "len = %u, doff = %u, numtowrite = %u\n",
4986 (unsigned int)numtowrite
));
4991 /****************************************************************************
4992 Reply to a write and X.
4993 ****************************************************************************/
4995 void reply_write_and_X(struct smb_request
*req
)
4997 connection_struct
*conn
= req
->conn
;
4998 struct smbXsrv_connection
*xconn
= req
->xconn
;
5000 struct lock_struct lock
;
5005 unsigned int smb_doff
;
5006 unsigned int smblen
;
5009 int saved_errno
= 0;
5011 START_PROFILE(SMBwriteX
);
5013 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5014 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5018 numtowrite
= SVAL(req
->vwv
+10, 0);
5019 smb_doff
= SVAL(req
->vwv
+11, 0);
5020 smblen
= smb_len(req
->inbuf
);
5022 if (req
->unread_bytes
> 0xFFFF ||
5023 (smblen
> smb_doff
&&
5024 smblen
- smb_doff
> 0xFFFF)) {
5025 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5028 if (req
->unread_bytes
) {
5029 /* Can't do a recvfile write on IPC$ */
5031 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5034 if (numtowrite
!= req
->unread_bytes
) {
5035 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5039 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5040 smb_doff
+ numtowrite
> smblen
) {
5041 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5046 /* If it's an IPC, pass off the pipe handler. */
5048 if (req
->unread_bytes
) {
5049 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5052 reply_pipe_write_and_X(req
);
5056 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5057 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5058 write_through
= BITSETW(req
->vwv
+7,0);
5060 if (!check_fsp(conn
, req
, fsp
)) {
5064 if (!CHECK_WRITE(fsp
)) {
5065 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5069 data
= smb_base(req
->inbuf
) + smb_doff
;
5071 if(req
->wct
== 14) {
5073 * This is a large offset (64 bit) write.
5075 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5079 /* X/Open SMB protocol says that, unlike SMBwrite
5080 if the length is zero then NO truncation is
5081 done, just a write of zero. To truncate a file,
5084 if(numtowrite
== 0) {
5087 if (req
->unread_bytes
== 0) {
5088 status
= schedule_aio_write_and_X(conn
,
5095 if (NT_STATUS_IS_OK(status
)) {
5096 /* write scheduled - we're done. */
5099 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5100 /* Real error - report to client. */
5101 reply_nterror(req
, status
);
5104 /* NT_STATUS_RETRY - fall through to sync write. */
5107 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5108 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5111 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5112 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5116 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5117 saved_errno
= errno
;
5119 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5123 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5127 if((nwritten
== 0) && (numtowrite
!= 0)) {
5128 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5132 reply_outbuf(req
, 6, 0);
5133 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5134 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5135 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5136 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5138 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5139 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5141 status
= sync_file(conn
, fsp
, write_through
);
5142 if (!NT_STATUS_IS_OK(status
)) {
5143 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5144 fsp_str_dbg(fsp
), nt_errstr(status
)));
5145 reply_nterror(req
, status
);
5149 END_PROFILE(SMBwriteX
);
5153 if (req
->unread_bytes
) {
5154 /* writeX failed. drain socket. */
5155 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5156 req
->unread_bytes
) {
5157 smb_panic("failed to drain pending bytes");
5159 req
->unread_bytes
= 0;
5162 END_PROFILE(SMBwriteX
);
5166 /****************************************************************************
5168 ****************************************************************************/
5170 void reply_lseek(struct smb_request
*req
)
5172 connection_struct
*conn
= req
->conn
;
5178 START_PROFILE(SMBlseek
);
5181 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5182 END_PROFILE(SMBlseek
);
5186 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5188 if (!check_fsp(conn
, req
, fsp
)) {
5192 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5194 mode
= SVAL(req
->vwv
+1, 0) & 3;
5195 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5196 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5205 res
= fsp
->fh
->pos
+ startpos
;
5216 if (umode
== SEEK_END
) {
5217 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5218 if(errno
== EINVAL
) {
5219 off_t current_pos
= startpos
;
5221 if(fsp_stat(fsp
) == -1) {
5223 map_nt_error_from_unix(errno
));
5224 END_PROFILE(SMBlseek
);
5228 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5230 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5235 reply_nterror(req
, map_nt_error_from_unix(errno
));
5236 END_PROFILE(SMBlseek
);
5243 reply_outbuf(req
, 2, 0);
5244 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5246 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5247 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5249 END_PROFILE(SMBlseek
);
5253 /****************************************************************************
5255 ****************************************************************************/
5257 void reply_flush(struct smb_request
*req
)
5259 connection_struct
*conn
= req
->conn
;
5263 START_PROFILE(SMBflush
);
5266 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5270 fnum
= SVAL(req
->vwv
+0, 0);
5271 fsp
= file_fsp(req
, fnum
);
5273 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5278 file_sync_all(conn
);
5280 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5281 if (!NT_STATUS_IS_OK(status
)) {
5282 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5283 fsp_str_dbg(fsp
), nt_errstr(status
)));
5284 reply_nterror(req
, status
);
5285 END_PROFILE(SMBflush
);
5290 reply_outbuf(req
, 0, 0);
5292 DEBUG(3,("flush\n"));
5293 END_PROFILE(SMBflush
);
5297 /****************************************************************************
5299 conn POINTER CAN BE NULL HERE !
5300 ****************************************************************************/
5302 void reply_exit(struct smb_request
*req
)
5304 START_PROFILE(SMBexit
);
5306 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5308 reply_outbuf(req
, 0, 0);
5310 DEBUG(3,("exit\n"));
5312 END_PROFILE(SMBexit
);
5316 struct reply_close_state
{
5318 struct smb_request
*smbreq
;
5321 static void do_smb1_close(struct tevent_req
*req
);
5323 void reply_close(struct smb_request
*req
)
5325 connection_struct
*conn
= req
->conn
;
5326 NTSTATUS status
= NT_STATUS_OK
;
5327 files_struct
*fsp
= NULL
;
5328 START_PROFILE(SMBclose
);
5331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5332 END_PROFILE(SMBclose
);
5336 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5339 * We can only use check_fsp if we know it's not a directory.
5342 if (!check_fsp_open(conn
, req
, fsp
)) {
5343 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5344 END_PROFILE(SMBclose
);
5348 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5349 fsp
->is_directory
? "directory" : "file",
5350 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5351 conn
->num_files_open
));
5353 if (!fsp
->is_directory
) {
5357 * Take care of any time sent in the close.
5360 t
= srv_make_unix_date3(req
->vwv
+1);
5361 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5364 if (fsp
->num_aio_requests
!= 0) {
5366 struct reply_close_state
*state
;
5368 DEBUG(10, ("closing with aio %u requests pending\n",
5369 fsp
->num_aio_requests
));
5372 * We depend on the aio_extra destructor to take care of this
5373 * close request once fsp->num_aio_request drops to 0.
5376 fsp
->deferred_close
= tevent_wait_send(
5377 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5378 if (fsp
->deferred_close
== NULL
) {
5379 status
= NT_STATUS_NO_MEMORY
;
5383 state
= talloc(fsp
, struct reply_close_state
);
5384 if (state
== NULL
) {
5385 TALLOC_FREE(fsp
->deferred_close
);
5386 status
= NT_STATUS_NO_MEMORY
;
5390 state
->smbreq
= talloc_move(fsp
, &req
);
5391 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5393 END_PROFILE(SMBclose
);
5398 * close_file() returns the unix errno if an error was detected on
5399 * close - normally this is due to a disk full error. If not then it
5400 * was probably an I/O error.
5403 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5405 if (!NT_STATUS_IS_OK(status
)) {
5406 reply_nterror(req
, status
);
5407 END_PROFILE(SMBclose
);
5411 reply_outbuf(req
, 0, 0);
5412 END_PROFILE(SMBclose
);
5416 static void do_smb1_close(struct tevent_req
*req
)
5418 struct reply_close_state
*state
= tevent_req_callback_data(
5419 req
, struct reply_close_state
);
5420 struct smb_request
*smbreq
;
5424 ret
= tevent_wait_recv(req
);
5427 DEBUG(10, ("tevent_wait_recv returned %s\n",
5430 * Continue anyway, this should never happen
5435 * fsp->smb2_close_request right now is a talloc grandchild of
5436 * fsp. When we close_file(fsp), it would go with it. No chance to
5439 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5441 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5442 if (NT_STATUS_IS_OK(status
)) {
5443 reply_outbuf(smbreq
, 0, 0);
5445 reply_nterror(smbreq
, status
);
5447 if (!srv_send_smb(smbreq
->xconn
,
5448 (char *)smbreq
->outbuf
,
5451 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5453 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5456 TALLOC_FREE(smbreq
);
5459 /****************************************************************************
5460 Reply to a writeclose (Core+ protocol).
5461 ****************************************************************************/
5463 void reply_writeclose(struct smb_request
*req
)
5465 connection_struct
*conn
= req
->conn
;
5467 ssize_t nwritten
= -1;
5468 NTSTATUS close_status
= NT_STATUS_OK
;
5471 struct timespec mtime
;
5473 struct lock_struct lock
;
5475 START_PROFILE(SMBwriteclose
);
5478 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5479 END_PROFILE(SMBwriteclose
);
5483 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5485 if (!check_fsp(conn
, req
, fsp
)) {
5486 END_PROFILE(SMBwriteclose
);
5489 if (!CHECK_WRITE(fsp
)) {
5490 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5491 END_PROFILE(SMBwriteclose
);
5495 numtowrite
= SVAL(req
->vwv
+1, 0);
5496 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5497 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5498 data
= (const char *)req
->buf
+ 1;
5500 if (fsp
->print_file
== NULL
) {
5501 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5502 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5505 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5506 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5507 END_PROFILE(SMBwriteclose
);
5512 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5514 if (fsp
->print_file
== NULL
) {
5515 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5518 set_close_write_time(fsp
, mtime
);
5521 * More insanity. W2K only closes the file if writelen > 0.
5525 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5526 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5527 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5530 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5531 "file %s\n", fsp_str_dbg(fsp
)));
5532 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5536 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5537 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5541 if(!NT_STATUS_IS_OK(close_status
)) {
5542 reply_nterror(req
, close_status
);
5546 reply_outbuf(req
, 1, 0);
5548 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5552 END_PROFILE(SMBwriteclose
);
5557 #define DBGC_CLASS DBGC_LOCKING
5559 /****************************************************************************
5561 ****************************************************************************/
5563 void reply_lock(struct smb_request
*req
)
5565 connection_struct
*conn
= req
->conn
;
5566 uint64_t count
,offset
;
5569 struct byte_range_lock
*br_lck
= NULL
;
5571 START_PROFILE(SMBlock
);
5574 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5575 END_PROFILE(SMBlock
);
5579 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5581 if (!check_fsp(conn
, req
, fsp
)) {
5582 END_PROFILE(SMBlock
);
5586 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5587 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5589 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5590 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5592 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5594 (uint64_t)req
->smbpid
,
5599 False
, /* Non-blocking lock. */
5603 TALLOC_FREE(br_lck
);
5605 if (NT_STATUS_V(status
)) {
5606 reply_nterror(req
, status
);
5607 END_PROFILE(SMBlock
);
5611 reply_outbuf(req
, 0, 0);
5613 END_PROFILE(SMBlock
);
5617 /****************************************************************************
5619 ****************************************************************************/
5621 void reply_unlock(struct smb_request
*req
)
5623 connection_struct
*conn
= req
->conn
;
5624 uint64_t count
,offset
;
5628 START_PROFILE(SMBunlock
);
5631 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5632 END_PROFILE(SMBunlock
);
5636 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5638 if (!check_fsp(conn
, req
, fsp
)) {
5639 END_PROFILE(SMBunlock
);
5643 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5644 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5646 status
= do_unlock(req
->sconn
->msg_ctx
,
5648 (uint64_t)req
->smbpid
,
5653 if (NT_STATUS_V(status
)) {
5654 reply_nterror(req
, status
);
5655 END_PROFILE(SMBunlock
);
5659 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5660 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5662 reply_outbuf(req
, 0, 0);
5664 END_PROFILE(SMBunlock
);
5669 #define DBGC_CLASS DBGC_ALL
5671 /****************************************************************************
5673 conn POINTER CAN BE NULL HERE !
5674 ****************************************************************************/
5676 void reply_tdis(struct smb_request
*req
)
5679 connection_struct
*conn
= req
->conn
;
5680 struct smbXsrv_tcon
*tcon
;
5682 START_PROFILE(SMBtdis
);
5685 DEBUG(4,("Invalid connection in tdis\n"));
5686 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5687 END_PROFILE(SMBtdis
);
5695 * TODO: cancel all outstanding requests on the tcon
5697 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5698 if (!NT_STATUS_IS_OK(status
)) {
5699 DEBUG(0, ("reply_tdis: "
5700 "smbXsrv_tcon_disconnect() failed: %s\n",
5701 nt_errstr(status
)));
5703 * If we hit this case, there is something completely
5704 * wrong, so we better disconnect the transport connection.
5706 END_PROFILE(SMBtdis
);
5707 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5713 reply_outbuf(req
, 0, 0);
5714 END_PROFILE(SMBtdis
);
5718 /****************************************************************************
5720 conn POINTER CAN BE NULL HERE !
5721 ****************************************************************************/
5723 void reply_echo(struct smb_request
*req
)
5725 connection_struct
*conn
= req
->conn
;
5726 struct smb_perfcount_data local_pcd
;
5727 struct smb_perfcount_data
*cur_pcd
;
5731 START_PROFILE(SMBecho
);
5733 smb_init_perfcount_data(&local_pcd
);
5736 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5737 END_PROFILE(SMBecho
);
5741 smb_reverb
= SVAL(req
->vwv
+0, 0);
5743 reply_outbuf(req
, 1, req
->buflen
);
5745 /* copy any incoming data back out */
5746 if (req
->buflen
> 0) {
5747 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5750 if (smb_reverb
> 100) {
5751 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5755 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5757 /* this makes sure we catch the request pcd */
5758 if (seq_num
== smb_reverb
) {
5759 cur_pcd
= &req
->pcd
;
5761 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5762 cur_pcd
= &local_pcd
;
5765 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5767 show_msg((char *)req
->outbuf
);
5768 if (!srv_send_smb(req
->xconn
,
5769 (char *)req
->outbuf
,
5770 true, req
->seqnum
+1,
5771 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5773 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5776 DEBUG(3,("echo %d times\n", smb_reverb
));
5778 TALLOC_FREE(req
->outbuf
);
5780 END_PROFILE(SMBecho
);
5784 /****************************************************************************
5785 Reply to a printopen.
5786 ****************************************************************************/
5788 void reply_printopen(struct smb_request
*req
)
5790 connection_struct
*conn
= req
->conn
;
5794 START_PROFILE(SMBsplopen
);
5797 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5798 END_PROFILE(SMBsplopen
);
5802 if (!CAN_PRINT(conn
)) {
5803 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5804 END_PROFILE(SMBsplopen
);
5808 status
= file_new(req
, conn
, &fsp
);
5809 if(!NT_STATUS_IS_OK(status
)) {
5810 reply_nterror(req
, status
);
5811 END_PROFILE(SMBsplopen
);
5815 /* Open for exclusive use, write only. */
5816 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5818 if (!NT_STATUS_IS_OK(status
)) {
5819 file_free(req
, fsp
);
5820 reply_nterror(req
, status
);
5821 END_PROFILE(SMBsplopen
);
5825 reply_outbuf(req
, 1, 0);
5826 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5828 DEBUG(3,("openprint fd=%d %s\n",
5829 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5831 END_PROFILE(SMBsplopen
);
5835 /****************************************************************************
5836 Reply to a printclose.
5837 ****************************************************************************/
5839 void reply_printclose(struct smb_request
*req
)
5841 connection_struct
*conn
= req
->conn
;
5845 START_PROFILE(SMBsplclose
);
5848 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5849 END_PROFILE(SMBsplclose
);
5853 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5855 if (!check_fsp(conn
, req
, fsp
)) {
5856 END_PROFILE(SMBsplclose
);
5860 if (!CAN_PRINT(conn
)) {
5861 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5862 END_PROFILE(SMBsplclose
);
5866 DEBUG(3,("printclose fd=%d %s\n",
5867 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5869 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5871 if(!NT_STATUS_IS_OK(status
)) {
5872 reply_nterror(req
, status
);
5873 END_PROFILE(SMBsplclose
);
5877 reply_outbuf(req
, 0, 0);
5879 END_PROFILE(SMBsplclose
);
5883 /****************************************************************************
5884 Reply to a printqueue.
5885 ****************************************************************************/
5887 void reply_printqueue(struct smb_request
*req
)
5889 connection_struct
*conn
= req
->conn
;
5893 START_PROFILE(SMBsplretq
);
5896 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5897 END_PROFILE(SMBsplretq
);
5901 max_count
= SVAL(req
->vwv
+0, 0);
5902 start_index
= SVAL(req
->vwv
+1, 0);
5904 /* we used to allow the client to get the cnum wrong, but that
5905 is really quite gross and only worked when there was only
5906 one printer - I think we should now only accept it if they
5907 get it right (tridge) */
5908 if (!CAN_PRINT(conn
)) {
5909 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5910 END_PROFILE(SMBsplretq
);
5914 reply_outbuf(req
, 2, 3);
5915 SSVAL(req
->outbuf
,smb_vwv0
,0);
5916 SSVAL(req
->outbuf
,smb_vwv1
,0);
5917 SCVAL(smb_buf(req
->outbuf
),0,1);
5918 SSVAL(smb_buf(req
->outbuf
),1,0);
5920 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5921 start_index
, max_count
));
5924 TALLOC_CTX
*mem_ctx
= talloc_tos();
5927 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5928 struct rpc_pipe_client
*cli
= NULL
;
5929 struct dcerpc_binding_handle
*b
= NULL
;
5930 struct policy_handle handle
;
5931 struct spoolss_DevmodeContainer devmode_ctr
;
5932 union spoolss_JobInfo
*info
;
5934 uint32_t num_to_get
;
5938 ZERO_STRUCT(handle
);
5940 status
= rpc_pipe_open_interface(conn
,
5943 conn
->sconn
->remote_address
,
5944 conn
->sconn
->msg_ctx
,
5946 if (!NT_STATUS_IS_OK(status
)) {
5947 DEBUG(0, ("reply_printqueue: "
5948 "could not connect to spoolss: %s\n",
5949 nt_errstr(status
)));
5950 reply_nterror(req
, status
);
5953 b
= cli
->binding_handle
;
5955 ZERO_STRUCT(devmode_ctr
);
5957 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5960 SEC_FLAG_MAXIMUM_ALLOWED
,
5963 if (!NT_STATUS_IS_OK(status
)) {
5964 reply_nterror(req
, status
);
5967 if (!W_ERROR_IS_OK(werr
)) {
5968 reply_nterror(req
, werror_to_ntstatus(werr
));
5972 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5980 if (!W_ERROR_IS_OK(werr
)) {
5981 reply_nterror(req
, werror_to_ntstatus(werr
));
5985 if (max_count
> 0) {
5986 first
= start_index
;
5988 first
= start_index
+ max_count
+ 1;
5991 if (first
>= count
) {
5994 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5997 for (i
= first
; i
< num_to_get
; i
++) {
6000 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6003 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6004 info
[i
].info2
.job_id
);
6006 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6012 srv_put_dos_date2(p
, 0, qtime
);
6013 SCVAL(p
, 4, qstatus
);
6014 SSVAL(p
, 5, qrapjobid
);
6015 SIVAL(p
, 7, info
[i
].info2
.size
);
6017 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6018 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6019 if (!NT_STATUS_IS_OK(status
)) {
6020 reply_nterror(req
, status
);
6023 if (message_push_blob(
6026 blob
, sizeof(blob
))) == -1) {
6027 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6033 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6034 SSVAL(req
->outbuf
,smb_vwv1
,
6035 (max_count
>0?first
+count
:first
-1));
6036 SCVAL(smb_buf(req
->outbuf
),0,1);
6037 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6041 DEBUG(3, ("%u entries returned in queue\n",
6045 if (b
&& is_valid_policy_hnd(&handle
)) {
6046 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6051 END_PROFILE(SMBsplretq
);
6055 /****************************************************************************
6056 Reply to a printwrite.
6057 ****************************************************************************/
6059 void reply_printwrite(struct smb_request
*req
)
6061 connection_struct
*conn
= req
->conn
;
6066 START_PROFILE(SMBsplwr
);
6069 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6070 END_PROFILE(SMBsplwr
);
6074 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6076 if (!check_fsp(conn
, req
, fsp
)) {
6077 END_PROFILE(SMBsplwr
);
6081 if (!fsp
->print_file
) {
6082 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6083 END_PROFILE(SMBsplwr
);
6087 if (!CHECK_WRITE(fsp
)) {
6088 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6089 END_PROFILE(SMBsplwr
);
6093 numtowrite
= SVAL(req
->buf
, 1);
6095 if (req
->buflen
< numtowrite
+ 3) {
6096 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6097 END_PROFILE(SMBsplwr
);
6101 data
= (const char *)req
->buf
+ 3;
6103 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6104 reply_nterror(req
, map_nt_error_from_unix(errno
));
6105 END_PROFILE(SMBsplwr
);
6109 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6111 END_PROFILE(SMBsplwr
);
6115 /****************************************************************************
6117 ****************************************************************************/
6119 void reply_mkdir(struct smb_request
*req
)
6121 connection_struct
*conn
= req
->conn
;
6122 struct smb_filename
*smb_dname
= NULL
;
6123 char *directory
= NULL
;
6125 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
6126 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6127 TALLOC_CTX
*ctx
= talloc_tos();
6129 START_PROFILE(SMBmkdir
);
6131 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6132 STR_TERMINATE
, &status
);
6133 if (!NT_STATUS_IS_OK(status
)) {
6134 reply_nterror(req
, status
);
6138 status
= filename_convert(ctx
, conn
,
6139 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6144 if (!NT_STATUS_IS_OK(status
)) {
6145 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6146 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6147 ERRSRV
, ERRbadpath
);
6150 reply_nterror(req
, status
);
6154 status
= create_directory(conn
, req
, smb_dname
);
6156 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6158 if (!NT_STATUS_IS_OK(status
)) {
6160 if (!use_nt_status()
6161 && NT_STATUS_EQUAL(status
,
6162 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6164 * Yes, in the DOS error code case we get a
6165 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6166 * samba4 torture test.
6168 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6171 reply_nterror(req
, status
);
6175 reply_outbuf(req
, 0, 0);
6177 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6179 TALLOC_FREE(smb_dname
);
6180 END_PROFILE(SMBmkdir
);
6184 /****************************************************************************
6186 ****************************************************************************/
6188 void reply_rmdir(struct smb_request
*req
)
6190 connection_struct
*conn
= req
->conn
;
6191 struct smb_filename
*smb_dname
= NULL
;
6192 char *directory
= NULL
;
6194 TALLOC_CTX
*ctx
= talloc_tos();
6195 files_struct
*fsp
= NULL
;
6197 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6198 struct smbd_server_connection
*sconn
= req
->sconn
;
6200 START_PROFILE(SMBrmdir
);
6202 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6203 STR_TERMINATE
, &status
);
6204 if (!NT_STATUS_IS_OK(status
)) {
6205 reply_nterror(req
, status
);
6209 status
= filename_convert(ctx
, conn
,
6210 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6215 if (!NT_STATUS_IS_OK(status
)) {
6216 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6217 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6218 ERRSRV
, ERRbadpath
);
6221 reply_nterror(req
, status
);
6225 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6226 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6230 status
= SMB_VFS_CREATE_FILE(
6233 0, /* root_dir_fid */
6234 smb_dname
, /* fname */
6235 DELETE_ACCESS
, /* access_mask */
6236 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6238 FILE_OPEN
, /* create_disposition*/
6239 FILE_DIRECTORY_FILE
, /* create_options */
6240 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6241 0, /* oplock_request */
6243 0, /* allocation_size */
6244 0, /* private_flags */
6249 NULL
, NULL
); /* create context */
6251 if (!NT_STATUS_IS_OK(status
)) {
6252 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6253 /* We have re-scheduled this call. */
6256 reply_nterror(req
, status
);
6260 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6261 if (!NT_STATUS_IS_OK(status
)) {
6262 close_file(req
, fsp
, ERROR_CLOSE
);
6263 reply_nterror(req
, status
);
6267 if (!set_delete_on_close(fsp
, true,
6268 conn
->session_info
->security_token
,
6269 conn
->session_info
->unix_token
)) {
6270 close_file(req
, fsp
, ERROR_CLOSE
);
6271 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6275 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6276 if (!NT_STATUS_IS_OK(status
)) {
6277 reply_nterror(req
, status
);
6279 reply_outbuf(req
, 0, 0);
6282 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6284 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6286 TALLOC_FREE(smb_dname
);
6287 END_PROFILE(SMBrmdir
);
6291 /*******************************************************************
6292 Resolve wildcards in a filename rename.
6293 ********************************************************************/
6295 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6300 char *name2_copy
= NULL
;
6305 char *p
,*p2
, *pname1
, *pname2
;
6307 name2_copy
= talloc_strdup(ctx
, name2
);
6312 pname1
= strrchr_m(name1
,'/');
6313 pname2
= strrchr_m(name2_copy
,'/');
6315 if (!pname1
|| !pname2
) {
6319 /* Truncate the copy of name2 at the last '/' */
6322 /* Now go past the '/' */
6326 root1
= talloc_strdup(ctx
, pname1
);
6327 root2
= talloc_strdup(ctx
, pname2
);
6329 if (!root1
|| !root2
) {
6333 p
= strrchr_m(root1
,'.');
6336 ext1
= talloc_strdup(ctx
, p
+1);
6338 ext1
= talloc_strdup(ctx
, "");
6340 p
= strrchr_m(root2
,'.');
6343 ext2
= talloc_strdup(ctx
, p
+1);
6345 ext2
= talloc_strdup(ctx
, "");
6348 if (!ext1
|| !ext2
) {
6356 /* Hmmm. Should this be mb-aware ? */
6359 } else if (*p2
== '*') {
6361 root2
= talloc_asprintf(ctx
, "%s%s",
6380 /* Hmmm. Should this be mb-aware ? */
6383 } else if (*p2
== '*') {
6385 ext2
= talloc_asprintf(ctx
, "%s%s",
6401 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6406 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6418 /****************************************************************************
6419 Ensure open files have their names updated. Updated to notify other smbd's
6421 ****************************************************************************/
6423 static void rename_open_files(connection_struct
*conn
,
6424 struct share_mode_lock
*lck
,
6426 uint32_t orig_name_hash
,
6427 const struct smb_filename
*smb_fname_dst
)
6430 bool did_rename
= False
;
6432 uint32_t new_name_hash
= 0;
6434 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6435 fsp
= file_find_di_next(fsp
)) {
6436 /* fsp_name is a relative path under the fsp. To change this for other
6437 sharepaths we need to manipulate relative paths. */
6438 /* TODO - create the absolute path and manipulate the newname
6439 relative to the sharepath. */
6440 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6443 if (fsp
->name_hash
!= orig_name_hash
) {
6446 DEBUG(10, ("rename_open_files: renaming file %s "
6447 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6448 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6449 smb_fname_str_dbg(smb_fname_dst
)));
6451 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6452 if (NT_STATUS_IS_OK(status
)) {
6454 new_name_hash
= fsp
->name_hash
;
6459 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6460 "for %s\n", file_id_string_tos(&id
),
6461 smb_fname_str_dbg(smb_fname_dst
)));
6464 /* Send messages to all smbd's (not ourself) that the name has changed. */
6465 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6466 orig_name_hash
, new_name_hash
,
6471 /****************************************************************************
6472 We need to check if the source path is a parent directory of the destination
6473 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6474 refuse the rename with a sharing violation. Under UNIX the above call can
6475 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6476 probably need to check that the client is a Windows one before disallowing
6477 this as a UNIX client (one with UNIX extensions) can know the source is a
6478 symlink and make this decision intelligently. Found by an excellent bug
6479 report from <AndyLiebman@aol.com>.
6480 ****************************************************************************/
6482 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6483 const struct smb_filename
*smb_fname_dst
)
6485 const char *psrc
= smb_fname_src
->base_name
;
6486 const char *pdst
= smb_fname_dst
->base_name
;
6489 if (psrc
[0] == '.' && psrc
[1] == '/') {
6492 if (pdst
[0] == '.' && pdst
[1] == '/') {
6495 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6498 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6502 * Do the notify calls from a rename
6505 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6506 const struct smb_filename
*smb_fname_src
,
6507 const struct smb_filename
*smb_fname_dst
)
6509 char *parent_dir_src
= NULL
;
6510 char *parent_dir_dst
= NULL
;
6513 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6514 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6516 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6517 &parent_dir_src
, NULL
) ||
6518 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6519 &parent_dir_dst
, NULL
)) {
6523 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6524 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6525 smb_fname_src
->base_name
);
6526 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6527 smb_fname_dst
->base_name
);
6530 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6531 smb_fname_src
->base_name
);
6532 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6533 smb_fname_dst
->base_name
);
6536 /* this is a strange one. w2k3 gives an additional event for
6537 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6538 files, but not directories */
6540 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6541 FILE_NOTIFY_CHANGE_ATTRIBUTES
6542 |FILE_NOTIFY_CHANGE_CREATION
,
6543 smb_fname_dst
->base_name
);
6546 TALLOC_FREE(parent_dir_src
);
6547 TALLOC_FREE(parent_dir_dst
);
6550 /****************************************************************************
6551 Returns an error if the parent directory for a filename is open in an
6553 ****************************************************************************/
6555 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6556 const struct smb_filename
*smb_fname_dst_in
)
6558 char *parent_dir
= NULL
;
6559 struct smb_filename smb_fname_parent
;
6561 files_struct
*fsp
= NULL
;
6564 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6565 &parent_dir
, NULL
)) {
6566 return NT_STATUS_NO_MEMORY
;
6568 ZERO_STRUCT(smb_fname_parent
);
6569 smb_fname_parent
.base_name
= parent_dir
;
6571 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6573 return map_nt_error_from_unix(errno
);
6577 * We're only checking on this smbd here, mostly good
6578 * enough.. and will pass tests.
6581 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6582 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6583 fsp
= file_find_di_next(fsp
)) {
6584 if (fsp
->access_mask
& DELETE_ACCESS
) {
6585 return NT_STATUS_SHARING_VIOLATION
;
6588 return NT_STATUS_OK
;
6591 /****************************************************************************
6592 Rename an open file - given an fsp.
6593 ****************************************************************************/
6595 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6597 const struct smb_filename
*smb_fname_dst_in
,
6599 bool replace_if_exists
)
6601 TALLOC_CTX
*ctx
= talloc_tos();
6602 struct smb_filename
*smb_fname_dst
= NULL
;
6603 NTSTATUS status
= NT_STATUS_OK
;
6604 struct share_mode_lock
*lck
= NULL
;
6605 bool dst_exists
, old_is_stream
, new_is_stream
;
6607 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6608 if (!NT_STATUS_IS_OK(status
)) {
6612 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6613 if (!NT_STATUS_IS_OK(status
)) {
6617 /* Make a copy of the dst smb_fname structs */
6619 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6620 if (smb_fname_dst
== NULL
) {
6621 status
= NT_STATUS_NO_MEMORY
;
6626 * Check for special case with case preserving and not
6627 * case sensitive. If the new last component differs from the original
6628 * last component only by case, then we should allow
6629 * the rename (user is trying to change the case of the
6632 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6633 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6634 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6635 char *fname_dst_parent
= NULL
;
6636 const char *fname_dst_lcomp
= NULL
;
6637 char *orig_lcomp_path
= NULL
;
6638 char *orig_lcomp_stream
= NULL
;
6642 * Split off the last component of the processed
6643 * destination name. We will compare this to
6644 * the split components of smb_fname_dst->original_lcomp.
6646 if (!parent_dirname(ctx
,
6647 smb_fname_dst
->base_name
,
6649 &fname_dst_lcomp
)) {
6650 status
= NT_STATUS_NO_MEMORY
;
6655 * The original_lcomp component contains
6656 * the last_component of the path + stream
6657 * name (if a stream exists).
6659 * Split off the stream name so we
6660 * can check them separately.
6663 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6664 /* POSIX - no stream component. */
6665 orig_lcomp_path
= talloc_strdup(ctx
,
6666 smb_fname_dst
->original_lcomp
);
6667 if (orig_lcomp_path
== NULL
) {
6671 ok
= split_stream_filename(ctx
,
6672 smb_fname_dst
->original_lcomp
,
6674 &orig_lcomp_stream
);
6678 TALLOC_FREE(fname_dst_parent
);
6679 status
= NT_STATUS_NO_MEMORY
;
6683 /* If the base names only differ by case, use original. */
6684 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6687 * Replace the modified last component with the
6690 if (!ISDOT(fname_dst_parent
)) {
6691 tmp
= talloc_asprintf(smb_fname_dst
,
6696 tmp
= talloc_strdup(smb_fname_dst
,
6700 status
= NT_STATUS_NO_MEMORY
;
6701 TALLOC_FREE(fname_dst_parent
);
6702 TALLOC_FREE(orig_lcomp_path
);
6703 TALLOC_FREE(orig_lcomp_stream
);
6706 TALLOC_FREE(smb_fname_dst
->base_name
);
6707 smb_fname_dst
->base_name
= tmp
;
6710 /* If the stream_names only differ by case, use original. */
6711 if(!strcsequal(smb_fname_dst
->stream_name
,
6712 orig_lcomp_stream
)) {
6713 /* Use the original stream. */
6714 char *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
->stream_name
);
6724 smb_fname_dst
->stream_name
= tmp
;
6726 TALLOC_FREE(fname_dst_parent
);
6727 TALLOC_FREE(orig_lcomp_path
);
6728 TALLOC_FREE(orig_lcomp_stream
);
6732 * If the src and dest names are identical - including case,
6733 * don't do the rename, just return success.
6736 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6737 strcsequal(fsp
->fsp_name
->stream_name
,
6738 smb_fname_dst
->stream_name
)) {
6739 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6740 "- returning success\n",
6741 smb_fname_str_dbg(smb_fname_dst
)));
6742 status
= NT_STATUS_OK
;
6746 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6747 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6749 /* Return the correct error code if both names aren't streams. */
6750 if (!old_is_stream
&& new_is_stream
) {
6751 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6755 if (old_is_stream
&& !new_is_stream
) {
6756 status
= NT_STATUS_INVALID_PARAMETER
;
6760 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6762 if(!replace_if_exists
&& dst_exists
) {
6763 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6764 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6765 smb_fname_str_dbg(smb_fname_dst
)));
6766 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6771 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6772 &smb_fname_dst
->st
);
6773 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6775 /* The file can be open when renaming a stream */
6776 if (dst_fsp
&& !new_is_stream
) {
6777 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6778 status
= NT_STATUS_ACCESS_DENIED
;
6783 /* Ensure we have a valid stat struct for the source. */
6784 status
= vfs_stat_fsp(fsp
);
6785 if (!NT_STATUS_IS_OK(status
)) {
6789 status
= can_rename(conn
, fsp
, attrs
);
6791 if (!NT_STATUS_IS_OK(status
)) {
6792 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6793 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6794 smb_fname_str_dbg(smb_fname_dst
)));
6795 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6796 status
= NT_STATUS_ACCESS_DENIED
;
6800 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6801 status
= NT_STATUS_ACCESS_DENIED
;
6804 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6807 * We have the file open ourselves, so not being able to get the
6808 * corresponding share mode lock is a fatal error.
6811 SMB_ASSERT(lck
!= NULL
);
6813 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6814 uint32_t create_options
= fsp
->fh
->private_options
;
6816 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6817 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6818 smb_fname_str_dbg(smb_fname_dst
)));
6820 if (!fsp
->is_directory
&&
6821 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6822 (lp_map_archive(SNUM(conn
)) ||
6823 lp_store_dos_attributes(SNUM(conn
)))) {
6824 /* We must set the archive bit on the newly
6826 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6827 uint32_t old_dosmode
= dos_mode(conn
,
6829 file_set_dosmode(conn
,
6831 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6837 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6840 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6844 * A rename acts as a new file create w.r.t. allowing an initial delete
6845 * on close, probably because in Windows there is a new handle to the
6846 * new file. If initial delete on close was requested but not
6847 * originally set, we need to set it here. This is probably not 100% correct,
6848 * but will work for the CIFSFS client which in non-posix mode
6849 * depends on these semantics. JRA.
6852 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6853 status
= can_set_delete_on_close(fsp
, 0);
6855 if (NT_STATUS_IS_OK(status
)) {
6856 /* Note that here we set the *inital* delete on close flag,
6857 * not the regular one. The magic gets handled in close. */
6858 fsp
->initial_delete_on_close
= True
;
6862 status
= NT_STATUS_OK
;
6868 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6869 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6871 status
= map_nt_error_from_unix(errno
);
6874 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6875 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6876 smb_fname_str_dbg(smb_fname_dst
)));
6879 TALLOC_FREE(smb_fname_dst
);
6884 /****************************************************************************
6885 The guts of the rename command, split out so it may be called by the NT SMB
6887 ****************************************************************************/
6889 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6890 connection_struct
*conn
,
6891 struct smb_request
*req
,
6892 struct smb_filename
*smb_fname_src
,
6893 struct smb_filename
*smb_fname_dst
,
6895 bool replace_if_exists
,
6898 uint32_t access_mask
)
6900 char *fname_src_dir
= NULL
;
6901 struct smb_filename
*smb_fname_src_dir
= NULL
;
6902 char *fname_src_mask
= NULL
;
6904 NTSTATUS status
= NT_STATUS_OK
;
6905 struct smb_Dir
*dir_hnd
= NULL
;
6906 const char *dname
= NULL
;
6907 char *talloced
= NULL
;
6909 int create_options
= 0;
6910 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6914 * Split the old name into directory and last component
6915 * strings. Note that unix_convert may have stripped off a
6916 * leading ./ from both name and newname if the rename is
6917 * at the root of the share. We need to make sure either both
6918 * name and newname contain a / character or neither of them do
6919 * as this is checked in resolve_wildcards().
6922 /* Split up the directory from the filename/mask. */
6923 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6924 &fname_src_dir
, &fname_src_mask
);
6925 if (!NT_STATUS_IS_OK(status
)) {
6926 status
= NT_STATUS_NO_MEMORY
;
6931 * We should only check the mangled cache
6932 * here if unix_convert failed. This means
6933 * that the path in 'mask' doesn't exist
6934 * on the file system and so we need to look
6935 * for a possible mangle. This patch from
6936 * Tine Smukavec <valentin.smukavec@hermes.si>.
6939 if (!VALID_STAT(smb_fname_src
->st
) &&
6940 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6941 char *new_mask
= NULL
;
6942 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6945 TALLOC_FREE(fname_src_mask
);
6946 fname_src_mask
= new_mask
;
6950 if (!src_has_wild
) {
6954 * Only one file needs to be renamed. Append the mask back
6955 * onto the directory.
6957 TALLOC_FREE(smb_fname_src
->base_name
);
6958 if (ISDOT(fname_src_dir
)) {
6959 /* Ensure we use canonical names on open. */
6960 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6964 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6969 if (!smb_fname_src
->base_name
) {
6970 status
= NT_STATUS_NO_MEMORY
;
6974 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6975 "case_preserve = %d, short case preserve = %d, "
6976 "directory = %s, newname = %s, "
6977 "last_component_dest = %s\n",
6978 conn
->case_sensitive
, conn
->case_preserve
,
6979 conn
->short_case_preserve
,
6980 smb_fname_str_dbg(smb_fname_src
),
6981 smb_fname_str_dbg(smb_fname_dst
),
6982 smb_fname_dst
->original_lcomp
));
6984 /* The dest name still may have wildcards. */
6985 if (dest_has_wild
) {
6986 char *fname_dst_mod
= NULL
;
6987 if (!resolve_wildcards(smb_fname_dst
,
6988 smb_fname_src
->base_name
,
6989 smb_fname_dst
->base_name
,
6991 DEBUG(6, ("rename_internals: resolve_wildcards "
6993 smb_fname_src
->base_name
,
6994 smb_fname_dst
->base_name
));
6995 status
= NT_STATUS_NO_MEMORY
;
6998 TALLOC_FREE(smb_fname_dst
->base_name
);
6999 smb_fname_dst
->base_name
= fname_dst_mod
;
7002 ZERO_STRUCT(smb_fname_src
->st
);
7003 if (posix_pathnames
) {
7004 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7006 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7009 status
= map_nt_error_from_unix_common(errno
);
7013 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7014 create_options
|= FILE_DIRECTORY_FILE
;
7017 status
= SMB_VFS_CREATE_FILE(
7020 0, /* root_dir_fid */
7021 smb_fname_src
, /* fname */
7022 access_mask
, /* access_mask */
7023 (FILE_SHARE_READ
| /* share_access */
7025 FILE_OPEN
, /* create_disposition*/
7026 create_options
, /* create_options */
7027 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7028 0, /* oplock_request */
7030 0, /* allocation_size */
7031 0, /* private_flags */
7036 NULL
, NULL
); /* create context */
7038 if (!NT_STATUS_IS_OK(status
)) {
7039 DEBUG(3, ("Could not open rename source %s: %s\n",
7040 smb_fname_str_dbg(smb_fname_src
),
7041 nt_errstr(status
)));
7045 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7046 attrs
, replace_if_exists
);
7048 close_file(req
, fsp
, NORMAL_CLOSE
);
7050 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7051 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7052 smb_fname_str_dbg(smb_fname_dst
)));
7058 * Wildcards - process each file that matches.
7060 if (strequal(fname_src_mask
, "????????.???")) {
7061 TALLOC_FREE(fname_src_mask
);
7062 fname_src_mask
= talloc_strdup(ctx
, "*");
7063 if (!fname_src_mask
) {
7064 status
= NT_STATUS_NO_MEMORY
;
7069 status
= check_name(conn
, fname_src_dir
);
7070 if (!NT_STATUS_IS_OK(status
)) {
7074 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7078 smb_fname_src
->flags
);
7079 if (smb_fname_src_dir
== NULL
) {
7080 status
= NT_STATUS_NO_MEMORY
;
7084 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7086 if (dir_hnd
== NULL
) {
7087 status
= map_nt_error_from_unix(errno
);
7091 status
= NT_STATUS_NO_SUCH_FILE
;
7093 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7094 * - gentest fix. JRA
7097 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7099 files_struct
*fsp
= NULL
;
7100 char *destname
= NULL
;
7101 bool sysdir_entry
= False
;
7103 /* Quick check for "." and ".." */
7104 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7105 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7106 sysdir_entry
= True
;
7108 TALLOC_FREE(talloced
);
7113 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7114 &smb_fname_src
->st
, false)) {
7115 TALLOC_FREE(talloced
);
7119 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7120 TALLOC_FREE(talloced
);
7125 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7129 TALLOC_FREE(smb_fname_src
->base_name
);
7130 if (ISDOT(fname_src_dir
)) {
7131 /* Ensure we use canonical names on open. */
7132 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7136 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7141 if (!smb_fname_src
->base_name
) {
7142 status
= NT_STATUS_NO_MEMORY
;
7146 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7147 smb_fname_dst
->base_name
,
7149 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7150 smb_fname_src
->base_name
, destname
));
7151 TALLOC_FREE(talloced
);
7155 status
= NT_STATUS_NO_MEMORY
;
7159 TALLOC_FREE(smb_fname_dst
->base_name
);
7160 smb_fname_dst
->base_name
= destname
;
7162 ZERO_STRUCT(smb_fname_src
->st
);
7163 if (posix_pathnames
) {
7164 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7166 SMB_VFS_STAT(conn
, smb_fname_src
);
7171 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7172 create_options
|= FILE_DIRECTORY_FILE
;
7175 status
= SMB_VFS_CREATE_FILE(
7178 0, /* root_dir_fid */
7179 smb_fname_src
, /* fname */
7180 access_mask
, /* access_mask */
7181 (FILE_SHARE_READ
| /* share_access */
7183 FILE_OPEN
, /* create_disposition*/
7184 create_options
, /* create_options */
7185 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7186 0, /* oplock_request */
7188 0, /* allocation_size */
7189 0, /* private_flags */
7194 NULL
, NULL
); /* create context */
7196 if (!NT_STATUS_IS_OK(status
)) {
7197 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7198 "returned %s rename %s -> %s\n",
7200 smb_fname_str_dbg(smb_fname_src
),
7201 smb_fname_str_dbg(smb_fname_dst
)));
7205 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7207 if (!smb_fname_dst
->original_lcomp
) {
7208 status
= NT_STATUS_NO_MEMORY
;
7212 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7213 attrs
, replace_if_exists
);
7215 close_file(req
, fsp
, NORMAL_CLOSE
);
7217 if (!NT_STATUS_IS_OK(status
)) {
7218 DEBUG(3, ("rename_internals_fsp returned %s for "
7219 "rename %s -> %s\n", nt_errstr(status
),
7220 smb_fname_str_dbg(smb_fname_src
),
7221 smb_fname_str_dbg(smb_fname_dst
)));
7227 DEBUG(3,("rename_internals: doing rename on %s -> "
7228 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7229 smb_fname_str_dbg(smb_fname_src
)));
7230 TALLOC_FREE(talloced
);
7232 TALLOC_FREE(dir_hnd
);
7234 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7235 status
= map_nt_error_from_unix(errno
);
7239 TALLOC_FREE(talloced
);
7240 TALLOC_FREE(smb_fname_src_dir
);
7241 TALLOC_FREE(fname_src_dir
);
7242 TALLOC_FREE(fname_src_mask
);
7246 /****************************************************************************
7248 ****************************************************************************/
7250 void reply_mv(struct smb_request
*req
)
7252 connection_struct
*conn
= req
->conn
;
7254 char *newname
= NULL
;
7258 bool src_has_wcard
= False
;
7259 bool dest_has_wcard
= False
;
7260 TALLOC_CTX
*ctx
= talloc_tos();
7261 struct smb_filename
*smb_fname_src
= NULL
;
7262 struct smb_filename
*smb_fname_dst
= NULL
;
7263 uint32_t src_ucf_flags
= (req
->posix_pathnames
?
7264 (UCF_UNIX_NAME_LOOKUP
|UCF_POSIX_PATHNAMES
) :
7265 UCF_COND_ALLOW_WCARD_LCOMP
);
7266 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
|
7267 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
:
7268 UCF_COND_ALLOW_WCARD_LCOMP
);
7269 bool stream_rename
= false;
7271 START_PROFILE(SMBmv
);
7274 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7278 attrs
= SVAL(req
->vwv
+0, 0);
7280 p
= (const char *)req
->buf
+ 1;
7281 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7282 &status
, &src_has_wcard
);
7283 if (!NT_STATUS_IS_OK(status
)) {
7284 reply_nterror(req
, status
);
7288 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7289 &status
, &dest_has_wcard
);
7290 if (!NT_STATUS_IS_OK(status
)) {
7291 reply_nterror(req
, status
);
7295 if (!req
->posix_pathnames
) {
7296 /* The newname must begin with a ':' if the
7297 name contains a ':'. */
7298 if (strchr_m(name
, ':')) {
7299 if (newname
[0] != ':') {
7300 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7303 stream_rename
= true;
7307 status
= filename_convert(ctx
,
7309 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7315 if (!NT_STATUS_IS_OK(status
)) {
7316 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7317 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7318 ERRSRV
, ERRbadpath
);
7321 reply_nterror(req
, status
);
7325 status
= filename_convert(ctx
,
7327 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7333 if (!NT_STATUS_IS_OK(status
)) {
7334 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7335 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7336 ERRSRV
, ERRbadpath
);
7339 reply_nterror(req
, status
);
7343 if (stream_rename
) {
7344 /* smb_fname_dst->base_name must be the same as
7345 smb_fname_src->base_name. */
7346 TALLOC_FREE(smb_fname_dst
->base_name
);
7347 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7348 smb_fname_src
->base_name
);
7349 if (!smb_fname_dst
->base_name
) {
7350 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7355 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7356 smb_fname_str_dbg(smb_fname_dst
)));
7358 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7359 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7361 if (!NT_STATUS_IS_OK(status
)) {
7362 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7363 /* We have re-scheduled this call. */
7366 reply_nterror(req
, status
);
7370 reply_outbuf(req
, 0, 0);
7372 TALLOC_FREE(smb_fname_src
);
7373 TALLOC_FREE(smb_fname_dst
);
7378 /*******************************************************************
7379 Copy a file as part of a reply_copy.
7380 ******************************************************************/
7383 * TODO: check error codes on all callers
7386 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7387 connection_struct
*conn
,
7388 struct smb_filename
*smb_fname_src
,
7389 struct smb_filename
*smb_fname_dst
,
7392 bool target_is_directory
)
7394 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7396 files_struct
*fsp1
,*fsp2
;
7398 uint32_t new_create_disposition
;
7402 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7403 if (smb_fname_dst_tmp
== NULL
) {
7404 return NT_STATUS_NO_MEMORY
;
7408 * If the target is a directory, extract the last component from the
7409 * src filename and append it to the dst filename
7411 if (target_is_directory
) {
7414 /* dest/target can't be a stream if it's a directory. */
7415 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7417 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7421 p
= smb_fname_src
->base_name
;
7423 smb_fname_dst_tmp
->base_name
=
7424 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7426 if (!smb_fname_dst_tmp
->base_name
) {
7427 status
= NT_STATUS_NO_MEMORY
;
7432 status
= vfs_file_exist(conn
, smb_fname_src
);
7433 if (!NT_STATUS_IS_OK(status
)) {
7437 if (!target_is_directory
&& count
) {
7438 new_create_disposition
= FILE_OPEN
;
7440 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7443 &new_create_disposition
,
7446 status
= NT_STATUS_INVALID_PARAMETER
;
7451 /* Open the src file for reading. */
7452 status
= SMB_VFS_CREATE_FILE(
7455 0, /* root_dir_fid */
7456 smb_fname_src
, /* fname */
7457 FILE_GENERIC_READ
, /* access_mask */
7458 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7459 FILE_OPEN
, /* create_disposition*/
7460 0, /* create_options */
7461 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7462 INTERNAL_OPEN_ONLY
, /* oplock_request */
7464 0, /* allocation_size */
7465 0, /* private_flags */
7470 NULL
, NULL
); /* create context */
7472 if (!NT_STATUS_IS_OK(status
)) {
7476 dosattrs
= dos_mode(conn
, smb_fname_src
);
7478 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7479 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7482 /* Open the dst file for writing. */
7483 status
= SMB_VFS_CREATE_FILE(
7486 0, /* root_dir_fid */
7487 smb_fname_dst
, /* fname */
7488 FILE_GENERIC_WRITE
, /* access_mask */
7489 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7490 new_create_disposition
, /* create_disposition*/
7491 0, /* create_options */
7492 dosattrs
, /* file_attributes */
7493 INTERNAL_OPEN_ONLY
, /* oplock_request */
7495 0, /* allocation_size */
7496 0, /* private_flags */
7501 NULL
, NULL
); /* create context */
7503 if (!NT_STATUS_IS_OK(status
)) {
7504 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7508 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7509 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7511 DEBUG(0, ("error - vfs lseek returned error %s\n",
7513 status
= map_nt_error_from_unix(errno
);
7514 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7515 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7520 /* Do the actual copy. */
7521 if (smb_fname_src
->st
.st_ex_size
) {
7522 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7527 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7529 /* Ensure the modtime is set correctly on the destination file. */
7530 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7533 * As we are opening fsp1 read-only we only expect
7534 * an error on close on fsp2 if we are out of space.
7535 * Thus we don't look at the error return from the
7538 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7540 if (!NT_STATUS_IS_OK(status
)) {
7544 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7545 status
= NT_STATUS_DISK_FULL
;
7549 status
= NT_STATUS_OK
;
7552 TALLOC_FREE(smb_fname_dst_tmp
);
7556 /****************************************************************************
7557 Reply to a file copy.
7558 ****************************************************************************/
7560 void reply_copy(struct smb_request
*req
)
7562 connection_struct
*conn
= req
->conn
;
7563 struct smb_filename
*smb_fname_src
= NULL
;
7564 struct smb_filename
*smb_fname_src_dir
= NULL
;
7565 struct smb_filename
*smb_fname_dst
= NULL
;
7566 char *fname_src
= NULL
;
7567 char *fname_dst
= NULL
;
7568 char *fname_src_mask
= NULL
;
7569 char *fname_src_dir
= NULL
;
7572 int error
= ERRnoaccess
;
7576 bool target_is_directory
=False
;
7577 bool source_has_wild
= False
;
7578 bool dest_has_wild
= False
;
7580 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7581 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7582 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7583 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7584 TALLOC_CTX
*ctx
= talloc_tos();
7586 START_PROFILE(SMBcopy
);
7589 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7593 tid2
= SVAL(req
->vwv
+0, 0);
7594 ofun
= SVAL(req
->vwv
+1, 0);
7595 flags
= SVAL(req
->vwv
+2, 0);
7597 p
= (const char *)req
->buf
;
7598 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7599 &status
, &source_has_wild
);
7600 if (!NT_STATUS_IS_OK(status
)) {
7601 reply_nterror(req
, status
);
7604 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7605 &status
, &dest_has_wild
);
7606 if (!NT_STATUS_IS_OK(status
)) {
7607 reply_nterror(req
, status
);
7611 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7613 if (tid2
!= conn
->cnum
) {
7614 /* can't currently handle inter share copies XXXX */
7615 DEBUG(3,("Rejecting inter-share copy\n"));
7616 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7620 status
= filename_convert(ctx
, conn
,
7621 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7626 if (!NT_STATUS_IS_OK(status
)) {
7627 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7628 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7629 ERRSRV
, ERRbadpath
);
7632 reply_nterror(req
, status
);
7636 status
= filename_convert(ctx
, conn
,
7637 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7642 if (!NT_STATUS_IS_OK(status
)) {
7643 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7644 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7645 ERRSRV
, ERRbadpath
);
7648 reply_nterror(req
, status
);
7652 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7654 if ((flags
&1) && target_is_directory
) {
7655 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7659 if ((flags
&2) && !target_is_directory
) {
7660 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7664 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7665 /* wants a tree copy! XXXX */
7666 DEBUG(3,("Rejecting tree copy\n"));
7667 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7671 /* Split up the directory from the filename/mask. */
7672 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7673 &fname_src_dir
, &fname_src_mask
);
7674 if (!NT_STATUS_IS_OK(status
)) {
7675 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7680 * We should only check the mangled cache
7681 * here if unix_convert failed. This means
7682 * that the path in 'mask' doesn't exist
7683 * on the file system and so we need to look
7684 * for a possible mangle. This patch from
7685 * Tine Smukavec <valentin.smukavec@hermes.si>.
7687 if (!VALID_STAT(smb_fname_src
->st
) &&
7688 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7689 char *new_mask
= NULL
;
7690 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7691 &new_mask
, conn
->params
);
7693 /* Use demangled name if one was successfully found. */
7695 TALLOC_FREE(fname_src_mask
);
7696 fname_src_mask
= new_mask
;
7700 if (!source_has_wild
) {
7703 * Only one file needs to be copied. Append the mask back onto
7706 TALLOC_FREE(smb_fname_src
->base_name
);
7707 if (ISDOT(fname_src_dir
)) {
7708 /* Ensure we use canonical names on open. */
7709 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7713 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7718 if (!smb_fname_src
->base_name
) {
7719 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7723 if (dest_has_wild
) {
7724 char *fname_dst_mod
= NULL
;
7725 if (!resolve_wildcards(smb_fname_dst
,
7726 smb_fname_src
->base_name
,
7727 smb_fname_dst
->base_name
,
7729 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7732 TALLOC_FREE(smb_fname_dst
->base_name
);
7733 smb_fname_dst
->base_name
= fname_dst_mod
;
7736 status
= check_name(conn
, smb_fname_src
->base_name
);
7737 if (!NT_STATUS_IS_OK(status
)) {
7738 reply_nterror(req
, status
);
7742 status
= check_name(conn
, smb_fname_dst
->base_name
);
7743 if (!NT_STATUS_IS_OK(status
)) {
7744 reply_nterror(req
, status
);
7748 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7749 ofun
, count
, target_is_directory
);
7751 if(!NT_STATUS_IS_OK(status
)) {
7752 reply_nterror(req
, status
);
7758 struct smb_Dir
*dir_hnd
= NULL
;
7759 const char *dname
= NULL
;
7760 char *talloced
= NULL
;
7764 * There is a wildcard that requires us to actually read the
7765 * src dir and copy each file matching the mask to the dst.
7766 * Right now streams won't be copied, but this could
7767 * presumably be added with a nested loop for reach dir entry.
7769 SMB_ASSERT(!smb_fname_src
->stream_name
);
7770 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7772 smb_fname_src
->stream_name
= NULL
;
7773 smb_fname_dst
->stream_name
= NULL
;
7775 if (strequal(fname_src_mask
,"????????.???")) {
7776 TALLOC_FREE(fname_src_mask
);
7777 fname_src_mask
= talloc_strdup(ctx
, "*");
7778 if (!fname_src_mask
) {
7779 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7784 status
= check_name(conn
, fname_src_dir
);
7785 if (!NT_STATUS_IS_OK(status
)) {
7786 reply_nterror(req
, status
);
7790 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7794 smb_fname_src
->flags
);
7795 if (smb_fname_src_dir
== NULL
) {
7796 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7800 dir_hnd
= OpenDir(ctx
,
7805 if (dir_hnd
== NULL
) {
7806 status
= map_nt_error_from_unix(errno
);
7807 reply_nterror(req
, status
);
7813 /* Iterate over the src dir copying each entry to the dst. */
7814 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7815 &smb_fname_src
->st
, &talloced
))) {
7816 char *destname
= NULL
;
7818 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7819 TALLOC_FREE(talloced
);
7823 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7824 &smb_fname_src
->st
, false)) {
7825 TALLOC_FREE(talloced
);
7829 if(!mask_match(dname
, fname_src_mask
,
7830 conn
->case_sensitive
)) {
7831 TALLOC_FREE(talloced
);
7835 error
= ERRnoaccess
;
7837 /* Get the src smb_fname struct setup. */
7838 TALLOC_FREE(smb_fname_src
->base_name
);
7839 if (ISDOT(fname_src_dir
)) {
7840 /* Ensure we use canonical names on open. */
7841 smb_fname_src
->base_name
=
7842 talloc_asprintf(smb_fname_src
, "%s",
7845 smb_fname_src
->base_name
=
7846 talloc_asprintf(smb_fname_src
, "%s/%s",
7847 fname_src_dir
, dname
);
7850 if (!smb_fname_src
->base_name
) {
7851 TALLOC_FREE(dir_hnd
);
7852 TALLOC_FREE(talloced
);
7853 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7857 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7858 smb_fname_dst
->base_name
,
7860 TALLOC_FREE(talloced
);
7864 TALLOC_FREE(dir_hnd
);
7865 TALLOC_FREE(talloced
);
7866 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7870 TALLOC_FREE(smb_fname_dst
->base_name
);
7871 smb_fname_dst
->base_name
= destname
;
7873 status
= check_name(conn
, smb_fname_src
->base_name
);
7874 if (!NT_STATUS_IS_OK(status
)) {
7875 TALLOC_FREE(dir_hnd
);
7876 TALLOC_FREE(talloced
);
7877 reply_nterror(req
, status
);
7881 status
= check_name(conn
, smb_fname_dst
->base_name
);
7882 if (!NT_STATUS_IS_OK(status
)) {
7883 TALLOC_FREE(dir_hnd
);
7884 TALLOC_FREE(talloced
);
7885 reply_nterror(req
, status
);
7889 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7890 smb_fname_src
->base_name
,
7891 smb_fname_dst
->base_name
));
7893 status
= copy_file(ctx
, conn
, smb_fname_src
,
7894 smb_fname_dst
, ofun
, count
,
7895 target_is_directory
);
7896 if (NT_STATUS_IS_OK(status
)) {
7900 TALLOC_FREE(talloced
);
7902 TALLOC_FREE(dir_hnd
);
7906 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7910 reply_outbuf(req
, 1, 0);
7911 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7913 TALLOC_FREE(smb_fname_src
);
7914 TALLOC_FREE(smb_fname_src_dir
);
7915 TALLOC_FREE(smb_fname_dst
);
7916 TALLOC_FREE(fname_src
);
7917 TALLOC_FREE(fname_dst
);
7918 TALLOC_FREE(fname_src_mask
);
7919 TALLOC_FREE(fname_src_dir
);
7921 END_PROFILE(SMBcopy
);
7926 #define DBGC_CLASS DBGC_LOCKING
7928 /****************************************************************************
7929 Get a lock pid, dealing with large count requests.
7930 ****************************************************************************/
7932 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7933 bool large_file_format
)
7935 if(!large_file_format
)
7936 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7938 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7941 /****************************************************************************
7942 Get a lock count, dealing with large count requests.
7943 ****************************************************************************/
7945 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7946 bool large_file_format
)
7950 if(!large_file_format
) {
7951 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7954 * No BVAL, this is reversed!
7956 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7957 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7963 /****************************************************************************
7964 Get a lock offset, dealing with large offset requests.
7965 ****************************************************************************/
7967 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7968 bool large_file_format
)
7970 uint64_t offset
= 0;
7972 if(!large_file_format
) {
7973 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7976 * No BVAL, this is reversed!
7978 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7979 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7985 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7990 struct smbd_lock_element
*locks
,
7993 connection_struct
*conn
= req
->conn
;
7995 NTSTATUS status
= NT_STATUS_OK
;
7999 /* Setup the timeout in seconds. */
8001 if (!lp_blocking_locks(SNUM(conn
))) {
8005 for(i
= 0; i
< (int)num_locks
; i
++) {
8006 struct smbd_lock_element
*e
= &locks
[i
];
8008 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8009 "%llu, file %s timeout = %d\n",
8012 (unsigned long long)e
->smblctx
,
8016 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8017 struct blocking_lock_record
*blr
= NULL
;
8019 if (num_locks
> 1) {
8021 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8022 * if the lock vector contains one entry. When given multiple cancel
8023 * requests in a single PDU we expect the server to return an
8024 * error. Windows servers seem to accept the request but only
8025 * cancel the first lock.
8026 * JRA - Do what Windows does (tm) :-).
8030 /* MS-CIFS (2.2.4.32.1) behavior. */
8031 return NT_STATUS_DOS(ERRDOS
,
8032 ERRcancelviolation
);
8034 /* Windows behavior. */
8036 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8037 "cancel request\n"));
8043 if (lp_blocking_locks(SNUM(conn
))) {
8045 /* Schedule a message to ourselves to
8046 remove the blocking lock record and
8047 return the right error. */
8049 blr
= blocking_lock_cancel_smb1(fsp
,
8055 NT_STATUS_FILE_LOCK_CONFLICT
);
8057 return NT_STATUS_DOS(
8059 ERRcancelviolation
);
8062 /* Remove a matching pending lock. */
8063 status
= do_lock_cancel(fsp
,
8069 bool blocking_lock
= timeout
? true : false;
8070 bool defer_lock
= false;
8071 struct byte_range_lock
*br_lck
;
8072 uint64_t block_smblctx
;
8074 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8085 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8086 /* Windows internal resolution for blocking locks seems
8087 to be about 200ms... Don't wait for less than that. JRA. */
8088 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8089 timeout
= lp_lock_spin_time();
8094 /* If a lock sent with timeout of zero would fail, and
8095 * this lock has been requested multiple times,
8096 * according to brl_lock_failed() we convert this
8097 * request to a blocking lock with a timeout of between
8098 * 150 - 300 milliseconds.
8100 * If lp_lock_spin_time() has been set to 0, we skip
8101 * this blocking retry and fail immediately.
8103 * Replacement for do_lock_spin(). JRA. */
8105 if (!req
->sconn
->using_smb2
&&
8106 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8107 lp_lock_spin_time() && !blocking_lock
&&
8108 NT_STATUS_EQUAL((status
),
8109 NT_STATUS_FILE_LOCK_CONFLICT
))
8112 timeout
= lp_lock_spin_time();
8115 if (br_lck
&& defer_lock
) {
8117 * A blocking lock was requested. Package up
8118 * this smb into a queued request and push it
8119 * onto the blocking lock queue.
8121 if(push_blocking_lock_request(br_lck
,
8132 TALLOC_FREE(br_lck
);
8134 return NT_STATUS_OK
;
8138 TALLOC_FREE(br_lck
);
8141 if (!NT_STATUS_IS_OK(status
)) {
8146 /* If any of the above locks failed, then we must unlock
8147 all of the previous locks (X/Open spec). */
8149 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8151 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8152 i
= -1; /* we want to skip the for loop */
8156 * Ensure we don't do a remove on the lock that just failed,
8157 * as under POSIX rules, if we have a lock already there, we
8158 * will delete it (and we shouldn't) .....
8160 for(i
--; i
>= 0; i
--) {
8161 struct smbd_lock_element
*e
= &locks
[i
];
8163 do_unlock(req
->sconn
->msg_ctx
,
8173 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8174 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8176 return NT_STATUS_OK
;
8179 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8181 uint16_t num_ulocks
,
8182 struct smbd_lock_element
*ulocks
)
8186 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8187 struct smbd_lock_element
*e
= &ulocks
[i
];
8190 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8191 "pid %u, file %s\n", __func__
,
8194 (unsigned int)e
->smblctx
,
8197 if (e
->brltype
!= UNLOCK_LOCK
) {
8198 /* this can only happen with SMB2 */
8199 return NT_STATUS_INVALID_PARAMETER
;
8202 status
= do_unlock(req
->sconn
->msg_ctx
,
8209 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8210 nt_errstr(status
)));
8212 if (!NT_STATUS_IS_OK(status
)) {
8217 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8220 return NT_STATUS_OK
;
8223 /****************************************************************************
8224 Reply to a lockingX request.
8225 ****************************************************************************/
8227 void reply_lockingX(struct smb_request
*req
)
8229 connection_struct
*conn
= req
->conn
;
8231 unsigned char locktype
;
8232 unsigned char oplocklevel
;
8233 uint16_t num_ulocks
;
8235 int32_t lock_timeout
;
8237 const uint8_t *data
;
8238 bool large_file_format
;
8239 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8240 struct smbd_lock_element
*ulocks
;
8241 struct smbd_lock_element
*locks
;
8244 START_PROFILE(SMBlockingX
);
8247 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8248 END_PROFILE(SMBlockingX
);
8252 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8253 locktype
= CVAL(req
->vwv
+3, 0);
8254 oplocklevel
= CVAL(req
->vwv
+3, 1);
8255 num_ulocks
= SVAL(req
->vwv
+6, 0);
8256 num_locks
= SVAL(req
->vwv
+7, 0);
8257 lock_timeout
= IVAL(req
->vwv
+4, 0);
8258 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8260 if (!check_fsp(conn
, req
, fsp
)) {
8261 END_PROFILE(SMBlockingX
);
8267 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8268 /* we don't support these - and CANCEL_LOCK makes w2k
8269 and XP reboot so I don't really want to be
8270 compatible! (tridge) */
8271 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8272 END_PROFILE(SMBlockingX
);
8276 /* Check if this is an oplock break on a file
8277 we have granted an oplock on.
8279 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8280 /* Client can insist on breaking to none. */
8281 bool break_to_none
= (oplocklevel
== 0);
8284 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8285 "for %s\n", (unsigned int)oplocklevel
,
8286 fsp_fnum_dbg(fsp
)));
8289 * Make sure we have granted an exclusive or batch oplock on
8293 if (fsp
->oplock_type
== 0) {
8295 /* The Samba4 nbench simulator doesn't understand
8296 the difference between break to level2 and break
8297 to none from level2 - it sends oplock break
8298 replies in both cases. Don't keep logging an error
8299 message here - just ignore it. JRA. */
8301 DEBUG(5,("reply_lockingX: Error : oplock break from "
8302 "client for %s (oplock=%d) and no "
8303 "oplock granted on this file (%s).\n",
8304 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8307 /* if this is a pure oplock break request then don't
8309 if (num_locks
== 0 && num_ulocks
== 0) {
8310 END_PROFILE(SMBlockingX
);
8313 END_PROFILE(SMBlockingX
);
8314 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8319 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8321 result
= remove_oplock(fsp
);
8323 result
= downgrade_oplock(fsp
);
8327 DEBUG(0, ("reply_lockingX: error in removing "
8328 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8329 /* Hmmm. Is this panic justified? */
8330 smb_panic("internal tdb error");
8333 /* if this is a pure oplock break request then don't send a
8335 if (num_locks
== 0 && num_ulocks
== 0) {
8336 /* Sanity check - ensure a pure oplock break is not a
8338 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8339 DEBUG(0,("reply_lockingX: Error : pure oplock "
8340 "break is a chained %d request !\n",
8341 (unsigned int)CVAL(req
->vwv
+0, 0)));
8343 END_PROFILE(SMBlockingX
);
8349 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8350 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8351 END_PROFILE(SMBlockingX
);
8355 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8356 if (ulocks
== NULL
) {
8357 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8358 END_PROFILE(SMBlockingX
);
8362 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8363 if (locks
== NULL
) {
8364 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8365 END_PROFILE(SMBlockingX
);
8369 /* Data now points at the beginning of the list
8370 of smb_unlkrng structs */
8371 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8372 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8373 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8374 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8375 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8378 /* Now do any requested locks */
8379 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8381 /* Data now points at the beginning of the list
8382 of smb_lkrng structs */
8384 for(i
= 0; i
< (int)num_locks
; i
++) {
8385 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8386 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8387 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8389 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8390 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8391 locks
[i
].brltype
= PENDING_READ_LOCK
;
8393 locks
[i
].brltype
= READ_LOCK
;
8396 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8397 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8399 locks
[i
].brltype
= WRITE_LOCK
;
8404 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8405 if (!NT_STATUS_IS_OK(status
)) {
8406 END_PROFILE(SMBlockingX
);
8407 reply_nterror(req
, status
);
8411 status
= smbd_do_locking(req
, fsp
,
8412 locktype
, lock_timeout
,
8415 if (!NT_STATUS_IS_OK(status
)) {
8416 END_PROFILE(SMBlockingX
);
8417 reply_nterror(req
, status
);
8421 END_PROFILE(SMBlockingX
);
8425 reply_outbuf(req
, 2, 0);
8426 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8427 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8429 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8430 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8432 END_PROFILE(SMBlockingX
);
8436 #define DBGC_CLASS DBGC_ALL
8438 /****************************************************************************
8439 Reply to a SMBreadbmpx (read block multiplex) request.
8440 Always reply with an error, if someone has a platform really needs this,
8441 please contact vl@samba.org
8442 ****************************************************************************/
8444 void reply_readbmpx(struct smb_request
*req
)
8446 START_PROFILE(SMBreadBmpx
);
8447 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8448 END_PROFILE(SMBreadBmpx
);
8452 /****************************************************************************
8453 Reply to a SMBreadbs (read block multiplex secondary) request.
8454 Always reply with an error, if someone has a platform really needs this,
8455 please contact vl@samba.org
8456 ****************************************************************************/
8458 void reply_readbs(struct smb_request
*req
)
8460 START_PROFILE(SMBreadBs
);
8461 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8462 END_PROFILE(SMBreadBs
);
8466 /****************************************************************************
8467 Reply to a SMBsetattrE.
8468 ****************************************************************************/
8470 void reply_setattrE(struct smb_request
*req
)
8472 connection_struct
*conn
= req
->conn
;
8473 struct smb_file_time ft
;
8477 START_PROFILE(SMBsetattrE
);
8481 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8485 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8487 if(!fsp
|| (fsp
->conn
!= conn
)) {
8488 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8493 * Convert the DOS times into unix times.
8496 ft
.atime
= convert_time_t_to_timespec(
8497 srv_make_unix_date2(req
->vwv
+3));
8498 ft
.mtime
= convert_time_t_to_timespec(
8499 srv_make_unix_date2(req
->vwv
+5));
8500 ft
.create_time
= convert_time_t_to_timespec(
8501 srv_make_unix_date2(req
->vwv
+1));
8503 reply_outbuf(req
, 0, 0);
8506 * Patch from Ray Frush <frush@engr.colostate.edu>
8507 * Sometimes times are sent as zero - ignore them.
8510 /* Ensure we have a valid stat struct for the source. */
8511 status
= vfs_stat_fsp(fsp
);
8512 if (!NT_STATUS_IS_OK(status
)) {
8513 reply_nterror(req
, status
);
8517 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8518 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8522 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8523 if (!NT_STATUS_IS_OK(status
)) {
8524 reply_nterror(req
, status
);
8528 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8531 (unsigned int)ft
.atime
.tv_sec
,
8532 (unsigned int)ft
.mtime
.tv_sec
,
8533 (unsigned int)ft
.create_time
.tv_sec
8536 END_PROFILE(SMBsetattrE
);
8541 /* Back from the dead for OS/2..... JRA. */
8543 /****************************************************************************
8544 Reply to a SMBwritebmpx (write block multiplex primary) request.
8545 Always reply with an error, if someone has a platform really needs this,
8546 please contact vl@samba.org
8547 ****************************************************************************/
8549 void reply_writebmpx(struct smb_request
*req
)
8551 START_PROFILE(SMBwriteBmpx
);
8552 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8553 END_PROFILE(SMBwriteBmpx
);
8557 /****************************************************************************
8558 Reply to a SMBwritebs (write block multiplex secondary) request.
8559 Always reply with an error, if someone has a platform really needs this,
8560 please contact vl@samba.org
8561 ****************************************************************************/
8563 void reply_writebs(struct smb_request
*req
)
8565 START_PROFILE(SMBwriteBs
);
8566 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8567 END_PROFILE(SMBwriteBs
);
8571 /****************************************************************************
8572 Reply to a SMBgetattrE.
8573 ****************************************************************************/
8575 void reply_getattrE(struct smb_request
*req
)
8577 connection_struct
*conn
= req
->conn
;
8580 struct timespec create_ts
;
8582 START_PROFILE(SMBgetattrE
);
8585 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8586 END_PROFILE(SMBgetattrE
);
8590 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8592 if(!fsp
|| (fsp
->conn
!= conn
)) {
8593 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8594 END_PROFILE(SMBgetattrE
);
8598 /* Do an fstat on this file */
8600 reply_nterror(req
, map_nt_error_from_unix(errno
));
8601 END_PROFILE(SMBgetattrE
);
8605 mode
= dos_mode(conn
, fsp
->fsp_name
);
8608 * Convert the times into dos times. Set create
8609 * date to be last modify date as UNIX doesn't save
8613 reply_outbuf(req
, 11, 0);
8615 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8616 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8617 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8618 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8619 /* Should we check pending modtime here ? JRA */
8620 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8621 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8623 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8624 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8625 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8627 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8628 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8629 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8631 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8633 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8635 END_PROFILE(SMBgetattrE
);