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 struct smb_filename smb_fname
;
1577 START_PROFILE(SMBdskattr
);
1579 ZERO_STRUCT(smb_fname
);
1580 smb_fname
.base_name
= discard_const_p(char, ".");
1582 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1583 reply_nterror(req
, map_nt_error_from_unix(errno
));
1584 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1585 END_PROFILE(SMBdskattr
);
1589 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1590 if (ret
== (uint64_t)-1) {
1591 reply_nterror(req
, map_nt_error_from_unix(errno
));
1592 END_PROFILE(SMBdskattr
);
1597 * Force max to fit in 16 bit fields.
1599 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1603 if (bsize
> (WORDMAX
*512)) {
1604 bsize
= (WORDMAX
*512);
1605 if (dsize
> WORDMAX
)
1607 if (dfree
> WORDMAX
)
1613 reply_outbuf(req
, 5, 0);
1615 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
1616 double total_space
, free_space
;
1617 /* we need to scale this to a number that DOS6 can handle. We
1618 use floating point so we can handle large drives on systems
1619 that don't have 64 bit integers
1621 we end up displaying a maximum of 2G to DOS systems
1623 total_space
= dsize
* (double)bsize
;
1624 free_space
= dfree
* (double)bsize
;
1626 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1627 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1629 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1630 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1632 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1633 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1634 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1635 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1637 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1638 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1639 SSVAL(req
->outbuf
,smb_vwv2
,512);
1640 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1643 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1645 END_PROFILE(SMBdskattr
);
1650 * Utility function to split the filename from the directory.
1652 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1653 char **fname_dir_out
,
1654 char **fname_mask_out
)
1656 const char *p
= NULL
;
1657 char *fname_dir
= NULL
;
1658 char *fname_mask
= NULL
;
1660 p
= strrchr_m(fname_in
, '/');
1662 fname_dir
= talloc_strdup(ctx
, ".");
1663 fname_mask
= talloc_strdup(ctx
, fname_in
);
1665 fname_dir
= talloc_strndup(ctx
, fname_in
,
1666 PTR_DIFF(p
, fname_in
));
1667 fname_mask
= talloc_strdup(ctx
, p
+1);
1670 if (!fname_dir
|| !fname_mask
) {
1671 TALLOC_FREE(fname_dir
);
1672 TALLOC_FREE(fname_mask
);
1673 return NT_STATUS_NO_MEMORY
;
1676 *fname_dir_out
= fname_dir
;
1677 *fname_mask_out
= fname_mask
;
1678 return NT_STATUS_OK
;
1681 /****************************************************************************
1683 ****************************************************************************/
1685 static bool make_dir_struct(TALLOC_CTX
*ctx
,
1695 char *mask2
= talloc_strdup(ctx
, mask
);
1701 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1705 memset(buf
+1,' ',11);
1706 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
1708 push_ascii(buf
+1,mask2
,8, 0);
1709 push_ascii(buf
+9,p
+1,3, 0);
1712 push_ascii(buf
+1,mask2
,11, 0);
1715 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1717 srv_put_dos_date(buf
,22,date
);
1718 SSVAL(buf
,26,size
& 0xFFFF);
1719 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1720 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1721 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1722 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1723 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1727 /****************************************************************************
1729 Can be called from SMBsearch, SMBffirst or SMBfunique.
1730 ****************************************************************************/
1732 void reply_search(struct smb_request
*req
)
1734 connection_struct
*conn
= req
->conn
;
1737 char *directory
= NULL
;
1738 struct smb_filename
*smb_fname
= NULL
;
1742 struct timespec date
;
1744 unsigned int numentries
= 0;
1745 unsigned int maxentries
= 0;
1746 bool finished
= False
;
1751 bool check_descend
= False
;
1752 bool expect_close
= False
;
1754 bool mask_contains_wcard
= False
;
1755 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1756 TALLOC_CTX
*ctx
= talloc_tos();
1757 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1758 struct dptr_struct
*dirptr
= NULL
;
1759 struct smbXsrv_connection
*xconn
= req
->xconn
;
1760 struct smbd_server_connection
*sconn
= req
->sconn
;
1762 START_PROFILE(SMBsearch
);
1765 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1769 if (req
->posix_pathnames
) {
1770 reply_unknown_new(req
, req
->cmd
);
1774 /* If we were called as SMBffirst then we must expect close. */
1775 if(req
->cmd
== SMBffirst
) {
1776 expect_close
= True
;
1779 reply_outbuf(req
, 1, 3);
1780 maxentries
= SVAL(req
->vwv
+0, 0);
1781 dirtype
= SVAL(req
->vwv
+1, 0);
1782 p
= (const char *)req
->buf
+ 1;
1783 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1784 &nt_status
, &mask_contains_wcard
);
1785 if (!NT_STATUS_IS_OK(nt_status
)) {
1786 reply_nterror(req
, nt_status
);
1791 status_len
= SVAL(p
, 0);
1794 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1796 if (status_len
== 0) {
1797 struct smb_filename
*smb_dname
= NULL
;
1798 uint32_t ucf_flags
= UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
1799 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1800 nt_status
= filename_convert(ctx
, conn
,
1801 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1804 &mask_contains_wcard
,
1806 if (!NT_STATUS_IS_OK(nt_status
)) {
1807 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1808 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1809 ERRSRV
, ERRbadpath
);
1812 reply_nterror(req
, nt_status
);
1816 directory
= smb_fname
->base_name
;
1818 p
= strrchr_m(directory
,'/');
1819 if ((p
!= NULL
) && (*directory
!= '/')) {
1820 mask
= talloc_strdup(ctx
, p
+ 1);
1821 directory
= talloc_strndup(ctx
, directory
,
1822 PTR_DIFF(p
, directory
));
1824 mask
= talloc_strdup(ctx
, directory
);
1825 directory
= talloc_strdup(ctx
,".");
1829 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1833 memset((char *)status
,'\0',21);
1834 SCVAL(status
,0,(dirtype
& 0x1F));
1836 smb_dname
= synthetic_smb_fname(talloc_tos(),
1841 if (smb_dname
== NULL
) {
1842 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1846 nt_status
= dptr_create(conn
,
1854 mask_contains_wcard
,
1858 TALLOC_FREE(smb_dname
);
1860 if (!NT_STATUS_IS_OK(nt_status
)) {
1861 reply_nterror(req
, nt_status
);
1864 dptr_num
= dptr_dnum(dirptr
);
1867 const char *dirpath
;
1869 memcpy(status
,p
,21);
1870 status_dirtype
= CVAL(status
,0) & 0x1F;
1871 if (status_dirtype
!= (dirtype
& 0x1F)) {
1872 dirtype
= status_dirtype
;
1875 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1879 dirpath
= dptr_path(sconn
, dptr_num
);
1880 directory
= talloc_strdup(ctx
, dirpath
);
1882 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1886 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1891 * For a 'continue' search we have no string. So
1892 * check from the initial saved string.
1894 if (!req
->posix_pathnames
) {
1895 mask_contains_wcard
= ms_has_wild(mask
);
1897 dirtype
= dptr_attr(sconn
, dptr_num
);
1900 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1902 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1903 dptr_init_search_op(dirptr
);
1905 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1906 char buf
[DIR_STRUCT_SIZE
];
1907 memcpy(buf
,status
,21);
1908 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1909 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1910 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1913 dptr_fill(sconn
, buf
+12,dptr_num
);
1914 if (dptr_zero(buf
+12) && (status_len
==0)) {
1919 if (message_push_blob(&req
->outbuf
,
1920 data_blob_const(buf
, sizeof(buf
)))
1922 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1927 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1928 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1930 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1932 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1933 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
1934 if (in_list(directory
, lp_dont_descend(ctx
, SNUM(conn
)),True
)) {
1935 check_descend
= True
;
1938 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1939 finished
= !get_dir_entry(ctx
,
1950 char buf
[DIR_STRUCT_SIZE
];
1951 memcpy(buf
,status
,21);
1952 if (!make_dir_struct(ctx
,
1958 convert_timespec_to_time_t(date
),
1959 !allow_long_path_components
)) {
1960 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1963 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1966 if (message_push_blob(&req
->outbuf
,
1967 data_blob_const(buf
, sizeof(buf
)))
1969 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1979 /* If we were called as SMBffirst with smb_search_id == NULL
1980 and no entries were found then return error and close dirptr
1983 if (numentries
== 0) {
1984 dptr_close(sconn
, &dptr_num
);
1985 } else if(expect_close
&& status_len
== 0) {
1986 /* Close the dptr - we know it's gone */
1987 dptr_close(sconn
, &dptr_num
);
1990 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1991 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1992 dptr_close(sconn
, &dptr_num
);
1995 if ((numentries
== 0) && !mask_contains_wcard
) {
1996 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
2000 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
2001 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
2002 SCVAL(smb_buf(req
->outbuf
),0,5);
2003 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
2005 /* The replies here are never long name. */
2006 SSVAL(req
->outbuf
, smb_flg2
,
2007 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
2008 if (!allow_long_path_components
) {
2009 SSVAL(req
->outbuf
, smb_flg2
,
2010 SVAL(req
->outbuf
, smb_flg2
)
2011 & (~FLAGS2_LONG_PATH_COMPONENTS
));
2014 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2015 SSVAL(req
->outbuf
, smb_flg2
,
2016 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
2018 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2019 smb_fn_name(req
->cmd
),
2026 TALLOC_FREE(directory
);
2028 TALLOC_FREE(smb_fname
);
2029 END_PROFILE(SMBsearch
);
2033 /****************************************************************************
2034 Reply to a fclose (stop directory search).
2035 ****************************************************************************/
2037 void reply_fclose(struct smb_request
*req
)
2045 bool path_contains_wcard
= False
;
2046 TALLOC_CTX
*ctx
= talloc_tos();
2047 struct smbd_server_connection
*sconn
= req
->sconn
;
2049 START_PROFILE(SMBfclose
);
2051 if (req
->posix_pathnames
) {
2052 reply_unknown_new(req
, req
->cmd
);
2053 END_PROFILE(SMBfclose
);
2057 p
= (const char *)req
->buf
+ 1;
2058 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
2059 &err
, &path_contains_wcard
);
2060 if (!NT_STATUS_IS_OK(err
)) {
2061 reply_nterror(req
, err
);
2062 END_PROFILE(SMBfclose
);
2066 status_len
= SVAL(p
,0);
2069 if (status_len
== 0) {
2070 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
2071 END_PROFILE(SMBfclose
);
2075 memcpy(status
,p
,21);
2077 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
2078 /* Close the dptr - we know it's gone */
2079 dptr_close(sconn
, &dptr_num
);
2082 reply_outbuf(req
, 1, 0);
2083 SSVAL(req
->outbuf
,smb_vwv0
,0);
2085 DEBUG(3,("search close\n"));
2087 END_PROFILE(SMBfclose
);
2091 /****************************************************************************
2093 ****************************************************************************/
2095 void reply_open(struct smb_request
*req
)
2097 connection_struct
*conn
= req
->conn
;
2098 struct smb_filename
*smb_fname
= NULL
;
2108 uint32_t access_mask
;
2109 uint32_t share_mode
;
2110 uint32_t create_disposition
;
2111 uint32_t create_options
= 0;
2112 uint32_t private_flags
= 0;
2114 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2115 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2116 TALLOC_CTX
*ctx
= talloc_tos();
2118 START_PROFILE(SMBopen
);
2121 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2125 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2126 deny_mode
= SVAL(req
->vwv
+0, 0);
2127 dos_attr
= SVAL(req
->vwv
+1, 0);
2129 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2130 STR_TERMINATE
, &status
);
2131 if (!NT_STATUS_IS_OK(status
)) {
2132 reply_nterror(req
, status
);
2136 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2137 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
2138 &share_mode
, &create_disposition
,
2139 &create_options
, &private_flags
)) {
2140 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2144 status
= filename_convert(ctx
,
2146 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2151 if (!NT_STATUS_IS_OK(status
)) {
2152 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2153 reply_botherror(req
,
2154 NT_STATUS_PATH_NOT_COVERED
,
2155 ERRSRV
, ERRbadpath
);
2158 reply_nterror(req
, status
);
2162 status
= SMB_VFS_CREATE_FILE(
2165 0, /* root_dir_fid */
2166 smb_fname
, /* fname */
2167 access_mask
, /* access_mask */
2168 share_mode
, /* share_access */
2169 create_disposition
, /* create_disposition*/
2170 create_options
, /* create_options */
2171 dos_attr
, /* file_attributes */
2172 oplock_request
, /* oplock_request */
2174 0, /* allocation_size */
2180 NULL
, NULL
); /* create context */
2182 if (!NT_STATUS_IS_OK(status
)) {
2183 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2184 /* We have re-scheduled this call. */
2187 reply_openerror(req
, status
);
2191 /* Ensure we're pointing at the correct stat struct. */
2192 TALLOC_FREE(smb_fname
);
2193 smb_fname
= fsp
->fsp_name
;
2195 size
= smb_fname
->st
.st_ex_size
;
2196 fattr
= dos_mode(conn
, smb_fname
);
2198 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
2200 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2201 DEBUG(3,("attempt to open a directory %s\n",
2203 close_file(req
, fsp
, ERROR_CLOSE
);
2204 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
2205 ERRDOS
, ERRnoaccess
);
2209 reply_outbuf(req
, 7, 0);
2210 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2211 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
2212 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2213 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
2215 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
2217 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
2218 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
2220 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2221 SCVAL(req
->outbuf
,smb_flg
,
2222 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2225 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2226 SCVAL(req
->outbuf
,smb_flg
,
2227 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2230 END_PROFILE(SMBopen
);
2234 /****************************************************************************
2235 Reply to an open and X.
2236 ****************************************************************************/
2238 void reply_open_and_X(struct smb_request
*req
)
2240 connection_struct
*conn
= req
->conn
;
2241 struct smb_filename
*smb_fname
= NULL
;
2243 uint16_t open_flags
;
2246 /* Breakout the oplock request bits so we can set the
2247 reply bits separately. */
2248 int ex_oplock_request
;
2249 int core_oplock_request
;
2252 int smb_sattr
= SVAL(req
->vwv
+4, 0);
2253 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
2261 uint64_t allocation_size
;
2262 ssize_t retval
= -1;
2263 uint32_t access_mask
;
2264 uint32_t share_mode
;
2265 uint32_t create_disposition
;
2266 uint32_t create_options
= 0;
2267 uint32_t private_flags
= 0;
2268 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2269 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2270 TALLOC_CTX
*ctx
= talloc_tos();
2272 START_PROFILE(SMBopenX
);
2274 if (req
->wct
< 15) {
2275 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2279 open_flags
= SVAL(req
->vwv
+2, 0);
2280 deny_mode
= SVAL(req
->vwv
+3, 0);
2281 smb_attr
= SVAL(req
->vwv
+5, 0);
2282 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
2283 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2284 oplock_request
= ex_oplock_request
| core_oplock_request
;
2285 smb_ofun
= SVAL(req
->vwv
+8, 0);
2286 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
2288 /* If it's an IPC, pass off the pipe handler. */
2290 if (lp_nt_pipe_support()) {
2291 reply_open_pipe_and_X(conn
, req
);
2293 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
2298 /* XXXX we need to handle passed times, sattr and flags */
2299 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
2300 STR_TERMINATE
, &status
);
2301 if (!NT_STATUS_IS_OK(status
)) {
2302 reply_nterror(req
, status
);
2306 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
2308 &access_mask
, &share_mode
,
2309 &create_disposition
,
2312 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
2316 status
= filename_convert(ctx
,
2318 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2323 if (!NT_STATUS_IS_OK(status
)) {
2324 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2325 reply_botherror(req
,
2326 NT_STATUS_PATH_NOT_COVERED
,
2327 ERRSRV
, ERRbadpath
);
2330 reply_nterror(req
, status
);
2334 status
= SMB_VFS_CREATE_FILE(
2337 0, /* root_dir_fid */
2338 smb_fname
, /* fname */
2339 access_mask
, /* access_mask */
2340 share_mode
, /* share_access */
2341 create_disposition
, /* create_disposition*/
2342 create_options
, /* create_options */
2343 smb_attr
, /* file_attributes */
2344 oplock_request
, /* oplock_request */
2346 0, /* allocation_size */
2351 &smb_action
, /* pinfo */
2352 NULL
, NULL
); /* create context */
2354 if (!NT_STATUS_IS_OK(status
)) {
2355 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2356 /* We have re-scheduled this call. */
2359 reply_openerror(req
, status
);
2363 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2364 if the file is truncated or created. */
2365 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2366 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2367 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2368 close_file(req
, fsp
, ERROR_CLOSE
);
2369 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2372 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2374 close_file(req
, fsp
, ERROR_CLOSE
);
2375 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2378 status
= vfs_stat_fsp(fsp
);
2379 if (!NT_STATUS_IS_OK(status
)) {
2380 close_file(req
, fsp
, ERROR_CLOSE
);
2381 reply_nterror(req
, status
);
2386 fattr
= dos_mode(conn
, fsp
->fsp_name
);
2387 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2388 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2389 close_file(req
, fsp
, ERROR_CLOSE
);
2390 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2394 /* If the caller set the extended oplock request bit
2395 and we granted one (by whatever means) - set the
2396 correct bit for extended oplock reply.
2399 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2400 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2403 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2404 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2407 /* If the caller set the core oplock request bit
2408 and we granted one (by whatever means) - set the
2409 correct bit for core oplock reply.
2412 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2413 reply_outbuf(req
, 19, 0);
2415 reply_outbuf(req
, 15, 0);
2418 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2419 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2421 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2422 SCVAL(req
->outbuf
, smb_flg
,
2423 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2426 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2427 SCVAL(req
->outbuf
, smb_flg
,
2428 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2431 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2432 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2433 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2434 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2436 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2438 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2439 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2440 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2442 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2443 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2447 TALLOC_FREE(smb_fname
);
2448 END_PROFILE(SMBopenX
);
2452 /****************************************************************************
2453 Reply to a SMBulogoffX.
2454 ****************************************************************************/
2456 void reply_ulogoffX(struct smb_request
*req
)
2458 struct smbd_server_connection
*sconn
= req
->sconn
;
2459 struct user_struct
*vuser
;
2460 struct smbXsrv_session
*session
= NULL
;
2463 START_PROFILE(SMBulogoffX
);
2465 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2468 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2469 (unsigned long long)req
->vuid
));
2471 req
->vuid
= UID_FIELD_INVALID
;
2472 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
2473 END_PROFILE(SMBulogoffX
);
2477 session
= vuser
->session
;
2481 * TODO: cancel all outstanding requests on the session
2483 status
= smbXsrv_session_logoff(session
);
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 DEBUG(0, ("reply_ulogoff: "
2486 "smbXsrv_session_logoff() failed: %s\n",
2487 nt_errstr(status
)));
2489 * If we hit this case, there is something completely
2490 * wrong, so we better disconnect the transport connection.
2492 END_PROFILE(SMBulogoffX
);
2493 exit_server(__location__
": smbXsrv_session_logoff failed");
2497 TALLOC_FREE(session
);
2499 reply_outbuf(req
, 2, 0);
2500 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2501 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2503 DEBUG(3, ("ulogoffX vuid=%llu\n",
2504 (unsigned long long)req
->vuid
));
2506 END_PROFILE(SMBulogoffX
);
2507 req
->vuid
= UID_FIELD_INVALID
;
2510 /****************************************************************************
2511 Reply to a mknew or a create.
2512 ****************************************************************************/
2514 void reply_mknew(struct smb_request
*req
)
2516 connection_struct
*conn
= req
->conn
;
2517 struct smb_filename
*smb_fname
= NULL
;
2520 struct smb_file_time ft
;
2522 int oplock_request
= 0;
2524 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2525 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2526 uint32_t create_disposition
;
2527 uint32_t create_options
= 0;
2528 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2529 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2530 TALLOC_CTX
*ctx
= talloc_tos();
2532 START_PROFILE(SMBcreate
);
2536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2540 fattr
= SVAL(req
->vwv
+0, 0);
2541 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2544 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2546 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2547 STR_TERMINATE
, &status
);
2548 if (!NT_STATUS_IS_OK(status
)) {
2549 reply_nterror(req
, status
);
2553 status
= filename_convert(ctx
,
2555 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2560 if (!NT_STATUS_IS_OK(status
)) {
2561 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2562 reply_botherror(req
,
2563 NT_STATUS_PATH_NOT_COVERED
,
2564 ERRSRV
, ERRbadpath
);
2567 reply_nterror(req
, status
);
2571 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2572 DEBUG(0,("Attempt to create file (%s) with volid set - "
2573 "please report this\n",
2574 smb_fname_str_dbg(smb_fname
)));
2577 if(req
->cmd
== SMBmknew
) {
2578 /* We should fail if file exists. */
2579 create_disposition
= FILE_CREATE
;
2581 /* Create if file doesn't exist, truncate if it does. */
2582 create_disposition
= FILE_OVERWRITE_IF
;
2585 status
= SMB_VFS_CREATE_FILE(
2588 0, /* root_dir_fid */
2589 smb_fname
, /* fname */
2590 access_mask
, /* access_mask */
2591 share_mode
, /* share_access */
2592 create_disposition
, /* create_disposition*/
2593 create_options
, /* create_options */
2594 fattr
, /* file_attributes */
2595 oplock_request
, /* oplock_request */
2597 0, /* allocation_size */
2598 0, /* private_flags */
2603 NULL
, NULL
); /* create context */
2605 if (!NT_STATUS_IS_OK(status
)) {
2606 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2607 /* We have re-scheduled this call. */
2610 reply_openerror(req
, status
);
2614 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2615 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2616 if (!NT_STATUS_IS_OK(status
)) {
2617 END_PROFILE(SMBcreate
);
2621 reply_outbuf(req
, 1, 0);
2622 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2624 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2625 SCVAL(req
->outbuf
,smb_flg
,
2626 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2629 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2630 SCVAL(req
->outbuf
,smb_flg
,
2631 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2634 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2635 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2636 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2637 (unsigned int)fattr
));
2640 TALLOC_FREE(smb_fname
);
2641 END_PROFILE(SMBcreate
);
2645 /****************************************************************************
2646 Reply to a create temporary file.
2647 ****************************************************************************/
2649 void reply_ctemp(struct smb_request
*req
)
2651 connection_struct
*conn
= req
->conn
;
2652 struct smb_filename
*smb_fname
= NULL
;
2653 char *wire_name
= NULL
;
2661 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
2662 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2663 TALLOC_CTX
*ctx
= talloc_tos();
2665 START_PROFILE(SMBctemp
);
2668 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2672 fattr
= SVAL(req
->vwv
+0, 0);
2673 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2675 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2676 STR_TERMINATE
, &status
);
2677 if (!NT_STATUS_IS_OK(status
)) {
2678 reply_nterror(req
, status
);
2682 for (i
= 0; i
< 10; i
++) {
2684 fname
= talloc_asprintf(ctx
,
2687 generate_random_str_list(ctx
, 5, "0123456789"));
2689 fname
= talloc_asprintf(ctx
,
2691 generate_random_str_list(ctx
, 5, "0123456789"));
2695 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2699 status
= filename_convert(ctx
, conn
,
2700 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2705 if (!NT_STATUS_IS_OK(status
)) {
2706 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2707 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2708 ERRSRV
, ERRbadpath
);
2711 reply_nterror(req
, status
);
2715 /* Create the file. */
2716 status
= SMB_VFS_CREATE_FILE(
2719 0, /* root_dir_fid */
2720 smb_fname
, /* fname */
2721 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2722 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2723 FILE_CREATE
, /* create_disposition*/
2724 0, /* create_options */
2725 fattr
, /* file_attributes */
2726 oplock_request
, /* oplock_request */
2728 0, /* allocation_size */
2729 0, /* private_flags */
2734 NULL
, NULL
); /* create context */
2736 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2738 TALLOC_FREE(smb_fname
);
2742 if (!NT_STATUS_IS_OK(status
)) {
2743 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2744 /* We have re-scheduled this call. */
2747 reply_openerror(req
, status
);
2755 /* Collision after 10 times... */
2756 reply_nterror(req
, status
);
2760 reply_outbuf(req
, 1, 0);
2761 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2763 /* the returned filename is relative to the directory */
2764 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2766 s
= fsp
->fsp_name
->base_name
;
2772 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2773 thing in the byte section. JRA */
2774 SSVALS(p
, 0, -1); /* what is this? not in spec */
2776 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2778 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2782 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2783 SCVAL(req
->outbuf
, smb_flg
,
2784 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2787 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2788 SCVAL(req
->outbuf
, smb_flg
,
2789 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2792 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2793 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2794 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2796 TALLOC_FREE(smb_fname
);
2797 TALLOC_FREE(wire_name
);
2798 END_PROFILE(SMBctemp
);
2802 /*******************************************************************
2803 Check if a user is allowed to rename a file.
2804 ********************************************************************/
2806 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2809 if (!CAN_WRITE(conn
)) {
2810 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2813 if ((dirtype
& (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) !=
2814 (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2815 /* Only bother to read the DOS attribute if we might deny the
2816 rename on the grounds of attribute mismatch. */
2817 uint32_t fmode
= dos_mode(conn
, fsp
->fsp_name
);
2818 if ((fmode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
2819 return NT_STATUS_NO_SUCH_FILE
;
2823 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
2824 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) {
2825 return NT_STATUS_OK
;
2828 /* If no pathnames are open below this
2829 directory, allow the rename. */
2831 if (lp_strict_rename(SNUM(conn
))) {
2833 * Strict rename, check open file db.
2835 if (have_file_open_below(fsp
->conn
, fsp
->fsp_name
)) {
2836 return NT_STATUS_ACCESS_DENIED
;
2838 } else if (file_find_subpath(fsp
)) {
2840 * No strict rename, just look in local process.
2842 return NT_STATUS_ACCESS_DENIED
;
2844 return NT_STATUS_OK
;
2847 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2848 return NT_STATUS_OK
;
2851 return NT_STATUS_ACCESS_DENIED
;
2854 /*******************************************************************
2855 * unlink a file with all relevant access checks
2856 *******************************************************************/
2858 static NTSTATUS
do_unlink(connection_struct
*conn
,
2859 struct smb_request
*req
,
2860 struct smb_filename
*smb_fname
,
2865 uint32_t dirtype_orig
= dirtype
;
2868 bool posix_paths
= (req
!= NULL
&& req
->posix_pathnames
);
2870 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2871 smb_fname_str_dbg(smb_fname
),
2874 if (!CAN_WRITE(conn
)) {
2875 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2879 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
2881 ret
= SMB_VFS_STAT(conn
, smb_fname
);
2884 return map_nt_error_from_unix(errno
);
2887 fattr
= dos_mode(conn
, smb_fname
);
2889 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2890 dirtype
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
;
2893 dirtype
&= (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
);
2895 return NT_STATUS_NO_SUCH_FILE
;
2898 if (!dir_check_ftype(fattr
, dirtype
)) {
2899 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2900 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2902 return NT_STATUS_NO_SUCH_FILE
;
2905 if (dirtype_orig
& 0x8000) {
2906 /* These will never be set for POSIX. */
2907 return NT_STATUS_NO_SUCH_FILE
;
2911 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2912 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2915 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2916 return NT_STATUS_NO_SUCH_FILE
;
2919 if (dirtype
& 0xFF00) {
2920 /* These will never be set for POSIX. */
2921 return NT_STATUS_NO_SUCH_FILE
;
2926 return NT_STATUS_NO_SUCH_FILE
;
2929 /* Can't delete a directory. */
2930 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2931 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2936 else if (dirtype
& FILE_ATTRIBUTE_DIRECTORY
) /* Asked for a directory and it isn't. */
2937 return NT_STATUS_OBJECT_NAME_INVALID
;
2938 #endif /* JRATEST */
2940 /* On open checks the open itself will check the share mode, so
2941 don't do it here as we'll get it wrong. */
2943 status
= SMB_VFS_CREATE_FILE
2946 0, /* root_dir_fid */
2947 smb_fname
, /* fname */
2948 DELETE_ACCESS
, /* access_mask */
2949 FILE_SHARE_NONE
, /* share_access */
2950 FILE_OPEN
, /* create_disposition*/
2951 FILE_NON_DIRECTORY_FILE
, /* create_options */
2952 /* file_attributes */
2953 posix_paths
? FILE_FLAG_POSIX_SEMANTICS
|0777 :
2954 FILE_ATTRIBUTE_NORMAL
,
2955 0, /* oplock_request */
2957 0, /* allocation_size */
2958 0, /* private_flags */
2963 NULL
, NULL
); /* create context */
2965 if (!NT_STATUS_IS_OK(status
)) {
2966 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2967 nt_errstr(status
)));
2971 status
= can_set_delete_on_close(fsp
, fattr
);
2972 if (!NT_STATUS_IS_OK(status
)) {
2973 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2975 smb_fname_str_dbg(smb_fname
),
2976 nt_errstr(status
)));
2977 close_file(req
, fsp
, NORMAL_CLOSE
);
2981 /* The set is across all open files on this dev/inode pair. */
2982 if (!set_delete_on_close(fsp
, True
,
2983 conn
->session_info
->security_token
,
2984 conn
->session_info
->unix_token
)) {
2985 close_file(req
, fsp
, NORMAL_CLOSE
);
2986 return NT_STATUS_ACCESS_DENIED
;
2989 return close_file(req
, fsp
, NORMAL_CLOSE
);
2992 /****************************************************************************
2993 The guts of the unlink command, split out so it may be called by the NT SMB
2995 ****************************************************************************/
2997 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2998 uint32_t dirtype
, struct smb_filename
*smb_fname
,
3001 char *fname_dir
= NULL
;
3002 char *fname_mask
= NULL
;
3004 NTSTATUS status
= NT_STATUS_OK
;
3005 struct smb_filename
*smb_fname_dir
= NULL
;
3006 TALLOC_CTX
*ctx
= talloc_tos();
3008 /* Split up the directory from the filename/mask. */
3009 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
3010 &fname_dir
, &fname_mask
);
3011 if (!NT_STATUS_IS_OK(status
)) {
3016 * We should only check the mangled cache
3017 * here if unix_convert failed. This means
3018 * that the path in 'mask' doesn't exist
3019 * on the file system and so we need to look
3020 * for a possible mangle. This patch from
3021 * Tine Smukavec <valentin.smukavec@hermes.si>.
3024 if (!VALID_STAT(smb_fname
->st
) &&
3025 mangle_is_mangled(fname_mask
, conn
->params
)) {
3026 char *new_mask
= NULL
;
3027 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
3028 &new_mask
, conn
->params
);
3030 TALLOC_FREE(fname_mask
);
3031 fname_mask
= new_mask
;
3038 * Only one file needs to be unlinked. Append the mask back
3039 * onto the directory.
3041 TALLOC_FREE(smb_fname
->base_name
);
3042 if (ISDOT(fname_dir
)) {
3043 /* Ensure we use canonical names on open. */
3044 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3048 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
3053 if (!smb_fname
->base_name
) {
3054 status
= NT_STATUS_NO_MEMORY
;
3058 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3061 status
= check_name(conn
, smb_fname
->base_name
);
3062 if (!NT_STATUS_IS_OK(status
)) {
3066 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3067 if (!NT_STATUS_IS_OK(status
)) {
3073 struct smb_Dir
*dir_hnd
= NULL
;
3075 const char *dname
= NULL
;
3076 char *talloced
= NULL
;
3078 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == FILE_ATTRIBUTE_DIRECTORY
) {
3079 status
= NT_STATUS_OBJECT_NAME_INVALID
;
3083 dirtype
= FILE_ATTRIBUTE_NORMAL
;
3086 if (strequal(fname_mask
,"????????.???")) {
3087 TALLOC_FREE(fname_mask
);
3088 fname_mask
= talloc_strdup(ctx
, "*");
3090 status
= NT_STATUS_NO_MEMORY
;
3095 status
= check_name(conn
, fname_dir
);
3096 if (!NT_STATUS_IS_OK(status
)) {
3100 smb_fname_dir
= synthetic_smb_fname(talloc_tos(),
3105 if (smb_fname_dir
== NULL
) {
3106 status
= NT_STATUS_NO_MEMORY
;
3110 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_dir
, fname_mask
,
3112 if (dir_hnd
== NULL
) {
3113 status
= map_nt_error_from_unix(errno
);
3117 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3118 the pattern matches against the long name, otherwise the short name
3119 We don't implement this yet XXXX
3122 status
= NT_STATUS_NO_SUCH_FILE
;
3124 while ((dname
= ReadDirName(dir_hnd
, &offset
,
3125 &smb_fname
->st
, &talloced
))) {
3126 TALLOC_CTX
*frame
= talloc_stackframe();
3128 if (!is_visible_file(conn
, fname_dir
, dname
,
3129 &smb_fname
->st
, true)) {
3131 TALLOC_FREE(talloced
);
3135 /* Quick check for "." and ".." */
3136 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
3138 TALLOC_FREE(talloced
);
3142 if(!mask_match(dname
, fname_mask
,
3143 conn
->case_sensitive
)) {
3145 TALLOC_FREE(talloced
);
3149 TALLOC_FREE(smb_fname
->base_name
);
3150 if (ISDOT(fname_dir
)) {
3151 /* Ensure we use canonical names on open. */
3152 smb_fname
->base_name
=
3153 talloc_asprintf(smb_fname
, "%s",
3156 smb_fname
->base_name
=
3157 talloc_asprintf(smb_fname
, "%s/%s",
3161 if (!smb_fname
->base_name
) {
3162 TALLOC_FREE(dir_hnd
);
3163 status
= NT_STATUS_NO_MEMORY
;
3165 TALLOC_FREE(talloced
);
3169 status
= check_name(conn
, smb_fname
->base_name
);
3170 if (!NT_STATUS_IS_OK(status
)) {
3171 TALLOC_FREE(dir_hnd
);
3173 TALLOC_FREE(talloced
);
3177 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
3178 if (!NT_STATUS_IS_OK(status
)) {
3179 TALLOC_FREE(dir_hnd
);
3181 TALLOC_FREE(talloced
);
3186 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3187 smb_fname
->base_name
));
3190 TALLOC_FREE(talloced
);
3192 TALLOC_FREE(dir_hnd
);
3195 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
3196 status
= map_nt_error_from_unix(errno
);
3200 TALLOC_FREE(smb_fname_dir
);
3201 TALLOC_FREE(fname_dir
);
3202 TALLOC_FREE(fname_mask
);
3206 /****************************************************************************
3208 ****************************************************************************/
3210 void reply_unlink(struct smb_request
*req
)
3212 connection_struct
*conn
= req
->conn
;
3214 struct smb_filename
*smb_fname
= NULL
;
3217 bool path_contains_wcard
= False
;
3218 uint32_t ucf_flags
= UCF_COND_ALLOW_WCARD_LCOMP
|
3219 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
3220 TALLOC_CTX
*ctx
= talloc_tos();
3222 START_PROFILE(SMBunlink
);
3225 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3229 dirtype
= SVAL(req
->vwv
+0, 0);
3231 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
3232 STR_TERMINATE
, &status
,
3233 &path_contains_wcard
);
3234 if (!NT_STATUS_IS_OK(status
)) {
3235 reply_nterror(req
, status
);
3239 status
= filename_convert(ctx
, conn
,
3240 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
3243 &path_contains_wcard
,
3245 if (!NT_STATUS_IS_OK(status
)) {
3246 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
3247 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
3248 ERRSRV
, ERRbadpath
);
3251 reply_nterror(req
, status
);
3255 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
3257 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
3258 path_contains_wcard
);
3259 if (!NT_STATUS_IS_OK(status
)) {
3260 if (open_was_deferred(req
->xconn
, req
->mid
)) {
3261 /* We have re-scheduled this call. */
3264 reply_nterror(req
, status
);
3268 reply_outbuf(req
, 0, 0);
3270 TALLOC_FREE(smb_fname
);
3271 END_PROFILE(SMBunlink
);
3275 /****************************************************************************
3277 ****************************************************************************/
3279 static void fail_readraw(void)
3281 const char *errstr
= talloc_asprintf(talloc_tos(),
3282 "FAIL ! reply_readbraw: socket write fail (%s)",
3287 exit_server_cleanly(errstr
);
3290 /****************************************************************************
3291 Fake (read/write) sendfile. Returns -1 on read or write fail.
3292 ****************************************************************************/
3294 ssize_t
fake_sendfile(struct smbXsrv_connection
*xconn
, files_struct
*fsp
,
3295 off_t startpos
, size_t nread
)
3298 size_t tosend
= nread
;
3305 bufsize
= MIN(nread
, 65536);
3307 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
3311 while (tosend
> 0) {
3315 cur_read
= MIN(tosend
, bufsize
);
3316 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
3322 /* If we had a short read, fill with zeros. */
3323 if (ret
< cur_read
) {
3324 memset(buf
+ ret
, '\0', cur_read
- ret
);
3327 ret
= write_data(xconn
->transport
.sock
, buf
, cur_read
);
3328 if (ret
!= cur_read
) {
3329 int saved_errno
= errno
;
3331 * Try and give an error message saying what
3334 DEBUG(0, ("write_data failed for client %s. "
3336 smbXsrv_connection_dbg(xconn
),
3337 strerror(saved_errno
)));
3339 errno
= saved_errno
;
3343 startpos
+= cur_read
;
3347 return (ssize_t
)nread
;
3350 /****************************************************************************
3351 Deal with the case of sendfile reading less bytes from the file than
3352 requested. Fill with zeros (all we can do). Returns 0 on success
3353 ****************************************************************************/
3355 ssize_t
sendfile_short_send(struct smbXsrv_connection
*xconn
,
3361 #define SHORT_SEND_BUFSIZE 1024
3362 if (nread
< headersize
) {
3363 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3364 "header for file %s (%s). Terminating\n",
3365 fsp_str_dbg(fsp
), strerror(errno
)));
3369 nread
-= headersize
;
3371 if (nread
< smb_maxcnt
) {
3372 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
3374 DEBUG(0,("sendfile_short_send: malloc failed "
3375 "for file %s (%s). Terminating\n",
3376 fsp_str_dbg(fsp
), strerror(errno
)));
3380 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3381 "with zeros !\n", fsp_str_dbg(fsp
)));
3383 while (nread
< smb_maxcnt
) {
3385 * We asked for the real file size and told sendfile
3386 * to not go beyond the end of the file. But it can
3387 * happen that in between our fstat call and the
3388 * sendfile call the file was truncated. This is very
3389 * bad because we have already announced the larger
3390 * number of bytes to the client.
3392 * The best we can do now is to send 0-bytes, just as
3393 * a read from a hole in a sparse file would do.
3395 * This should happen rarely enough that I don't care
3396 * about efficiency here :-)
3401 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
3402 ret
= write_data(xconn
->transport
.sock
, buf
, to_write
);
3403 if (ret
!= to_write
) {
3404 int saved_errno
= errno
;
3406 * Try and give an error message saying what
3409 DEBUG(0, ("write_data failed for client %s. "
3411 smbXsrv_connection_dbg(xconn
),
3412 strerror(saved_errno
)));
3413 errno
= saved_errno
;
3424 /****************************************************************************
3425 Return a readbraw error (4 bytes of zero).
3426 ****************************************************************************/
3428 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
3434 smbd_lock_socket(xconn
);
3435 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
3436 int saved_errno
= errno
;
3438 * Try and give an error message saying what
3441 DEBUG(0, ("write_data failed for client %s. "
3443 smbXsrv_connection_dbg(xconn
),
3444 strerror(saved_errno
)));
3445 errno
= saved_errno
;
3449 smbd_unlock_socket(xconn
);
3452 /****************************************************************************
3453 Use sendfile in readbraw.
3454 ****************************************************************************/
3456 static void send_file_readbraw(connection_struct
*conn
,
3457 struct smb_request
*req
,
3463 struct smbXsrv_connection
*xconn
= req
->xconn
;
3464 char *outbuf
= NULL
;
3468 * We can only use sendfile on a non-chained packet
3469 * but we can use on a non-oplocked file. tridge proved this
3470 * on a train in Germany :-). JRA.
3471 * reply_readbraw has already checked the length.
3474 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
3475 (fsp
->wcp
== NULL
) &&
3476 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3477 ssize_t sendfile_read
= -1;
3479 DATA_BLOB header_blob
;
3481 _smb_setlen(header
,nread
);
3482 header_blob
= data_blob_const(header
, 4);
3484 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
3485 &header_blob
, startpos
,
3487 if (sendfile_read
== -1) {
3488 /* Returning ENOSYS means no data at all was sent.
3489 * Do this as a normal read. */
3490 if (errno
== ENOSYS
) {
3491 goto normal_readbraw
;
3495 * Special hack for broken Linux with no working sendfile. If we
3496 * return EINTR we sent the header but not the rest of the data.
3497 * Fake this up by doing read/write calls.
3499 if (errno
== EINTR
) {
3500 /* Ensure we don't do this again. */
3501 set_use_sendfile(SNUM(conn
), False
);
3502 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3504 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
3505 DEBUG(0,("send_file_readbraw: "
3506 "fake_sendfile failed for "
3510 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3515 DEBUG(0,("send_file_readbraw: sendfile failed for "
3516 "file %s (%s). Terminating\n",
3517 fsp_str_dbg(fsp
), strerror(errno
)));
3518 exit_server_cleanly("send_file_readbraw sendfile failed");
3519 } else if (sendfile_read
== 0) {
3521 * Some sendfile implementations return 0 to indicate
3522 * that there was a short read, but nothing was
3523 * actually written to the socket. In this case,
3524 * fallback to the normal read path so the header gets
3525 * the correct byte count.
3527 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3528 "bytes falling back to the normal read: "
3529 "%s\n", fsp_str_dbg(fsp
)));
3530 goto normal_readbraw
;
3533 /* Deal with possible short send. */
3534 if (sendfile_read
!= 4+nread
) {
3535 ret
= sendfile_short_send(xconn
, fsp
,
3536 sendfile_read
, 4, nread
);
3546 outbuf
= talloc_array(NULL
, char, nread
+4);
3548 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3549 (unsigned)(nread
+4)));
3550 reply_readbraw_error(xconn
);
3555 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
3556 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3565 _smb_setlen(outbuf
,ret
);
3566 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
3567 int saved_errno
= errno
;
3569 * Try and give an error message saying what
3572 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3573 smbXsrv_connection_dbg(xconn
),
3574 strerror(saved_errno
)));
3575 errno
= saved_errno
;
3580 TALLOC_FREE(outbuf
);
3583 /****************************************************************************
3584 Reply to a readbraw (core+ protocol).
3585 ****************************************************************************/
3587 void reply_readbraw(struct smb_request
*req
)
3589 connection_struct
*conn
= req
->conn
;
3590 struct smbXsrv_connection
*xconn
= req
->xconn
;
3591 ssize_t maxcount
,mincount
;
3595 struct lock_struct lock
;
3598 START_PROFILE(SMBreadbraw
);
3600 if (srv_is_signing_active(xconn
) || req
->encrypted
) {
3601 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3602 "raw reads/writes are disallowed.");
3606 reply_readbraw_error(xconn
);
3607 END_PROFILE(SMBreadbraw
);
3611 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3612 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3613 "'async smb echo handler = yes'\n"));
3614 reply_readbraw_error(xconn
);
3615 END_PROFILE(SMBreadbraw
);
3620 * Special check if an oplock break has been issued
3621 * and the readraw request croses on the wire, we must
3622 * return a zero length response here.
3625 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3628 * We have to do a check_fsp by hand here, as
3629 * we must always return 4 zero bytes on error,
3633 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3634 req
->vuid
!= fsp
->vuid
||
3635 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3637 * fsp could be NULL here so use the value from the packet. JRA.
3639 DEBUG(3,("reply_readbraw: fnum %d not valid "
3641 (int)SVAL(req
->vwv
+0, 0)));
3642 reply_readbraw_error(xconn
);
3643 END_PROFILE(SMBreadbraw
);
3647 /* Do a "by hand" version of CHECK_READ. */
3648 if (!(fsp
->can_read
||
3649 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3650 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3651 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3652 (int)SVAL(req
->vwv
+0, 0)));
3653 reply_readbraw_error(xconn
);
3654 END_PROFILE(SMBreadbraw
);
3658 flush_write_cache(fsp
, SAMBA_READRAW_FLUSH
);
3660 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3661 if(req
->wct
== 10) {
3663 * This is a large offset (64 bit) read.
3666 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3669 DEBUG(0,("reply_readbraw: negative 64 bit "
3670 "readraw offset (%.0f) !\n",
3671 (double)startpos
));
3672 reply_readbraw_error(xconn
);
3673 END_PROFILE(SMBreadbraw
);
3678 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3679 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3681 /* ensure we don't overrun the packet size */
3682 maxcount
= MIN(65535,maxcount
);
3684 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3685 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3688 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3689 reply_readbraw_error(xconn
);
3690 END_PROFILE(SMBreadbraw
);
3694 if (fsp_stat(fsp
) == 0) {
3695 size
= fsp
->fsp_name
->st
.st_ex_size
;
3698 if (startpos
>= size
) {
3701 nread
= MIN(maxcount
,(size
- startpos
));
3704 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3705 if (nread
< mincount
)
3709 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3710 "min=%lu nread=%lu\n",
3711 fsp_fnum_dbg(fsp
), (double)startpos
,
3712 (unsigned long)maxcount
,
3713 (unsigned long)mincount
,
3714 (unsigned long)nread
) );
3716 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3718 DEBUG(5,("reply_readbraw finished\n"));
3720 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3722 END_PROFILE(SMBreadbraw
);
3727 #define DBGC_CLASS DBGC_LOCKING
3729 /****************************************************************************
3730 Reply to a lockread (core+ protocol).
3731 ****************************************************************************/
3733 void reply_lockread(struct smb_request
*req
)
3735 connection_struct
*conn
= req
->conn
;
3743 struct byte_range_lock
*br_lck
= NULL
;
3745 struct smbXsrv_connection
*xconn
= req
->xconn
;
3747 START_PROFILE(SMBlockread
);
3750 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3751 END_PROFILE(SMBlockread
);
3755 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3757 if (!check_fsp(conn
, req
, fsp
)) {
3758 END_PROFILE(SMBlockread
);
3762 if (!CHECK_READ(fsp
,req
)) {
3763 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3764 END_PROFILE(SMBlockread
);
3768 numtoread
= SVAL(req
->vwv
+1, 0);
3769 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3772 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3773 * protocol request that predates the read/write lock concept.
3774 * Thus instead of asking for a read lock here we need to ask
3775 * for a write lock. JRA.
3776 * Note that the requested lock size is unaffected by max_send.
3779 br_lck
= do_lock(req
->sconn
->msg_ctx
,
3781 (uint64_t)req
->smbpid
,
3782 (uint64_t)numtoread
,
3786 False
, /* Non-blocking lock. */
3789 TALLOC_FREE(br_lck
);
3791 if (NT_STATUS_V(status
)) {
3792 reply_nterror(req
, status
);
3793 END_PROFILE(SMBlockread
);
3798 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3800 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3802 if (numtoread
> maxtoread
) {
3803 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3804 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3805 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3806 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3807 numtoread
= maxtoread
;
3810 reply_outbuf(req
, 5, numtoread
+ 3);
3812 data
= smb_buf(req
->outbuf
) + 3;
3814 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3817 reply_nterror(req
, map_nt_error_from_unix(errno
));
3818 END_PROFILE(SMBlockread
);
3822 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3824 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3825 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3826 p
= smb_buf(req
->outbuf
);
3827 SCVAL(p
,0,0); /* pad byte. */
3830 DEBUG(3,("lockread %s num=%d nread=%d\n",
3831 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3833 END_PROFILE(SMBlockread
);
3838 #define DBGC_CLASS DBGC_ALL
3840 /****************************************************************************
3842 ****************************************************************************/
3844 void reply_read(struct smb_request
*req
)
3846 connection_struct
*conn
= req
->conn
;
3853 struct lock_struct lock
;
3854 struct smbXsrv_connection
*xconn
= req
->xconn
;
3856 START_PROFILE(SMBread
);
3859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3860 END_PROFILE(SMBread
);
3864 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3866 if (!check_fsp(conn
, req
, fsp
)) {
3867 END_PROFILE(SMBread
);
3871 if (!CHECK_READ(fsp
,req
)) {
3872 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3873 END_PROFILE(SMBread
);
3877 numtoread
= SVAL(req
->vwv
+1, 0);
3878 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3881 * The requested read size cannot be greater than max_send. JRA.
3883 maxtoread
= xconn
->smb1
.sessions
.max_send
- (smb_size
+ 5*2 + 3);
3885 if (numtoread
> maxtoread
) {
3886 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3887 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3888 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3889 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3890 numtoread
= maxtoread
;
3893 reply_outbuf(req
, 5, numtoread
+3);
3895 data
= smb_buf(req
->outbuf
) + 3;
3897 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3898 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3901 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3902 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3903 END_PROFILE(SMBread
);
3908 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3911 reply_nterror(req
, map_nt_error_from_unix(errno
));
3915 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3917 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3918 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3919 SCVAL(smb_buf(req
->outbuf
),0,1);
3920 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3922 DEBUG(3, ("read %s num=%d nread=%d\n",
3923 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3926 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3928 END_PROFILE(SMBread
);
3932 /****************************************************************************
3934 ****************************************************************************/
3936 int setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3940 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3943 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3945 SCVAL(outbuf
,smb_vwv0
,0xFF);
3946 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3947 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3948 SSVAL(outbuf
,smb_vwv6
,
3949 (smb_wct
- 4) /* offset from smb header to wct */
3950 + 1 /* the wct field */
3951 + 12 * sizeof(uint16_t) /* vwv */
3952 + 2 /* the buflen field */
3953 + 1); /* padding byte */
3954 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3955 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3956 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3957 _smb_setlen_large(outbuf
,
3958 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3962 /****************************************************************************
3963 Reply to a read and X - possibly using sendfile.
3964 ****************************************************************************/
3966 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3967 files_struct
*fsp
, off_t startpos
,
3970 struct smbXsrv_connection
*xconn
= req
->xconn
;
3972 struct lock_struct lock
;
3973 int saved_errno
= 0;
3975 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
3976 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3979 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3980 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3985 * We can only use sendfile on a non-chained packet
3986 * but we can use on a non-oplocked file. tridge proved this
3987 * on a train in Germany :-). JRA.
3990 if (!req_is_in_chain(req
) &&
3992 (fsp
->base_fsp
== NULL
) &&
3993 (fsp
->wcp
== NULL
) &&
3994 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3995 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3998 if(fsp_stat(fsp
) == -1) {
3999 reply_nterror(req
, map_nt_error_from_unix(errno
));
4003 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4004 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4005 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4007 * We already know that we would do a short read, so don't
4008 * try the sendfile() path.
4010 goto nosendfile_read
;
4014 * Set up the packet header before send. We
4015 * assume here the sendfile will work (get the
4016 * correct amount of data).
4019 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
4021 construct_reply_common_req(req
, (char *)headerbuf
);
4022 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4024 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
4025 startpos
, smb_maxcnt
);
4027 saved_errno
= errno
;
4029 /* Returning ENOSYS means no data at all was sent.
4030 Do this as a normal read. */
4031 if (errno
== ENOSYS
) {
4036 * Special hack for broken Linux with no working sendfile. If we
4037 * return EINTR we sent the header but not the rest of the data.
4038 * Fake this up by doing read/write calls.
4041 if (errno
== EINTR
) {
4042 /* Ensure we don't do this again. */
4043 set_use_sendfile(SNUM(conn
), False
);
4044 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4045 nread
= fake_sendfile(xconn
, fsp
, startpos
,
4048 saved_errno
= errno
;
4049 DEBUG(0,("send_file_readX: "
4050 "fake_sendfile failed for "
4051 "file %s (%s) for client %s. "
4054 smbXsrv_connection_dbg(xconn
),
4055 strerror(saved_errno
)));
4056 errno
= saved_errno
;
4057 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4059 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4060 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4061 /* No outbuf here means successful sendfile. */
4065 DEBUG(0,("send_file_readX: sendfile failed for file "
4066 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
4068 exit_server_cleanly("send_file_readX sendfile failed");
4069 } else if (nread
== 0) {
4071 * Some sendfile implementations return 0 to indicate
4072 * that there was a short read, but nothing was
4073 * actually written to the socket. In this case,
4074 * fallback to the normal read path so the header gets
4075 * the correct byte count.
4077 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4078 "falling back to the normal read: %s\n",
4083 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4084 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4086 /* Deal with possible short send. */
4087 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
4090 ret
= sendfile_short_send(xconn
, fsp
, nread
,
4091 sizeof(headerbuf
), smb_maxcnt
);
4094 r
= "send_file_readX: sendfile_short_send failed";
4095 DEBUG(0,("%s for file %s (%s).\n",
4096 r
, fsp_str_dbg(fsp
), strerror(errno
)));
4097 exit_server_cleanly(r
);
4100 /* No outbuf here means successful sendfile. */
4101 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
4102 SMB_PERFCOUNT_END(&req
->pcd
);
4108 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
4109 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
4112 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
4113 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
4114 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
4116 * We already know that we would do a short
4117 * read, so don't try the sendfile() path.
4119 goto nosendfile_read
;
4122 construct_reply_common_req(req
, (char *)headerbuf
);
4123 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
4125 /* Send out the header. */
4126 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
4128 if (ret
!= sizeof(headerbuf
)) {
4129 saved_errno
= errno
;
4131 * Try and give an error message saying what
4134 DEBUG(0,("send_file_readX: write_data 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 sendfile failed");
4142 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
4144 saved_errno
= errno
;
4145 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4146 "%s (%s) for client %s. Terminating\n",
4148 smbXsrv_connection_dbg(xconn
),
4149 strerror(saved_errno
)));
4150 errno
= saved_errno
;
4151 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4158 reply_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
4159 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4160 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4162 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
4163 startpos
, smb_maxcnt
);
4164 saved_errno
= errno
;
4166 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4169 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4173 setup_readX_header((char *)req
->outbuf
, nread
);
4175 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4176 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
4180 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4181 TALLOC_FREE(req
->outbuf
);
4185 /****************************************************************************
4186 Work out how much space we have for a read return.
4187 ****************************************************************************/
4189 static size_t calc_max_read_pdu(const struct smb_request
*req
)
4191 struct smbXsrv_connection
*xconn
= req
->xconn
;
4193 if (xconn
->protocol
< PROTOCOL_NT1
) {
4194 return xconn
->smb1
.sessions
.max_send
;
4197 if (!lp_large_readwrite()) {
4198 return xconn
->smb1
.sessions
.max_send
;
4201 if (req_is_in_chain(req
)) {
4202 return xconn
->smb1
.sessions
.max_send
;
4205 if (req
->encrypted
) {
4207 * Don't take encrypted traffic up to the
4208 * limit. There are padding considerations
4209 * that make that tricky.
4211 return xconn
->smb1
.sessions
.max_send
;
4214 if (srv_is_signing_active(xconn
)) {
4218 if (!lp_unix_extensions()) {
4223 * We can do ultra-large POSIX reads.
4228 /****************************************************************************
4229 Calculate how big a read can be. Copes with all clients. It's always
4230 safe to return a short read - Windows does this.
4231 ****************************************************************************/
4233 static size_t calc_read_size(const struct smb_request
*req
,
4237 struct smbXsrv_connection
*xconn
= req
->xconn
;
4238 size_t max_pdu
= calc_max_read_pdu(req
);
4239 size_t total_size
= 0;
4240 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
4241 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
4244 * Windows explicitly ignores upper size of 0xFFFF.
4245 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4246 * We must do the same as these will never fit even in
4247 * an extended size NetBIOS packet.
4249 if (upper_size
== 0xFFFF) {
4253 if (xconn
->protocol
< PROTOCOL_NT1
) {
4257 total_size
= ((upper_size
<<16) | lower_size
);
4260 * LARGE_READX test shows it's always safe to return
4261 * a short read. Windows does so.
4263 return MIN(total_size
, max_len
);
4266 /****************************************************************************
4267 Reply to a read and X.
4268 ****************************************************************************/
4270 void reply_read_and_X(struct smb_request
*req
)
4272 connection_struct
*conn
= req
->conn
;
4277 bool big_readX
= False
;
4279 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
4282 START_PROFILE(SMBreadX
);
4284 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
4285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4289 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4290 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4291 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
4293 /* If it's an IPC, pass off the pipe handler. */
4295 reply_pipe_read_and_X(req
);
4296 END_PROFILE(SMBreadX
);
4300 if (!check_fsp(conn
, req
, fsp
)) {
4301 END_PROFILE(SMBreadX
);
4305 if (!CHECK_READ(fsp
,req
)) {
4306 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4307 END_PROFILE(SMBreadX
);
4311 upper_size
= SVAL(req
->vwv
+7, 0);
4312 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
4313 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
4315 * This is a heuristic to avoid keeping large
4316 * outgoing buffers around over long-lived aio
4322 if (req
->wct
== 12) {
4324 * This is a large offset (64 bit) read.
4326 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
4331 NTSTATUS status
= schedule_aio_read_and_X(conn
,
4336 if (NT_STATUS_IS_OK(status
)) {
4337 /* Read scheduled - we're done. */
4340 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4341 /* Real error - report to client. */
4342 END_PROFILE(SMBreadX
);
4343 reply_nterror(req
, status
);
4346 /* NT_STATUS_RETRY - fall back to sync read. */
4349 smbd_lock_socket(req
->xconn
);
4350 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
4351 smbd_unlock_socket(req
->xconn
);
4354 END_PROFILE(SMBreadX
);
4358 /****************************************************************************
4359 Error replies to writebraw must have smb_wct == 1. Fix this up.
4360 ****************************************************************************/
4362 void error_to_writebrawerr(struct smb_request
*req
)
4364 uint8_t *old_outbuf
= req
->outbuf
;
4366 reply_outbuf(req
, 1, 0);
4368 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
4369 TALLOC_FREE(old_outbuf
);
4372 /****************************************************************************
4373 Read 4 bytes of a smb packet and return the smb length of the packet.
4374 Store the result in the buffer. This version of the function will
4375 never return a session keepalive (length of zero).
4376 Timeout is in milliseconds.
4377 ****************************************************************************/
4379 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
4382 uint8_t msgtype
= NBSSkeepalive
;
4384 while (msgtype
== NBSSkeepalive
) {
4387 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
4389 if (!NT_STATUS_IS_OK(status
)) {
4390 char addr
[INET6_ADDRSTRLEN
];
4391 /* Try and give an error message
4392 * saying what client failed. */
4393 DEBUG(0, ("read_fd_with_timeout failed for "
4394 "client %s read error = %s.\n",
4395 get_peer_addr(fd
,addr
,sizeof(addr
)),
4396 nt_errstr(status
)));
4400 msgtype
= CVAL(inbuf
, 0);
4403 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4404 (unsigned long)len
));
4406 return NT_STATUS_OK
;
4409 /****************************************************************************
4410 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4411 ****************************************************************************/
4413 void reply_writebraw(struct smb_request
*req
)
4415 connection_struct
*conn
= req
->conn
;
4416 struct smbXsrv_connection
*xconn
= req
->xconn
;
4419 ssize_t total_written
=0;
4420 size_t numtowrite
=0;
4423 const char *data
=NULL
;
4426 struct lock_struct lock
;
4429 START_PROFILE(SMBwritebraw
);
4432 * If we ever reply with an error, it must have the SMB command
4433 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4436 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
4438 if (srv_is_signing_active(xconn
)) {
4439 END_PROFILE(SMBwritebraw
);
4440 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4441 "raw reads/writes are disallowed.");
4444 if (req
->wct
< 12) {
4445 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4446 error_to_writebrawerr(req
);
4447 END_PROFILE(SMBwritebraw
);
4451 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4452 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4453 "'async smb echo handler = yes'\n"));
4454 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
4455 error_to_writebrawerr(req
);
4456 END_PROFILE(SMBwritebraw
);
4460 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4461 if (!check_fsp(conn
, req
, fsp
)) {
4462 error_to_writebrawerr(req
);
4463 END_PROFILE(SMBwritebraw
);
4467 if (!CHECK_WRITE(fsp
)) {
4468 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4469 error_to_writebrawerr(req
);
4470 END_PROFILE(SMBwritebraw
);
4474 tcount
= IVAL(req
->vwv
+1, 0);
4475 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4476 write_through
= BITSETW(req
->vwv
+7,0);
4478 /* We have to deal with slightly different formats depending
4479 on whether we are using the core+ or lanman1.0 protocol */
4481 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
4482 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
4483 data
= smb_buf_const(req
->inbuf
);
4485 numtowrite
= SVAL(req
->vwv
+10, 0);
4486 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
4489 /* Ensure we don't write bytes past the end of this packet. */
4490 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
4491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4492 error_to_writebrawerr(req
);
4493 END_PROFILE(SMBwritebraw
);
4497 if (!fsp
->print_file
) {
4498 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4499 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
4502 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4503 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4504 error_to_writebrawerr(req
);
4505 END_PROFILE(SMBwritebraw
);
4511 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4514 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4515 "wrote=%d sync=%d\n",
4516 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4517 (int)nwritten
, (int)write_through
));
4519 if (nwritten
< (ssize_t
)numtowrite
) {
4520 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4521 error_to_writebrawerr(req
);
4525 total_written
= nwritten
;
4527 /* Allocate a buffer of 64k + length. */
4528 buf
= talloc_array(NULL
, char, 65540);
4530 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4531 error_to_writebrawerr(req
);
4535 /* Return a SMBwritebraw message to the redirector to tell
4536 * it to send more bytes */
4538 memcpy(buf
, req
->inbuf
, smb_size
);
4539 srv_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
4540 SCVAL(buf
,smb_com
,SMBwritebraw
);
4541 SSVALS(buf
,smb_vwv0
,0xFFFF);
4543 if (!srv_send_smb(req
->xconn
,
4545 false, 0, /* no signing */
4546 IS_CONN_ENCRYPTED(conn
),
4548 exit_server_cleanly("reply_writebraw: srv_send_smb "
4552 /* Now read the raw data into the buffer and write it */
4553 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4555 if (!NT_STATUS_IS_OK(status
)) {
4556 exit_server_cleanly("secondary writebraw failed");
4559 /* Set up outbuf to return the correct size */
4560 reply_outbuf(req
, 1, 0);
4562 if (numtowrite
!= 0) {
4564 if (numtowrite
> 0xFFFF) {
4565 DEBUG(0,("reply_writebraw: Oversize secondary write "
4566 "raw requested (%u). Terminating\n",
4567 (unsigned int)numtowrite
));
4568 exit_server_cleanly("secondary writebraw failed");
4571 if (tcount
> nwritten
+numtowrite
) {
4572 DEBUG(3,("reply_writebraw: Client overestimated the "
4574 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4577 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4580 if (!NT_STATUS_IS_OK(status
)) {
4581 /* Try and give an error message
4582 * saying what client failed. */
4583 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4584 "raw read failed (%s) for client %s. "
4585 "Terminating\n", nt_errstr(status
),
4586 smbXsrv_connection_dbg(xconn
)));
4587 exit_server_cleanly("secondary writebraw failed");
4590 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4591 if (nwritten
== -1) {
4593 reply_nterror(req
, map_nt_error_from_unix(errno
));
4594 error_to_writebrawerr(req
);
4598 if (nwritten
< (ssize_t
)numtowrite
) {
4599 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4600 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4604 total_written
+= nwritten
;
4609 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4611 status
= sync_file(conn
, fsp
, write_through
);
4612 if (!NT_STATUS_IS_OK(status
)) {
4613 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4614 fsp_str_dbg(fsp
), nt_errstr(status
)));
4615 reply_nterror(req
, status
);
4616 error_to_writebrawerr(req
);
4620 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4622 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4623 (int)total_written
));
4625 if (!fsp
->print_file
) {
4626 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4629 /* We won't return a status if write through is not selected - this
4630 * follows what WfWg does */
4631 END_PROFILE(SMBwritebraw
);
4633 if (!write_through
&& total_written
==tcount
) {
4635 #if RABBIT_PELLET_FIX
4637 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4638 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4641 if (!send_keepalive(xconn
->transport
.sock
)) {
4642 exit_server_cleanly("reply_writebraw: send of "
4643 "keepalive failed");
4646 TALLOC_FREE(req
->outbuf
);
4651 if (!fsp
->print_file
) {
4652 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4655 END_PROFILE(SMBwritebraw
);
4660 #define DBGC_CLASS DBGC_LOCKING
4662 /****************************************************************************
4663 Reply to a writeunlock (core+).
4664 ****************************************************************************/
4666 void reply_writeunlock(struct smb_request
*req
)
4668 connection_struct
*conn
= req
->conn
;
4669 ssize_t nwritten
= -1;
4673 NTSTATUS status
= NT_STATUS_OK
;
4675 struct lock_struct lock
;
4676 int saved_errno
= 0;
4678 START_PROFILE(SMBwriteunlock
);
4681 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4682 END_PROFILE(SMBwriteunlock
);
4686 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4688 if (!check_fsp(conn
, req
, fsp
)) {
4689 END_PROFILE(SMBwriteunlock
);
4693 if (!CHECK_WRITE(fsp
)) {
4694 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4695 END_PROFILE(SMBwriteunlock
);
4699 numtowrite
= SVAL(req
->vwv
+1, 0);
4700 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4701 data
= (const char *)req
->buf
+ 3;
4703 if (!fsp
->print_file
&& numtowrite
> 0) {
4704 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4705 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4708 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4709 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4710 END_PROFILE(SMBwriteunlock
);
4715 /* The special X/Open SMB protocol handling of
4716 zero length writes is *NOT* done for
4718 if(numtowrite
== 0) {
4721 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4722 saved_errno
= errno
;
4725 status
= sync_file(conn
, fsp
, False
/* write through */);
4726 if (!NT_STATUS_IS_OK(status
)) {
4727 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4728 fsp_str_dbg(fsp
), nt_errstr(status
)));
4729 reply_nterror(req
, status
);
4734 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4738 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4739 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4743 if (numtowrite
&& !fsp
->print_file
) {
4744 status
= do_unlock(req
->sconn
->msg_ctx
,
4746 (uint64_t)req
->smbpid
,
4747 (uint64_t)numtowrite
,
4751 if (NT_STATUS_V(status
)) {
4752 reply_nterror(req
, status
);
4757 reply_outbuf(req
, 1, 0);
4759 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4761 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4762 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4765 if (numtowrite
&& !fsp
->print_file
) {
4766 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4769 END_PROFILE(SMBwriteunlock
);
4774 #define DBGC_CLASS DBGC_ALL
4776 /****************************************************************************
4778 ****************************************************************************/
4780 void reply_write(struct smb_request
*req
)
4782 connection_struct
*conn
= req
->conn
;
4784 ssize_t nwritten
= -1;
4788 struct lock_struct lock
;
4790 int saved_errno
= 0;
4792 START_PROFILE(SMBwrite
);
4795 END_PROFILE(SMBwrite
);
4796 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4800 /* If it's an IPC, pass off the pipe handler. */
4802 reply_pipe_write(req
);
4803 END_PROFILE(SMBwrite
);
4807 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4809 if (!check_fsp(conn
, req
, fsp
)) {
4810 END_PROFILE(SMBwrite
);
4814 if (!CHECK_WRITE(fsp
)) {
4815 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4816 END_PROFILE(SMBwrite
);
4820 numtowrite
= SVAL(req
->vwv
+1, 0);
4821 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4822 data
= (const char *)req
->buf
+ 3;
4824 if (!fsp
->print_file
) {
4825 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
4826 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4829 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4830 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4831 END_PROFILE(SMBwrite
);
4837 * X/Open SMB protocol says that if smb_vwv1 is
4838 * zero then the file size should be extended or
4839 * truncated to the size given in smb_vwv[2-3].
4842 if(numtowrite
== 0) {
4844 * This is actually an allocate call, and set EOF. JRA.
4846 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4848 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4851 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4853 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4856 trigger_write_time_update_immediate(fsp
);
4858 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4861 status
= sync_file(conn
, fsp
, False
);
4862 if (!NT_STATUS_IS_OK(status
)) {
4863 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4864 fsp_str_dbg(fsp
), nt_errstr(status
)));
4865 reply_nterror(req
, status
);
4870 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4874 if((nwritten
== 0) && (numtowrite
!= 0)) {
4875 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4879 reply_outbuf(req
, 1, 0);
4881 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4883 if (nwritten
< (ssize_t
)numtowrite
) {
4884 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4885 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4888 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4891 if (!fsp
->print_file
) {
4892 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4895 END_PROFILE(SMBwrite
);
4899 /****************************************************************************
4900 Ensure a buffer is a valid writeX for recvfile purposes.
4901 ****************************************************************************/
4903 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4904 (2*14) + /* word count (including bcc) */ \
4907 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4908 const uint8_t *inbuf
)
4911 unsigned int doff
= 0;
4912 size_t len
= smb_len_large(inbuf
);
4914 struct smbXsrv_open
*op
= NULL
;
4915 struct files_struct
*fsp
= NULL
;
4918 if (is_encrypted_packet(inbuf
)) {
4919 /* Can't do this on encrypted
4924 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4928 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4929 CVAL(inbuf
,smb_wct
) != 14) {
4930 DEBUG(10,("is_valid_writeX_buffer: chained or "
4931 "invalid word length.\n"));
4935 fnum
= SVAL(inbuf
, smb_vwv2
);
4936 status
= smb1srv_open_lookup(xconn
,
4940 if (!NT_STATUS_IS_OK(status
)) {
4941 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4946 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4949 if (fsp
->conn
== NULL
) {
4950 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4954 if (IS_IPC(fsp
->conn
)) {
4955 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4958 if (IS_PRINT(fsp
->conn
)) {
4959 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4962 doff
= SVAL(inbuf
,smb_vwv11
);
4964 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4966 if (len
> doff
&& len
- doff
> 0xFFFF) {
4967 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4970 if (numtowrite
== 0) {
4971 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4975 /* Ensure the sizes match up. */
4976 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4977 /* no pad byte...old smbclient :-( */
4978 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4980 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4984 if (len
- doff
!= numtowrite
) {
4985 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4986 "len = %u, doff = %u, numtowrite = %u\n",
4989 (unsigned int)numtowrite
));
4993 DEBUG(10,("is_valid_writeX_buffer: true "
4994 "len = %u, doff = %u, numtowrite = %u\n",
4997 (unsigned int)numtowrite
));
5002 /****************************************************************************
5003 Reply to a write and X.
5004 ****************************************************************************/
5006 void reply_write_and_X(struct smb_request
*req
)
5008 connection_struct
*conn
= req
->conn
;
5009 struct smbXsrv_connection
*xconn
= req
->xconn
;
5011 struct lock_struct lock
;
5016 unsigned int smb_doff
;
5017 unsigned int smblen
;
5020 int saved_errno
= 0;
5022 START_PROFILE(SMBwriteX
);
5024 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
5025 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5029 numtowrite
= SVAL(req
->vwv
+10, 0);
5030 smb_doff
= SVAL(req
->vwv
+11, 0);
5031 smblen
= smb_len(req
->inbuf
);
5033 if (req
->unread_bytes
> 0xFFFF ||
5034 (smblen
> smb_doff
&&
5035 smblen
- smb_doff
> 0xFFFF)) {
5036 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
5039 if (req
->unread_bytes
) {
5040 /* Can't do a recvfile write on IPC$ */
5042 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5045 if (numtowrite
!= req
->unread_bytes
) {
5046 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5050 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
5051 smb_doff
+ numtowrite
> smblen
) {
5052 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5057 /* If it's an IPC, pass off the pipe handler. */
5059 if (req
->unread_bytes
) {
5060 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5063 reply_pipe_write_and_X(req
);
5067 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
5068 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
5069 write_through
= BITSETW(req
->vwv
+7,0);
5071 if (!check_fsp(conn
, req
, fsp
)) {
5075 if (!CHECK_WRITE(fsp
)) {
5076 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5080 data
= smb_base(req
->inbuf
) + smb_doff
;
5082 if(req
->wct
== 14) {
5084 * This is a large offset (64 bit) write.
5086 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
5090 /* X/Open SMB protocol says that, unlike SMBwrite
5091 if the length is zero then NO truncation is
5092 done, just a write of zero. To truncate a file,
5095 if(numtowrite
== 0) {
5098 if (req
->unread_bytes
== 0) {
5099 status
= schedule_aio_write_and_X(conn
,
5106 if (NT_STATUS_IS_OK(status
)) {
5107 /* write scheduled - we're done. */
5110 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
5111 /* Real error - report to client. */
5112 reply_nterror(req
, status
);
5115 /* NT_STATUS_RETRY - fall through to sync write. */
5118 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5119 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5122 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5123 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5127 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5128 saved_errno
= errno
;
5130 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5134 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
5138 if((nwritten
== 0) && (numtowrite
!= 0)) {
5139 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5143 reply_outbuf(req
, 6, 0);
5144 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
5145 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
5146 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
5147 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
5149 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5150 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
5152 status
= sync_file(conn
, fsp
, write_through
);
5153 if (!NT_STATUS_IS_OK(status
)) {
5154 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5155 fsp_str_dbg(fsp
), nt_errstr(status
)));
5156 reply_nterror(req
, status
);
5160 END_PROFILE(SMBwriteX
);
5164 if (req
->unread_bytes
) {
5165 /* writeX failed. drain socket. */
5166 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
5167 req
->unread_bytes
) {
5168 smb_panic("failed to drain pending bytes");
5170 req
->unread_bytes
= 0;
5173 END_PROFILE(SMBwriteX
);
5177 /****************************************************************************
5179 ****************************************************************************/
5181 void reply_lseek(struct smb_request
*req
)
5183 connection_struct
*conn
= req
->conn
;
5189 START_PROFILE(SMBlseek
);
5192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5193 END_PROFILE(SMBlseek
);
5197 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5199 if (!check_fsp(conn
, req
, fsp
)) {
5203 flush_write_cache(fsp
, SAMBA_SEEK_FLUSH
);
5205 mode
= SVAL(req
->vwv
+1, 0) & 3;
5206 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5207 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
5216 res
= fsp
->fh
->pos
+ startpos
;
5227 if (umode
== SEEK_END
) {
5228 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
5229 if(errno
== EINVAL
) {
5230 off_t current_pos
= startpos
;
5232 if(fsp_stat(fsp
) == -1) {
5234 map_nt_error_from_unix(errno
));
5235 END_PROFILE(SMBlseek
);
5239 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
5241 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
5246 reply_nterror(req
, map_nt_error_from_unix(errno
));
5247 END_PROFILE(SMBlseek
);
5254 reply_outbuf(req
, 2, 0);
5255 SIVAL(req
->outbuf
,smb_vwv0
,res
);
5257 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5258 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
5260 END_PROFILE(SMBlseek
);
5264 /****************************************************************************
5266 ****************************************************************************/
5268 void reply_flush(struct smb_request
*req
)
5270 connection_struct
*conn
= req
->conn
;
5274 START_PROFILE(SMBflush
);
5277 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5281 fnum
= SVAL(req
->vwv
+0, 0);
5282 fsp
= file_fsp(req
, fnum
);
5284 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
5289 file_sync_all(conn
);
5291 NTSTATUS status
= sync_file(conn
, fsp
, True
);
5292 if (!NT_STATUS_IS_OK(status
)) {
5293 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5294 fsp_str_dbg(fsp
), nt_errstr(status
)));
5295 reply_nterror(req
, status
);
5296 END_PROFILE(SMBflush
);
5301 reply_outbuf(req
, 0, 0);
5303 DEBUG(3,("flush\n"));
5304 END_PROFILE(SMBflush
);
5308 /****************************************************************************
5310 conn POINTER CAN BE NULL HERE !
5311 ****************************************************************************/
5313 void reply_exit(struct smb_request
*req
)
5315 START_PROFILE(SMBexit
);
5317 file_close_pid(req
->sconn
, req
->smbpid
, req
->vuid
);
5319 reply_outbuf(req
, 0, 0);
5321 DEBUG(3,("exit\n"));
5323 END_PROFILE(SMBexit
);
5327 struct reply_close_state
{
5329 struct smb_request
*smbreq
;
5332 static void do_smb1_close(struct tevent_req
*req
);
5334 void reply_close(struct smb_request
*req
)
5336 connection_struct
*conn
= req
->conn
;
5337 NTSTATUS status
= NT_STATUS_OK
;
5338 files_struct
*fsp
= NULL
;
5339 START_PROFILE(SMBclose
);
5342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5343 END_PROFILE(SMBclose
);
5347 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5350 * We can only use check_fsp if we know it's not a directory.
5353 if (!check_fsp_open(conn
, req
, fsp
)) {
5354 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5355 END_PROFILE(SMBclose
);
5359 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5360 fsp
->is_directory
? "directory" : "file",
5361 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
),
5362 conn
->num_files_open
));
5364 if (!fsp
->is_directory
) {
5368 * Take care of any time sent in the close.
5371 t
= srv_make_unix_date3(req
->vwv
+1);
5372 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
5375 if (fsp
->num_aio_requests
!= 0) {
5377 struct reply_close_state
*state
;
5379 DEBUG(10, ("closing with aio %u requests pending\n",
5380 fsp
->num_aio_requests
));
5383 * We depend on the aio_extra destructor to take care of this
5384 * close request once fsp->num_aio_request drops to 0.
5387 fsp
->deferred_close
= tevent_wait_send(
5388 fsp
, fsp
->conn
->sconn
->ev_ctx
);
5389 if (fsp
->deferred_close
== NULL
) {
5390 status
= NT_STATUS_NO_MEMORY
;
5394 state
= talloc(fsp
, struct reply_close_state
);
5395 if (state
== NULL
) {
5396 TALLOC_FREE(fsp
->deferred_close
);
5397 status
= NT_STATUS_NO_MEMORY
;
5401 state
->smbreq
= talloc_move(fsp
, &req
);
5402 tevent_req_set_callback(fsp
->deferred_close
, do_smb1_close
,
5404 END_PROFILE(SMBclose
);
5409 * close_file() returns the unix errno if an error was detected on
5410 * close - normally this is due to a disk full error. If not then it
5411 * was probably an I/O error.
5414 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5416 if (!NT_STATUS_IS_OK(status
)) {
5417 reply_nterror(req
, status
);
5418 END_PROFILE(SMBclose
);
5422 reply_outbuf(req
, 0, 0);
5423 END_PROFILE(SMBclose
);
5427 static void do_smb1_close(struct tevent_req
*req
)
5429 struct reply_close_state
*state
= tevent_req_callback_data(
5430 req
, struct reply_close_state
);
5431 struct smb_request
*smbreq
;
5435 ret
= tevent_wait_recv(req
);
5438 DEBUG(10, ("tevent_wait_recv returned %s\n",
5441 * Continue anyway, this should never happen
5446 * fsp->smb2_close_request right now is a talloc grandchild of
5447 * fsp. When we close_file(fsp), it would go with it. No chance to
5450 smbreq
= talloc_move(talloc_tos(), &state
->smbreq
);
5452 status
= close_file(smbreq
, state
->fsp
, NORMAL_CLOSE
);
5453 if (NT_STATUS_IS_OK(status
)) {
5454 reply_outbuf(smbreq
, 0, 0);
5456 reply_nterror(smbreq
, status
);
5458 if (!srv_send_smb(smbreq
->xconn
,
5459 (char *)smbreq
->outbuf
,
5462 IS_CONN_ENCRYPTED(smbreq
->conn
)||smbreq
->encrypted
,
5464 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5467 TALLOC_FREE(smbreq
);
5470 /****************************************************************************
5471 Reply to a writeclose (Core+ protocol).
5472 ****************************************************************************/
5474 void reply_writeclose(struct smb_request
*req
)
5476 connection_struct
*conn
= req
->conn
;
5478 ssize_t nwritten
= -1;
5479 NTSTATUS close_status
= NT_STATUS_OK
;
5482 struct timespec mtime
;
5484 struct lock_struct lock
;
5486 START_PROFILE(SMBwriteclose
);
5489 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5490 END_PROFILE(SMBwriteclose
);
5494 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5496 if (!check_fsp(conn
, req
, fsp
)) {
5497 END_PROFILE(SMBwriteclose
);
5500 if (!CHECK_WRITE(fsp
)) {
5501 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5502 END_PROFILE(SMBwriteclose
);
5506 numtowrite
= SVAL(req
->vwv
+1, 0);
5507 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5508 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
5509 data
= (const char *)req
->buf
+ 1;
5511 if (fsp
->print_file
== NULL
) {
5512 init_strict_lock_struct(fsp
, (uint64_t)req
->smbpid
,
5513 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
5516 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
5517 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5518 END_PROFILE(SMBwriteclose
);
5523 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5525 if (fsp
->print_file
== NULL
) {
5526 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
5529 set_close_write_time(fsp
, mtime
);
5532 * More insanity. W2K only closes the file if writelen > 0.
5536 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5537 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5538 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5541 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5542 "file %s\n", fsp_str_dbg(fsp
)));
5543 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5547 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5548 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5552 if(!NT_STATUS_IS_OK(close_status
)) {
5553 reply_nterror(req
, close_status
);
5557 reply_outbuf(req
, 1, 0);
5559 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5563 END_PROFILE(SMBwriteclose
);
5568 #define DBGC_CLASS DBGC_LOCKING
5570 /****************************************************************************
5572 ****************************************************************************/
5574 void reply_lock(struct smb_request
*req
)
5576 connection_struct
*conn
= req
->conn
;
5577 uint64_t count
,offset
;
5580 struct byte_range_lock
*br_lck
= NULL
;
5582 START_PROFILE(SMBlock
);
5585 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5586 END_PROFILE(SMBlock
);
5590 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5592 if (!check_fsp(conn
, req
, fsp
)) {
5593 END_PROFILE(SMBlock
);
5597 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5598 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5600 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5601 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
));
5603 br_lck
= do_lock(req
->sconn
->msg_ctx
,
5605 (uint64_t)req
->smbpid
,
5610 False
, /* Non-blocking lock. */
5614 TALLOC_FREE(br_lck
);
5616 if (NT_STATUS_V(status
)) {
5617 reply_nterror(req
, status
);
5618 END_PROFILE(SMBlock
);
5622 reply_outbuf(req
, 0, 0);
5624 END_PROFILE(SMBlock
);
5628 /****************************************************************************
5630 ****************************************************************************/
5632 void reply_unlock(struct smb_request
*req
)
5634 connection_struct
*conn
= req
->conn
;
5635 uint64_t count
,offset
;
5639 START_PROFILE(SMBunlock
);
5642 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5643 END_PROFILE(SMBunlock
);
5647 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5649 if (!check_fsp(conn
, req
, fsp
)) {
5650 END_PROFILE(SMBunlock
);
5654 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
5655 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
5657 status
= do_unlock(req
->sconn
->msg_ctx
,
5659 (uint64_t)req
->smbpid
,
5664 if (NT_STATUS_V(status
)) {
5665 reply_nterror(req
, status
);
5666 END_PROFILE(SMBunlock
);
5670 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5671 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
), (double)offset
, (double)count
) );
5673 reply_outbuf(req
, 0, 0);
5675 END_PROFILE(SMBunlock
);
5680 #define DBGC_CLASS DBGC_ALL
5682 /****************************************************************************
5684 conn POINTER CAN BE NULL HERE !
5685 ****************************************************************************/
5687 void reply_tdis(struct smb_request
*req
)
5690 connection_struct
*conn
= req
->conn
;
5691 struct smbXsrv_tcon
*tcon
;
5693 START_PROFILE(SMBtdis
);
5696 DEBUG(4,("Invalid connection in tdis\n"));
5697 reply_force_doserror(req
, ERRSRV
, ERRinvnid
);
5698 END_PROFILE(SMBtdis
);
5706 * TODO: cancel all outstanding requests on the tcon
5708 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
5709 if (!NT_STATUS_IS_OK(status
)) {
5710 DEBUG(0, ("reply_tdis: "
5711 "smbXsrv_tcon_disconnect() failed: %s\n",
5712 nt_errstr(status
)));
5714 * If we hit this case, there is something completely
5715 * wrong, so we better disconnect the transport connection.
5717 END_PROFILE(SMBtdis
);
5718 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5724 reply_outbuf(req
, 0, 0);
5725 END_PROFILE(SMBtdis
);
5729 /****************************************************************************
5731 conn POINTER CAN BE NULL HERE !
5732 ****************************************************************************/
5734 void reply_echo(struct smb_request
*req
)
5736 connection_struct
*conn
= req
->conn
;
5737 struct smb_perfcount_data local_pcd
;
5738 struct smb_perfcount_data
*cur_pcd
;
5742 START_PROFILE(SMBecho
);
5744 smb_init_perfcount_data(&local_pcd
);
5747 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5748 END_PROFILE(SMBecho
);
5752 smb_reverb
= SVAL(req
->vwv
+0, 0);
5754 reply_outbuf(req
, 1, req
->buflen
);
5756 /* copy any incoming data back out */
5757 if (req
->buflen
> 0) {
5758 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5761 if (smb_reverb
> 100) {
5762 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5766 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5768 /* this makes sure we catch the request pcd */
5769 if (seq_num
== smb_reverb
) {
5770 cur_pcd
= &req
->pcd
;
5772 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5773 cur_pcd
= &local_pcd
;
5776 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5778 show_msg((char *)req
->outbuf
);
5779 if (!srv_send_smb(req
->xconn
,
5780 (char *)req
->outbuf
,
5781 true, req
->seqnum
+1,
5782 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5784 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5787 DEBUG(3,("echo %d times\n", smb_reverb
));
5789 TALLOC_FREE(req
->outbuf
);
5791 END_PROFILE(SMBecho
);
5795 /****************************************************************************
5796 Reply to a printopen.
5797 ****************************************************************************/
5799 void reply_printopen(struct smb_request
*req
)
5801 connection_struct
*conn
= req
->conn
;
5805 START_PROFILE(SMBsplopen
);
5808 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5809 END_PROFILE(SMBsplopen
);
5813 if (!CAN_PRINT(conn
)) {
5814 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5815 END_PROFILE(SMBsplopen
);
5819 status
= file_new(req
, conn
, &fsp
);
5820 if(!NT_STATUS_IS_OK(status
)) {
5821 reply_nterror(req
, status
);
5822 END_PROFILE(SMBsplopen
);
5826 /* Open for exclusive use, write only. */
5827 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5829 if (!NT_STATUS_IS_OK(status
)) {
5830 file_free(req
, fsp
);
5831 reply_nterror(req
, status
);
5832 END_PROFILE(SMBsplopen
);
5836 reply_outbuf(req
, 1, 0);
5837 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5839 DEBUG(3,("openprint fd=%d %s\n",
5840 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5842 END_PROFILE(SMBsplopen
);
5846 /****************************************************************************
5847 Reply to a printclose.
5848 ****************************************************************************/
5850 void reply_printclose(struct smb_request
*req
)
5852 connection_struct
*conn
= req
->conn
;
5856 START_PROFILE(SMBsplclose
);
5859 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5860 END_PROFILE(SMBsplclose
);
5864 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5866 if (!check_fsp(conn
, req
, fsp
)) {
5867 END_PROFILE(SMBsplclose
);
5871 if (!CAN_PRINT(conn
)) {
5872 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5873 END_PROFILE(SMBsplclose
);
5877 DEBUG(3,("printclose fd=%d %s\n",
5878 fsp
->fh
->fd
, fsp_fnum_dbg(fsp
)));
5880 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5882 if(!NT_STATUS_IS_OK(status
)) {
5883 reply_nterror(req
, status
);
5884 END_PROFILE(SMBsplclose
);
5888 reply_outbuf(req
, 0, 0);
5890 END_PROFILE(SMBsplclose
);
5894 /****************************************************************************
5895 Reply to a printqueue.
5896 ****************************************************************************/
5898 void reply_printqueue(struct smb_request
*req
)
5900 connection_struct
*conn
= req
->conn
;
5904 START_PROFILE(SMBsplretq
);
5907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5908 END_PROFILE(SMBsplretq
);
5912 max_count
= SVAL(req
->vwv
+0, 0);
5913 start_index
= SVAL(req
->vwv
+1, 0);
5915 /* we used to allow the client to get the cnum wrong, but that
5916 is really quite gross and only worked when there was only
5917 one printer - I think we should now only accept it if they
5918 get it right (tridge) */
5919 if (!CAN_PRINT(conn
)) {
5920 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5921 END_PROFILE(SMBsplretq
);
5925 reply_outbuf(req
, 2, 3);
5926 SSVAL(req
->outbuf
,smb_vwv0
,0);
5927 SSVAL(req
->outbuf
,smb_vwv1
,0);
5928 SCVAL(smb_buf(req
->outbuf
),0,1);
5929 SSVAL(smb_buf(req
->outbuf
),1,0);
5931 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5932 start_index
, max_count
));
5935 TALLOC_CTX
*mem_ctx
= talloc_tos();
5938 const char *sharename
= lp_servicename(mem_ctx
, SNUM(conn
));
5939 struct rpc_pipe_client
*cli
= NULL
;
5940 struct dcerpc_binding_handle
*b
= NULL
;
5941 struct policy_handle handle
;
5942 struct spoolss_DevmodeContainer devmode_ctr
;
5943 union spoolss_JobInfo
*info
;
5945 uint32_t num_to_get
;
5949 ZERO_STRUCT(handle
);
5951 status
= rpc_pipe_open_interface(conn
,
5954 conn
->sconn
->remote_address
,
5955 conn
->sconn
->msg_ctx
,
5957 if (!NT_STATUS_IS_OK(status
)) {
5958 DEBUG(0, ("reply_printqueue: "
5959 "could not connect to spoolss: %s\n",
5960 nt_errstr(status
)));
5961 reply_nterror(req
, status
);
5964 b
= cli
->binding_handle
;
5966 ZERO_STRUCT(devmode_ctr
);
5968 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5971 SEC_FLAG_MAXIMUM_ALLOWED
,
5974 if (!NT_STATUS_IS_OK(status
)) {
5975 reply_nterror(req
, status
);
5978 if (!W_ERROR_IS_OK(werr
)) {
5979 reply_nterror(req
, werror_to_ntstatus(werr
));
5983 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5991 if (!W_ERROR_IS_OK(werr
)) {
5992 reply_nterror(req
, werror_to_ntstatus(werr
));
5996 if (max_count
> 0) {
5997 first
= start_index
;
5999 first
= start_index
+ max_count
+ 1;
6002 if (first
>= count
) {
6005 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6008 for (i
= first
; i
< num_to_get
; i
++) {
6011 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6014 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6015 info
[i
].info2
.job_id
);
6017 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6023 srv_put_dos_date2(p
, 0, qtime
);
6024 SCVAL(p
, 4, qstatus
);
6025 SSVAL(p
, 5, qrapjobid
);
6026 SIVAL(p
, 7, info
[i
].info2
.size
);
6028 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6029 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6030 if (!NT_STATUS_IS_OK(status
)) {
6031 reply_nterror(req
, status
);
6034 if (message_push_blob(
6037 blob
, sizeof(blob
))) == -1) {
6038 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6044 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6045 SSVAL(req
->outbuf
,smb_vwv1
,
6046 (max_count
>0?first
+count
:first
-1));
6047 SCVAL(smb_buf(req
->outbuf
),0,1);
6048 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6052 DEBUG(3, ("%u entries returned in queue\n",
6056 if (b
&& is_valid_policy_hnd(&handle
)) {
6057 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6062 END_PROFILE(SMBsplretq
);
6066 /****************************************************************************
6067 Reply to a printwrite.
6068 ****************************************************************************/
6070 void reply_printwrite(struct smb_request
*req
)
6072 connection_struct
*conn
= req
->conn
;
6077 START_PROFILE(SMBsplwr
);
6080 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6081 END_PROFILE(SMBsplwr
);
6085 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6087 if (!check_fsp(conn
, req
, fsp
)) {
6088 END_PROFILE(SMBsplwr
);
6092 if (!fsp
->print_file
) {
6093 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6094 END_PROFILE(SMBsplwr
);
6098 if (!CHECK_WRITE(fsp
)) {
6099 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6100 END_PROFILE(SMBsplwr
);
6104 numtowrite
= SVAL(req
->buf
, 1);
6106 if (req
->buflen
< numtowrite
+ 3) {
6107 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6108 END_PROFILE(SMBsplwr
);
6112 data
= (const char *)req
->buf
+ 3;
6114 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6115 reply_nterror(req
, map_nt_error_from_unix(errno
));
6116 END_PROFILE(SMBsplwr
);
6120 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6122 END_PROFILE(SMBsplwr
);
6126 /****************************************************************************
6128 ****************************************************************************/
6130 void reply_mkdir(struct smb_request
*req
)
6132 connection_struct
*conn
= req
->conn
;
6133 struct smb_filename
*smb_dname
= NULL
;
6134 char *directory
= NULL
;
6136 uint32_t ucf_flags
= UCF_PREP_CREATEFILE
|
6137 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6138 TALLOC_CTX
*ctx
= talloc_tos();
6140 START_PROFILE(SMBmkdir
);
6142 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6143 STR_TERMINATE
, &status
);
6144 if (!NT_STATUS_IS_OK(status
)) {
6145 reply_nterror(req
, status
);
6149 status
= filename_convert(ctx
, conn
,
6150 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6155 if (!NT_STATUS_IS_OK(status
)) {
6156 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6157 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6158 ERRSRV
, ERRbadpath
);
6161 reply_nterror(req
, status
);
6165 status
= create_directory(conn
, req
, smb_dname
);
6167 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6169 if (!NT_STATUS_IS_OK(status
)) {
6171 if (!use_nt_status()
6172 && NT_STATUS_EQUAL(status
,
6173 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6175 * Yes, in the DOS error code case we get a
6176 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6177 * samba4 torture test.
6179 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6182 reply_nterror(req
, status
);
6186 reply_outbuf(req
, 0, 0);
6188 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6190 TALLOC_FREE(smb_dname
);
6191 END_PROFILE(SMBmkdir
);
6195 /****************************************************************************
6197 ****************************************************************************/
6199 void reply_rmdir(struct smb_request
*req
)
6201 connection_struct
*conn
= req
->conn
;
6202 struct smb_filename
*smb_dname
= NULL
;
6203 char *directory
= NULL
;
6205 TALLOC_CTX
*ctx
= talloc_tos();
6206 files_struct
*fsp
= NULL
;
6208 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6209 struct smbd_server_connection
*sconn
= req
->sconn
;
6211 START_PROFILE(SMBrmdir
);
6213 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6214 STR_TERMINATE
, &status
);
6215 if (!NT_STATUS_IS_OK(status
)) {
6216 reply_nterror(req
, status
);
6220 status
= filename_convert(ctx
, conn
,
6221 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6226 if (!NT_STATUS_IS_OK(status
)) {
6227 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6228 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6229 ERRSRV
, ERRbadpath
);
6232 reply_nterror(req
, status
);
6236 if (is_ntfs_stream_smb_fname(smb_dname
)) {
6237 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
6241 status
= SMB_VFS_CREATE_FILE(
6244 0, /* root_dir_fid */
6245 smb_dname
, /* fname */
6246 DELETE_ACCESS
, /* access_mask */
6247 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6249 FILE_OPEN
, /* create_disposition*/
6250 FILE_DIRECTORY_FILE
, /* create_options */
6251 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6252 0, /* oplock_request */
6254 0, /* allocation_size */
6255 0, /* private_flags */
6260 NULL
, NULL
); /* create context */
6262 if (!NT_STATUS_IS_OK(status
)) {
6263 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6264 /* We have re-scheduled this call. */
6267 reply_nterror(req
, status
);
6271 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6272 if (!NT_STATUS_IS_OK(status
)) {
6273 close_file(req
, fsp
, ERROR_CLOSE
);
6274 reply_nterror(req
, status
);
6278 if (!set_delete_on_close(fsp
, true,
6279 conn
->session_info
->security_token
,
6280 conn
->session_info
->unix_token
)) {
6281 close_file(req
, fsp
, ERROR_CLOSE
);
6282 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6286 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
6287 if (!NT_STATUS_IS_OK(status
)) {
6288 reply_nterror(req
, status
);
6290 reply_outbuf(req
, 0, 0);
6293 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
6295 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6297 TALLOC_FREE(smb_dname
);
6298 END_PROFILE(SMBrmdir
);
6302 /*******************************************************************
6303 Resolve wildcards in a filename rename.
6304 ********************************************************************/
6306 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
6311 char *name2_copy
= NULL
;
6316 char *p
,*p2
, *pname1
, *pname2
;
6318 name2_copy
= talloc_strdup(ctx
, name2
);
6323 pname1
= strrchr_m(name1
,'/');
6324 pname2
= strrchr_m(name2_copy
,'/');
6326 if (!pname1
|| !pname2
) {
6330 /* Truncate the copy of name2 at the last '/' */
6333 /* Now go past the '/' */
6337 root1
= talloc_strdup(ctx
, pname1
);
6338 root2
= talloc_strdup(ctx
, pname2
);
6340 if (!root1
|| !root2
) {
6344 p
= strrchr_m(root1
,'.');
6347 ext1
= talloc_strdup(ctx
, p
+1);
6349 ext1
= talloc_strdup(ctx
, "");
6351 p
= strrchr_m(root2
,'.');
6354 ext2
= talloc_strdup(ctx
, p
+1);
6356 ext2
= talloc_strdup(ctx
, "");
6359 if (!ext1
|| !ext2
) {
6367 /* Hmmm. Should this be mb-aware ? */
6370 } else if (*p2
== '*') {
6372 root2
= talloc_asprintf(ctx
, "%s%s",
6391 /* Hmmm. Should this be mb-aware ? */
6394 } else if (*p2
== '*') {
6396 ext2
= talloc_asprintf(ctx
, "%s%s",
6412 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
6417 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
6429 /****************************************************************************
6430 Ensure open files have their names updated. Updated to notify other smbd's
6432 ****************************************************************************/
6434 static void rename_open_files(connection_struct
*conn
,
6435 struct share_mode_lock
*lck
,
6437 uint32_t orig_name_hash
,
6438 const struct smb_filename
*smb_fname_dst
)
6441 bool did_rename
= False
;
6443 uint32_t new_name_hash
= 0;
6445 for(fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6446 fsp
= file_find_di_next(fsp
)) {
6447 /* fsp_name is a relative path under the fsp. To change this for other
6448 sharepaths we need to manipulate relative paths. */
6449 /* TODO - create the absolute path and manipulate the newname
6450 relative to the sharepath. */
6451 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
6454 if (fsp
->name_hash
!= orig_name_hash
) {
6457 DEBUG(10, ("rename_open_files: renaming file %s "
6458 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp
),
6459 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
6460 smb_fname_str_dbg(smb_fname_dst
)));
6462 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
6463 if (NT_STATUS_IS_OK(status
)) {
6465 new_name_hash
= fsp
->name_hash
;
6470 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6471 "for %s\n", file_id_string_tos(&id
),
6472 smb_fname_str_dbg(smb_fname_dst
)));
6475 /* Send messages to all smbd's (not ourself) that the name has changed. */
6476 rename_share_filename(conn
->sconn
->msg_ctx
, lck
, id
, conn
->connectpath
,
6477 orig_name_hash
, new_name_hash
,
6482 /****************************************************************************
6483 We need to check if the source path is a parent directory of the destination
6484 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6485 refuse the rename with a sharing violation. Under UNIX the above call can
6486 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6487 probably need to check that the client is a Windows one before disallowing
6488 this as a UNIX client (one with UNIX extensions) can know the source is a
6489 symlink and make this decision intelligently. Found by an excellent bug
6490 report from <AndyLiebman@aol.com>.
6491 ****************************************************************************/
6493 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
6494 const struct smb_filename
*smb_fname_dst
)
6496 const char *psrc
= smb_fname_src
->base_name
;
6497 const char *pdst
= smb_fname_dst
->base_name
;
6500 if (psrc
[0] == '.' && psrc
[1] == '/') {
6503 if (pdst
[0] == '.' && pdst
[1] == '/') {
6506 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
6509 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
6513 * Do the notify calls from a rename
6516 static void notify_rename(connection_struct
*conn
, bool is_dir
,
6517 const struct smb_filename
*smb_fname_src
,
6518 const struct smb_filename
*smb_fname_dst
)
6520 char *parent_dir_src
= NULL
;
6521 char *parent_dir_dst
= NULL
;
6524 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
6525 : FILE_NOTIFY_CHANGE_FILE_NAME
;
6527 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
6528 &parent_dir_src
, NULL
) ||
6529 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
6530 &parent_dir_dst
, NULL
)) {
6534 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
6535 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
6536 smb_fname_src
->base_name
);
6537 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
6538 smb_fname_dst
->base_name
);
6541 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
6542 smb_fname_src
->base_name
);
6543 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
6544 smb_fname_dst
->base_name
);
6547 /* this is a strange one. w2k3 gives an additional event for
6548 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6549 files, but not directories */
6551 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6552 FILE_NOTIFY_CHANGE_ATTRIBUTES
6553 |FILE_NOTIFY_CHANGE_CREATION
,
6554 smb_fname_dst
->base_name
);
6557 TALLOC_FREE(parent_dir_src
);
6558 TALLOC_FREE(parent_dir_dst
);
6561 /****************************************************************************
6562 Returns an error if the parent directory for a filename is open in an
6564 ****************************************************************************/
6566 static NTSTATUS
parent_dirname_compatible_open(connection_struct
*conn
,
6567 const struct smb_filename
*smb_fname_dst_in
)
6569 char *parent_dir
= NULL
;
6570 struct smb_filename smb_fname_parent
;
6572 files_struct
*fsp
= NULL
;
6575 if (!parent_dirname(talloc_tos(), smb_fname_dst_in
->base_name
,
6576 &parent_dir
, NULL
)) {
6577 return NT_STATUS_NO_MEMORY
;
6579 ZERO_STRUCT(smb_fname_parent
);
6580 smb_fname_parent
.base_name
= parent_dir
;
6582 ret
= SMB_VFS_LSTAT(conn
, &smb_fname_parent
);
6584 return map_nt_error_from_unix(errno
);
6588 * We're only checking on this smbd here, mostly good
6589 * enough.. and will pass tests.
6592 id
= vfs_file_id_from_sbuf(conn
, &smb_fname_parent
.st
);
6593 for (fsp
= file_find_di_first(conn
->sconn
, id
); fsp
;
6594 fsp
= file_find_di_next(fsp
)) {
6595 if (fsp
->access_mask
& DELETE_ACCESS
) {
6596 return NT_STATUS_SHARING_VIOLATION
;
6599 return NT_STATUS_OK
;
6602 /****************************************************************************
6603 Rename an open file - given an fsp.
6604 ****************************************************************************/
6606 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
6608 const struct smb_filename
*smb_fname_dst_in
,
6610 bool replace_if_exists
)
6612 TALLOC_CTX
*ctx
= talloc_tos();
6613 struct smb_filename
*smb_fname_dst
= NULL
;
6614 NTSTATUS status
= NT_STATUS_OK
;
6615 struct share_mode_lock
*lck
= NULL
;
6616 bool dst_exists
, old_is_stream
, new_is_stream
;
6618 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
6619 if (!NT_STATUS_IS_OK(status
)) {
6623 status
= parent_dirname_compatible_open(conn
, smb_fname_dst_in
);
6624 if (!NT_STATUS_IS_OK(status
)) {
6628 /* Make a copy of the dst smb_fname structs */
6630 smb_fname_dst
= cp_smb_filename(ctx
, smb_fname_dst_in
);
6631 if (smb_fname_dst
== NULL
) {
6632 status
= NT_STATUS_NO_MEMORY
;
6637 * Check for special case with case preserving and not
6638 * case sensitive. If the new last component differs from the original
6639 * last component only by case, then we should allow
6640 * the rename (user is trying to change the case of the
6643 if (!conn
->case_sensitive
&& conn
->case_preserve
&&
6644 strequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6645 strequal(fsp
->fsp_name
->stream_name
, smb_fname_dst
->stream_name
)) {
6646 char *fname_dst_parent
= NULL
;
6647 const char *fname_dst_lcomp
= NULL
;
6648 char *orig_lcomp_path
= NULL
;
6649 char *orig_lcomp_stream
= NULL
;
6653 * Split off the last component of the processed
6654 * destination name. We will compare this to
6655 * the split components of smb_fname_dst->original_lcomp.
6657 if (!parent_dirname(ctx
,
6658 smb_fname_dst
->base_name
,
6660 &fname_dst_lcomp
)) {
6661 status
= NT_STATUS_NO_MEMORY
;
6666 * The original_lcomp component contains
6667 * the last_component of the path + stream
6668 * name (if a stream exists).
6670 * Split off the stream name so we
6671 * can check them separately.
6674 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) {
6675 /* POSIX - no stream component. */
6676 orig_lcomp_path
= talloc_strdup(ctx
,
6677 smb_fname_dst
->original_lcomp
);
6678 if (orig_lcomp_path
== NULL
) {
6682 ok
= split_stream_filename(ctx
,
6683 smb_fname_dst
->original_lcomp
,
6685 &orig_lcomp_stream
);
6689 TALLOC_FREE(fname_dst_parent
);
6690 status
= NT_STATUS_NO_MEMORY
;
6694 /* If the base names only differ by case, use original. */
6695 if(!strcsequal(fname_dst_lcomp
, orig_lcomp_path
)) {
6698 * Replace the modified last component with the
6701 if (!ISDOT(fname_dst_parent
)) {
6702 tmp
= talloc_asprintf(smb_fname_dst
,
6707 tmp
= talloc_strdup(smb_fname_dst
,
6711 status
= NT_STATUS_NO_MEMORY
;
6712 TALLOC_FREE(fname_dst_parent
);
6713 TALLOC_FREE(orig_lcomp_path
);
6714 TALLOC_FREE(orig_lcomp_stream
);
6717 TALLOC_FREE(smb_fname_dst
->base_name
);
6718 smb_fname_dst
->base_name
= tmp
;
6721 /* If the stream_names only differ by case, use original. */
6722 if(!strcsequal(smb_fname_dst
->stream_name
,
6723 orig_lcomp_stream
)) {
6724 /* Use the original stream. */
6725 char *tmp
= talloc_strdup(smb_fname_dst
,
6728 status
= NT_STATUS_NO_MEMORY
;
6729 TALLOC_FREE(fname_dst_parent
);
6730 TALLOC_FREE(orig_lcomp_path
);
6731 TALLOC_FREE(orig_lcomp_stream
);
6734 TALLOC_FREE(smb_fname_dst
->stream_name
);
6735 smb_fname_dst
->stream_name
= tmp
;
6737 TALLOC_FREE(fname_dst_parent
);
6738 TALLOC_FREE(orig_lcomp_path
);
6739 TALLOC_FREE(orig_lcomp_stream
);
6743 * If the src and dest names are identical - including case,
6744 * don't do the rename, just return success.
6747 if (strcsequal(fsp
->fsp_name
->base_name
, smb_fname_dst
->base_name
) &&
6748 strcsequal(fsp
->fsp_name
->stream_name
,
6749 smb_fname_dst
->stream_name
)) {
6750 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6751 "- returning success\n",
6752 smb_fname_str_dbg(smb_fname_dst
)));
6753 status
= NT_STATUS_OK
;
6757 old_is_stream
= is_ntfs_stream_smb_fname(fsp
->fsp_name
);
6758 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
6760 /* Return the correct error code if both names aren't streams. */
6761 if (!old_is_stream
&& new_is_stream
) {
6762 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6766 if (old_is_stream
&& !new_is_stream
) {
6767 status
= NT_STATUS_INVALID_PARAMETER
;
6771 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
6773 if(!replace_if_exists
&& dst_exists
) {
6774 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6775 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6776 smb_fname_str_dbg(smb_fname_dst
)));
6777 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6782 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6783 &smb_fname_dst
->st
);
6784 files_struct
*dst_fsp
= file_find_di_first(conn
->sconn
,
6786 /* The file can be open when renaming a stream */
6787 if (dst_fsp
&& !new_is_stream
) {
6788 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6789 status
= NT_STATUS_ACCESS_DENIED
;
6794 /* Ensure we have a valid stat struct for the source. */
6795 status
= vfs_stat_fsp(fsp
);
6796 if (!NT_STATUS_IS_OK(status
)) {
6800 status
= can_rename(conn
, fsp
, attrs
);
6802 if (!NT_STATUS_IS_OK(status
)) {
6803 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6804 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6805 smb_fname_str_dbg(smb_fname_dst
)));
6806 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6807 status
= NT_STATUS_ACCESS_DENIED
;
6811 if (rename_path_prefix_equal(fsp
->fsp_name
, smb_fname_dst
)) {
6812 status
= NT_STATUS_ACCESS_DENIED
;
6815 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6818 * We have the file open ourselves, so not being able to get the
6819 * corresponding share mode lock is a fatal error.
6822 SMB_ASSERT(lck
!= NULL
);
6824 if(SMB_VFS_RENAME(conn
, fsp
->fsp_name
, smb_fname_dst
) == 0) {
6825 uint32_t create_options
= fsp
->fh
->private_options
;
6827 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6828 "%s -> %s\n", smb_fname_str_dbg(fsp
->fsp_name
),
6829 smb_fname_str_dbg(smb_fname_dst
)));
6831 if (!fsp
->is_directory
&&
6832 !(fsp
->posix_flags
& FSP_POSIX_FLAGS_PATHNAMES
) &&
6833 (lp_map_archive(SNUM(conn
)) ||
6834 lp_store_dos_attributes(SNUM(conn
)))) {
6835 /* We must set the archive bit on the newly
6837 if (SMB_VFS_STAT(conn
, smb_fname_dst
) == 0) {
6838 uint32_t old_dosmode
= dos_mode(conn
,
6840 file_set_dosmode(conn
,
6842 old_dosmode
| FILE_ATTRIBUTE_ARCHIVE
,
6848 notify_rename(conn
, fsp
->is_directory
, fsp
->fsp_name
,
6851 rename_open_files(conn
, lck
, fsp
->file_id
, fsp
->name_hash
,
6855 * A rename acts as a new file create w.r.t. allowing an initial delete
6856 * on close, probably because in Windows there is a new handle to the
6857 * new file. If initial delete on close was requested but not
6858 * originally set, we need to set it here. This is probably not 100% correct,
6859 * but will work for the CIFSFS client which in non-posix mode
6860 * depends on these semantics. JRA.
6863 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6864 status
= can_set_delete_on_close(fsp
, 0);
6866 if (NT_STATUS_IS_OK(status
)) {
6867 /* Note that here we set the *inital* delete on close flag,
6868 * not the regular one. The magic gets handled in close. */
6869 fsp
->initial_delete_on_close
= True
;
6873 status
= NT_STATUS_OK
;
6879 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6880 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6882 status
= map_nt_error_from_unix(errno
);
6885 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6886 nt_errstr(status
), smb_fname_str_dbg(fsp
->fsp_name
),
6887 smb_fname_str_dbg(smb_fname_dst
)));
6890 TALLOC_FREE(smb_fname_dst
);
6895 /****************************************************************************
6896 The guts of the rename command, split out so it may be called by the NT SMB
6898 ****************************************************************************/
6900 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6901 connection_struct
*conn
,
6902 struct smb_request
*req
,
6903 struct smb_filename
*smb_fname_src
,
6904 struct smb_filename
*smb_fname_dst
,
6906 bool replace_if_exists
,
6909 uint32_t access_mask
)
6911 char *fname_src_dir
= NULL
;
6912 struct smb_filename
*smb_fname_src_dir
= NULL
;
6913 char *fname_src_mask
= NULL
;
6915 NTSTATUS status
= NT_STATUS_OK
;
6916 struct smb_Dir
*dir_hnd
= NULL
;
6917 const char *dname
= NULL
;
6918 char *talloced
= NULL
;
6920 int create_options
= 0;
6921 bool posix_pathnames
= (req
!= NULL
&& req
->posix_pathnames
);
6925 * Split the old name into directory and last component
6926 * strings. Note that unix_convert may have stripped off a
6927 * leading ./ from both name and newname if the rename is
6928 * at the root of the share. We need to make sure either both
6929 * name and newname contain a / character or neither of them do
6930 * as this is checked in resolve_wildcards().
6933 /* Split up the directory from the filename/mask. */
6934 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6935 &fname_src_dir
, &fname_src_mask
);
6936 if (!NT_STATUS_IS_OK(status
)) {
6937 status
= NT_STATUS_NO_MEMORY
;
6942 * We should only check the mangled cache
6943 * here if unix_convert failed. This means
6944 * that the path in 'mask' doesn't exist
6945 * on the file system and so we need to look
6946 * for a possible mangle. This patch from
6947 * Tine Smukavec <valentin.smukavec@hermes.si>.
6950 if (!VALID_STAT(smb_fname_src
->st
) &&
6951 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6952 char *new_mask
= NULL
;
6953 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6956 TALLOC_FREE(fname_src_mask
);
6957 fname_src_mask
= new_mask
;
6961 if (!src_has_wild
) {
6965 * Only one file needs to be renamed. Append the mask back
6966 * onto the directory.
6968 TALLOC_FREE(smb_fname_src
->base_name
);
6969 if (ISDOT(fname_src_dir
)) {
6970 /* Ensure we use canonical names on open. */
6971 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6975 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6980 if (!smb_fname_src
->base_name
) {
6981 status
= NT_STATUS_NO_MEMORY
;
6985 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6986 "case_preserve = %d, short case preserve = %d, "
6987 "directory = %s, newname = %s, "
6988 "last_component_dest = %s\n",
6989 conn
->case_sensitive
, conn
->case_preserve
,
6990 conn
->short_case_preserve
,
6991 smb_fname_str_dbg(smb_fname_src
),
6992 smb_fname_str_dbg(smb_fname_dst
),
6993 smb_fname_dst
->original_lcomp
));
6995 /* The dest name still may have wildcards. */
6996 if (dest_has_wild
) {
6997 char *fname_dst_mod
= NULL
;
6998 if (!resolve_wildcards(smb_fname_dst
,
6999 smb_fname_src
->base_name
,
7000 smb_fname_dst
->base_name
,
7002 DEBUG(6, ("rename_internals: resolve_wildcards "
7004 smb_fname_src
->base_name
,
7005 smb_fname_dst
->base_name
));
7006 status
= NT_STATUS_NO_MEMORY
;
7009 TALLOC_FREE(smb_fname_dst
->base_name
);
7010 smb_fname_dst
->base_name
= fname_dst_mod
;
7013 ZERO_STRUCT(smb_fname_src
->st
);
7014 if (posix_pathnames
) {
7015 rc
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
7017 rc
= SMB_VFS_STAT(conn
, smb_fname_src
);
7020 status
= map_nt_error_from_unix_common(errno
);
7024 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7025 create_options
|= FILE_DIRECTORY_FILE
;
7028 status
= SMB_VFS_CREATE_FILE(
7031 0, /* root_dir_fid */
7032 smb_fname_src
, /* fname */
7033 access_mask
, /* access_mask */
7034 (FILE_SHARE_READ
| /* share_access */
7036 FILE_OPEN
, /* create_disposition*/
7037 create_options
, /* create_options */
7038 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7039 0, /* oplock_request */
7041 0, /* allocation_size */
7042 0, /* private_flags */
7047 NULL
, NULL
); /* create context */
7049 if (!NT_STATUS_IS_OK(status
)) {
7050 DEBUG(3, ("Could not open rename source %s: %s\n",
7051 smb_fname_str_dbg(smb_fname_src
),
7052 nt_errstr(status
)));
7056 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7057 attrs
, replace_if_exists
);
7059 close_file(req
, fsp
, NORMAL_CLOSE
);
7061 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7062 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
7063 smb_fname_str_dbg(smb_fname_dst
)));
7069 * Wildcards - process each file that matches.
7071 if (strequal(fname_src_mask
, "????????.???")) {
7072 TALLOC_FREE(fname_src_mask
);
7073 fname_src_mask
= talloc_strdup(ctx
, "*");
7074 if (!fname_src_mask
) {
7075 status
= NT_STATUS_NO_MEMORY
;
7080 status
= check_name(conn
, fname_src_dir
);
7081 if (!NT_STATUS_IS_OK(status
)) {
7085 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7089 smb_fname_src
->flags
);
7090 if (smb_fname_src_dir
== NULL
) {
7091 status
= NT_STATUS_NO_MEMORY
;
7095 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_fname_src_dir
, fname_src_mask
,
7097 if (dir_hnd
== NULL
) {
7098 status
= map_nt_error_from_unix(errno
);
7102 status
= NT_STATUS_NO_SUCH_FILE
;
7104 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7105 * - gentest fix. JRA
7108 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
,
7110 files_struct
*fsp
= NULL
;
7111 char *destname
= NULL
;
7112 bool sysdir_entry
= False
;
7114 /* Quick check for "." and ".." */
7115 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7116 if (attrs
& FILE_ATTRIBUTE_DIRECTORY
) {
7117 sysdir_entry
= True
;
7119 TALLOC_FREE(talloced
);
7124 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7125 &smb_fname_src
->st
, false)) {
7126 TALLOC_FREE(talloced
);
7130 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
7131 TALLOC_FREE(talloced
);
7136 status
= NT_STATUS_OBJECT_NAME_INVALID
;
7140 TALLOC_FREE(smb_fname_src
->base_name
);
7141 if (ISDOT(fname_src_dir
)) {
7142 /* Ensure we use canonical names on open. */
7143 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7147 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7152 if (!smb_fname_src
->base_name
) {
7153 status
= NT_STATUS_NO_MEMORY
;
7157 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7158 smb_fname_dst
->base_name
,
7160 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7161 smb_fname_src
->base_name
, destname
));
7162 TALLOC_FREE(talloced
);
7166 status
= NT_STATUS_NO_MEMORY
;
7170 TALLOC_FREE(smb_fname_dst
->base_name
);
7171 smb_fname_dst
->base_name
= destname
;
7173 ZERO_STRUCT(smb_fname_src
->st
);
7174 if (posix_pathnames
) {
7175 SMB_VFS_LSTAT(conn
, smb_fname_src
);
7177 SMB_VFS_STAT(conn
, smb_fname_src
);
7182 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
7183 create_options
|= FILE_DIRECTORY_FILE
;
7186 status
= SMB_VFS_CREATE_FILE(
7189 0, /* root_dir_fid */
7190 smb_fname_src
, /* fname */
7191 access_mask
, /* access_mask */
7192 (FILE_SHARE_READ
| /* share_access */
7194 FILE_OPEN
, /* create_disposition*/
7195 create_options
, /* create_options */
7196 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
7197 0, /* oplock_request */
7199 0, /* allocation_size */
7200 0, /* private_flags */
7205 NULL
, NULL
); /* create context */
7207 if (!NT_STATUS_IS_OK(status
)) {
7208 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7209 "returned %s rename %s -> %s\n",
7211 smb_fname_str_dbg(smb_fname_src
),
7212 smb_fname_str_dbg(smb_fname_dst
)));
7216 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
7218 if (!smb_fname_dst
->original_lcomp
) {
7219 status
= NT_STATUS_NO_MEMORY
;
7223 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
7224 attrs
, replace_if_exists
);
7226 close_file(req
, fsp
, NORMAL_CLOSE
);
7228 if (!NT_STATUS_IS_OK(status
)) {
7229 DEBUG(3, ("rename_internals_fsp returned %s for "
7230 "rename %s -> %s\n", nt_errstr(status
),
7231 smb_fname_str_dbg(smb_fname_src
),
7232 smb_fname_str_dbg(smb_fname_dst
)));
7238 DEBUG(3,("rename_internals: doing rename on %s -> "
7239 "%s\n", smb_fname_str_dbg(smb_fname_src
),
7240 smb_fname_str_dbg(smb_fname_src
)));
7241 TALLOC_FREE(talloced
);
7243 TALLOC_FREE(dir_hnd
);
7245 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
7246 status
= map_nt_error_from_unix(errno
);
7250 TALLOC_FREE(talloced
);
7251 TALLOC_FREE(smb_fname_src_dir
);
7252 TALLOC_FREE(fname_src_dir
);
7253 TALLOC_FREE(fname_src_mask
);
7257 /****************************************************************************
7259 ****************************************************************************/
7261 void reply_mv(struct smb_request
*req
)
7263 connection_struct
*conn
= req
->conn
;
7265 char *newname
= NULL
;
7269 bool src_has_wcard
= False
;
7270 bool dest_has_wcard
= False
;
7271 TALLOC_CTX
*ctx
= talloc_tos();
7272 struct smb_filename
*smb_fname_src
= NULL
;
7273 struct smb_filename
*smb_fname_dst
= NULL
;
7274 uint32_t src_ucf_flags
= (req
->posix_pathnames
?
7275 (UCF_UNIX_NAME_LOOKUP
|UCF_POSIX_PATHNAMES
) :
7276 UCF_COND_ALLOW_WCARD_LCOMP
);
7277 uint32_t dst_ucf_flags
= UCF_SAVE_LCOMP
|
7278 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
:
7279 UCF_COND_ALLOW_WCARD_LCOMP
);
7280 bool stream_rename
= false;
7282 START_PROFILE(SMBmv
);
7285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7289 attrs
= SVAL(req
->vwv
+0, 0);
7291 p
= (const char *)req
->buf
+ 1;
7292 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
7293 &status
, &src_has_wcard
);
7294 if (!NT_STATUS_IS_OK(status
)) {
7295 reply_nterror(req
, status
);
7299 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
7300 &status
, &dest_has_wcard
);
7301 if (!NT_STATUS_IS_OK(status
)) {
7302 reply_nterror(req
, status
);
7306 if (!req
->posix_pathnames
) {
7307 /* The newname must begin with a ':' if the
7308 name contains a ':'. */
7309 if (strchr_m(name
, ':')) {
7310 if (newname
[0] != ':') {
7311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7314 stream_rename
= true;
7318 status
= filename_convert(ctx
,
7320 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7326 if (!NT_STATUS_IS_OK(status
)) {
7327 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7328 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7329 ERRSRV
, ERRbadpath
);
7332 reply_nterror(req
, status
);
7336 status
= filename_convert(ctx
,
7338 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7344 if (!NT_STATUS_IS_OK(status
)) {
7345 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7346 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7347 ERRSRV
, ERRbadpath
);
7350 reply_nterror(req
, status
);
7354 if (stream_rename
) {
7355 /* smb_fname_dst->base_name must be the same as
7356 smb_fname_src->base_name. */
7357 TALLOC_FREE(smb_fname_dst
->base_name
);
7358 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
7359 smb_fname_src
->base_name
);
7360 if (!smb_fname_dst
->base_name
) {
7361 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7366 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
7367 smb_fname_str_dbg(smb_fname_dst
)));
7369 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
7370 attrs
, False
, src_has_wcard
, dest_has_wcard
,
7372 if (!NT_STATUS_IS_OK(status
)) {
7373 if (open_was_deferred(req
->xconn
, req
->mid
)) {
7374 /* We have re-scheduled this call. */
7377 reply_nterror(req
, status
);
7381 reply_outbuf(req
, 0, 0);
7383 TALLOC_FREE(smb_fname_src
);
7384 TALLOC_FREE(smb_fname_dst
);
7389 /*******************************************************************
7390 Copy a file as part of a reply_copy.
7391 ******************************************************************/
7394 * TODO: check error codes on all callers
7397 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
7398 connection_struct
*conn
,
7399 struct smb_filename
*smb_fname_src
,
7400 struct smb_filename
*smb_fname_dst
,
7403 bool target_is_directory
)
7405 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
7407 files_struct
*fsp1
,*fsp2
;
7409 uint32_t new_create_disposition
;
7413 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
7414 if (smb_fname_dst_tmp
== NULL
) {
7415 return NT_STATUS_NO_MEMORY
;
7419 * If the target is a directory, extract the last component from the
7420 * src filename and append it to the dst filename
7422 if (target_is_directory
) {
7425 /* dest/target can't be a stream if it's a directory. */
7426 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
7428 p
= strrchr_m(smb_fname_src
->base_name
,'/');
7432 p
= smb_fname_src
->base_name
;
7434 smb_fname_dst_tmp
->base_name
=
7435 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
7437 if (!smb_fname_dst_tmp
->base_name
) {
7438 status
= NT_STATUS_NO_MEMORY
;
7443 status
= vfs_file_exist(conn
, smb_fname_src
);
7444 if (!NT_STATUS_IS_OK(status
)) {
7448 if (!target_is_directory
&& count
) {
7449 new_create_disposition
= FILE_OPEN
;
7451 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
->base_name
,
7454 &new_create_disposition
,
7457 status
= NT_STATUS_INVALID_PARAMETER
;
7462 /* Open the src file for reading. */
7463 status
= SMB_VFS_CREATE_FILE(
7466 0, /* root_dir_fid */
7467 smb_fname_src
, /* fname */
7468 FILE_GENERIC_READ
, /* access_mask */
7469 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7470 FILE_OPEN
, /* create_disposition*/
7471 0, /* create_options */
7472 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7473 INTERNAL_OPEN_ONLY
, /* oplock_request */
7475 0, /* allocation_size */
7476 0, /* private_flags */
7481 NULL
, NULL
); /* create context */
7483 if (!NT_STATUS_IS_OK(status
)) {
7487 dosattrs
= dos_mode(conn
, smb_fname_src
);
7489 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
7490 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
7493 /* Open the dst file for writing. */
7494 status
= SMB_VFS_CREATE_FILE(
7497 0, /* root_dir_fid */
7498 smb_fname_dst
, /* fname */
7499 FILE_GENERIC_WRITE
, /* access_mask */
7500 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
7501 new_create_disposition
, /* create_disposition*/
7502 0, /* create_options */
7503 dosattrs
, /* file_attributes */
7504 INTERNAL_OPEN_ONLY
, /* oplock_request */
7506 0, /* allocation_size */
7507 0, /* private_flags */
7512 NULL
, NULL
); /* create context */
7514 if (!NT_STATUS_IS_OK(status
)) {
7515 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7519 if (ofun
& OPENX_FILE_EXISTS_OPEN
) {
7520 ret
= SMB_VFS_LSEEK(fsp2
, 0, SEEK_END
);
7522 DEBUG(0, ("error - vfs lseek returned error %s\n",
7524 status
= map_nt_error_from_unix(errno
);
7525 close_file(NULL
, fsp1
, ERROR_CLOSE
);
7526 close_file(NULL
, fsp2
, ERROR_CLOSE
);
7531 /* Do the actual copy. */
7532 if (smb_fname_src
->st
.st_ex_size
) {
7533 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
7538 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
7540 /* Ensure the modtime is set correctly on the destination file. */
7541 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
7544 * As we are opening fsp1 read-only we only expect
7545 * an error on close on fsp2 if we are out of space.
7546 * Thus we don't look at the error return from the
7549 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
7551 if (!NT_STATUS_IS_OK(status
)) {
7555 if (ret
!= (off_t
)smb_fname_src
->st
.st_ex_size
) {
7556 status
= NT_STATUS_DISK_FULL
;
7560 status
= NT_STATUS_OK
;
7563 TALLOC_FREE(smb_fname_dst_tmp
);
7567 /****************************************************************************
7568 Reply to a file copy.
7569 ****************************************************************************/
7571 void reply_copy(struct smb_request
*req
)
7573 connection_struct
*conn
= req
->conn
;
7574 struct smb_filename
*smb_fname_src
= NULL
;
7575 struct smb_filename
*smb_fname_src_dir
= NULL
;
7576 struct smb_filename
*smb_fname_dst
= NULL
;
7577 char *fname_src
= NULL
;
7578 char *fname_dst
= NULL
;
7579 char *fname_src_mask
= NULL
;
7580 char *fname_src_dir
= NULL
;
7583 int error
= ERRnoaccess
;
7587 bool target_is_directory
=False
;
7588 bool source_has_wild
= False
;
7589 bool dest_has_wild
= False
;
7591 uint32_t ucf_flags_src
= UCF_COND_ALLOW_WCARD_LCOMP
|
7592 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7593 uint32_t ucf_flags_dst
= UCF_COND_ALLOW_WCARD_LCOMP
|
7594 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
7595 TALLOC_CTX
*ctx
= talloc_tos();
7597 START_PROFILE(SMBcopy
);
7600 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7604 tid2
= SVAL(req
->vwv
+0, 0);
7605 ofun
= SVAL(req
->vwv
+1, 0);
7606 flags
= SVAL(req
->vwv
+2, 0);
7608 p
= (const char *)req
->buf
;
7609 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
7610 &status
, &source_has_wild
);
7611 if (!NT_STATUS_IS_OK(status
)) {
7612 reply_nterror(req
, status
);
7615 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
7616 &status
, &dest_has_wild
);
7617 if (!NT_STATUS_IS_OK(status
)) {
7618 reply_nterror(req
, status
);
7622 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
7624 if (tid2
!= conn
->cnum
) {
7625 /* can't currently handle inter share copies XXXX */
7626 DEBUG(3,("Rejecting inter-share copy\n"));
7627 reply_nterror(req
, NT_STATUS_BAD_DEVICE_TYPE
);
7631 status
= filename_convert(ctx
, conn
,
7632 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7637 if (!NT_STATUS_IS_OK(status
)) {
7638 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7639 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7640 ERRSRV
, ERRbadpath
);
7643 reply_nterror(req
, status
);
7647 status
= filename_convert(ctx
, conn
,
7648 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
7653 if (!NT_STATUS_IS_OK(status
)) {
7654 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
7655 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
7656 ERRSRV
, ERRbadpath
);
7659 reply_nterror(req
, status
);
7663 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
7665 if ((flags
&1) && target_is_directory
) {
7666 reply_nterror(req
, NT_STATUS_NO_SUCH_FILE
);
7670 if ((flags
&2) && !target_is_directory
) {
7671 reply_nterror(req
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
7675 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
7676 /* wants a tree copy! XXXX */
7677 DEBUG(3,("Rejecting tree copy\n"));
7678 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7682 /* Split up the directory from the filename/mask. */
7683 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
7684 &fname_src_dir
, &fname_src_mask
);
7685 if (!NT_STATUS_IS_OK(status
)) {
7686 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7691 * We should only check the mangled cache
7692 * here if unix_convert failed. This means
7693 * that the path in 'mask' doesn't exist
7694 * on the file system and so we need to look
7695 * for a possible mangle. This patch from
7696 * Tine Smukavec <valentin.smukavec@hermes.si>.
7698 if (!VALID_STAT(smb_fname_src
->st
) &&
7699 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
7700 char *new_mask
= NULL
;
7701 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
7702 &new_mask
, conn
->params
);
7704 /* Use demangled name if one was successfully found. */
7706 TALLOC_FREE(fname_src_mask
);
7707 fname_src_mask
= new_mask
;
7711 if (!source_has_wild
) {
7714 * Only one file needs to be copied. Append the mask back onto
7717 TALLOC_FREE(smb_fname_src
->base_name
);
7718 if (ISDOT(fname_src_dir
)) {
7719 /* Ensure we use canonical names on open. */
7720 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7724 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
7729 if (!smb_fname_src
->base_name
) {
7730 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7734 if (dest_has_wild
) {
7735 char *fname_dst_mod
= NULL
;
7736 if (!resolve_wildcards(smb_fname_dst
,
7737 smb_fname_src
->base_name
,
7738 smb_fname_dst
->base_name
,
7740 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7743 TALLOC_FREE(smb_fname_dst
->base_name
);
7744 smb_fname_dst
->base_name
= fname_dst_mod
;
7747 status
= check_name(conn
, smb_fname_src
->base_name
);
7748 if (!NT_STATUS_IS_OK(status
)) {
7749 reply_nterror(req
, status
);
7753 status
= check_name(conn
, smb_fname_dst
->base_name
);
7754 if (!NT_STATUS_IS_OK(status
)) {
7755 reply_nterror(req
, status
);
7759 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
7760 ofun
, count
, target_is_directory
);
7762 if(!NT_STATUS_IS_OK(status
)) {
7763 reply_nterror(req
, status
);
7769 struct smb_Dir
*dir_hnd
= NULL
;
7770 const char *dname
= NULL
;
7771 char *talloced
= NULL
;
7775 * There is a wildcard that requires us to actually read the
7776 * src dir and copy each file matching the mask to the dst.
7777 * Right now streams won't be copied, but this could
7778 * presumably be added with a nested loop for reach dir entry.
7780 SMB_ASSERT(!smb_fname_src
->stream_name
);
7781 SMB_ASSERT(!smb_fname_dst
->stream_name
);
7783 smb_fname_src
->stream_name
= NULL
;
7784 smb_fname_dst
->stream_name
= NULL
;
7786 if (strequal(fname_src_mask
,"????????.???")) {
7787 TALLOC_FREE(fname_src_mask
);
7788 fname_src_mask
= talloc_strdup(ctx
, "*");
7789 if (!fname_src_mask
) {
7790 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7795 status
= check_name(conn
, fname_src_dir
);
7796 if (!NT_STATUS_IS_OK(status
)) {
7797 reply_nterror(req
, status
);
7801 smb_fname_src_dir
= synthetic_smb_fname(talloc_tos(),
7805 smb_fname_src
->flags
);
7806 if (smb_fname_src_dir
== NULL
) {
7807 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7811 dir_hnd
= OpenDir(ctx
,
7816 if (dir_hnd
== NULL
) {
7817 status
= map_nt_error_from_unix(errno
);
7818 reply_nterror(req
, status
);
7824 /* Iterate over the src dir copying each entry to the dst. */
7825 while ((dname
= ReadDirName(dir_hnd
, &offset
,
7826 &smb_fname_src
->st
, &talloced
))) {
7827 char *destname
= NULL
;
7829 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
7830 TALLOC_FREE(talloced
);
7834 if (!is_visible_file(conn
, fname_src_dir
, dname
,
7835 &smb_fname_src
->st
, false)) {
7836 TALLOC_FREE(talloced
);
7840 if(!mask_match(dname
, fname_src_mask
,
7841 conn
->case_sensitive
)) {
7842 TALLOC_FREE(talloced
);
7846 error
= ERRnoaccess
;
7848 /* Get the src smb_fname struct setup. */
7849 TALLOC_FREE(smb_fname_src
->base_name
);
7850 if (ISDOT(fname_src_dir
)) {
7851 /* Ensure we use canonical names on open. */
7852 smb_fname_src
->base_name
=
7853 talloc_asprintf(smb_fname_src
, "%s",
7856 smb_fname_src
->base_name
=
7857 talloc_asprintf(smb_fname_src
, "%s/%s",
7858 fname_src_dir
, dname
);
7861 if (!smb_fname_src
->base_name
) {
7862 TALLOC_FREE(dir_hnd
);
7863 TALLOC_FREE(talloced
);
7864 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7868 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
7869 smb_fname_dst
->base_name
,
7871 TALLOC_FREE(talloced
);
7875 TALLOC_FREE(dir_hnd
);
7876 TALLOC_FREE(talloced
);
7877 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7881 TALLOC_FREE(smb_fname_dst
->base_name
);
7882 smb_fname_dst
->base_name
= destname
;
7884 status
= check_name(conn
, smb_fname_src
->base_name
);
7885 if (!NT_STATUS_IS_OK(status
)) {
7886 TALLOC_FREE(dir_hnd
);
7887 TALLOC_FREE(talloced
);
7888 reply_nterror(req
, status
);
7892 status
= check_name(conn
, smb_fname_dst
->base_name
);
7893 if (!NT_STATUS_IS_OK(status
)) {
7894 TALLOC_FREE(dir_hnd
);
7895 TALLOC_FREE(talloced
);
7896 reply_nterror(req
, status
);
7900 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7901 smb_fname_src
->base_name
,
7902 smb_fname_dst
->base_name
));
7904 status
= copy_file(ctx
, conn
, smb_fname_src
,
7905 smb_fname_dst
, ofun
, count
,
7906 target_is_directory
);
7907 if (NT_STATUS_IS_OK(status
)) {
7911 TALLOC_FREE(talloced
);
7913 TALLOC_FREE(dir_hnd
);
7917 reply_nterror(req
, dos_to_ntstatus(ERRDOS
, error
));
7921 reply_outbuf(req
, 1, 0);
7922 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7924 TALLOC_FREE(smb_fname_src
);
7925 TALLOC_FREE(smb_fname_src_dir
);
7926 TALLOC_FREE(smb_fname_dst
);
7927 TALLOC_FREE(fname_src
);
7928 TALLOC_FREE(fname_dst
);
7929 TALLOC_FREE(fname_src_mask
);
7930 TALLOC_FREE(fname_src_dir
);
7932 END_PROFILE(SMBcopy
);
7937 #define DBGC_CLASS DBGC_LOCKING
7939 /****************************************************************************
7940 Get a lock pid, dealing with large count requests.
7941 ****************************************************************************/
7943 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
7944 bool large_file_format
)
7946 if(!large_file_format
)
7947 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7949 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7952 /****************************************************************************
7953 Get a lock count, dealing with large count requests.
7954 ****************************************************************************/
7956 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7957 bool large_file_format
)
7961 if(!large_file_format
) {
7962 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7965 * No BVAL, this is reversed!
7967 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7968 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7974 /****************************************************************************
7975 Get a lock offset, dealing with large offset requests.
7976 ****************************************************************************/
7978 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7979 bool large_file_format
)
7981 uint64_t offset
= 0;
7983 if(!large_file_format
) {
7984 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7987 * No BVAL, this is reversed!
7989 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7990 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7996 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
8001 struct smbd_lock_element
*locks
,
8004 connection_struct
*conn
= req
->conn
;
8006 NTSTATUS status
= NT_STATUS_OK
;
8010 /* Setup the timeout in seconds. */
8012 if (!lp_blocking_locks(SNUM(conn
))) {
8016 for(i
= 0; i
< (int)num_locks
; i
++) {
8017 struct smbd_lock_element
*e
= &locks
[i
];
8019 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8020 "%llu, file %s timeout = %d\n",
8023 (unsigned long long)e
->smblctx
,
8027 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8028 struct blocking_lock_record
*blr
= NULL
;
8030 if (num_locks
> 1) {
8032 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8033 * if the lock vector contains one entry. When given multiple cancel
8034 * requests in a single PDU we expect the server to return an
8035 * error. Windows servers seem to accept the request but only
8036 * cancel the first lock.
8037 * JRA - Do what Windows does (tm) :-).
8041 /* MS-CIFS (2.2.4.32.1) behavior. */
8042 return NT_STATUS_DOS(ERRDOS
,
8043 ERRcancelviolation
);
8045 /* Windows behavior. */
8047 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8048 "cancel request\n"));
8054 if (lp_blocking_locks(SNUM(conn
))) {
8056 /* Schedule a message to ourselves to
8057 remove the blocking lock record and
8058 return the right error. */
8060 blr
= blocking_lock_cancel_smb1(fsp
,
8066 NT_STATUS_FILE_LOCK_CONFLICT
);
8068 return NT_STATUS_DOS(
8070 ERRcancelviolation
);
8073 /* Remove a matching pending lock. */
8074 status
= do_lock_cancel(fsp
,
8080 bool blocking_lock
= timeout
? true : false;
8081 bool defer_lock
= false;
8082 struct byte_range_lock
*br_lck
;
8083 uint64_t block_smblctx
;
8085 br_lck
= do_lock(req
->sconn
->msg_ctx
,
8096 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
8097 /* Windows internal resolution for blocking locks seems
8098 to be about 200ms... Don't wait for less than that. JRA. */
8099 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
8100 timeout
= lp_lock_spin_time();
8105 /* If a lock sent with timeout of zero would fail, and
8106 * this lock has been requested multiple times,
8107 * according to brl_lock_failed() we convert this
8108 * request to a blocking lock with a timeout of between
8109 * 150 - 300 milliseconds.
8111 * If lp_lock_spin_time() has been set to 0, we skip
8112 * this blocking retry and fail immediately.
8114 * Replacement for do_lock_spin(). JRA. */
8116 if (!req
->sconn
->using_smb2
&&
8117 br_lck
&& lp_blocking_locks(SNUM(conn
)) &&
8118 lp_lock_spin_time() && !blocking_lock
&&
8119 NT_STATUS_EQUAL((status
),
8120 NT_STATUS_FILE_LOCK_CONFLICT
))
8123 timeout
= lp_lock_spin_time();
8126 if (br_lck
&& defer_lock
) {
8128 * A blocking lock was requested. Package up
8129 * this smb into a queued request and push it
8130 * onto the blocking lock queue.
8132 if(push_blocking_lock_request(br_lck
,
8143 TALLOC_FREE(br_lck
);
8145 return NT_STATUS_OK
;
8149 TALLOC_FREE(br_lck
);
8152 if (!NT_STATUS_IS_OK(status
)) {
8157 /* If any of the above locks failed, then we must unlock
8158 all of the previous locks (X/Open spec). */
8160 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
8162 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
8163 i
= -1; /* we want to skip the for loop */
8167 * Ensure we don't do a remove on the lock that just failed,
8168 * as under POSIX rules, if we have a lock already there, we
8169 * will delete it (and we shouldn't) .....
8171 for(i
--; i
>= 0; i
--) {
8172 struct smbd_lock_element
*e
= &locks
[i
];
8174 do_unlock(req
->sconn
->msg_ctx
,
8184 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8185 fsp_fnum_dbg(fsp
), (unsigned int)type
, num_locks
));
8187 return NT_STATUS_OK
;
8190 NTSTATUS
smbd_do_unlocking(struct smb_request
*req
,
8192 uint16_t num_ulocks
,
8193 struct smbd_lock_element
*ulocks
)
8197 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8198 struct smbd_lock_element
*e
= &ulocks
[i
];
8201 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8202 "pid %u, file %s\n", __func__
,
8205 (unsigned int)e
->smblctx
,
8208 if (e
->brltype
!= UNLOCK_LOCK
) {
8209 /* this can only happen with SMB2 */
8210 return NT_STATUS_INVALID_PARAMETER
;
8213 status
= do_unlock(req
->sconn
->msg_ctx
,
8220 DEBUG(10, ("%s: unlock returned %s\n", __func__
,
8221 nt_errstr(status
)));
8223 if (!NT_STATUS_IS_OK(status
)) {
8228 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__
, fsp_fnum_dbg(fsp
),
8231 return NT_STATUS_OK
;
8234 /****************************************************************************
8235 Reply to a lockingX request.
8236 ****************************************************************************/
8238 void reply_lockingX(struct smb_request
*req
)
8240 connection_struct
*conn
= req
->conn
;
8242 unsigned char locktype
;
8243 unsigned char oplocklevel
;
8244 uint16_t num_ulocks
;
8246 int32_t lock_timeout
;
8248 const uint8_t *data
;
8249 bool large_file_format
;
8250 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
8251 struct smbd_lock_element
*ulocks
;
8252 struct smbd_lock_element
*locks
;
8255 START_PROFILE(SMBlockingX
);
8258 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8259 END_PROFILE(SMBlockingX
);
8263 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
8264 locktype
= CVAL(req
->vwv
+3, 0);
8265 oplocklevel
= CVAL(req
->vwv
+3, 1);
8266 num_ulocks
= SVAL(req
->vwv
+6, 0);
8267 num_locks
= SVAL(req
->vwv
+7, 0);
8268 lock_timeout
= IVAL(req
->vwv
+4, 0);
8269 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
8271 if (!check_fsp(conn
, req
, fsp
)) {
8272 END_PROFILE(SMBlockingX
);
8278 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
8279 /* we don't support these - and CANCEL_LOCK makes w2k
8280 and XP reboot so I don't really want to be
8281 compatible! (tridge) */
8282 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
8283 END_PROFILE(SMBlockingX
);
8287 /* Check if this is an oplock break on a file
8288 we have granted an oplock on.
8290 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
8291 /* Client can insist on breaking to none. */
8292 bool break_to_none
= (oplocklevel
== 0);
8295 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8296 "for %s\n", (unsigned int)oplocklevel
,
8297 fsp_fnum_dbg(fsp
)));
8300 * Make sure we have granted an exclusive or batch oplock on
8304 if (fsp
->oplock_type
== 0) {
8306 /* The Samba4 nbench simulator doesn't understand
8307 the difference between break to level2 and break
8308 to none from level2 - it sends oplock break
8309 replies in both cases. Don't keep logging an error
8310 message here - just ignore it. JRA. */
8312 DEBUG(5,("reply_lockingX: Error : oplock break from "
8313 "client for %s (oplock=%d) and no "
8314 "oplock granted on this file (%s).\n",
8315 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
8318 /* if this is a pure oplock break request then don't
8320 if (num_locks
== 0 && num_ulocks
== 0) {
8321 END_PROFILE(SMBlockingX
);
8324 END_PROFILE(SMBlockingX
);
8325 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
8330 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
8332 result
= remove_oplock(fsp
);
8334 result
= downgrade_oplock(fsp
);
8338 DEBUG(0, ("reply_lockingX: error in removing "
8339 "oplock on file %s\n", fsp_str_dbg(fsp
)));
8340 /* Hmmm. Is this panic justified? */
8341 smb_panic("internal tdb error");
8344 /* if this is a pure oplock break request then don't send a
8346 if (num_locks
== 0 && num_ulocks
== 0) {
8347 /* Sanity check - ensure a pure oplock break is not a
8349 if (CVAL(req
->vwv
+0, 0) != 0xff) {
8350 DEBUG(0,("reply_lockingX: Error : pure oplock "
8351 "break is a chained %d request !\n",
8352 (unsigned int)CVAL(req
->vwv
+0, 0)));
8354 END_PROFILE(SMBlockingX
);
8360 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
8361 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8362 END_PROFILE(SMBlockingX
);
8366 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
8367 if (ulocks
== NULL
) {
8368 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8369 END_PROFILE(SMBlockingX
);
8373 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
8374 if (locks
== NULL
) {
8375 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8376 END_PROFILE(SMBlockingX
);
8380 /* Data now points at the beginning of the list
8381 of smb_unlkrng structs */
8382 for(i
= 0; i
< (int)num_ulocks
; i
++) {
8383 ulocks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8384 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8385 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8386 ulocks
[i
].brltype
= UNLOCK_LOCK
;
8389 /* Now do any requested locks */
8390 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
8392 /* Data now points at the beginning of the list
8393 of smb_lkrng structs */
8395 for(i
= 0; i
< (int)num_locks
; i
++) {
8396 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
8397 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
8398 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
8400 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
8401 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8402 locks
[i
].brltype
= PENDING_READ_LOCK
;
8404 locks
[i
].brltype
= READ_LOCK
;
8407 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
8408 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
8410 locks
[i
].brltype
= WRITE_LOCK
;
8415 status
= smbd_do_unlocking(req
, fsp
, num_ulocks
, ulocks
);
8416 if (!NT_STATUS_IS_OK(status
)) {
8417 END_PROFILE(SMBlockingX
);
8418 reply_nterror(req
, status
);
8422 status
= smbd_do_locking(req
, fsp
,
8423 locktype
, lock_timeout
,
8426 if (!NT_STATUS_IS_OK(status
)) {
8427 END_PROFILE(SMBlockingX
);
8428 reply_nterror(req
, status
);
8432 END_PROFILE(SMBlockingX
);
8436 reply_outbuf(req
, 2, 0);
8437 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
8438 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
8440 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8441 fsp_fnum_dbg(fsp
), (unsigned int)locktype
, num_locks
, num_ulocks
));
8443 END_PROFILE(SMBlockingX
);
8447 #define DBGC_CLASS DBGC_ALL
8449 /****************************************************************************
8450 Reply to a SMBreadbmpx (read block multiplex) request.
8451 Always reply with an error, if someone has a platform really needs this,
8452 please contact vl@samba.org
8453 ****************************************************************************/
8455 void reply_readbmpx(struct smb_request
*req
)
8457 START_PROFILE(SMBreadBmpx
);
8458 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8459 END_PROFILE(SMBreadBmpx
);
8463 /****************************************************************************
8464 Reply to a SMBreadbs (read block multiplex secondary) request.
8465 Always reply with an error, if someone has a platform really needs this,
8466 please contact vl@samba.org
8467 ****************************************************************************/
8469 void reply_readbs(struct smb_request
*req
)
8471 START_PROFILE(SMBreadBs
);
8472 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8473 END_PROFILE(SMBreadBs
);
8477 /****************************************************************************
8478 Reply to a SMBsetattrE.
8479 ****************************************************************************/
8481 void reply_setattrE(struct smb_request
*req
)
8483 connection_struct
*conn
= req
->conn
;
8484 struct smb_file_time ft
;
8488 START_PROFILE(SMBsetattrE
);
8492 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8496 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8498 if(!fsp
|| (fsp
->conn
!= conn
)) {
8499 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8504 * Convert the DOS times into unix times.
8507 ft
.atime
= convert_time_t_to_timespec(
8508 srv_make_unix_date2(req
->vwv
+3));
8509 ft
.mtime
= convert_time_t_to_timespec(
8510 srv_make_unix_date2(req
->vwv
+5));
8511 ft
.create_time
= convert_time_t_to_timespec(
8512 srv_make_unix_date2(req
->vwv
+1));
8514 reply_outbuf(req
, 0, 0);
8517 * Patch from Ray Frush <frush@engr.colostate.edu>
8518 * Sometimes times are sent as zero - ignore them.
8521 /* Ensure we have a valid stat struct for the source. */
8522 status
= vfs_stat_fsp(fsp
);
8523 if (!NT_STATUS_IS_OK(status
)) {
8524 reply_nterror(req
, status
);
8528 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
8529 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8533 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
8534 if (!NT_STATUS_IS_OK(status
)) {
8535 reply_nterror(req
, status
);
8539 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8542 (unsigned int)ft
.atime
.tv_sec
,
8543 (unsigned int)ft
.mtime
.tv_sec
,
8544 (unsigned int)ft
.create_time
.tv_sec
8547 END_PROFILE(SMBsetattrE
);
8552 /* Back from the dead for OS/2..... JRA. */
8554 /****************************************************************************
8555 Reply to a SMBwritebmpx (write block multiplex primary) request.
8556 Always reply with an error, if someone has a platform really needs this,
8557 please contact vl@samba.org
8558 ****************************************************************************/
8560 void reply_writebmpx(struct smb_request
*req
)
8562 START_PROFILE(SMBwriteBmpx
);
8563 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8564 END_PROFILE(SMBwriteBmpx
);
8568 /****************************************************************************
8569 Reply to a SMBwritebs (write block multiplex secondary) request.
8570 Always reply with an error, if someone has a platform really needs this,
8571 please contact vl@samba.org
8572 ****************************************************************************/
8574 void reply_writebs(struct smb_request
*req
)
8576 START_PROFILE(SMBwriteBs
);
8577 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
8578 END_PROFILE(SMBwriteBs
);
8582 /****************************************************************************
8583 Reply to a SMBgetattrE.
8584 ****************************************************************************/
8586 void reply_getattrE(struct smb_request
*req
)
8588 connection_struct
*conn
= req
->conn
;
8591 struct timespec create_ts
;
8593 START_PROFILE(SMBgetattrE
);
8596 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8597 END_PROFILE(SMBgetattrE
);
8601 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
8603 if(!fsp
|| (fsp
->conn
!= conn
)) {
8604 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8605 END_PROFILE(SMBgetattrE
);
8609 /* Do an fstat on this file */
8611 reply_nterror(req
, map_nt_error_from_unix(errno
));
8612 END_PROFILE(SMBgetattrE
);
8616 mode
= dos_mode(conn
, fsp
->fsp_name
);
8619 * Convert the times into dos times. Set create
8620 * date to be last modify date as UNIX doesn't save
8624 reply_outbuf(req
, 11, 0);
8626 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
8627 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
8628 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
8629 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
8630 /* Should we check pending modtime here ? JRA */
8631 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
8632 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
8634 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
8635 SIVAL(req
->outbuf
, smb_vwv6
, 0);
8636 SIVAL(req
->outbuf
, smb_vwv8
, 0);
8638 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
8639 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
8640 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
8642 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
8644 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
8646 END_PROFILE(SMBgetattrE
);