2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
266 bool posix_pathnames,
268 bool *contains_wcard)
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 *err = NT_STATUS_INVALID_PARAMETER;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
369 return srvstr_get_path_wcard_internal(ctx,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
396 return srvstr_get_path_wcard_internal(ctx,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
416 *err = NT_STATUS_INVALID_PARAMETER;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
497 if (!check_fsp_open(conn, req, fsp)) {
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
508 fsp->num_smb_operations++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
520 if (!check_fsp_open(conn, req, fsp)) {
524 if (fsp->is_directory) {
528 if (fsp->fake_file_handle == NULL) {
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 if (fsp->fake_file_handle->private_data == NULL) {
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
547 char *trim_name_type;
548 const char *retarget_parm;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
570 if (trim_name_type == NULL) {
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm == NULL) {
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
600 if (sscanf(p, "%x", &retarget_type) != 1) {
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
607 DEBUG(10, ("could not resolve %s\n", retarget));
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name);
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1, name_type2;
668 int name_len1, name_len2;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf);
755 reload_services(sconn, conn_snum_used, true);
758 xconn->transport.nbt.got_session = true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
792 /****************************************************************************
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request *req)
799 connection_struct *conn = req->conn;
801 char *service_buf = NULL;
802 char *password = NULL;
808 TALLOC_CTX *ctx = talloc_tos();
809 struct smbXsrv_connection *xconn = req->xconn;
810 NTTIME now = timeval_to_nttime(&req->request_time);
812 START_PROFILE(SMBtcon);
814 if (req->buflen < 4) {
815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
816 END_PROFILE(SMBtcon);
821 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
823 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
825 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
828 if (service_buf == NULL || password == NULL || dev == NULL) {
829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830 END_PROFILE(SMBtcon);
833 p2 = strrchr_m(service_buf,'\\');
837 service = service_buf;
840 conn = make_connection(req, now, service, dev,
841 req->vuid,&nt_status);
845 reply_nterror(req, nt_status);
846 END_PROFILE(SMBtcon);
850 reply_outbuf(req, 2, 0);
851 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
852 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
853 SSVAL(req->outbuf,smb_tid,conn->cnum);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service, conn->cnum));
858 END_PROFILE(SMBtcon);
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request *req)
869 connection_struct *conn = req->conn;
870 const char *service = NULL;
871 TALLOC_CTX *ctx = talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype = NULL;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype;
882 struct smbXsrv_session *session = NULL;
883 NTTIME now = timeval_to_nttime(&req->request_time);
884 bool session_key_updated = false;
885 uint16_t optional_support = 0;
886 struct smbXsrv_connection *xconn = req->xconn;
888 START_PROFILE(SMBtconX);
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 END_PROFILE(SMBtconX);
896 passlen = SVAL(req->vwv+3, 0);
897 tcon_flags = SVAL(req->vwv+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
901 struct smbXsrv_tcon *tcon;
909 * TODO: cancel all outstanding requests on the tcon
911 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
912 if (!NT_STATUS_IS_OK(status)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX);
921 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
928 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
929 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
930 END_PROFILE(SMBtconX);
934 if (xconn->smb1.negprot.encrypted_passwords) {
935 p = req->buf + passlen;
937 p = req->buf + passlen + 1;
940 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
944 END_PROFILE(SMBtconX);
949 * the service name can be either: \\server\share
950 * or share directly like on the DELL PowerVault 705
953 q = strchr_m(path+2,'\\');
955 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
956 END_PROFILE(SMBtconX);
964 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
965 &client_devicetype, p,
966 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
968 if (client_devicetype == NULL) {
969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 END_PROFILE(SMBtconX);
974 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
976 nt_status = smb1srv_session_lookup(xconn,
977 req->vuid, now, &session);
978 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
979 reply_force_doserror(req, ERRSRV, ERRbaduid);
980 END_PROFILE(SMBtconX);
983 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
984 reply_nterror(req, nt_status);
985 END_PROFILE(SMBtconX);
988 if (!NT_STATUS_IS_OK(nt_status)) {
989 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
990 END_PROFILE(SMBtconX);
994 if (session->global->auth_session_info == NULL) {
995 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
996 END_PROFILE(SMBtconX);
1001 * If there is no application key defined yet
1004 * This means we setup the application key on the
1005 * first tcon that happens via the given session.
1007 * Once the application key is defined, it does not
1010 if (session->global->application_key.length == 0 &&
1011 session->global->signing_key.length > 0)
1013 struct smbXsrv_session *x = session;
1014 struct auth_session_info *session_info =
1015 session->global->auth_session_info;
1016 uint8_t session_key[16];
1018 ZERO_STRUCT(session_key);
1019 memcpy(session_key, x->global->signing_key.data,
1020 MIN(x->global->signing_key.length, sizeof(session_key)));
1023 * The application key is truncated/padded to 16 bytes
1025 x->global->application_key = data_blob_talloc(x->global,
1027 sizeof(session_key));
1028 ZERO_STRUCT(session_key);
1029 if (x->global->application_key.data == NULL) {
1030 reply_nterror(req, NT_STATUS_NO_MEMORY);
1031 END_PROFILE(SMBtconX);
1035 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1036 smb_key_derivation(x->global->application_key.data,
1037 x->global->application_key.length,
1038 x->global->application_key.data);
1039 optional_support |= SMB_EXTENDED_SIGNATURES;
1043 * Place the application key into the session_info
1045 data_blob_clear_free(&session_info->session_key);
1046 session_info->session_key = data_blob_dup_talloc(session_info,
1047 x->global->application_key);
1048 if (session_info->session_key.data == NULL) {
1049 data_blob_clear_free(&x->global->application_key);
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1051 END_PROFILE(SMBtconX);
1054 session_key_updated = true;
1057 conn = make_connection(req, now, service, client_devicetype,
1058 req->vuid, &nt_status);
1062 if (session_key_updated) {
1063 struct smbXsrv_session *x = session;
1064 struct auth_session_info *session_info =
1065 session->global->auth_session_info;
1066 data_blob_clear_free(&x->global->application_key);
1067 data_blob_clear_free(&session_info->session_key);
1069 reply_nterror(req, nt_status);
1070 END_PROFILE(SMBtconX);
1075 server_devicetype = "IPC";
1076 else if ( IS_PRINT(conn) )
1077 server_devicetype = "LPT1:";
1079 server_devicetype = "A:";
1081 if (get_Protocol() < PROTOCOL_NT1) {
1082 reply_outbuf(req, 2, 0);
1083 if (message_push_string(&req->outbuf, server_devicetype,
1084 STR_TERMINATE|STR_ASCII) == -1) {
1085 reply_nterror(req, NT_STATUS_NO_MEMORY);
1086 END_PROFILE(SMBtconX);
1090 /* NT sets the fstype of IPC$ to the null string */
1091 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1093 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1094 /* Return permissions. */
1098 reply_outbuf(req, 7, 0);
1101 perm1 = FILE_ALL_ACCESS;
1102 perm2 = FILE_ALL_ACCESS;
1104 perm1 = conn->share_access;
1107 SIVAL(req->outbuf, smb_vwv3, perm1);
1108 SIVAL(req->outbuf, smb_vwv5, perm2);
1110 reply_outbuf(req, 3, 0);
1113 if ((message_push_string(&req->outbuf, server_devicetype,
1114 STR_TERMINATE|STR_ASCII) == -1)
1115 || (message_push_string(&req->outbuf, fstype,
1116 STR_TERMINATE) == -1)) {
1117 reply_nterror(req, NT_STATUS_NO_MEMORY);
1118 END_PROFILE(SMBtconX);
1122 /* what does setting this bit do? It is set by NT4 and
1123 may affect the ability to autorun mounted cdroms */
1124 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1126 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1128 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1129 DEBUG(2,("Serving %s as a Dfs root\n",
1130 lp_servicename(ctx, SNUM(conn)) ));
1131 optional_support |= SMB_SHARE_IN_DFS;
1134 SSVAL(req->outbuf, smb_vwv2, optional_support);
1137 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1138 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1140 DEBUG(3,("tconX service=%s \n",
1143 /* set the incoming and outgoing tid to the just created one */
1144 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1145 SSVAL(req->outbuf,smb_tid,conn->cnum);
1147 END_PROFILE(SMBtconX);
1149 req->tid = conn->cnum;
1152 /****************************************************************************
1153 Reply to an unknown type.
1154 ****************************************************************************/
1156 void reply_unknown_new(struct smb_request *req, uint8_t type)
1158 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1159 smb_fn_name(type), type, type));
1160 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1164 /****************************************************************************
1166 conn POINTER CAN BE NULL HERE !
1167 ****************************************************************************/
1169 void reply_ioctl(struct smb_request *req)
1171 connection_struct *conn = req->conn;
1174 uint32_t ioctl_code;
1178 START_PROFILE(SMBioctl);
1181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1182 END_PROFILE(SMBioctl);
1186 device = SVAL(req->vwv+1, 0);
1187 function = SVAL(req->vwv+2, 0);
1188 ioctl_code = (device << 16) + function;
1190 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1192 switch (ioctl_code) {
1193 case IOCTL_QUERY_JOB_INFO:
1197 reply_force_doserror(req, ERRSRV, ERRnosupport);
1198 END_PROFILE(SMBioctl);
1202 reply_outbuf(req, 8, replysize+1);
1203 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1204 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1205 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1206 p = smb_buf(req->outbuf);
1207 memset(p, '\0', replysize+1); /* valgrind-safe. */
1208 p += 1; /* Allow for alignment */
1210 switch (ioctl_code) {
1211 case IOCTL_QUERY_JOB_INFO:
1215 files_struct *fsp = file_fsp(
1216 req, SVAL(req->vwv+0, 0));
1218 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1219 END_PROFILE(SMBioctl);
1223 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1225 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1226 lp_netbios_name(), 15,
1227 STR_TERMINATE|STR_ASCII, &len);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 reply_nterror(req, status);
1230 END_PROFILE(SMBioctl);
1234 status = srvstr_push((char *)req->outbuf, req->flags2,
1236 lp_servicename(talloc_tos(),
1238 13, STR_TERMINATE|STR_ASCII, &len);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 reply_nterror(req, status);
1241 END_PROFILE(SMBioctl);
1245 memset(p+18, 0, 13);
1251 END_PROFILE(SMBioctl);
1255 /****************************************************************************
1256 Strange checkpath NTSTATUS mapping.
1257 ****************************************************************************/
1259 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1261 /* Strange DOS error code semantics only for checkpath... */
1262 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1263 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1264 /* We need to map to ERRbadpath */
1265 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1271 /****************************************************************************
1272 Reply to a checkpath.
1273 ****************************************************************************/
1275 void reply_checkpath(struct smb_request *req)
1277 connection_struct *conn = req->conn;
1278 struct smb_filename *smb_fname = NULL;
1281 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1282 TALLOC_CTX *ctx = talloc_tos();
1284 START_PROFILE(SMBcheckpath);
1286 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1287 STR_TERMINATE, &status);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 status = map_checkpath_error(req->flags2, status);
1291 reply_nterror(req, status);
1292 END_PROFILE(SMBcheckpath);
1296 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1298 status = filename_convert(ctx,
1300 req->flags2 & FLAGS2_DFS_PATHNAMES,
1306 if (!NT_STATUS_IS_OK(status)) {
1307 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1308 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1309 ERRSRV, ERRbadpath);
1310 END_PROFILE(SMBcheckpath);
1316 if (!VALID_STAT(smb_fname->st) &&
1317 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1318 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1319 smb_fname_str_dbg(smb_fname), strerror(errno)));
1320 status = map_nt_error_from_unix(errno);
1324 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1325 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1326 ERRDOS, ERRbadpath);
1330 reply_outbuf(req, 0, 0);
1333 /* We special case this - as when a Windows machine
1334 is parsing a path is steps through the components
1335 one at a time - if a component fails it expects
1336 ERRbadpath, not ERRbadfile.
1338 status = map_checkpath_error(req->flags2, status);
1339 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1341 * Windows returns different error codes if
1342 * the parent directory is valid but not the
1343 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1344 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1345 * if the path is invalid.
1347 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1348 ERRDOS, ERRbadpath);
1352 reply_nterror(req, status);
1355 TALLOC_FREE(smb_fname);
1356 END_PROFILE(SMBcheckpath);
1360 /****************************************************************************
1362 ****************************************************************************/
1364 void reply_getatr(struct smb_request *req)
1366 connection_struct *conn = req->conn;
1367 struct smb_filename *smb_fname = NULL;
1374 TALLOC_CTX *ctx = talloc_tos();
1375 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1377 START_PROFILE(SMBgetatr);
1379 p = (const char *)req->buf + 1;
1380 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 reply_nterror(req, status);
1386 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1387 under WfWg - weird! */
1388 if (*fname == '\0') {
1389 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1390 if (!CAN_WRITE(conn)) {
1391 mode |= FILE_ATTRIBUTE_READONLY;
1396 uint32_t ucf_flags = (req->posix_pathnames ?
1397 UCF_POSIX_PATHNAMES : 0);
1398 status = filename_convert(ctx,
1400 req->flags2 & FLAGS2_DFS_PATHNAMES,
1405 if (!NT_STATUS_IS_OK(status)) {
1406 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1407 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1408 ERRSRV, ERRbadpath);
1411 reply_nterror(req, status);
1414 if (!VALID_STAT(smb_fname->st) &&
1415 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1416 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1417 smb_fname_str_dbg(smb_fname),
1419 reply_nterror(req, map_nt_error_from_unix(errno));
1423 mode = dos_mode(conn, smb_fname);
1424 size = smb_fname->st.st_ex_size;
1426 if (ask_sharemode) {
1427 struct timespec write_time_ts;
1428 struct file_id fileid;
1430 ZERO_STRUCT(write_time_ts);
1431 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1432 get_file_infos(fileid, 0, NULL, &write_time_ts);
1433 if (!null_timespec(write_time_ts)) {
1434 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1438 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1439 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1444 reply_outbuf(req, 10, 0);
1446 SSVAL(req->outbuf,smb_vwv0,mode);
1447 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1448 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1450 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1452 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1454 if (get_Protocol() >= PROTOCOL_NT1) {
1455 SSVAL(req->outbuf, smb_flg2,
1456 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1459 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1460 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1463 TALLOC_FREE(smb_fname);
1465 END_PROFILE(SMBgetatr);
1469 /****************************************************************************
1471 ****************************************************************************/
1473 void reply_setatr(struct smb_request *req)
1475 struct smb_file_time ft;
1476 connection_struct *conn = req->conn;
1477 struct smb_filename *smb_fname = NULL;
1483 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1484 TALLOC_CTX *ctx = talloc_tos();
1486 START_PROFILE(SMBsetatr);
1491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1495 p = (const char *)req->buf + 1;
1496 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 reply_nterror(req, status);
1502 status = filename_convert(ctx,
1504 req->flags2 & FLAGS2_DFS_PATHNAMES,
1509 if (!NT_STATUS_IS_OK(status)) {
1510 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1511 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1512 ERRSRV, ERRbadpath);
1515 reply_nterror(req, status);
1519 if (smb_fname->base_name[0] == '.' &&
1520 smb_fname->base_name[1] == '\0') {
1522 * Not sure here is the right place to catch this
1523 * condition. Might be moved to somewhere else later -- vl
1525 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1529 mode = SVAL(req->vwv+0, 0);
1530 mtime = srv_make_unix_date3(req->vwv+1);
1532 if (mode != FILE_ATTRIBUTE_NORMAL) {
1533 if (VALID_STAT_OF_DIR(smb_fname->st))
1534 mode |= FILE_ATTRIBUTE_DIRECTORY;
1536 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1538 status = check_access(conn, NULL, smb_fname,
1539 FILE_WRITE_ATTRIBUTES);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 reply_nterror(req, status);
1545 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1547 reply_nterror(req, map_nt_error_from_unix(errno));
1552 ft.mtime = convert_time_t_to_timespec(mtime);
1553 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 reply_nterror(req, status);
1559 reply_outbuf(req, 0, 0);
1561 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1564 TALLOC_FREE(smb_fname);
1565 END_PROFILE(SMBsetatr);
1569 /****************************************************************************
1571 ****************************************************************************/
1573 void reply_dskattr(struct smb_request *req)
1575 connection_struct *conn = req->conn;
1577 uint64_t dfree,dsize,bsize;
1578 struct smb_filename smb_fname;
1579 START_PROFILE(SMBdskattr);
1581 ZERO_STRUCT(smb_fname);
1582 smb_fname.base_name = discard_const_p(char, ".");
1584 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1585 reply_nterror(req, map_nt_error_from_unix(errno));
1586 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1587 END_PROFILE(SMBdskattr);
1591 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1592 if (ret == (uint64_t)-1) {
1593 reply_nterror(req, map_nt_error_from_unix(errno));
1594 END_PROFILE(SMBdskattr);
1599 * Force max to fit in 16 bit fields.
1601 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1605 if (bsize > (WORDMAX*512)) {
1606 bsize = (WORDMAX*512);
1607 if (dsize > WORDMAX)
1609 if (dfree > WORDMAX)
1615 reply_outbuf(req, 5, 0);
1617 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1618 double total_space, free_space;
1619 /* we need to scale this to a number that DOS6 can handle. We
1620 use floating point so we can handle large drives on systems
1621 that don't have 64 bit integers
1623 we end up displaying a maximum of 2G to DOS systems
1625 total_space = dsize * (double)bsize;
1626 free_space = dfree * (double)bsize;
1628 dsize = (uint64_t)((total_space+63*512) / (64*512));
1629 dfree = (uint64_t)((free_space+63*512) / (64*512));
1631 if (dsize > 0xFFFF) dsize = 0xFFFF;
1632 if (dfree > 0xFFFF) dfree = 0xFFFF;
1634 SSVAL(req->outbuf,smb_vwv0,dsize);
1635 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1636 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1637 SSVAL(req->outbuf,smb_vwv3,dfree);
1639 SSVAL(req->outbuf,smb_vwv0,dsize);
1640 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1641 SSVAL(req->outbuf,smb_vwv2,512);
1642 SSVAL(req->outbuf,smb_vwv3,dfree);
1645 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1647 END_PROFILE(SMBdskattr);
1652 * Utility function to split the filename from the directory.
1654 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1655 char **fname_dir_out,
1656 char **fname_mask_out)
1658 const char *p = NULL;
1659 char *fname_dir = NULL;
1660 char *fname_mask = NULL;
1662 p = strrchr_m(fname_in, '/');
1664 fname_dir = talloc_strdup(ctx, ".");
1665 fname_mask = talloc_strdup(ctx, fname_in);
1667 fname_dir = talloc_strndup(ctx, fname_in,
1668 PTR_DIFF(p, fname_in));
1669 fname_mask = talloc_strdup(ctx, p+1);
1672 if (!fname_dir || !fname_mask) {
1673 TALLOC_FREE(fname_dir);
1674 TALLOC_FREE(fname_mask);
1675 return NT_STATUS_NO_MEMORY;
1678 *fname_dir_out = fname_dir;
1679 *fname_mask_out = fname_mask;
1680 return NT_STATUS_OK;
1683 /****************************************************************************
1685 ****************************************************************************/
1687 static bool make_dir_struct(TALLOC_CTX *ctx,
1697 char *mask2 = talloc_strdup(ctx, mask);
1703 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1707 memset(buf+1,' ',11);
1708 if ((p = strchr_m(mask2,'.')) != NULL) {
1710 push_ascii(buf+1,mask2,8, 0);
1711 push_ascii(buf+9,p+1,3, 0);
1714 push_ascii(buf+1,mask2,11, 0);
1717 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1719 srv_put_dos_date(buf,22,date);
1720 SSVAL(buf,26,size & 0xFFFF);
1721 SSVAL(buf,28,(size >> 16)&0xFFFF);
1722 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1723 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1724 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1725 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1729 /****************************************************************************
1731 Can be called from SMBsearch, SMBffirst or SMBfunique.
1732 ****************************************************************************/
1734 void reply_search(struct smb_request *req)
1736 connection_struct *conn = req->conn;
1739 char *directory = NULL;
1740 struct smb_filename *smb_fname = NULL;
1744 struct timespec date;
1746 unsigned int numentries = 0;
1747 unsigned int maxentries = 0;
1748 bool finished = False;
1753 bool check_descend = False;
1754 bool expect_close = False;
1756 bool mask_contains_wcard = False;
1757 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1758 TALLOC_CTX *ctx = talloc_tos();
1759 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1760 struct dptr_struct *dirptr = NULL;
1761 struct smbXsrv_connection *xconn = req->xconn;
1762 struct smbd_server_connection *sconn = req->sconn;
1764 START_PROFILE(SMBsearch);
1767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1771 if (req->posix_pathnames) {
1772 reply_unknown_new(req, req->cmd);
1776 /* If we were called as SMBffirst then we must expect close. */
1777 if(req->cmd == SMBffirst) {
1778 expect_close = True;
1781 reply_outbuf(req, 1, 3);
1782 maxentries = SVAL(req->vwv+0, 0);
1783 dirtype = SVAL(req->vwv+1, 0);
1784 p = (const char *)req->buf + 1;
1785 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1786 &nt_status, &mask_contains_wcard);
1787 if (!NT_STATUS_IS_OK(nt_status)) {
1788 reply_nterror(req, nt_status);
1793 status_len = SVAL(p, 0);
1796 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1798 if (status_len == 0) {
1799 struct smb_filename *smb_dname = NULL;
1800 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1801 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1802 nt_status = filename_convert(ctx, conn,
1803 req->flags2 & FLAGS2_DFS_PATHNAMES,
1806 &mask_contains_wcard,
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1810 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1811 ERRSRV, ERRbadpath);
1814 reply_nterror(req, nt_status);
1818 directory = smb_fname->base_name;
1820 p = strrchr_m(directory,'/');
1821 if ((p != NULL) && (*directory != '/')) {
1822 mask = talloc_strdup(ctx, p + 1);
1823 directory = talloc_strndup(ctx, directory,
1824 PTR_DIFF(p, directory));
1826 mask = talloc_strdup(ctx, directory);
1827 directory = talloc_strdup(ctx,".");
1831 reply_nterror(req, NT_STATUS_NO_MEMORY);
1835 memset((char *)status,'\0',21);
1836 SCVAL(status,0,(dirtype & 0x1F));
1838 smb_dname = synthetic_smb_fname(talloc_tos(),
1843 if (smb_dname == NULL) {
1844 reply_nterror(req, NT_STATUS_NO_MEMORY);
1848 nt_status = dptr_create(conn,
1856 mask_contains_wcard,
1860 TALLOC_FREE(smb_dname);
1862 if (!NT_STATUS_IS_OK(nt_status)) {
1863 reply_nterror(req, nt_status);
1866 dptr_num = dptr_dnum(dirptr);
1869 const char *dirpath;
1871 memcpy(status,p,21);
1872 status_dirtype = CVAL(status,0) & 0x1F;
1873 if (status_dirtype != (dirtype & 0x1F)) {
1874 dirtype = status_dirtype;
1877 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1881 dirpath = dptr_path(sconn, dptr_num);
1882 directory = talloc_strdup(ctx, dirpath);
1884 reply_nterror(req, NT_STATUS_NO_MEMORY);
1888 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1893 * For a 'continue' search we have no string. So
1894 * check from the initial saved string.
1896 if (!req->posix_pathnames) {
1897 mask_contains_wcard = ms_has_wild(mask);
1899 dirtype = dptr_attr(sconn, dptr_num);
1902 DEBUG(4,("dptr_num is %d\n",dptr_num));
1904 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1905 dptr_init_search_op(dirptr);
1907 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1908 char buf[DIR_STRUCT_SIZE];
1909 memcpy(buf,status,21);
1910 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1911 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1912 reply_nterror(req, NT_STATUS_NO_MEMORY);
1915 dptr_fill(sconn, buf+12,dptr_num);
1916 if (dptr_zero(buf+12) && (status_len==0)) {
1921 if (message_push_blob(&req->outbuf,
1922 data_blob_const(buf, sizeof(buf)))
1924 reply_nterror(req, NT_STATUS_NO_MEMORY);
1929 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1930 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1932 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1934 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1935 directory,lp_dont_descend(ctx, SNUM(conn))));
1936 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1937 check_descend = True;
1940 for (i=numentries;(i<maxentries) && !finished;i++) {
1941 finished = !get_dir_entry(ctx,
1952 char buf[DIR_STRUCT_SIZE];
1953 memcpy(buf,status,21);
1954 if (!make_dir_struct(ctx,
1960 convert_timespec_to_time_t(date),
1961 !allow_long_path_components)) {
1962 reply_nterror(req, NT_STATUS_NO_MEMORY);
1965 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1968 if (message_push_blob(&req->outbuf,
1969 data_blob_const(buf, sizeof(buf)))
1971 reply_nterror(req, NT_STATUS_NO_MEMORY);
1981 /* If we were called as SMBffirst with smb_search_id == NULL
1982 and no entries were found then return error and close dirptr
1985 if (numentries == 0) {
1986 dptr_close(sconn, &dptr_num);
1987 } else if(expect_close && status_len == 0) {
1988 /* Close the dptr - we know it's gone */
1989 dptr_close(sconn, &dptr_num);
1992 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1993 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1994 dptr_close(sconn, &dptr_num);
1997 if ((numentries == 0) && !mask_contains_wcard) {
1998 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2002 SSVAL(req->outbuf,smb_vwv0,numentries);
2003 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2004 SCVAL(smb_buf(req->outbuf),0,5);
2005 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2007 /* The replies here are never long name. */
2008 SSVAL(req->outbuf, smb_flg2,
2009 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2010 if (!allow_long_path_components) {
2011 SSVAL(req->outbuf, smb_flg2,
2012 SVAL(req->outbuf, smb_flg2)
2013 & (~FLAGS2_LONG_PATH_COMPONENTS));
2016 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2017 SSVAL(req->outbuf, smb_flg2,
2018 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2020 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2021 smb_fn_name(req->cmd),
2028 TALLOC_FREE(directory);
2030 TALLOC_FREE(smb_fname);
2031 END_PROFILE(SMBsearch);
2035 /****************************************************************************
2036 Reply to a fclose (stop directory search).
2037 ****************************************************************************/
2039 void reply_fclose(struct smb_request *req)
2047 bool path_contains_wcard = False;
2048 TALLOC_CTX *ctx = talloc_tos();
2049 struct smbd_server_connection *sconn = req->sconn;
2051 START_PROFILE(SMBfclose);
2053 if (req->posix_pathnames) {
2054 reply_unknown_new(req, req->cmd);
2055 END_PROFILE(SMBfclose);
2059 p = (const char *)req->buf + 1;
2060 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2061 &err, &path_contains_wcard);
2062 if (!NT_STATUS_IS_OK(err)) {
2063 reply_nterror(req, err);
2064 END_PROFILE(SMBfclose);
2068 status_len = SVAL(p,0);
2071 if (status_len == 0) {
2072 reply_force_doserror(req, ERRSRV, ERRsrverror);
2073 END_PROFILE(SMBfclose);
2077 memcpy(status,p,21);
2079 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2080 /* Close the dptr - we know it's gone */
2081 dptr_close(sconn, &dptr_num);
2084 reply_outbuf(req, 1, 0);
2085 SSVAL(req->outbuf,smb_vwv0,0);
2087 DEBUG(3,("search close\n"));
2089 END_PROFILE(SMBfclose);
2093 /****************************************************************************
2095 ****************************************************************************/
2097 void reply_open(struct smb_request *req)
2099 connection_struct *conn = req->conn;
2100 struct smb_filename *smb_fname = NULL;
2110 uint32_t access_mask;
2111 uint32_t share_mode;
2112 uint32_t create_disposition;
2113 uint32_t create_options = 0;
2114 uint32_t private_flags = 0;
2117 TALLOC_CTX *ctx = talloc_tos();
2119 START_PROFILE(SMBopen);
2122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2126 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2127 deny_mode = SVAL(req->vwv+0, 0);
2128 dos_attr = SVAL(req->vwv+1, 0);
2130 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2131 STR_TERMINATE, &status);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 reply_nterror(req, status);
2137 if (!map_open_params_to_ntcreate(fname, deny_mode,
2138 OPENX_FILE_EXISTS_OPEN, &access_mask,
2139 &share_mode, &create_disposition,
2140 &create_options, &private_flags)) {
2141 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2145 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2147 status = filename_convert(ctx,
2149 req->flags2 & FLAGS2_DFS_PATHNAMES,
2154 if (!NT_STATUS_IS_OK(status)) {
2155 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2156 reply_botherror(req,
2157 NT_STATUS_PATH_NOT_COVERED,
2158 ERRSRV, ERRbadpath);
2161 reply_nterror(req, status);
2165 status = SMB_VFS_CREATE_FILE(
2168 0, /* root_dir_fid */
2169 smb_fname, /* fname */
2170 access_mask, /* access_mask */
2171 share_mode, /* share_access */
2172 create_disposition, /* create_disposition*/
2173 create_options, /* create_options */
2174 dos_attr, /* file_attributes */
2175 oplock_request, /* oplock_request */
2177 0, /* allocation_size */
2183 NULL, NULL); /* create context */
2185 if (!NT_STATUS_IS_OK(status)) {
2186 if (open_was_deferred(req->xconn, req->mid)) {
2187 /* We have re-scheduled this call. */
2190 reply_openerror(req, status);
2194 /* Ensure we're pointing at the correct stat struct. */
2195 TALLOC_FREE(smb_fname);
2196 smb_fname = fsp->fsp_name;
2198 size = smb_fname->st.st_ex_size;
2199 fattr = dos_mode(conn, smb_fname);
2201 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2203 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2204 DEBUG(3,("attempt to open a directory %s\n",
2206 close_file(req, fsp, ERROR_CLOSE);
2207 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2208 ERRDOS, ERRnoaccess);
2212 reply_outbuf(req, 7, 0);
2213 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2214 SSVAL(req->outbuf,smb_vwv1,fattr);
2215 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2216 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2218 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2220 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2221 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2223 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2224 SCVAL(req->outbuf,smb_flg,
2225 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2229 SCVAL(req->outbuf,smb_flg,
2230 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2233 END_PROFILE(SMBopen);
2237 /****************************************************************************
2238 Reply to an open and X.
2239 ****************************************************************************/
2241 void reply_open_and_X(struct smb_request *req)
2243 connection_struct *conn = req->conn;
2244 struct smb_filename *smb_fname = NULL;
2246 uint16_t open_flags;
2249 /* Breakout the oplock request bits so we can set the
2250 reply bits separately. */
2251 int ex_oplock_request;
2252 int core_oplock_request;
2255 int smb_sattr = SVAL(req->vwv+4, 0);
2256 uint32_t smb_time = make_unix_date3(req->vwv+6);
2264 uint64_t allocation_size;
2265 ssize_t retval = -1;
2266 uint32_t access_mask;
2267 uint32_t share_mode;
2268 uint32_t create_disposition;
2269 uint32_t create_options = 0;
2270 uint32_t private_flags = 0;
2272 TALLOC_CTX *ctx = talloc_tos();
2274 START_PROFILE(SMBopenX);
2276 if (req->wct < 15) {
2277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2281 open_flags = SVAL(req->vwv+2, 0);
2282 deny_mode = SVAL(req->vwv+3, 0);
2283 smb_attr = SVAL(req->vwv+5, 0);
2284 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2285 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2286 oplock_request = ex_oplock_request | core_oplock_request;
2287 smb_ofun = SVAL(req->vwv+8, 0);
2288 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2290 /* If it's an IPC, pass off the pipe handler. */
2292 if (lp_nt_pipe_support()) {
2293 reply_open_pipe_and_X(conn, req);
2295 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2300 /* XXXX we need to handle passed times, sattr and flags */
2301 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2302 STR_TERMINATE, &status);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 reply_nterror(req, status);
2308 if (!map_open_params_to_ntcreate(fname, deny_mode,
2310 &access_mask, &share_mode,
2311 &create_disposition,
2314 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2318 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2320 status = filename_convert(ctx,
2322 req->flags2 & FLAGS2_DFS_PATHNAMES,
2327 if (!NT_STATUS_IS_OK(status)) {
2328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2329 reply_botherror(req,
2330 NT_STATUS_PATH_NOT_COVERED,
2331 ERRSRV, ERRbadpath);
2334 reply_nterror(req, status);
2338 status = SMB_VFS_CREATE_FILE(
2341 0, /* root_dir_fid */
2342 smb_fname, /* fname */
2343 access_mask, /* access_mask */
2344 share_mode, /* share_access */
2345 create_disposition, /* create_disposition*/
2346 create_options, /* create_options */
2347 smb_attr, /* file_attributes */
2348 oplock_request, /* oplock_request */
2350 0, /* allocation_size */
2355 &smb_action, /* pinfo */
2356 NULL, NULL); /* create context */
2358 if (!NT_STATUS_IS_OK(status)) {
2359 if (open_was_deferred(req->xconn, req->mid)) {
2360 /* We have re-scheduled this call. */
2363 reply_openerror(req, status);
2367 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2368 if the file is truncated or created. */
2369 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2370 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2371 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2372 close_file(req, fsp, ERROR_CLOSE);
2373 reply_nterror(req, NT_STATUS_DISK_FULL);
2376 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2378 close_file(req, fsp, ERROR_CLOSE);
2379 reply_nterror(req, NT_STATUS_DISK_FULL);
2382 status = vfs_stat_fsp(fsp);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 close_file(req, fsp, ERROR_CLOSE);
2385 reply_nterror(req, status);
2390 fattr = dos_mode(conn, fsp->fsp_name);
2391 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2392 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2393 close_file(req, fsp, ERROR_CLOSE);
2394 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2398 /* If the caller set the extended oplock request bit
2399 and we granted one (by whatever means) - set the
2400 correct bit for extended oplock reply.
2403 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2404 smb_action |= EXTENDED_OPLOCK_GRANTED;
2407 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2408 smb_action |= EXTENDED_OPLOCK_GRANTED;
2411 /* If the caller set the core oplock request bit
2412 and we granted one (by whatever means) - set the
2413 correct bit for core oplock reply.
2416 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2417 reply_outbuf(req, 19, 0);
2419 reply_outbuf(req, 15, 0);
2422 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2423 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2425 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2426 SCVAL(req->outbuf, smb_flg,
2427 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2430 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2431 SCVAL(req->outbuf, smb_flg,
2432 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2435 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2436 SSVAL(req->outbuf,smb_vwv3,fattr);
2437 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2438 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2440 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2442 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2443 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2444 SSVAL(req->outbuf,smb_vwv11,smb_action);
2446 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2447 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2451 TALLOC_FREE(smb_fname);
2452 END_PROFILE(SMBopenX);
2456 /****************************************************************************
2457 Reply to a SMBulogoffX.
2458 ****************************************************************************/
2460 void reply_ulogoffX(struct smb_request *req)
2462 struct smbd_server_connection *sconn = req->sconn;
2463 struct user_struct *vuser;
2464 struct smbXsrv_session *session = NULL;
2467 START_PROFILE(SMBulogoffX);
2469 vuser = get_valid_user_struct(sconn, req->vuid);
2472 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2473 (unsigned long long)req->vuid));
2475 req->vuid = UID_FIELD_INVALID;
2476 reply_force_doserror(req, ERRSRV, ERRbaduid);
2477 END_PROFILE(SMBulogoffX);
2481 session = vuser->session;
2485 * TODO: cancel all outstanding requests on the session
2487 status = smbXsrv_session_logoff(session);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(0, ("reply_ulogoff: "
2490 "smbXsrv_session_logoff() failed: %s\n",
2491 nt_errstr(status)));
2493 * If we hit this case, there is something completely
2494 * wrong, so we better disconnect the transport connection.
2496 END_PROFILE(SMBulogoffX);
2497 exit_server(__location__ ": smbXsrv_session_logoff failed");
2501 TALLOC_FREE(session);
2503 reply_outbuf(req, 2, 0);
2504 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2505 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2507 DEBUG(3, ("ulogoffX vuid=%llu\n",
2508 (unsigned long long)req->vuid));
2510 END_PROFILE(SMBulogoffX);
2511 req->vuid = UID_FIELD_INVALID;
2514 /****************************************************************************
2515 Reply to a mknew or a create.
2516 ****************************************************************************/
2518 void reply_mknew(struct smb_request *req)
2520 connection_struct *conn = req->conn;
2521 struct smb_filename *smb_fname = NULL;
2524 struct smb_file_time ft;
2526 int oplock_request = 0;
2528 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2529 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2530 uint32_t create_disposition;
2531 uint32_t create_options = 0;
2533 TALLOC_CTX *ctx = talloc_tos();
2535 START_PROFILE(SMBcreate);
2539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2543 fattr = SVAL(req->vwv+0, 0);
2544 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2546 if (req->cmd == SMBmknew) {
2547 /* We should fail if file exists. */
2548 create_disposition = FILE_CREATE;
2550 /* Create if file doesn't exist, truncate if it does. */
2551 create_disposition = FILE_OVERWRITE_IF;
2555 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2557 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2558 STR_TERMINATE, &status);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 reply_nterror(req, status);
2564 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2565 status = filename_convert(ctx,
2567 req->flags2 & FLAGS2_DFS_PATHNAMES,
2572 if (!NT_STATUS_IS_OK(status)) {
2573 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2574 reply_botherror(req,
2575 NT_STATUS_PATH_NOT_COVERED,
2576 ERRSRV, ERRbadpath);
2579 reply_nterror(req, status);
2583 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2584 DEBUG(0,("Attempt to create file (%s) with volid set - "
2585 "please report this\n",
2586 smb_fname_str_dbg(smb_fname)));
2589 status = SMB_VFS_CREATE_FILE(
2592 0, /* root_dir_fid */
2593 smb_fname, /* fname */
2594 access_mask, /* access_mask */
2595 share_mode, /* share_access */
2596 create_disposition, /* create_disposition*/
2597 create_options, /* create_options */
2598 fattr, /* file_attributes */
2599 oplock_request, /* oplock_request */
2601 0, /* allocation_size */
2602 0, /* private_flags */
2607 NULL, NULL); /* create context */
2609 if (!NT_STATUS_IS_OK(status)) {
2610 if (open_was_deferred(req->xconn, req->mid)) {
2611 /* We have re-scheduled this call. */
2614 reply_openerror(req, status);
2618 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2619 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 END_PROFILE(SMBcreate);
2625 reply_outbuf(req, 1, 0);
2626 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2628 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2629 SCVAL(req->outbuf,smb_flg,
2630 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2633 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2634 SCVAL(req->outbuf,smb_flg,
2635 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2638 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2639 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2640 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2641 (unsigned int)fattr));
2644 TALLOC_FREE(smb_fname);
2645 END_PROFILE(SMBcreate);
2649 /****************************************************************************
2650 Reply to a create temporary file.
2651 ****************************************************************************/
2653 void reply_ctemp(struct smb_request *req)
2655 connection_struct *conn = req->conn;
2656 struct smb_filename *smb_fname = NULL;
2657 char *wire_name = NULL;
2666 TALLOC_CTX *ctx = talloc_tos();
2668 START_PROFILE(SMBctemp);
2671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2675 fattr = SVAL(req->vwv+0, 0);
2676 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2678 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2679 STR_TERMINATE, &status);
2680 if (!NT_STATUS_IS_OK(status)) {
2681 reply_nterror(req, status);
2685 for (i = 0; i < 10; i++) {
2687 fname = talloc_asprintf(ctx,
2690 generate_random_str_list(ctx, 5, "0123456789"));
2692 fname = talloc_asprintf(ctx,
2694 generate_random_str_list(ctx, 5, "0123456789"));
2698 reply_nterror(req, NT_STATUS_NO_MEMORY);
2702 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2703 status = filename_convert(ctx, conn,
2704 req->flags2 & FLAGS2_DFS_PATHNAMES,
2709 if (!NT_STATUS_IS_OK(status)) {
2710 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2711 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2712 ERRSRV, ERRbadpath);
2715 reply_nterror(req, status);
2719 /* Create the file. */
2720 status = SMB_VFS_CREATE_FILE(
2723 0, /* root_dir_fid */
2724 smb_fname, /* fname */
2725 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2726 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2727 FILE_CREATE, /* create_disposition*/
2728 0, /* create_options */
2729 fattr, /* file_attributes */
2730 oplock_request, /* oplock_request */
2732 0, /* allocation_size */
2733 0, /* private_flags */
2738 NULL, NULL); /* create context */
2740 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2742 TALLOC_FREE(smb_fname);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 if (open_was_deferred(req->xconn, req->mid)) {
2748 /* We have re-scheduled this call. */
2751 reply_openerror(req, status);
2759 /* Collision after 10 times... */
2760 reply_nterror(req, status);
2764 reply_outbuf(req, 1, 0);
2765 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2767 /* the returned filename is relative to the directory */
2768 s = strrchr_m(fsp->fsp_name->base_name, '/');
2770 s = fsp->fsp_name->base_name;
2776 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2777 thing in the byte section. JRA */
2778 SSVALS(p, 0, -1); /* what is this? not in spec */
2780 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2782 reply_nterror(req, NT_STATUS_NO_MEMORY);
2786 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2787 SCVAL(req->outbuf, smb_flg,
2788 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2791 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2792 SCVAL(req->outbuf, smb_flg,
2793 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2796 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2797 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2798 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2800 TALLOC_FREE(smb_fname);
2801 TALLOC_FREE(wire_name);
2802 END_PROFILE(SMBctemp);
2806 /*******************************************************************
2807 Check if a user is allowed to rename a file.
2808 ********************************************************************/
2810 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2813 if (!CAN_WRITE(conn)) {
2814 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2817 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2818 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2819 /* Only bother to read the DOS attribute if we might deny the
2820 rename on the grounds of attribute mismatch. */
2821 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2822 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2823 return NT_STATUS_NO_SUCH_FILE;
2827 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2828 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2829 return NT_STATUS_OK;
2832 /* If no pathnames are open below this
2833 directory, allow the rename. */
2835 if (lp_strict_rename(SNUM(conn))) {
2837 * Strict rename, check open file db.
2839 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2840 return NT_STATUS_ACCESS_DENIED;
2842 } else if (file_find_subpath(fsp)) {
2844 * No strict rename, just look in local process.
2846 return NT_STATUS_ACCESS_DENIED;
2848 return NT_STATUS_OK;
2851 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2852 return NT_STATUS_OK;
2855 return NT_STATUS_ACCESS_DENIED;
2858 /*******************************************************************
2859 * unlink a file with all relevant access checks
2860 *******************************************************************/
2862 static NTSTATUS do_unlink(connection_struct *conn,
2863 struct smb_request *req,
2864 struct smb_filename *smb_fname,
2869 uint32_t dirtype_orig = dirtype;
2872 bool posix_paths = (req != NULL && req->posix_pathnames);
2874 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2875 smb_fname_str_dbg(smb_fname),
2878 if (!CAN_WRITE(conn)) {
2879 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2883 ret = SMB_VFS_LSTAT(conn, smb_fname);
2885 ret = SMB_VFS_STAT(conn, smb_fname);
2888 return map_nt_error_from_unix(errno);
2891 fattr = dos_mode(conn, smb_fname);
2893 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2894 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2897 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2899 return NT_STATUS_NO_SUCH_FILE;
2902 if (!dir_check_ftype(fattr, dirtype)) {
2903 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2904 return NT_STATUS_FILE_IS_A_DIRECTORY;
2906 return NT_STATUS_NO_SUCH_FILE;
2909 if (dirtype_orig & 0x8000) {
2910 /* These will never be set for POSIX. */
2911 return NT_STATUS_NO_SUCH_FILE;
2915 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2916 return NT_STATUS_FILE_IS_A_DIRECTORY;
2919 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2920 return NT_STATUS_NO_SUCH_FILE;
2923 if (dirtype & 0xFF00) {
2924 /* These will never be set for POSIX. */
2925 return NT_STATUS_NO_SUCH_FILE;
2930 return NT_STATUS_NO_SUCH_FILE;
2933 /* Can't delete a directory. */
2934 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2935 return NT_STATUS_FILE_IS_A_DIRECTORY;
2940 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2941 return NT_STATUS_OBJECT_NAME_INVALID;
2942 #endif /* JRATEST */
2944 /* On open checks the open itself will check the share mode, so
2945 don't do it here as we'll get it wrong. */
2947 status = SMB_VFS_CREATE_FILE
2950 0, /* root_dir_fid */
2951 smb_fname, /* fname */
2952 DELETE_ACCESS, /* access_mask */
2953 FILE_SHARE_NONE, /* share_access */
2954 FILE_OPEN, /* create_disposition*/
2955 FILE_NON_DIRECTORY_FILE, /* create_options */
2956 /* file_attributes */
2957 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2958 FILE_ATTRIBUTE_NORMAL,
2959 0, /* oplock_request */
2961 0, /* allocation_size */
2962 0, /* private_flags */
2967 NULL, NULL); /* create context */
2969 if (!NT_STATUS_IS_OK(status)) {
2970 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2971 nt_errstr(status)));
2975 status = can_set_delete_on_close(fsp, fattr);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2979 smb_fname_str_dbg(smb_fname),
2980 nt_errstr(status)));
2981 close_file(req, fsp, NORMAL_CLOSE);
2985 /* The set is across all open files on this dev/inode pair. */
2986 if (!set_delete_on_close(fsp, True,
2987 conn->session_info->security_token,
2988 conn->session_info->unix_token)) {
2989 close_file(req, fsp, NORMAL_CLOSE);
2990 return NT_STATUS_ACCESS_DENIED;
2993 return close_file(req, fsp, NORMAL_CLOSE);
2996 /****************************************************************************
2997 The guts of the unlink command, split out so it may be called by the NT SMB
2999 ****************************************************************************/
3001 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3002 uint32_t dirtype, struct smb_filename *smb_fname,
3005 char *fname_dir = NULL;
3006 char *fname_mask = NULL;
3008 NTSTATUS status = NT_STATUS_OK;
3009 struct smb_filename *smb_fname_dir = NULL;
3010 TALLOC_CTX *ctx = talloc_tos();
3012 /* Split up the directory from the filename/mask. */
3013 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3014 &fname_dir, &fname_mask);
3015 if (!NT_STATUS_IS_OK(status)) {
3020 * We should only check the mangled cache
3021 * here if unix_convert failed. This means
3022 * that the path in 'mask' doesn't exist
3023 * on the file system and so we need to look
3024 * for a possible mangle. This patch from
3025 * Tine Smukavec <valentin.smukavec@hermes.si>.
3028 if (!VALID_STAT(smb_fname->st) &&
3029 mangle_is_mangled(fname_mask, conn->params)) {
3030 char *new_mask = NULL;
3031 mangle_lookup_name_from_8_3(ctx, fname_mask,
3032 &new_mask, conn->params);
3034 TALLOC_FREE(fname_mask);
3035 fname_mask = new_mask;
3042 * Only one file needs to be unlinked. Append the mask back
3043 * onto the directory.
3045 TALLOC_FREE(smb_fname->base_name);
3046 if (ISDOT(fname_dir)) {
3047 /* Ensure we use canonical names on open. */
3048 smb_fname->base_name = talloc_asprintf(smb_fname,
3052 smb_fname->base_name = talloc_asprintf(smb_fname,
3057 if (!smb_fname->base_name) {
3058 status = NT_STATUS_NO_MEMORY;
3062 dirtype = FILE_ATTRIBUTE_NORMAL;
3065 status = check_name(conn, smb_fname->base_name);
3066 if (!NT_STATUS_IS_OK(status)) {
3070 status = do_unlink(conn, req, smb_fname, dirtype);
3071 if (!NT_STATUS_IS_OK(status)) {
3077 struct smb_Dir *dir_hnd = NULL;
3079 const char *dname = NULL;
3080 char *talloced = NULL;
3082 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3083 status = NT_STATUS_OBJECT_NAME_INVALID;
3087 dirtype = FILE_ATTRIBUTE_NORMAL;
3090 if (strequal(fname_mask,"????????.???")) {
3091 TALLOC_FREE(fname_mask);
3092 fname_mask = talloc_strdup(ctx, "*");
3094 status = NT_STATUS_NO_MEMORY;
3099 status = check_name(conn, fname_dir);
3100 if (!NT_STATUS_IS_OK(status)) {
3104 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3109 if (smb_fname_dir == NULL) {
3110 status = NT_STATUS_NO_MEMORY;
3114 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3116 if (dir_hnd == NULL) {
3117 status = map_nt_error_from_unix(errno);
3121 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3122 the pattern matches against the long name, otherwise the short name
3123 We don't implement this yet XXXX
3126 status = NT_STATUS_NO_SUCH_FILE;
3128 while ((dname = ReadDirName(dir_hnd, &offset,
3129 &smb_fname->st, &talloced))) {
3130 TALLOC_CTX *frame = talloc_stackframe();
3132 if (!is_visible_file(conn, fname_dir, dname,
3133 &smb_fname->st, true)) {
3135 TALLOC_FREE(talloced);
3139 /* Quick check for "." and ".." */
3140 if (ISDOT(dname) || ISDOTDOT(dname)) {
3142 TALLOC_FREE(talloced);
3146 if(!mask_match(dname, fname_mask,
3147 conn->case_sensitive)) {
3149 TALLOC_FREE(talloced);
3153 TALLOC_FREE(smb_fname->base_name);
3154 if (ISDOT(fname_dir)) {
3155 /* Ensure we use canonical names on open. */
3156 smb_fname->base_name =
3157 talloc_asprintf(smb_fname, "%s",
3160 smb_fname->base_name =
3161 talloc_asprintf(smb_fname, "%s/%s",
3165 if (!smb_fname->base_name) {
3166 TALLOC_FREE(dir_hnd);
3167 status = NT_STATUS_NO_MEMORY;
3169 TALLOC_FREE(talloced);
3173 status = check_name(conn, smb_fname->base_name);
3174 if (!NT_STATUS_IS_OK(status)) {
3175 TALLOC_FREE(dir_hnd);
3177 TALLOC_FREE(talloced);
3181 status = do_unlink(conn, req, smb_fname, dirtype);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 TALLOC_FREE(dir_hnd);
3185 TALLOC_FREE(talloced);
3190 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3191 smb_fname->base_name));
3194 TALLOC_FREE(talloced);
3196 TALLOC_FREE(dir_hnd);
3199 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3200 status = map_nt_error_from_unix(errno);
3204 TALLOC_FREE(smb_fname_dir);
3205 TALLOC_FREE(fname_dir);
3206 TALLOC_FREE(fname_mask);
3210 /****************************************************************************
3212 ****************************************************************************/
3214 void reply_unlink(struct smb_request *req)
3216 connection_struct *conn = req->conn;
3218 struct smb_filename *smb_fname = NULL;
3221 bool path_contains_wcard = False;
3222 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3223 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
3224 TALLOC_CTX *ctx = talloc_tos();
3226 START_PROFILE(SMBunlink);
3229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3233 dirtype = SVAL(req->vwv+0, 0);
3235 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3236 STR_TERMINATE, &status,
3237 &path_contains_wcard);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 reply_nterror(req, status);
3243 status = filename_convert(ctx, conn,
3244 req->flags2 & FLAGS2_DFS_PATHNAMES,
3247 &path_contains_wcard,
3249 if (!NT_STATUS_IS_OK(status)) {
3250 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3251 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3252 ERRSRV, ERRbadpath);
3255 reply_nterror(req, status);
3259 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3261 status = unlink_internals(conn, req, dirtype, smb_fname,
3262 path_contains_wcard);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 if (open_was_deferred(req->xconn, req->mid)) {
3265 /* We have re-scheduled this call. */
3268 reply_nterror(req, status);
3272 reply_outbuf(req, 0, 0);
3274 TALLOC_FREE(smb_fname);
3275 END_PROFILE(SMBunlink);
3279 /****************************************************************************
3281 ****************************************************************************/
3283 static void fail_readraw(void)
3285 const char *errstr = talloc_asprintf(talloc_tos(),
3286 "FAIL ! reply_readbraw: socket write fail (%s)",
3291 exit_server_cleanly(errstr);
3294 /****************************************************************************
3295 Fake (read/write) sendfile. Returns -1 on read or write fail.
3296 ****************************************************************************/
3298 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3299 off_t startpos, size_t nread)
3302 size_t tosend = nread;
3309 bufsize = MIN(nread, 65536);
3311 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3315 while (tosend > 0) {
3319 cur_read = MIN(tosend, bufsize);
3320 ret = read_file(fsp,buf,startpos,cur_read);
3326 /* If we had a short read, fill with zeros. */
3327 if (ret < cur_read) {
3328 memset(buf + ret, '\0', cur_read - ret);
3331 ret = write_data(xconn->transport.sock, buf, cur_read);
3332 if (ret != cur_read) {
3333 int saved_errno = errno;
3335 * Try and give an error message saying what
3338 DEBUG(0, ("write_data failed for client %s. "
3340 smbXsrv_connection_dbg(xconn),
3341 strerror(saved_errno)));
3343 errno = saved_errno;
3347 startpos += cur_read;
3351 return (ssize_t)nread;
3354 /****************************************************************************
3355 Deal with the case of sendfile reading less bytes from the file than
3356 requested. Fill with zeros (all we can do). Returns 0 on success
3357 ****************************************************************************/
3359 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3365 #define SHORT_SEND_BUFSIZE 1024
3366 if (nread < headersize) {
3367 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3368 "header for file %s (%s). Terminating\n",
3369 fsp_str_dbg(fsp), strerror(errno)));
3373 nread -= headersize;
3375 if (nread < smb_maxcnt) {
3376 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3378 DEBUG(0,("sendfile_short_send: malloc failed "
3379 "for file %s (%s). Terminating\n",
3380 fsp_str_dbg(fsp), strerror(errno)));
3384 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3385 "with zeros !\n", fsp_str_dbg(fsp)));
3387 while (nread < smb_maxcnt) {
3389 * We asked for the real file size and told sendfile
3390 * to not go beyond the end of the file. But it can
3391 * happen that in between our fstat call and the
3392 * sendfile call the file was truncated. This is very
3393 * bad because we have already announced the larger
3394 * number of bytes to the client.
3396 * The best we can do now is to send 0-bytes, just as
3397 * a read from a hole in a sparse file would do.
3399 * This should happen rarely enough that I don't care
3400 * about efficiency here :-)
3405 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3406 ret = write_data(xconn->transport.sock, buf, to_write);
3407 if (ret != to_write) {
3408 int saved_errno = errno;
3410 * Try and give an error message saying what
3413 DEBUG(0, ("write_data failed for client %s. "
3415 smbXsrv_connection_dbg(xconn),
3416 strerror(saved_errno)));
3417 errno = saved_errno;
3428 /****************************************************************************
3429 Return a readbraw error (4 bytes of zero).
3430 ****************************************************************************/
3432 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3438 smbd_lock_socket(xconn);
3439 if (write_data(xconn->transport.sock,header,4) != 4) {
3440 int saved_errno = errno;
3442 * Try and give an error message saying what
3445 DEBUG(0, ("write_data failed for client %s. "
3447 smbXsrv_connection_dbg(xconn),
3448 strerror(saved_errno)));
3449 errno = saved_errno;
3453 smbd_unlock_socket(xconn);
3456 /****************************************************************************
3457 Use sendfile in readbraw.
3458 ****************************************************************************/
3460 static void send_file_readbraw(connection_struct *conn,
3461 struct smb_request *req,
3467 struct smbXsrv_connection *xconn = req->xconn;
3468 char *outbuf = NULL;
3472 * We can only use sendfile on a non-chained packet
3473 * but we can use on a non-oplocked file. tridge proved this
3474 * on a train in Germany :-). JRA.
3475 * reply_readbraw has already checked the length.
3478 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3479 (fsp->wcp == NULL) &&
3480 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3481 ssize_t sendfile_read = -1;
3483 DATA_BLOB header_blob;
3485 _smb_setlen(header,nread);
3486 header_blob = data_blob_const(header, 4);
3488 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3489 &header_blob, startpos,
3491 if (sendfile_read == -1) {
3492 /* Returning ENOSYS means no data at all was sent.
3493 * Do this as a normal read. */
3494 if (errno == ENOSYS) {
3495 goto normal_readbraw;
3499 * Special hack for broken Linux with no working sendfile. If we
3500 * return EINTR we sent the header but not the rest of the data.
3501 * Fake this up by doing read/write calls.
3503 if (errno == EINTR) {
3504 /* Ensure we don't do this again. */
3505 set_use_sendfile(SNUM(conn), False);
3506 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3508 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3509 DEBUG(0,("send_file_readbraw: "
3510 "fake_sendfile failed for "
3514 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3519 DEBUG(0,("send_file_readbraw: sendfile failed for "
3520 "file %s (%s). Terminating\n",
3521 fsp_str_dbg(fsp), strerror(errno)));
3522 exit_server_cleanly("send_file_readbraw sendfile failed");
3523 } else if (sendfile_read == 0) {
3525 * Some sendfile implementations return 0 to indicate
3526 * that there was a short read, but nothing was
3527 * actually written to the socket. In this case,
3528 * fallback to the normal read path so the header gets
3529 * the correct byte count.
3531 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3532 "bytes falling back to the normal read: "
3533 "%s\n", fsp_str_dbg(fsp)));
3534 goto normal_readbraw;
3537 /* Deal with possible short send. */
3538 if (sendfile_read != 4+nread) {
3539 ret = sendfile_short_send(xconn, fsp,
3540 sendfile_read, 4, nread);
3550 outbuf = talloc_array(NULL, char, nread+4);
3552 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3553 (unsigned)(nread+4)));
3554 reply_readbraw_error(xconn);
3559 ret = read_file(fsp,outbuf+4,startpos,nread);
3560 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3569 _smb_setlen(outbuf,ret);
3570 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3571 int saved_errno = errno;
3573 * Try and give an error message saying what
3576 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3577 smbXsrv_connection_dbg(xconn),
3578 strerror(saved_errno)));
3579 errno = saved_errno;
3584 TALLOC_FREE(outbuf);
3587 /****************************************************************************
3588 Reply to a readbraw (core+ protocol).
3589 ****************************************************************************/
3591 void reply_readbraw(struct smb_request *req)
3593 connection_struct *conn = req->conn;
3594 struct smbXsrv_connection *xconn = req->xconn;
3595 ssize_t maxcount,mincount;
3599 struct lock_struct lock;
3602 START_PROFILE(SMBreadbraw);
3604 if (srv_is_signing_active(xconn) || req->encrypted) {
3605 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3606 "raw reads/writes are disallowed.");
3610 reply_readbraw_error(xconn);
3611 END_PROFILE(SMBreadbraw);
3615 if (xconn->smb1.echo_handler.trusted_fde) {
3616 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3617 "'async smb echo handler = yes'\n"));
3618 reply_readbraw_error(xconn);
3619 END_PROFILE(SMBreadbraw);
3624 * Special check if an oplock break has been issued
3625 * and the readraw request croses on the wire, we must
3626 * return a zero length response here.
3629 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3632 * We have to do a check_fsp by hand here, as
3633 * we must always return 4 zero bytes on error,
3637 if (!fsp || !conn || conn != fsp->conn ||
3638 req->vuid != fsp->vuid ||
3639 fsp->is_directory || fsp->fh->fd == -1) {
3641 * fsp could be NULL here so use the value from the packet. JRA.
3643 DEBUG(3,("reply_readbraw: fnum %d not valid "
3645 (int)SVAL(req->vwv+0, 0)));
3646 reply_readbraw_error(xconn);
3647 END_PROFILE(SMBreadbraw);
3651 /* Do a "by hand" version of CHECK_READ. */
3652 if (!(fsp->can_read ||
3653 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3654 (fsp->access_mask & FILE_EXECUTE)))) {
3655 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3656 (int)SVAL(req->vwv+0, 0)));
3657 reply_readbraw_error(xconn);
3658 END_PROFILE(SMBreadbraw);
3662 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3664 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3665 if(req->wct == 10) {
3667 * This is a large offset (64 bit) read.
3670 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3673 DEBUG(0,("reply_readbraw: negative 64 bit "
3674 "readraw offset (%.0f) !\n",
3675 (double)startpos ));
3676 reply_readbraw_error(xconn);
3677 END_PROFILE(SMBreadbraw);
3682 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3683 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3685 /* ensure we don't overrun the packet size */
3686 maxcount = MIN(65535,maxcount);
3688 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3689 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3692 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3693 reply_readbraw_error(xconn);
3694 END_PROFILE(SMBreadbraw);
3698 if (fsp_stat(fsp) == 0) {
3699 size = fsp->fsp_name->st.st_ex_size;
3702 if (startpos >= size) {
3705 nread = MIN(maxcount,(size - startpos));
3708 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3709 if (nread < mincount)
3713 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3714 "min=%lu nread=%lu\n",
3715 fsp_fnum_dbg(fsp), (double)startpos,
3716 (unsigned long)maxcount,
3717 (unsigned long)mincount,
3718 (unsigned long)nread ) );
3720 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3722 DEBUG(5,("reply_readbraw finished\n"));
3724 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3726 END_PROFILE(SMBreadbraw);
3731 #define DBGC_CLASS DBGC_LOCKING
3733 /****************************************************************************
3734 Reply to a lockread (core+ protocol).
3735 ****************************************************************************/
3737 void reply_lockread(struct smb_request *req)
3739 connection_struct *conn = req->conn;
3747 struct byte_range_lock *br_lck = NULL;
3749 struct smbXsrv_connection *xconn = req->xconn;
3751 START_PROFILE(SMBlockread);
3754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3755 END_PROFILE(SMBlockread);
3759 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3761 if (!check_fsp(conn, req, fsp)) {
3762 END_PROFILE(SMBlockread);
3766 if (!CHECK_READ(fsp,req)) {
3767 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3768 END_PROFILE(SMBlockread);
3772 numtoread = SVAL(req->vwv+1, 0);
3773 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3776 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3777 * protocol request that predates the read/write lock concept.
3778 * Thus instead of asking for a read lock here we need to ask
3779 * for a write lock. JRA.
3780 * Note that the requested lock size is unaffected by max_send.
3783 br_lck = do_lock(req->sconn->msg_ctx,
3785 (uint64_t)req->smbpid,
3786 (uint64_t)numtoread,
3790 False, /* Non-blocking lock. */
3793 TALLOC_FREE(br_lck);
3795 if (NT_STATUS_V(status)) {
3796 reply_nterror(req, status);
3797 END_PROFILE(SMBlockread);
3802 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3804 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3806 if (numtoread > maxtoread) {
3807 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3808 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3809 (unsigned int)numtoread, (unsigned int)maxtoread,
3810 (unsigned int)xconn->smb1.sessions.max_send));
3811 numtoread = maxtoread;
3814 reply_outbuf(req, 5, numtoread + 3);
3816 data = smb_buf(req->outbuf) + 3;
3818 nread = read_file(fsp,data,startpos,numtoread);
3821 reply_nterror(req, map_nt_error_from_unix(errno));
3822 END_PROFILE(SMBlockread);
3826 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3828 SSVAL(req->outbuf,smb_vwv0,nread);
3829 SSVAL(req->outbuf,smb_vwv5,nread+3);
3830 p = smb_buf(req->outbuf);
3831 SCVAL(p,0,0); /* pad byte. */
3834 DEBUG(3,("lockread %s num=%d nread=%d\n",
3835 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3837 END_PROFILE(SMBlockread);
3842 #define DBGC_CLASS DBGC_ALL
3844 /****************************************************************************
3846 ****************************************************************************/
3848 void reply_read(struct smb_request *req)
3850 connection_struct *conn = req->conn;
3857 struct lock_struct lock;
3858 struct smbXsrv_connection *xconn = req->xconn;
3860 START_PROFILE(SMBread);
3863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864 END_PROFILE(SMBread);
3868 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3870 if (!check_fsp(conn, req, fsp)) {
3871 END_PROFILE(SMBread);
3875 if (!CHECK_READ(fsp,req)) {
3876 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3877 END_PROFILE(SMBread);
3881 numtoread = SVAL(req->vwv+1, 0);
3882 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3885 * The requested read size cannot be greater than max_send. JRA.
3887 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3889 if (numtoread > maxtoread) {
3890 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3891 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3892 (unsigned int)numtoread, (unsigned int)maxtoread,
3893 (unsigned int)xconn->smb1.sessions.max_send));
3894 numtoread = maxtoread;
3897 reply_outbuf(req, 5, numtoread+3);
3899 data = smb_buf(req->outbuf) + 3;
3901 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3902 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3905 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3906 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3907 END_PROFILE(SMBread);
3912 nread = read_file(fsp,data,startpos,numtoread);
3915 reply_nterror(req, map_nt_error_from_unix(errno));
3919 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3921 SSVAL(req->outbuf,smb_vwv0,nread);
3922 SSVAL(req->outbuf,smb_vwv5,nread+3);
3923 SCVAL(smb_buf(req->outbuf),0,1);
3924 SSVAL(smb_buf(req->outbuf),1,nread);
3926 DEBUG(3, ("read %s num=%d nread=%d\n",
3927 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3930 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3932 END_PROFILE(SMBread);
3936 /****************************************************************************
3938 ****************************************************************************/
3940 int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3944 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3947 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3949 SCVAL(outbuf,smb_vwv0,0xFF);
3950 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3951 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3952 SSVAL(outbuf,smb_vwv6,
3953 (smb_wct - 4) /* offset from smb header to wct */
3954 + 1 /* the wct field */
3955 + 12 * sizeof(uint16_t) /* vwv */
3956 + 2 /* the buflen field */
3957 + 1); /* padding byte */
3958 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3959 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3960 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3961 _smb_setlen_large(outbuf,
3962 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3966 /****************************************************************************
3967 Reply to a read and X - possibly using sendfile.
3968 ****************************************************************************/
3970 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3971 files_struct *fsp, off_t startpos,
3974 struct smbXsrv_connection *xconn = req->xconn;
3976 struct lock_struct lock;
3977 int saved_errno = 0;
3979 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3980 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3983 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3984 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3989 * We can only use sendfile on a non-chained packet
3990 * but we can use on a non-oplocked file. tridge proved this
3991 * on a train in Germany :-). JRA.
3994 if (!req_is_in_chain(req) &&
3996 (fsp->base_fsp == NULL) &&
3997 (fsp->wcp == NULL) &&
3998 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3999 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4002 if(fsp_stat(fsp) == -1) {
4003 reply_nterror(req, map_nt_error_from_unix(errno));
4007 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4008 (startpos > fsp->fsp_name->st.st_ex_size) ||
4009 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4011 * We already know that we would do a short read, so don't
4012 * try the sendfile() path.
4014 goto nosendfile_read;
4018 * Set up the packet header before send. We
4019 * assume here the sendfile will work (get the
4020 * correct amount of data).
4023 header = data_blob_const(headerbuf, sizeof(headerbuf));
4025 construct_reply_common_req(req, (char *)headerbuf);
4026 setup_readX_header((char *)headerbuf, smb_maxcnt);
4028 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4029 startpos, smb_maxcnt);
4031 saved_errno = errno;
4033 /* Returning ENOSYS means no data at all was sent.
4034 Do this as a normal read. */
4035 if (errno == ENOSYS) {
4040 * Special hack for broken Linux with no working sendfile. If we
4041 * return EINTR we sent the header but not the rest of the data.
4042 * Fake this up by doing read/write calls.
4045 if (errno == EINTR) {
4046 /* Ensure we don't do this again. */
4047 set_use_sendfile(SNUM(conn), False);
4048 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4049 nread = fake_sendfile(xconn, fsp, startpos,
4052 saved_errno = errno;
4053 DEBUG(0,("send_file_readX: "
4054 "fake_sendfile failed for "
4055 "file %s (%s) for client %s. "
4058 smbXsrv_connection_dbg(xconn),
4059 strerror(saved_errno)));
4060 errno = saved_errno;
4061 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4063 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4064 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4065 /* No outbuf here means successful sendfile. */
4069 DEBUG(0,("send_file_readX: sendfile failed for file "
4070 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4072 exit_server_cleanly("send_file_readX sendfile failed");
4073 } else if (nread == 0) {
4075 * Some sendfile implementations return 0 to indicate
4076 * that there was a short read, but nothing was
4077 * actually written to the socket. In this case,
4078 * fallback to the normal read path so the header gets
4079 * the correct byte count.
4081 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4082 "falling back to the normal read: %s\n",
4087 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4088 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4090 /* Deal with possible short send. */
4091 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4094 ret = sendfile_short_send(xconn, fsp, nread,
4095 sizeof(headerbuf), smb_maxcnt);
4098 r = "send_file_readX: sendfile_short_send failed";
4099 DEBUG(0,("%s for file %s (%s).\n",
4100 r, fsp_str_dbg(fsp), strerror(errno)));
4101 exit_server_cleanly(r);
4104 /* No outbuf here means successful sendfile. */
4105 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4106 SMB_PERFCOUNT_END(&req->pcd);
4112 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4113 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4116 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4117 (startpos > fsp->fsp_name->st.st_ex_size) ||
4118 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4120 * We already know that we would do a short
4121 * read, so don't try the sendfile() path.
4123 goto nosendfile_read;
4126 construct_reply_common_req(req, (char *)headerbuf);
4127 setup_readX_header((char *)headerbuf, smb_maxcnt);
4129 /* Send out the header. */
4130 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4132 if (ret != sizeof(headerbuf)) {
4133 saved_errno = errno;
4135 * Try and give an error message saying what
4138 DEBUG(0,("send_file_readX: write_data failed for file "
4139 "%s (%s) for client %s. Terminating\n",
4141 smbXsrv_connection_dbg(xconn),
4142 strerror(saved_errno)));
4143 errno = saved_errno;
4144 exit_server_cleanly("send_file_readX sendfile failed");
4146 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4148 saved_errno = errno;
4149 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4150 "%s (%s) for client %s. Terminating\n",
4152 smbXsrv_connection_dbg(xconn),
4153 strerror(saved_errno)));
4154 errno = saved_errno;
4155 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4162 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4163 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4164 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4166 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4167 startpos, smb_maxcnt);
4168 saved_errno = errno;
4170 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4173 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4177 setup_readX_header((char *)req->outbuf, nread);
4179 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4180 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4184 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4185 TALLOC_FREE(req->outbuf);
4189 /****************************************************************************
4190 Work out how much space we have for a read return.
4191 ****************************************************************************/
4193 static size_t calc_max_read_pdu(const struct smb_request *req)
4195 struct smbXsrv_connection *xconn = req->xconn;
4197 if (xconn->protocol < PROTOCOL_NT1) {
4198 return xconn->smb1.sessions.max_send;
4201 if (!lp_large_readwrite()) {
4202 return xconn->smb1.sessions.max_send;
4205 if (req_is_in_chain(req)) {
4206 return xconn->smb1.sessions.max_send;
4209 if (req->encrypted) {
4211 * Don't take encrypted traffic up to the
4212 * limit. There are padding considerations
4213 * that make that tricky.
4215 return xconn->smb1.sessions.max_send;
4218 if (srv_is_signing_active(xconn)) {
4222 if (!lp_unix_extensions()) {
4227 * We can do ultra-large POSIX reads.
4232 /****************************************************************************
4233 Calculate how big a read can be. Copes with all clients. It's always
4234 safe to return a short read - Windows does this.
4235 ****************************************************************************/
4237 static size_t calc_read_size(const struct smb_request *req,
4241 struct smbXsrv_connection *xconn = req->xconn;
4242 size_t max_pdu = calc_max_read_pdu(req);
4243 size_t total_size = 0;
4244 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4245 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4248 * Windows explicitly ignores upper size of 0xFFFF.
4249 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4250 * We must do the same as these will never fit even in
4251 * an extended size NetBIOS packet.
4253 if (upper_size == 0xFFFF) {
4257 if (xconn->protocol < PROTOCOL_NT1) {
4261 total_size = ((upper_size<<16) | lower_size);
4264 * LARGE_READX test shows it's always safe to return
4265 * a short read. Windows does so.
4267 return MIN(total_size, max_len);
4270 /****************************************************************************
4271 Reply to a read and X.
4272 ****************************************************************************/
4274 void reply_read_and_X(struct smb_request *req)
4276 connection_struct *conn = req->conn;
4281 bool big_readX = False;
4283 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4286 START_PROFILE(SMBreadX);
4288 if ((req->wct != 10) && (req->wct != 12)) {
4289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4293 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4294 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4295 smb_maxcnt = SVAL(req->vwv+5, 0);
4297 /* If it's an IPC, pass off the pipe handler. */
4299 reply_pipe_read_and_X(req);
4300 END_PROFILE(SMBreadX);
4304 if (!check_fsp(conn, req, fsp)) {
4305 END_PROFILE(SMBreadX);
4309 if (!CHECK_READ(fsp,req)) {
4310 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4311 END_PROFILE(SMBreadX);
4315 upper_size = SVAL(req->vwv+7, 0);
4316 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4317 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4319 * This is a heuristic to avoid keeping large
4320 * outgoing buffers around over long-lived aio
4326 if (req->wct == 12) {
4328 * This is a large offset (64 bit) read.
4330 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4335 NTSTATUS status = schedule_aio_read_and_X(conn,
4340 if (NT_STATUS_IS_OK(status)) {
4341 /* Read scheduled - we're done. */
4344 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4345 /* Real error - report to client. */
4346 END_PROFILE(SMBreadX);
4347 reply_nterror(req, status);
4350 /* NT_STATUS_RETRY - fall back to sync read. */
4353 smbd_lock_socket(req->xconn);
4354 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4355 smbd_unlock_socket(req->xconn);
4358 END_PROFILE(SMBreadX);
4362 /****************************************************************************
4363 Error replies to writebraw must have smb_wct == 1. Fix this up.
4364 ****************************************************************************/
4366 void error_to_writebrawerr(struct smb_request *req)
4368 uint8_t *old_outbuf = req->outbuf;
4370 reply_outbuf(req, 1, 0);
4372 memcpy(req->outbuf, old_outbuf, smb_size);
4373 TALLOC_FREE(old_outbuf);
4376 /****************************************************************************
4377 Read 4 bytes of a smb packet and return the smb length of the packet.
4378 Store the result in the buffer. This version of the function will
4379 never return a session keepalive (length of zero).
4380 Timeout is in milliseconds.
4381 ****************************************************************************/
4383 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4386 uint8_t msgtype = NBSSkeepalive;
4388 while (msgtype == NBSSkeepalive) {
4391 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4393 if (!NT_STATUS_IS_OK(status)) {
4394 char addr[INET6_ADDRSTRLEN];
4395 /* Try and give an error message
4396 * saying what client failed. */
4397 DEBUG(0, ("read_fd_with_timeout failed for "
4398 "client %s read error = %s.\n",
4399 get_peer_addr(fd,addr,sizeof(addr)),
4400 nt_errstr(status)));
4404 msgtype = CVAL(inbuf, 0);
4407 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4408 (unsigned long)len));
4410 return NT_STATUS_OK;
4413 /****************************************************************************
4414 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4415 ****************************************************************************/
4417 void reply_writebraw(struct smb_request *req)
4419 connection_struct *conn = req->conn;
4420 struct smbXsrv_connection *xconn = req->xconn;
4423 ssize_t total_written=0;
4424 size_t numtowrite=0;
4427 const char *data=NULL;
4430 struct lock_struct lock;
4433 START_PROFILE(SMBwritebraw);
4436 * If we ever reply with an error, it must have the SMB command
4437 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4440 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4442 if (srv_is_signing_active(xconn)) {
4443 END_PROFILE(SMBwritebraw);
4444 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4445 "raw reads/writes are disallowed.");
4448 if (req->wct < 12) {
4449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4450 error_to_writebrawerr(req);
4451 END_PROFILE(SMBwritebraw);
4455 if (xconn->smb1.echo_handler.trusted_fde) {
4456 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4457 "'async smb echo handler = yes'\n"));
4458 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4459 error_to_writebrawerr(req);
4460 END_PROFILE(SMBwritebraw);
4464 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4465 if (!check_fsp(conn, req, fsp)) {
4466 error_to_writebrawerr(req);
4467 END_PROFILE(SMBwritebraw);
4471 if (!CHECK_WRITE(fsp)) {
4472 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4473 error_to_writebrawerr(req);
4474 END_PROFILE(SMBwritebraw);
4478 tcount = IVAL(req->vwv+1, 0);
4479 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4480 write_through = BITSETW(req->vwv+7,0);
4482 /* We have to deal with slightly different formats depending
4483 on whether we are using the core+ or lanman1.0 protocol */
4485 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4486 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4487 data = smb_buf_const(req->inbuf);
4489 numtowrite = SVAL(req->vwv+10, 0);
4490 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4493 /* Ensure we don't write bytes past the end of this packet. */
4494 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4496 error_to_writebrawerr(req);
4497 END_PROFILE(SMBwritebraw);
4501 if (!fsp->print_file) {
4502 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4503 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4506 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4507 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4508 error_to_writebrawerr(req);
4509 END_PROFILE(SMBwritebraw);
4515 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4518 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4519 "wrote=%d sync=%d\n",
4520 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4521 (int)nwritten, (int)write_through));
4523 if (nwritten < (ssize_t)numtowrite) {
4524 reply_nterror(req, NT_STATUS_DISK_FULL);
4525 error_to_writebrawerr(req);
4529 total_written = nwritten;
4531 /* Allocate a buffer of 64k + length. */
4532 buf = talloc_array(NULL, char, 65540);
4534 reply_nterror(req, NT_STATUS_NO_MEMORY);
4535 error_to_writebrawerr(req);
4539 /* Return a SMBwritebraw message to the redirector to tell
4540 * it to send more bytes */
4542 memcpy(buf, req->inbuf, smb_size);
4543 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4544 SCVAL(buf,smb_com,SMBwritebraw);
4545 SSVALS(buf,smb_vwv0,0xFFFF);
4547 if (!srv_send_smb(req->xconn,
4549 false, 0, /* no signing */
4550 IS_CONN_ENCRYPTED(conn),
4552 exit_server_cleanly("reply_writebraw: srv_send_smb "
4556 /* Now read the raw data into the buffer and write it */
4557 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4559 if (!NT_STATUS_IS_OK(status)) {
4560 exit_server_cleanly("secondary writebraw failed");
4563 /* Set up outbuf to return the correct size */
4564 reply_outbuf(req, 1, 0);
4566 if (numtowrite != 0) {
4568 if (numtowrite > 0xFFFF) {
4569 DEBUG(0,("reply_writebraw: Oversize secondary write "
4570 "raw requested (%u). Terminating\n",
4571 (unsigned int)numtowrite ));
4572 exit_server_cleanly("secondary writebraw failed");
4575 if (tcount > nwritten+numtowrite) {
4576 DEBUG(3,("reply_writebraw: Client overestimated the "
4578 (int)tcount,(int)nwritten,(int)numtowrite));
4581 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4584 if (!NT_STATUS_IS_OK(status)) {
4585 /* Try and give an error message
4586 * saying what client failed. */
4587 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4588 "raw read failed (%s) for client %s. "
4589 "Terminating\n", nt_errstr(status),
4590 smbXsrv_connection_dbg(xconn)));
4591 exit_server_cleanly("secondary writebraw failed");
4594 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4595 if (nwritten == -1) {
4597 reply_nterror(req, map_nt_error_from_unix(errno));
4598 error_to_writebrawerr(req);
4602 if (nwritten < (ssize_t)numtowrite) {
4603 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4604 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4608 total_written += nwritten;
4613 SSVAL(req->outbuf,smb_vwv0,total_written);
4615 status = sync_file(conn, fsp, write_through);
4616 if (!NT_STATUS_IS_OK(status)) {
4617 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4618 fsp_str_dbg(fsp), nt_errstr(status)));
4619 reply_nterror(req, status);
4620 error_to_writebrawerr(req);
4624 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4626 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4627 (int)total_written));
4629 if (!fsp->print_file) {
4630 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4633 /* We won't return a status if write through is not selected - this
4634 * follows what WfWg does */
4635 END_PROFILE(SMBwritebraw);
4637 if (!write_through && total_written==tcount) {
4639 #if RABBIT_PELLET_FIX
4641 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4642 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4645 if (!send_keepalive(xconn->transport.sock)) {
4646 exit_server_cleanly("reply_writebraw: send of "
4647 "keepalive failed");
4650 TALLOC_FREE(req->outbuf);
4655 if (!fsp->print_file) {
4656 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4659 END_PROFILE(SMBwritebraw);
4664 #define DBGC_CLASS DBGC_LOCKING
4666 /****************************************************************************
4667 Reply to a writeunlock (core+).
4668 ****************************************************************************/
4670 void reply_writeunlock(struct smb_request *req)
4672 connection_struct *conn = req->conn;
4673 ssize_t nwritten = -1;
4677 NTSTATUS status = NT_STATUS_OK;
4679 struct lock_struct lock;
4680 int saved_errno = 0;
4682 START_PROFILE(SMBwriteunlock);
4685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4686 END_PROFILE(SMBwriteunlock);
4690 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4692 if (!check_fsp(conn, req, fsp)) {
4693 END_PROFILE(SMBwriteunlock);
4697 if (!CHECK_WRITE(fsp)) {
4698 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4699 END_PROFILE(SMBwriteunlock);
4703 numtowrite = SVAL(req->vwv+1, 0);
4704 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4705 data = (const char *)req->buf + 3;
4707 if (!fsp->print_file && numtowrite > 0) {
4708 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4709 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4712 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4713 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4714 END_PROFILE(SMBwriteunlock);
4719 /* The special X/Open SMB protocol handling of
4720 zero length writes is *NOT* done for
4722 if(numtowrite == 0) {
4725 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4726 saved_errno = errno;
4729 status = sync_file(conn, fsp, False /* write through */);
4730 if (!NT_STATUS_IS_OK(status)) {
4731 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4732 fsp_str_dbg(fsp), nt_errstr(status)));
4733 reply_nterror(req, status);
4738 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4742 if((nwritten < numtowrite) && (numtowrite != 0)) {
4743 reply_nterror(req, NT_STATUS_DISK_FULL);
4747 if (numtowrite && !fsp->print_file) {
4748 status = do_unlock(req->sconn->msg_ctx,
4750 (uint64_t)req->smbpid,
4751 (uint64_t)numtowrite,
4755 if (NT_STATUS_V(status)) {
4756 reply_nterror(req, status);
4761 reply_outbuf(req, 1, 0);
4763 SSVAL(req->outbuf,smb_vwv0,nwritten);
4765 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4766 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4769 if (numtowrite && !fsp->print_file) {
4770 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4773 END_PROFILE(SMBwriteunlock);
4778 #define DBGC_CLASS DBGC_ALL
4780 /****************************************************************************
4782 ****************************************************************************/
4784 void reply_write(struct smb_request *req)
4786 connection_struct *conn = req->conn;
4788 ssize_t nwritten = -1;
4792 struct lock_struct lock;
4794 int saved_errno = 0;
4796 START_PROFILE(SMBwrite);
4799 END_PROFILE(SMBwrite);
4800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4804 /* If it's an IPC, pass off the pipe handler. */
4806 reply_pipe_write(req);
4807 END_PROFILE(SMBwrite);
4811 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4813 if (!check_fsp(conn, req, fsp)) {
4814 END_PROFILE(SMBwrite);
4818 if (!CHECK_WRITE(fsp)) {
4819 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4820 END_PROFILE(SMBwrite);
4824 numtowrite = SVAL(req->vwv+1, 0);
4825 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4826 data = (const char *)req->buf + 3;
4828 if (!fsp->print_file) {
4829 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4830 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4833 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4834 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4835 END_PROFILE(SMBwrite);
4841 * X/Open SMB protocol says that if smb_vwv1 is
4842 * zero then the file size should be extended or
4843 * truncated to the size given in smb_vwv[2-3].
4846 if(numtowrite == 0) {
4848 * This is actually an allocate call, and set EOF. JRA.
4850 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4852 reply_nterror(req, NT_STATUS_DISK_FULL);
4855 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4857 reply_nterror(req, NT_STATUS_DISK_FULL);
4860 trigger_write_time_update_immediate(fsp);
4862 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4865 status = sync_file(conn, fsp, False);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4868 fsp_str_dbg(fsp), nt_errstr(status)));
4869 reply_nterror(req, status);
4874 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4878 if((nwritten == 0) && (numtowrite != 0)) {
4879 reply_nterror(req, NT_STATUS_DISK_FULL);
4883 reply_outbuf(req, 1, 0);
4885 SSVAL(req->outbuf,smb_vwv0,nwritten);
4887 if (nwritten < (ssize_t)numtowrite) {
4888 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4889 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4892 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4895 if (!fsp->print_file) {
4896 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4899 END_PROFILE(SMBwrite);
4903 /****************************************************************************
4904 Ensure a buffer is a valid writeX for recvfile purposes.
4905 ****************************************************************************/
4907 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4908 (2*14) + /* word count (including bcc) */ \
4911 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4912 const uint8_t *inbuf)
4915 unsigned int doff = 0;
4916 size_t len = smb_len_large(inbuf);
4918 struct smbXsrv_open *op = NULL;
4919 struct files_struct *fsp = NULL;
4922 if (is_encrypted_packet(inbuf)) {
4923 /* Can't do this on encrypted
4928 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4932 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4933 CVAL(inbuf,smb_wct) != 14) {
4934 DEBUG(10,("is_valid_writeX_buffer: chained or "
4935 "invalid word length.\n"));
4939 fnum = SVAL(inbuf, smb_vwv2);
4940 status = smb1srv_open_lookup(xconn,
4944 if (!NT_STATUS_IS_OK(status)) {
4945 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4950 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4953 if (fsp->conn == NULL) {
4954 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4958 if (IS_IPC(fsp->conn)) {
4959 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4962 if (IS_PRINT(fsp->conn)) {
4963 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4966 doff = SVAL(inbuf,smb_vwv11);
4968 numtowrite = SVAL(inbuf,smb_vwv10);
4970 if (len > doff && len - doff > 0xFFFF) {
4971 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4974 if (numtowrite == 0) {
4975 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4979 /* Ensure the sizes match up. */
4980 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4981 /* no pad byte...old smbclient :-( */
4982 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4984 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4988 if (len - doff != numtowrite) {
4989 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4990 "len = %u, doff = %u, numtowrite = %u\n",
4993 (unsigned int)numtowrite ));
4997 DEBUG(10,("is_valid_writeX_buffer: true "
4998 "len = %u, doff = %u, numtowrite = %u\n",
5001 (unsigned int)numtowrite ));
5006 /****************************************************************************
5007 Reply to a write and X.
5008 ****************************************************************************/
5010 void reply_write_and_X(struct smb_request *req)
5012 connection_struct *conn = req->conn;
5013 struct smbXsrv_connection *xconn = req->xconn;
5015 struct lock_struct lock;
5020 unsigned int smb_doff;
5021 unsigned int smblen;
5024 int saved_errno = 0;
5026 START_PROFILE(SMBwriteX);
5028 if ((req->wct != 12) && (req->wct != 14)) {
5029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5033 numtowrite = SVAL(req->vwv+10, 0);
5034 smb_doff = SVAL(req->vwv+11, 0);
5035 smblen = smb_len(req->inbuf);
5037 if (req->unread_bytes > 0xFFFF ||
5038 (smblen > smb_doff &&
5039 smblen - smb_doff > 0xFFFF)) {
5040 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5043 if (req->unread_bytes) {
5044 /* Can't do a recvfile write on IPC$ */
5046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5049 if (numtowrite != req->unread_bytes) {
5050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5054 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5055 smb_doff + numtowrite > smblen) {
5056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5061 /* If it's an IPC, pass off the pipe handler. */
5063 if (req->unread_bytes) {
5064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5067 reply_pipe_write_and_X(req);
5071 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5072 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5073 write_through = BITSETW(req->vwv+7,0);
5075 if (!check_fsp(conn, req, fsp)) {
5079 if (!CHECK_WRITE(fsp)) {
5080 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5084 data = smb_base(req->inbuf) + smb_doff;
5086 if(req->wct == 14) {
5088 * This is a large offset (64 bit) write.
5090 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5094 /* X/Open SMB protocol says that, unlike SMBwrite
5095 if the length is zero then NO truncation is
5096 done, just a write of zero. To truncate a file,
5099 if(numtowrite == 0) {
5102 if (req->unread_bytes == 0) {
5103 status = schedule_aio_write_and_X(conn,
5110 if (NT_STATUS_IS_OK(status)) {
5111 /* write scheduled - we're done. */
5114 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5115 /* Real error - report to client. */
5116 reply_nterror(req, status);
5119 /* NT_STATUS_RETRY - fall through to sync write. */
5122 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5123 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5126 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5127 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5131 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5132 saved_errno = errno;
5134 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5138 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5142 if((nwritten == 0) && (numtowrite != 0)) {
5143 reply_nterror(req, NT_STATUS_DISK_FULL);
5147 reply_outbuf(req, 6, 0);
5148 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5149 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5150 SSVAL(req->outbuf,smb_vwv2,nwritten);
5151 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5153 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5154 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5156 status = sync_file(conn, fsp, write_through);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5159 fsp_str_dbg(fsp), nt_errstr(status)));
5160 reply_nterror(req, status);
5164 END_PROFILE(SMBwriteX);
5168 if (req->unread_bytes) {
5169 /* writeX failed. drain socket. */
5170 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5171 req->unread_bytes) {
5172 smb_panic("failed to drain pending bytes");
5174 req->unread_bytes = 0;
5177 END_PROFILE(SMBwriteX);
5181 /****************************************************************************
5183 ****************************************************************************/
5185 void reply_lseek(struct smb_request *req)
5187 connection_struct *conn = req->conn;
5193 START_PROFILE(SMBlseek);
5196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5197 END_PROFILE(SMBlseek);
5201 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5203 if (!check_fsp(conn, req, fsp)) {
5207 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5209 mode = SVAL(req->vwv+1, 0) & 3;
5210 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5211 startpos = (off_t)IVALS(req->vwv+2, 0);
5220 res = fsp->fh->pos + startpos;
5231 if (umode == SEEK_END) {
5232 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5233 if(errno == EINVAL) {
5234 off_t current_pos = startpos;
5236 if(fsp_stat(fsp) == -1) {
5238 map_nt_error_from_unix(errno));
5239 END_PROFILE(SMBlseek);
5243 current_pos += fsp->fsp_name->st.st_ex_size;
5245 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5250 reply_nterror(req, map_nt_error_from_unix(errno));
5251 END_PROFILE(SMBlseek);
5258 reply_outbuf(req, 2, 0);
5259 SIVAL(req->outbuf,smb_vwv0,res);
5261 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5262 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5264 END_PROFILE(SMBlseek);
5268 /****************************************************************************
5270 ****************************************************************************/
5272 void reply_flush(struct smb_request *req)
5274 connection_struct *conn = req->conn;
5278 START_PROFILE(SMBflush);
5281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5285 fnum = SVAL(req->vwv+0, 0);
5286 fsp = file_fsp(req, fnum);
5288 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5293 file_sync_all(conn);
5295 NTSTATUS status = sync_file(conn, fsp, True);
5296 if (!NT_STATUS_IS_OK(status)) {
5297 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5298 fsp_str_dbg(fsp), nt_errstr(status)));
5299 reply_nterror(req, status);
5300 END_PROFILE(SMBflush);
5305 reply_outbuf(req, 0, 0);
5307 DEBUG(3,("flush\n"));
5308 END_PROFILE(SMBflush);
5312 /****************************************************************************
5314 conn POINTER CAN BE NULL HERE !
5315 ****************************************************************************/
5317 void reply_exit(struct smb_request *req)
5319 START_PROFILE(SMBexit);
5321 file_close_pid(req->sconn, req->smbpid, req->vuid);
5323 reply_outbuf(req, 0, 0);
5325 DEBUG(3,("exit\n"));
5327 END_PROFILE(SMBexit);
5331 struct reply_close_state {
5333 struct smb_request *smbreq;
5336 static void do_smb1_close(struct tevent_req *req);
5338 void reply_close(struct smb_request *req)
5340 connection_struct *conn = req->conn;
5341 NTSTATUS status = NT_STATUS_OK;
5342 files_struct *fsp = NULL;
5343 START_PROFILE(SMBclose);
5346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5347 END_PROFILE(SMBclose);
5351 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5354 * We can only use check_fsp if we know it's not a directory.
5357 if (!check_fsp_open(conn, req, fsp)) {
5358 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5359 END_PROFILE(SMBclose);
5363 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5364 fsp->is_directory ? "directory" : "file",
5365 fsp->fh->fd, fsp_fnum_dbg(fsp),
5366 conn->num_files_open));
5368 if (!fsp->is_directory) {
5372 * Take care of any time sent in the close.
5375 t = srv_make_unix_date3(req->vwv+1);
5376 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5379 if (fsp->num_aio_requests != 0) {
5381 struct reply_close_state *state;
5383 DEBUG(10, ("closing with aio %u requests pending\n",
5384 fsp->num_aio_requests));
5387 * We depend on the aio_extra destructor to take care of this
5388 * close request once fsp->num_aio_request drops to 0.
5391 fsp->deferred_close = tevent_wait_send(
5392 fsp, fsp->conn->sconn->ev_ctx);
5393 if (fsp->deferred_close == NULL) {
5394 status = NT_STATUS_NO_MEMORY;
5398 state = talloc(fsp, struct reply_close_state);
5399 if (state == NULL) {
5400 TALLOC_FREE(fsp->deferred_close);
5401 status = NT_STATUS_NO_MEMORY;
5405 state->smbreq = talloc_move(fsp, &req);
5406 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5408 END_PROFILE(SMBclose);
5413 * close_file() returns the unix errno if an error was detected on
5414 * close - normally this is due to a disk full error. If not then it
5415 * was probably an I/O error.
5418 status = close_file(req, fsp, NORMAL_CLOSE);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 reply_nterror(req, status);
5422 END_PROFILE(SMBclose);
5426 reply_outbuf(req, 0, 0);
5427 END_PROFILE(SMBclose);
5431 static void do_smb1_close(struct tevent_req *req)
5433 struct reply_close_state *state = tevent_req_callback_data(
5434 req, struct reply_close_state);
5435 struct smb_request *smbreq;
5439 ret = tevent_wait_recv(req);
5442 DEBUG(10, ("tevent_wait_recv returned %s\n",
5445 * Continue anyway, this should never happen
5450 * fsp->smb2_close_request right now is a talloc grandchild of
5451 * fsp. When we close_file(fsp), it would go with it. No chance to
5454 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5456 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5457 if (NT_STATUS_IS_OK(status)) {
5458 reply_outbuf(smbreq, 0, 0);
5460 reply_nterror(smbreq, status);
5462 if (!srv_send_smb(smbreq->xconn,
5463 (char *)smbreq->outbuf,
5466 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5468 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5471 TALLOC_FREE(smbreq);
5474 /****************************************************************************
5475 Reply to a writeclose (Core+ protocol).
5476 ****************************************************************************/
5478 void reply_writeclose(struct smb_request *req)
5480 connection_struct *conn = req->conn;
5482 ssize_t nwritten = -1;
5483 NTSTATUS close_status = NT_STATUS_OK;
5486 struct timespec mtime;
5488 struct lock_struct lock;
5490 START_PROFILE(SMBwriteclose);
5493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5494 END_PROFILE(SMBwriteclose);
5498 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5500 if (!check_fsp(conn, req, fsp)) {
5501 END_PROFILE(SMBwriteclose);
5504 if (!CHECK_WRITE(fsp)) {
5505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5506 END_PROFILE(SMBwriteclose);
5510 numtowrite = SVAL(req->vwv+1, 0);
5511 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5512 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5513 data = (const char *)req->buf + 1;
5515 if (fsp->print_file == NULL) {
5516 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5517 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5520 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5521 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5522 END_PROFILE(SMBwriteclose);
5527 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5529 if (fsp->print_file == NULL) {
5530 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5533 set_close_write_time(fsp, mtime);
5536 * More insanity. W2K only closes the file if writelen > 0.
5540 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5541 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5542 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5545 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5546 "file %s\n", fsp_str_dbg(fsp)));
5547 close_status = close_file(req, fsp, NORMAL_CLOSE);
5551 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5552 reply_nterror(req, NT_STATUS_DISK_FULL);
5556 if(!NT_STATUS_IS_OK(close_status)) {
5557 reply_nterror(req, close_status);
5561 reply_outbuf(req, 1, 0);
5563 SSVAL(req->outbuf,smb_vwv0,nwritten);
5567 END_PROFILE(SMBwriteclose);
5572 #define DBGC_CLASS DBGC_LOCKING
5574 /****************************************************************************
5576 ****************************************************************************/
5578 void reply_lock(struct smb_request *req)
5580 connection_struct *conn = req->conn;
5581 uint64_t count,offset;
5584 struct byte_range_lock *br_lck = NULL;
5586 START_PROFILE(SMBlock);
5589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5590 END_PROFILE(SMBlock);
5594 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5596 if (!check_fsp(conn, req, fsp)) {
5597 END_PROFILE(SMBlock);
5601 count = (uint64_t)IVAL(req->vwv+1, 0);
5602 offset = (uint64_t)IVAL(req->vwv+3, 0);
5604 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5605 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5607 br_lck = do_lock(req->sconn->msg_ctx,
5609 (uint64_t)req->smbpid,
5614 False, /* Non-blocking lock. */
5618 TALLOC_FREE(br_lck);
5620 if (NT_STATUS_V(status)) {
5621 reply_nterror(req, status);
5622 END_PROFILE(SMBlock);
5626 reply_outbuf(req, 0, 0);
5628 END_PROFILE(SMBlock);
5632 /****************************************************************************
5634 ****************************************************************************/
5636 void reply_unlock(struct smb_request *req)
5638 connection_struct *conn = req->conn;
5639 uint64_t count,offset;
5643 START_PROFILE(SMBunlock);
5646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5647 END_PROFILE(SMBunlock);
5651 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5653 if (!check_fsp(conn, req, fsp)) {
5654 END_PROFILE(SMBunlock);
5658 count = (uint64_t)IVAL(req->vwv+1, 0);
5659 offset = (uint64_t)IVAL(req->vwv+3, 0);
5661 status = do_unlock(req->sconn->msg_ctx,
5663 (uint64_t)req->smbpid,
5668 if (NT_STATUS_V(status)) {
5669 reply_nterror(req, status);
5670 END_PROFILE(SMBunlock);
5674 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5675 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5677 reply_outbuf(req, 0, 0);
5679 END_PROFILE(SMBunlock);
5684 #define DBGC_CLASS DBGC_ALL
5686 /****************************************************************************
5688 conn POINTER CAN BE NULL HERE !
5689 ****************************************************************************/
5691 void reply_tdis(struct smb_request *req)
5694 connection_struct *conn = req->conn;
5695 struct smbXsrv_tcon *tcon;
5697 START_PROFILE(SMBtdis);
5700 DEBUG(4,("Invalid connection in tdis\n"));
5701 reply_force_doserror(req, ERRSRV, ERRinvnid);
5702 END_PROFILE(SMBtdis);
5710 * TODO: cancel all outstanding requests on the tcon
5712 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5713 if (!NT_STATUS_IS_OK(status)) {
5714 DEBUG(0, ("reply_tdis: "
5715 "smbXsrv_tcon_disconnect() failed: %s\n",
5716 nt_errstr(status)));
5718 * If we hit this case, there is something completely
5719 * wrong, so we better disconnect the transport connection.
5721 END_PROFILE(SMBtdis);
5722 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5728 reply_outbuf(req, 0, 0);
5729 END_PROFILE(SMBtdis);
5733 /****************************************************************************
5735 conn POINTER CAN BE NULL HERE !
5736 ****************************************************************************/
5738 void reply_echo(struct smb_request *req)
5740 connection_struct *conn = req->conn;
5741 struct smb_perfcount_data local_pcd;
5742 struct smb_perfcount_data *cur_pcd;
5746 START_PROFILE(SMBecho);
5748 smb_init_perfcount_data(&local_pcd);
5751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5752 END_PROFILE(SMBecho);
5756 smb_reverb = SVAL(req->vwv+0, 0);
5758 reply_outbuf(req, 1, req->buflen);
5760 /* copy any incoming data back out */
5761 if (req->buflen > 0) {
5762 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5765 if (smb_reverb > 100) {
5766 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5770 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5772 /* this makes sure we catch the request pcd */
5773 if (seq_num == smb_reverb) {
5774 cur_pcd = &req->pcd;
5776 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5777 cur_pcd = &local_pcd;
5780 SSVAL(req->outbuf,smb_vwv0,seq_num);
5782 show_msg((char *)req->outbuf);
5783 if (!srv_send_smb(req->xconn,
5784 (char *)req->outbuf,
5785 true, req->seqnum+1,
5786 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5788 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5791 DEBUG(3,("echo %d times\n", smb_reverb));
5793 TALLOC_FREE(req->outbuf);
5795 END_PROFILE(SMBecho);
5799 /****************************************************************************
5800 Reply to a printopen.
5801 ****************************************************************************/
5803 void reply_printopen(struct smb_request *req)
5805 connection_struct *conn = req->conn;
5809 START_PROFILE(SMBsplopen);
5812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5813 END_PROFILE(SMBsplopen);
5817 if (!CAN_PRINT(conn)) {
5818 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5819 END_PROFILE(SMBsplopen);
5823 status = file_new(req, conn, &fsp);
5824 if(!NT_STATUS_IS_OK(status)) {
5825 reply_nterror(req, status);
5826 END_PROFILE(SMBsplopen);
5830 /* Open for exclusive use, write only. */
5831 status = print_spool_open(fsp, NULL, req->vuid);
5833 if (!NT_STATUS_IS_OK(status)) {
5834 file_free(req, fsp);
5835 reply_nterror(req, status);
5836 END_PROFILE(SMBsplopen);
5840 reply_outbuf(req, 1, 0);
5841 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5843 DEBUG(3,("openprint fd=%d %s\n",
5844 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5846 END_PROFILE(SMBsplopen);
5850 /****************************************************************************
5851 Reply to a printclose.
5852 ****************************************************************************/
5854 void reply_printclose(struct smb_request *req)
5856 connection_struct *conn = req->conn;
5860 START_PROFILE(SMBsplclose);
5863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5864 END_PROFILE(SMBsplclose);
5868 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5870 if (!check_fsp(conn, req, fsp)) {
5871 END_PROFILE(SMBsplclose);
5875 if (!CAN_PRINT(conn)) {
5876 reply_force_doserror(req, ERRSRV, ERRerror);
5877 END_PROFILE(SMBsplclose);
5881 DEBUG(3,("printclose fd=%d %s\n",
5882 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5884 status = close_file(req, fsp, NORMAL_CLOSE);
5886 if(!NT_STATUS_IS_OK(status)) {
5887 reply_nterror(req, status);
5888 END_PROFILE(SMBsplclose);
5892 reply_outbuf(req, 0, 0);
5894 END_PROFILE(SMBsplclose);
5898 /****************************************************************************
5899 Reply to a printqueue.
5900 ****************************************************************************/
5902 void reply_printqueue(struct smb_request *req)
5904 connection_struct *conn = req->conn;
5908 START_PROFILE(SMBsplretq);
5911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5912 END_PROFILE(SMBsplretq);
5916 max_count = SVAL(req->vwv+0, 0);
5917 start_index = SVAL(req->vwv+1, 0);
5919 /* we used to allow the client to get the cnum wrong, but that
5920 is really quite gross and only worked when there was only
5921 one printer - I think we should now only accept it if they
5922 get it right (tridge) */
5923 if (!CAN_PRINT(conn)) {
5924 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5925 END_PROFILE(SMBsplretq);
5929 reply_outbuf(req, 2, 3);
5930 SSVAL(req->outbuf,smb_vwv0,0);
5931 SSVAL(req->outbuf,smb_vwv1,0);
5932 SCVAL(smb_buf(req->outbuf),0,1);
5933 SSVAL(smb_buf(req->outbuf),1,0);
5935 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5936 start_index, max_count));
5939 TALLOC_CTX *mem_ctx = talloc_tos();
5942 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5943 struct rpc_pipe_client *cli = NULL;
5944 struct dcerpc_binding_handle *b = NULL;
5945 struct policy_handle handle;
5946 struct spoolss_DevmodeContainer devmode_ctr;
5947 union spoolss_JobInfo *info;
5949 uint32_t num_to_get;
5953 ZERO_STRUCT(handle);
5955 status = rpc_pipe_open_interface(conn,
5958 conn->sconn->remote_address,
5959 conn->sconn->msg_ctx,
5961 if (!NT_STATUS_IS_OK(status)) {
5962 DEBUG(0, ("reply_printqueue: "
5963 "could not connect to spoolss: %s\n",
5964 nt_errstr(status)));
5965 reply_nterror(req, status);
5968 b = cli->binding_handle;
5970 ZERO_STRUCT(devmode_ctr);
5972 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5975 SEC_FLAG_MAXIMUM_ALLOWED,
5978 if (!NT_STATUS_IS_OK(status)) {
5979 reply_nterror(req, status);
5982 if (!W_ERROR_IS_OK(werr)) {
5983 reply_nterror(req, werror_to_ntstatus(werr));
5987 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5995 if (!W_ERROR_IS_OK(werr)) {
5996 reply_nterror(req, werror_to_ntstatus(werr));
6000 if (max_count > 0) {
6001 first = start_index;
6003 first = start_index + max_count + 1;
6006 if (first >= count) {
6009 num_to_get = first + MIN(ABS(max_count), count - first);
6012 for (i = first; i < num_to_get; i++) {
6015 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6018 uint16_t qrapjobid = pjobid_to_rap(sharename,
6019 info[i].info2.job_id);
6021 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6027 srv_put_dos_date2(p, 0, qtime);
6028 SCVAL(p, 4, qstatus);
6029 SSVAL(p, 5, qrapjobid);
6030 SIVAL(p, 7, info[i].info2.size);
6032 status = srvstr_push(blob, req->flags2, p+12,
6033 info[i].info2.notify_name, 16, STR_ASCII, &len);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 reply_nterror(req, status);
6038 if (message_push_blob(
6041 blob, sizeof(blob))) == -1) {
6042 reply_nterror(req, NT_STATUS_NO_MEMORY);
6048 SSVAL(req->outbuf,smb_vwv0,count);
6049 SSVAL(req->outbuf,smb_vwv1,
6050 (max_count>0?first+count:first-1));
6051 SCVAL(smb_buf(req->outbuf),0,1);
6052 SSVAL(smb_buf(req->outbuf),1,28*count);
6056 DEBUG(3, ("%u entries returned in queue\n",
6060 if (b && is_valid_policy_hnd(&handle)) {
6061 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6066 END_PROFILE(SMBsplretq);
6070 /****************************************************************************
6071 Reply to a printwrite.
6072 ****************************************************************************/
6074 void reply_printwrite(struct smb_request *req)
6076 connection_struct *conn = req->conn;
6081 START_PROFILE(SMBsplwr);
6084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6085 END_PROFILE(SMBsplwr);
6089 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6091 if (!check_fsp(conn, req, fsp)) {
6092 END_PROFILE(SMBsplwr);
6096 if (!fsp->print_file) {
6097 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6098 END_PROFILE(SMBsplwr);
6102 if (!CHECK_WRITE(fsp)) {
6103 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6104 END_PROFILE(SMBsplwr);
6108 numtowrite = SVAL(req->buf, 1);
6110 if (req->buflen < numtowrite + 3) {
6111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6112 END_PROFILE(SMBsplwr);
6116 data = (const char *)req->buf + 3;
6118 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6119 reply_nterror(req, map_nt_error_from_unix(errno));
6120 END_PROFILE(SMBsplwr);
6124 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6126 END_PROFILE(SMBsplwr);
6130 /****************************************************************************
6132 ****************************************************************************/
6134 void reply_mkdir(struct smb_request *req)
6136 connection_struct *conn = req->conn;
6137 struct smb_filename *smb_dname = NULL;
6138 char *directory = NULL;
6141 TALLOC_CTX *ctx = talloc_tos();
6143 START_PROFILE(SMBmkdir);
6145 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6146 STR_TERMINATE, &status);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 reply_nterror(req, status);
6152 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6153 status = filename_convert(ctx, conn,
6154 req->flags2 & FLAGS2_DFS_PATHNAMES,
6159 if (!NT_STATUS_IS_OK(status)) {
6160 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6161 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6162 ERRSRV, ERRbadpath);
6165 reply_nterror(req, status);
6169 status = create_directory(conn, req, smb_dname);
6171 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6173 if (!NT_STATUS_IS_OK(status)) {
6175 if (!use_nt_status()
6176 && NT_STATUS_EQUAL(status,
6177 NT_STATUS_OBJECT_NAME_COLLISION)) {
6179 * Yes, in the DOS error code case we get a
6180 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6181 * samba4 torture test.
6183 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6186 reply_nterror(req, status);
6190 reply_outbuf(req, 0, 0);
6192 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6194 TALLOC_FREE(smb_dname);
6195 END_PROFILE(SMBmkdir);
6199 /****************************************************************************
6201 ****************************************************************************/
6203 void reply_rmdir(struct smb_request *req)
6205 connection_struct *conn = req->conn;
6206 struct smb_filename *smb_dname = NULL;
6207 char *directory = NULL;
6209 TALLOC_CTX *ctx = talloc_tos();
6210 files_struct *fsp = NULL;
6212 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6213 struct smbd_server_connection *sconn = req->sconn;
6215 START_PROFILE(SMBrmdir);
6217 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6218 STR_TERMINATE, &status);
6219 if (!NT_STATUS_IS_OK(status)) {
6220 reply_nterror(req, status);
6224 status = filename_convert(ctx, conn,
6225 req->flags2 & FLAGS2_DFS_PATHNAMES,
6230 if (!NT_STATUS_IS_OK(status)) {
6231 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6232 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6233 ERRSRV, ERRbadpath);
6236 reply_nterror(req, status);
6240 if (is_ntfs_stream_smb_fname(smb_dname)) {
6241 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6245 status = SMB_VFS_CREATE_FILE(
6248 0, /* root_dir_fid */
6249 smb_dname, /* fname */
6250 DELETE_ACCESS, /* access_mask */
6251 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6253 FILE_OPEN, /* create_disposition*/
6254 FILE_DIRECTORY_FILE, /* create_options */
6255 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6256 0, /* oplock_request */
6258 0, /* allocation_size */
6259 0, /* private_flags */
6264 NULL, NULL); /* create context */
6266 if (!NT_STATUS_IS_OK(status)) {
6267 if (open_was_deferred(req->xconn, req->mid)) {
6268 /* We have re-scheduled this call. */
6271 reply_nterror(req, status);
6275 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 close_file(req, fsp, ERROR_CLOSE);
6278 reply_nterror(req, status);
6282 if (!set_delete_on_close(fsp, true,
6283 conn->session_info->security_token,
6284 conn->session_info->unix_token)) {
6285 close_file(req, fsp, ERROR_CLOSE);
6286 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6290 status = close_file(req, fsp, NORMAL_CLOSE);
6291 if (!NT_STATUS_IS_OK(status)) {
6292 reply_nterror(req, status);
6294 reply_outbuf(req, 0, 0);
6297 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6299 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6301 TALLOC_FREE(smb_dname);
6302 END_PROFILE(SMBrmdir);
6306 /*******************************************************************
6307 Resolve wildcards in a filename rename.
6308 ********************************************************************/
6310 static bool resolve_wildcards(TALLOC_CTX *ctx,
6315 char *name2_copy = NULL;
6320 char *p,*p2, *pname1, *pname2;
6322 name2_copy = talloc_strdup(ctx, name2);
6327 pname1 = strrchr_m(name1,'/');
6328 pname2 = strrchr_m(name2_copy,'/');
6330 if (!pname1 || !pname2) {
6334 /* Truncate the copy of name2 at the last '/' */
6337 /* Now go past the '/' */
6341 root1 = talloc_strdup(ctx, pname1);
6342 root2 = talloc_strdup(ctx, pname2);
6344 if (!root1 || !root2) {
6348 p = strrchr_m(root1,'.');
6351 ext1 = talloc_strdup(ctx, p+1);
6353 ext1 = talloc_strdup(ctx, "");
6355 p = strrchr_m(root2,'.');
6358 ext2 = talloc_strdup(ctx, p+1);
6360 ext2 = talloc_strdup(ctx, "");
6363 if (!ext1 || !ext2) {
6371 /* Hmmm. Should this be mb-aware ? */
6374 } else if (*p2 == '*') {
6376 root2 = talloc_asprintf(ctx, "%s%s",
6395 /* Hmmm. Should this be mb-aware ? */
6398 } else if (*p2 == '*') {
6400 ext2 = talloc_asprintf(ctx, "%s%s",
6416 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6421 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6433 /****************************************************************************
6434 Ensure open files have their names updated. Updated to notify other smbd's
6436 ****************************************************************************/
6438 static void rename_open_files(connection_struct *conn,
6439 struct share_mode_lock *lck,
6441 uint32_t orig_name_hash,
6442 const struct smb_filename *smb_fname_dst)
6445 bool did_rename = False;
6447 uint32_t new_name_hash = 0;
6449 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6450 fsp = file_find_di_next(fsp)) {
6451 /* fsp_name is a relative path under the fsp. To change this for other
6452 sharepaths we need to manipulate relative paths. */
6453 /* TODO - create the absolute path and manipulate the newname
6454 relative to the sharepath. */
6455 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6458 if (fsp->name_hash != orig_name_hash) {
6461 DEBUG(10, ("rename_open_files: renaming file %s "
6462 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6463 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6464 smb_fname_str_dbg(smb_fname_dst)));
6466 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6467 if (NT_STATUS_IS_OK(status)) {
6469 new_name_hash = fsp->name_hash;
6474 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6475 "for %s\n", file_id_string_tos(&id),
6476 smb_fname_str_dbg(smb_fname_dst)));
6479 /* Send messages to all smbd's (not ourself) that the name has changed. */
6480 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6481 orig_name_hash, new_name_hash,
6486 /****************************************************************************
6487 We need to check if the source path is a parent directory of the destination
6488 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6489 refuse the rename with a sharing violation. Under UNIX the above call can
6490 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6491 probably need to check that the client is a Windows one before disallowing
6492 this as a UNIX client (one with UNIX extensions) can know the source is a
6493 symlink and make this decision intelligently. Found by an excellent bug
6494 report from <AndyLiebman@aol.com>.
6495 ****************************************************************************/
6497 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6498 const struct smb_filename *smb_fname_dst)
6500 const char *psrc = smb_fname_src->base_name;
6501 const char *pdst = smb_fname_dst->base_name;
6504 if (psrc[0] == '.' && psrc[1] == '/') {
6507 if (pdst[0] == '.' && pdst[1] == '/') {
6510 if ((slen = strlen(psrc)) > strlen(pdst)) {
6513 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6517 * Do the notify calls from a rename
6520 static void notify_rename(connection_struct *conn, bool is_dir,
6521 const struct smb_filename *smb_fname_src,
6522 const struct smb_filename *smb_fname_dst)
6524 char *parent_dir_src = NULL;
6525 char *parent_dir_dst = NULL;
6528 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6529 : FILE_NOTIFY_CHANGE_FILE_NAME;
6531 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6532 &parent_dir_src, NULL) ||
6533 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6534 &parent_dir_dst, NULL)) {
6538 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6539 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6540 smb_fname_src->base_name);
6541 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6542 smb_fname_dst->base_name);
6545 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6546 smb_fname_src->base_name);
6547 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6548 smb_fname_dst->base_name);
6551 /* this is a strange one. w2k3 gives an additional event for
6552 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6553 files, but not directories */
6555 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6556 FILE_NOTIFY_CHANGE_ATTRIBUTES
6557 |FILE_NOTIFY_CHANGE_CREATION,
6558 smb_fname_dst->base_name);
6561 TALLOC_FREE(parent_dir_src);
6562 TALLOC_FREE(parent_dir_dst);
6565 /****************************************************************************
6566 Returns an error if the parent directory for a filename is open in an
6568 ****************************************************************************/
6570 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6571 const struct smb_filename *smb_fname_dst_in)
6573 char *parent_dir = NULL;
6574 struct smb_filename smb_fname_parent;
6576 files_struct *fsp = NULL;
6579 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6580 &parent_dir, NULL)) {
6581 return NT_STATUS_NO_MEMORY;
6583 ZERO_STRUCT(smb_fname_parent);
6584 smb_fname_parent.base_name = parent_dir;
6586 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6588 return map_nt_error_from_unix(errno);
6592 * We're only checking on this smbd here, mostly good
6593 * enough.. and will pass tests.
6596 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6597 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6598 fsp = file_find_di_next(fsp)) {
6599 if (fsp->access_mask & DELETE_ACCESS) {
6600 return NT_STATUS_SHARING_VIOLATION;
6603 return NT_STATUS_OK;
6606 /****************************************************************************
6607 Rename an open file - given an fsp.
6608 ****************************************************************************/
6610 NTSTATUS rename_internals_fsp(connection_struct *conn,
6612 const struct smb_filename *smb_fname_dst_in,
6614 bool replace_if_exists)
6616 TALLOC_CTX *ctx = talloc_tos();
6617 struct smb_filename *smb_fname_dst = NULL;
6618 NTSTATUS status = NT_STATUS_OK;
6619 struct share_mode_lock *lck = NULL;
6620 uint32_t access_mask = SEC_DIR_ADD_FILE;
6621 bool dst_exists, old_is_stream, new_is_stream;
6623 status = check_name(conn, smb_fname_dst_in->base_name);
6624 if (!NT_STATUS_IS_OK(status)) {
6628 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6629 if (!NT_STATUS_IS_OK(status)) {
6633 /* Make a copy of the dst smb_fname structs */
6635 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6636 if (smb_fname_dst == NULL) {
6637 status = NT_STATUS_NO_MEMORY;
6642 * Check for special case with case preserving and not
6643 * case sensitive. If the new last component differs from the original
6644 * last component only by case, then we should allow
6645 * the rename (user is trying to change the case of the
6648 if (!conn->case_sensitive && conn->case_preserve &&
6649 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6650 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6651 char *fname_dst_parent = NULL;
6652 const char *fname_dst_lcomp = NULL;
6653 char *orig_lcomp_path = NULL;
6654 char *orig_lcomp_stream = NULL;
6658 * Split off the last component of the processed
6659 * destination name. We will compare this to
6660 * the split components of smb_fname_dst->original_lcomp.
6662 if (!parent_dirname(ctx,
6663 smb_fname_dst->base_name,
6665 &fname_dst_lcomp)) {
6666 status = NT_STATUS_NO_MEMORY;
6671 * The original_lcomp component contains
6672 * the last_component of the path + stream
6673 * name (if a stream exists).
6675 * Split off the stream name so we
6676 * can check them separately.
6679 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6680 /* POSIX - no stream component. */
6681 orig_lcomp_path = talloc_strdup(ctx,
6682 smb_fname_dst->original_lcomp);
6683 if (orig_lcomp_path == NULL) {
6687 ok = split_stream_filename(ctx,
6688 smb_fname_dst->original_lcomp,
6690 &orig_lcomp_stream);
6694 TALLOC_FREE(fname_dst_parent);
6695 status = NT_STATUS_NO_MEMORY;
6699 /* If the base names only differ by case, use original. */
6700 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6703 * Replace the modified last component with the
6706 if (!ISDOT(fname_dst_parent)) {
6707 tmp = talloc_asprintf(smb_fname_dst,
6712 tmp = talloc_strdup(smb_fname_dst,
6716 status = NT_STATUS_NO_MEMORY;
6717 TALLOC_FREE(fname_dst_parent);
6718 TALLOC_FREE(orig_lcomp_path);
6719 TALLOC_FREE(orig_lcomp_stream);
6722 TALLOC_FREE(smb_fname_dst->base_name);
6723 smb_fname_dst->base_name = tmp;
6726 /* If the stream_names only differ by case, use original. */
6727 if(!strcsequal(smb_fname_dst->stream_name,
6728 orig_lcomp_stream)) {
6729 /* Use the original stream. */
6730 char *tmp = talloc_strdup(smb_fname_dst,
6733 status = NT_STATUS_NO_MEMORY;
6734 TALLOC_FREE(fname_dst_parent);
6735 TALLOC_FREE(orig_lcomp_path);
6736 TALLOC_FREE(orig_lcomp_stream);
6739 TALLOC_FREE(smb_fname_dst->stream_name);
6740 smb_fname_dst->stream_name = tmp;
6742 TALLOC_FREE(fname_dst_parent);
6743 TALLOC_FREE(orig_lcomp_path);
6744 TALLOC_FREE(orig_lcomp_stream);
6748 * If the src and dest names are identical - including case,
6749 * don't do the rename, just return success.
6752 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6753 strcsequal(fsp->fsp_name->stream_name,
6754 smb_fname_dst->stream_name)) {
6755 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6756 "- returning success\n",
6757 smb_fname_str_dbg(smb_fname_dst)));
6758 status = NT_STATUS_OK;
6762 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6763 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6765 /* Return the correct error code if both names aren't streams. */
6766 if (!old_is_stream && new_is_stream) {
6767 status = NT_STATUS_OBJECT_NAME_INVALID;
6771 if (old_is_stream && !new_is_stream) {
6772 status = NT_STATUS_INVALID_PARAMETER;
6776 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6778 if(!replace_if_exists && dst_exists) {
6779 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6780 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6781 smb_fname_str_dbg(smb_fname_dst)));
6782 status = NT_STATUS_OBJECT_NAME_COLLISION;
6787 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6788 &smb_fname_dst->st);
6789 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6791 /* The file can be open when renaming a stream */
6792 if (dst_fsp && !new_is_stream) {
6793 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6794 status = NT_STATUS_ACCESS_DENIED;
6799 /* Ensure we have a valid stat struct for the source. */
6800 status = vfs_stat_fsp(fsp);
6801 if (!NT_STATUS_IS_OK(status)) {
6805 status = can_rename(conn, fsp, attrs);
6807 if (!NT_STATUS_IS_OK(status)) {
6808 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6809 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6810 smb_fname_str_dbg(smb_fname_dst)));
6811 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6812 status = NT_STATUS_ACCESS_DENIED;
6816 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6817 status = NT_STATUS_ACCESS_DENIED;
6821 /* Do we have rights to move into the destination ? */
6822 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6823 /* We're moving a directory. */
6824 access_mask = SEC_DIR_ADD_SUBDIR;
6826 status = check_parent_access(conn,
6829 if (!NT_STATUS_IS_OK(status)) {
6830 DBG_INFO("check_parent_access on "
6831 "dst %s returned %s\n",
6832 smb_fname_str_dbg(smb_fname_dst),
6837 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6840 * We have the file open ourselves, so not being able to get the
6841 * corresponding share mode lock is a fatal error.
6844 SMB_ASSERT(lck != NULL);
6846 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6847 uint32_t create_options = fsp->fh->private_options;
6849 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6850 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6851 smb_fname_str_dbg(smb_fname_dst)));
6853 if (!fsp->is_directory &&
6854 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6855 (lp_map_archive(SNUM(conn)) ||
6856 lp_store_dos_attributes(SNUM(conn)))) {
6857 /* We must set the archive bit on the newly
6859 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6860 uint32_t old_dosmode = dos_mode(conn,
6862 file_set_dosmode(conn,
6864 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6870 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6873 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6877 * A rename acts as a new file create w.r.t. allowing an initial delete
6878 * on close, probably because in Windows there is a new handle to the
6879 * new file. If initial delete on close was requested but not
6880 * originally set, we need to set it here. This is probably not 100% correct,
6881 * but will work for the CIFSFS client which in non-posix mode
6882 * depends on these semantics. JRA.
6885 if (create_options & FILE_DELETE_ON_CLOSE) {
6886 status = can_set_delete_on_close(fsp, 0);
6888 if (NT_STATUS_IS_OK(status)) {
6889 /* Note that here we set the *inital* delete on close flag,
6890 * not the regular one. The magic gets handled in close. */
6891 fsp->initial_delete_on_close = True;
6895 status = NT_STATUS_OK;
6901 if (errno == ENOTDIR || errno == EISDIR) {
6902 status = NT_STATUS_OBJECT_NAME_COLLISION;
6904 status = map_nt_error_from_unix(errno);
6907 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6908 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6909 smb_fname_str_dbg(smb_fname_dst)));
6912 TALLOC_FREE(smb_fname_dst);
6917 /****************************************************************************
6918 The guts of the rename command, split out so it may be called by the NT SMB
6920 ****************************************************************************/
6922 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6923 connection_struct *conn,
6924 struct smb_request *req,
6925 struct smb_filename *smb_fname_src,
6926 struct smb_filename *smb_fname_dst,
6928 bool replace_if_exists,
6931 uint32_t access_mask)
6933 char *fname_src_dir = NULL;
6934 struct smb_filename *smb_fname_src_dir = NULL;
6935 char *fname_src_mask = NULL;
6937 NTSTATUS status = NT_STATUS_OK;
6938 struct smb_Dir *dir_hnd = NULL;
6939 const char *dname = NULL;
6940 char *talloced = NULL;
6942 int create_options = 0;
6943 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6947 * Split the old name into directory and last component
6948 * strings. Note that unix_convert may have stripped off a
6949 * leading ./ from both name and newname if the rename is
6950 * at the root of the share. We need to make sure either both
6951 * name and newname contain a / character or neither of them do
6952 * as this is checked in resolve_wildcards().
6955 /* Split up the directory from the filename/mask. */
6956 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6957 &fname_src_dir, &fname_src_mask);
6958 if (!NT_STATUS_IS_OK(status)) {
6959 status = NT_STATUS_NO_MEMORY;
6964 * We should only check the mangled cache
6965 * here if unix_convert failed. This means
6966 * that the path in 'mask' doesn't exist
6967 * on the file system and so we need to look
6968 * for a possible mangle. This patch from
6969 * Tine Smukavec <valentin.smukavec@hermes.si>.
6972 if (!VALID_STAT(smb_fname_src->st) &&
6973 mangle_is_mangled(fname_src_mask, conn->params)) {
6974 char *new_mask = NULL;
6975 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6978 TALLOC_FREE(fname_src_mask);
6979 fname_src_mask = new_mask;
6983 if (!src_has_wild) {
6987 * Only one file needs to be renamed. Append the mask back
6988 * onto the directory.
6990 TALLOC_FREE(smb_fname_src->base_name);
6991 if (ISDOT(fname_src_dir)) {
6992 /* Ensure we use canonical names on open. */
6993 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6997 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7002 if (!smb_fname_src->base_name) {
7003 status = NT_STATUS_NO_MEMORY;
7007 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7008 "case_preserve = %d, short case preserve = %d, "
7009 "directory = %s, newname = %s, "
7010 "last_component_dest = %s\n",
7011 conn->case_sensitive, conn->case_preserve,
7012 conn->short_case_preserve,
7013 smb_fname_str_dbg(smb_fname_src),
7014 smb_fname_str_dbg(smb_fname_dst),
7015 smb_fname_dst->original_lcomp));
7017 /* The dest name still may have wildcards. */
7018 if (dest_has_wild) {
7019 char *fname_dst_mod = NULL;
7020 if (!resolve_wildcards(smb_fname_dst,
7021 smb_fname_src->base_name,
7022 smb_fname_dst->base_name,
7024 DEBUG(6, ("rename_internals: resolve_wildcards "
7026 smb_fname_src->base_name,
7027 smb_fname_dst->base_name));
7028 status = NT_STATUS_NO_MEMORY;
7031 TALLOC_FREE(smb_fname_dst->base_name);
7032 smb_fname_dst->base_name = fname_dst_mod;
7035 ZERO_STRUCT(smb_fname_src->st);
7036 if (posix_pathnames) {
7037 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7039 rc = SMB_VFS_STAT(conn, smb_fname_src);
7042 status = map_nt_error_from_unix_common(errno);
7046 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7047 create_options |= FILE_DIRECTORY_FILE;
7050 status = SMB_VFS_CREATE_FILE(
7053 0, /* root_dir_fid */
7054 smb_fname_src, /* fname */
7055 access_mask, /* access_mask */
7056 (FILE_SHARE_READ | /* share_access */
7058 FILE_OPEN, /* create_disposition*/
7059 create_options, /* create_options */
7060 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7061 0, /* oplock_request */
7063 0, /* allocation_size */
7064 0, /* private_flags */
7069 NULL, NULL); /* create context */
7071 if (!NT_STATUS_IS_OK(status)) {
7072 DEBUG(3, ("Could not open rename source %s: %s\n",
7073 smb_fname_str_dbg(smb_fname_src),
7074 nt_errstr(status)));
7078 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7079 attrs, replace_if_exists);
7081 close_file(req, fsp, NORMAL_CLOSE);
7083 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7084 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7085 smb_fname_str_dbg(smb_fname_dst)));
7091 * Wildcards - process each file that matches.
7093 if (strequal(fname_src_mask, "????????.???")) {
7094 TALLOC_FREE(fname_src_mask);
7095 fname_src_mask = talloc_strdup(ctx, "*");
7096 if (!fname_src_mask) {
7097 status = NT_STATUS_NO_MEMORY;
7102 status = check_name(conn, fname_src_dir);
7103 if (!NT_STATUS_IS_OK(status)) {
7107 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7111 smb_fname_src->flags);
7112 if (smb_fname_src_dir == NULL) {
7113 status = NT_STATUS_NO_MEMORY;
7117 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7119 if (dir_hnd == NULL) {
7120 status = map_nt_error_from_unix(errno);
7124 status = NT_STATUS_NO_SUCH_FILE;
7126 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7127 * - gentest fix. JRA
7130 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7132 files_struct *fsp = NULL;
7133 char *destname = NULL;
7134 bool sysdir_entry = False;
7136 /* Quick check for "." and ".." */
7137 if (ISDOT(dname) || ISDOTDOT(dname)) {
7138 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7139 sysdir_entry = True;
7141 TALLOC_FREE(talloced);
7146 if (!is_visible_file(conn, fname_src_dir, dname,
7147 &smb_fname_src->st, false)) {
7148 TALLOC_FREE(talloced);
7152 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7153 TALLOC_FREE(talloced);
7158 status = NT_STATUS_OBJECT_NAME_INVALID;
7162 TALLOC_FREE(smb_fname_src->base_name);
7163 if (ISDOT(fname_src_dir)) {
7164 /* Ensure we use canonical names on open. */
7165 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7169 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7174 if (!smb_fname_src->base_name) {
7175 status = NT_STATUS_NO_MEMORY;
7179 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7180 smb_fname_dst->base_name,
7182 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7183 smb_fname_src->base_name, destname));
7184 TALLOC_FREE(talloced);
7188 status = NT_STATUS_NO_MEMORY;
7192 TALLOC_FREE(smb_fname_dst->base_name);
7193 smb_fname_dst->base_name = destname;
7195 ZERO_STRUCT(smb_fname_src->st);
7196 if (posix_pathnames) {
7197 SMB_VFS_LSTAT(conn, smb_fname_src);
7199 SMB_VFS_STAT(conn, smb_fname_src);
7204 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7205 create_options |= FILE_DIRECTORY_FILE;
7208 status = SMB_VFS_CREATE_FILE(
7211 0, /* root_dir_fid */
7212 smb_fname_src, /* fname */
7213 access_mask, /* access_mask */
7214 (FILE_SHARE_READ | /* share_access */
7216 FILE_OPEN, /* create_disposition*/
7217 create_options, /* create_options */
7218 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7219 0, /* oplock_request */
7221 0, /* allocation_size */
7222 0, /* private_flags */
7227 NULL, NULL); /* create context */
7229 if (!NT_STATUS_IS_OK(status)) {
7230 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7231 "returned %s rename %s -> %s\n",
7233 smb_fname_str_dbg(smb_fname_src),
7234 smb_fname_str_dbg(smb_fname_dst)));
7238 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7240 if (!smb_fname_dst->original_lcomp) {
7241 status = NT_STATUS_NO_MEMORY;
7245 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7246 attrs, replace_if_exists);
7248 close_file(req, fsp, NORMAL_CLOSE);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 DEBUG(3, ("rename_internals_fsp returned %s for "
7252 "rename %s -> %s\n", nt_errstr(status),
7253 smb_fname_str_dbg(smb_fname_src),
7254 smb_fname_str_dbg(smb_fname_dst)));
7260 DEBUG(3,("rename_internals: doing rename on %s -> "
7261 "%s\n", smb_fname_str_dbg(smb_fname_src),
7262 smb_fname_str_dbg(smb_fname_src)));
7263 TALLOC_FREE(talloced);
7265 TALLOC_FREE(dir_hnd);
7267 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7268 status = map_nt_error_from_unix(errno);
7272 TALLOC_FREE(talloced);
7273 TALLOC_FREE(smb_fname_src_dir);
7274 TALLOC_FREE(fname_src_dir);
7275 TALLOC_FREE(fname_src_mask);
7279 /****************************************************************************
7281 ****************************************************************************/
7283 void reply_mv(struct smb_request *req)
7285 connection_struct *conn = req->conn;
7287 char *newname = NULL;
7291 bool src_has_wcard = False;
7292 bool dest_has_wcard = False;
7293 TALLOC_CTX *ctx = talloc_tos();
7294 struct smb_filename *smb_fname_src = NULL;
7295 struct smb_filename *smb_fname_dst = NULL;
7296 uint32_t src_ucf_flags = (req->posix_pathnames ?
7297 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7298 UCF_COND_ALLOW_WCARD_LCOMP);
7299 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7300 (req->posix_pathnames ? UCF_POSIX_PATHNAMES :
7301 UCF_COND_ALLOW_WCARD_LCOMP);
7302 bool stream_rename = false;
7304 START_PROFILE(SMBmv);
7307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 attrs = SVAL(req->vwv+0, 0);
7313 p = (const char *)req->buf + 1;
7314 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7315 &status, &src_has_wcard);
7316 if (!NT_STATUS_IS_OK(status)) {
7317 reply_nterror(req, status);
7321 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7322 &status, &dest_has_wcard);
7323 if (!NT_STATUS_IS_OK(status)) {
7324 reply_nterror(req, status);
7328 if (!req->posix_pathnames) {
7329 /* The newname must begin with a ':' if the
7330 name contains a ':'. */
7331 if (strchr_m(name, ':')) {
7332 if (newname[0] != ':') {
7333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7336 stream_rename = true;
7340 status = filename_convert(ctx,
7342 req->flags2 & FLAGS2_DFS_PATHNAMES,
7348 if (!NT_STATUS_IS_OK(status)) {
7349 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7350 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7351 ERRSRV, ERRbadpath);
7354 reply_nterror(req, status);
7358 status = filename_convert(ctx,
7360 req->flags2 & FLAGS2_DFS_PATHNAMES,
7366 if (!NT_STATUS_IS_OK(status)) {
7367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7368 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7369 ERRSRV, ERRbadpath);
7372 reply_nterror(req, status);
7376 if (stream_rename) {
7377 /* smb_fname_dst->base_name must be the same as
7378 smb_fname_src->base_name. */
7379 TALLOC_FREE(smb_fname_dst->base_name);
7380 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7381 smb_fname_src->base_name);
7382 if (!smb_fname_dst->base_name) {
7383 reply_nterror(req, NT_STATUS_NO_MEMORY);
7388 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7389 smb_fname_str_dbg(smb_fname_dst)));
7391 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7392 attrs, False, src_has_wcard, dest_has_wcard,
7394 if (!NT_STATUS_IS_OK(status)) {
7395 if (open_was_deferred(req->xconn, req->mid)) {
7396 /* We have re-scheduled this call. */
7399 reply_nterror(req, status);
7403 reply_outbuf(req, 0, 0);
7405 TALLOC_FREE(smb_fname_src);
7406 TALLOC_FREE(smb_fname_dst);
7411 /*******************************************************************
7412 Copy a file as part of a reply_copy.
7413 ******************************************************************/
7416 * TODO: check error codes on all callers
7419 NTSTATUS copy_file(TALLOC_CTX *ctx,
7420 connection_struct *conn,
7421 struct smb_filename *smb_fname_src,
7422 struct smb_filename *smb_fname_dst,
7425 bool target_is_directory)
7427 struct smb_filename *smb_fname_dst_tmp = NULL;
7429 files_struct *fsp1,*fsp2;
7431 uint32_t new_create_disposition;
7435 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7436 if (smb_fname_dst_tmp == NULL) {
7437 return NT_STATUS_NO_MEMORY;
7441 * If the target is a directory, extract the last component from the
7442 * src filename and append it to the dst filename
7444 if (target_is_directory) {
7447 /* dest/target can't be a stream if it's a directory. */
7448 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7450 p = strrchr_m(smb_fname_src->base_name,'/');
7454 p = smb_fname_src->base_name;
7456 smb_fname_dst_tmp->base_name =
7457 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7459 if (!smb_fname_dst_tmp->base_name) {
7460 status = NT_STATUS_NO_MEMORY;
7465 status = vfs_file_exist(conn, smb_fname_src);
7466 if (!NT_STATUS_IS_OK(status)) {
7470 if (!target_is_directory && count) {
7471 new_create_disposition = FILE_OPEN;
7473 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7476 &new_create_disposition,
7479 status = NT_STATUS_INVALID_PARAMETER;
7484 /* Open the src file for reading. */
7485 status = SMB_VFS_CREATE_FILE(
7488 0, /* root_dir_fid */
7489 smb_fname_src, /* fname */
7490 FILE_GENERIC_READ, /* access_mask */
7491 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7492 FILE_OPEN, /* create_disposition*/
7493 0, /* create_options */
7494 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7495 INTERNAL_OPEN_ONLY, /* oplock_request */
7497 0, /* allocation_size */
7498 0, /* private_flags */
7503 NULL, NULL); /* create context */
7505 if (!NT_STATUS_IS_OK(status)) {
7509 dosattrs = dos_mode(conn, smb_fname_src);
7511 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7512 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7515 /* Open the dst file for writing. */
7516 status = SMB_VFS_CREATE_FILE(
7519 0, /* root_dir_fid */
7520 smb_fname_dst, /* fname */
7521 FILE_GENERIC_WRITE, /* access_mask */
7522 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7523 new_create_disposition, /* create_disposition*/
7524 0, /* create_options */
7525 dosattrs, /* file_attributes */
7526 INTERNAL_OPEN_ONLY, /* oplock_request */
7528 0, /* allocation_size */
7529 0, /* private_flags */
7534 NULL, NULL); /* create context */
7536 if (!NT_STATUS_IS_OK(status)) {
7537 close_file(NULL, fsp1, ERROR_CLOSE);
7541 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7542 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7544 DEBUG(0, ("error - vfs lseek returned error %s\n",
7546 status = map_nt_error_from_unix(errno);
7547 close_file(NULL, fsp1, ERROR_CLOSE);
7548 close_file(NULL, fsp2, ERROR_CLOSE);
7553 /* Do the actual copy. */
7554 if (smb_fname_src->st.st_ex_size) {
7555 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7560 close_file(NULL, fsp1, NORMAL_CLOSE);
7562 /* Ensure the modtime is set correctly on the destination file. */
7563 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7566 * As we are opening fsp1 read-only we only expect
7567 * an error on close on fsp2 if we are out of space.
7568 * Thus we don't look at the error return from the
7571 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7573 if (!NT_STATUS_IS_OK(status)) {
7577 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7578 status = NT_STATUS_DISK_FULL;
7582 status = NT_STATUS_OK;
7585 TALLOC_FREE(smb_fname_dst_tmp);
7589 /****************************************************************************
7590 Reply to a file copy.
7591 ****************************************************************************/
7593 void reply_copy(struct smb_request *req)
7595 connection_struct *conn = req->conn;
7596 struct smb_filename *smb_fname_src = NULL;
7597 struct smb_filename *smb_fname_src_dir = NULL;
7598 struct smb_filename *smb_fname_dst = NULL;
7599 char *fname_src = NULL;
7600 char *fname_dst = NULL;
7601 char *fname_src_mask = NULL;
7602 char *fname_src_dir = NULL;
7605 int error = ERRnoaccess;
7609 bool target_is_directory=False;
7610 bool source_has_wild = False;
7611 bool dest_has_wild = False;
7613 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7614 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7615 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7616 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7617 TALLOC_CTX *ctx = talloc_tos();
7619 START_PROFILE(SMBcopy);
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7626 tid2 = SVAL(req->vwv+0, 0);
7627 ofun = SVAL(req->vwv+1, 0);
7628 flags = SVAL(req->vwv+2, 0);
7630 p = (const char *)req->buf;
7631 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7632 &status, &source_has_wild);
7633 if (!NT_STATUS_IS_OK(status)) {
7634 reply_nterror(req, status);
7637 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7638 &status, &dest_has_wild);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 reply_nterror(req, status);
7644 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7646 if (tid2 != conn->cnum) {
7647 /* can't currently handle inter share copies XXXX */
7648 DEBUG(3,("Rejecting inter-share copy\n"));
7649 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7653 status = filename_convert(ctx, conn,
7654 req->flags2 & FLAGS2_DFS_PATHNAMES,
7659 if (!NT_STATUS_IS_OK(status)) {
7660 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7661 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7662 ERRSRV, ERRbadpath);
7665 reply_nterror(req, status);
7669 status = filename_convert(ctx, conn,
7670 req->flags2 & FLAGS2_DFS_PATHNAMES,
7675 if (!NT_STATUS_IS_OK(status)) {
7676 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7677 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7678 ERRSRV, ERRbadpath);
7681 reply_nterror(req, status);
7685 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7687 if ((flags&1) && target_is_directory) {
7688 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7692 if ((flags&2) && !target_is_directory) {
7693 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7697 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7698 /* wants a tree copy! XXXX */
7699 DEBUG(3,("Rejecting tree copy\n"));
7700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7704 /* Split up the directory from the filename/mask. */
7705 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7706 &fname_src_dir, &fname_src_mask);
7707 if (!NT_STATUS_IS_OK(status)) {
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7713 * We should only check the mangled cache
7714 * here if unix_convert failed. This means
7715 * that the path in 'mask' doesn't exist
7716 * on the file system and so we need to look
7717 * for a possible mangle. This patch from
7718 * Tine Smukavec <valentin.smukavec@hermes.si>.
7720 if (!VALID_STAT(smb_fname_src->st) &&
7721 mangle_is_mangled(fname_src_mask, conn->params)) {
7722 char *new_mask = NULL;
7723 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7724 &new_mask, conn->params);
7726 /* Use demangled name if one was successfully found. */
7728 TALLOC_FREE(fname_src_mask);
7729 fname_src_mask = new_mask;
7733 if (!source_has_wild) {
7736 * Only one file needs to be copied. Append the mask back onto
7739 TALLOC_FREE(smb_fname_src->base_name);
7740 if (ISDOT(fname_src_dir)) {
7741 /* Ensure we use canonical names on open. */
7742 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7746 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7751 if (!smb_fname_src->base_name) {
7752 reply_nterror(req, NT_STATUS_NO_MEMORY);
7756 if (dest_has_wild) {
7757 char *fname_dst_mod = NULL;
7758 if (!resolve_wildcards(smb_fname_dst,
7759 smb_fname_src->base_name,
7760 smb_fname_dst->base_name,
7762 reply_nterror(req, NT_STATUS_NO_MEMORY);
7765 TALLOC_FREE(smb_fname_dst->base_name);
7766 smb_fname_dst->base_name = fname_dst_mod;
7769 status = check_name(conn, smb_fname_src->base_name);
7770 if (!NT_STATUS_IS_OK(status)) {
7771 reply_nterror(req, status);
7775 status = check_name(conn, smb_fname_dst->base_name);
7776 if (!NT_STATUS_IS_OK(status)) {
7777 reply_nterror(req, status);
7781 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7782 ofun, count, target_is_directory);
7784 if(!NT_STATUS_IS_OK(status)) {
7785 reply_nterror(req, status);
7791 struct smb_Dir *dir_hnd = NULL;
7792 const char *dname = NULL;
7793 char *talloced = NULL;
7797 * There is a wildcard that requires us to actually read the
7798 * src dir and copy each file matching the mask to the dst.
7799 * Right now streams won't be copied, but this could
7800 * presumably be added with a nested loop for reach dir entry.
7802 SMB_ASSERT(!smb_fname_src->stream_name);
7803 SMB_ASSERT(!smb_fname_dst->stream_name);
7805 smb_fname_src->stream_name = NULL;
7806 smb_fname_dst->stream_name = NULL;
7808 if (strequal(fname_src_mask,"????????.???")) {
7809 TALLOC_FREE(fname_src_mask);
7810 fname_src_mask = talloc_strdup(ctx, "*");
7811 if (!fname_src_mask) {
7812 reply_nterror(req, NT_STATUS_NO_MEMORY);
7817 status = check_name(conn, fname_src_dir);
7818 if (!NT_STATUS_IS_OK(status)) {
7819 reply_nterror(req, status);
7823 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7827 smb_fname_src->flags);
7828 if (smb_fname_src_dir == NULL) {
7829 reply_nterror(req, NT_STATUS_NO_MEMORY);
7833 dir_hnd = OpenDir(ctx,
7838 if (dir_hnd == NULL) {
7839 status = map_nt_error_from_unix(errno);
7840 reply_nterror(req, status);
7846 /* Iterate over the src dir copying each entry to the dst. */
7847 while ((dname = ReadDirName(dir_hnd, &offset,
7848 &smb_fname_src->st, &talloced))) {
7849 char *destname = NULL;
7851 if (ISDOT(dname) || ISDOTDOT(dname)) {
7852 TALLOC_FREE(talloced);
7856 if (!is_visible_file(conn, fname_src_dir, dname,
7857 &smb_fname_src->st, false)) {
7858 TALLOC_FREE(talloced);
7862 if(!mask_match(dname, fname_src_mask,
7863 conn->case_sensitive)) {
7864 TALLOC_FREE(talloced);
7868 error = ERRnoaccess;
7870 /* Get the src smb_fname struct setup. */
7871 TALLOC_FREE(smb_fname_src->base_name);
7872 if (ISDOT(fname_src_dir)) {
7873 /* Ensure we use canonical names on open. */
7874 smb_fname_src->base_name =
7875 talloc_asprintf(smb_fname_src, "%s",
7878 smb_fname_src->base_name =
7879 talloc_asprintf(smb_fname_src, "%s/%s",
7880 fname_src_dir, dname);
7883 if (!smb_fname_src->base_name) {
7884 TALLOC_FREE(dir_hnd);
7885 TALLOC_FREE(talloced);
7886 reply_nterror(req, NT_STATUS_NO_MEMORY);
7890 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7891 smb_fname_dst->base_name,
7893 TALLOC_FREE(talloced);
7897 TALLOC_FREE(dir_hnd);
7898 TALLOC_FREE(talloced);
7899 reply_nterror(req, NT_STATUS_NO_MEMORY);
7903 TALLOC_FREE(smb_fname_dst->base_name);
7904 smb_fname_dst->base_name = destname;
7906 status = check_name(conn, smb_fname_src->base_name);
7907 if (!NT_STATUS_IS_OK(status)) {
7908 TALLOC_FREE(dir_hnd);
7909 TALLOC_FREE(talloced);
7910 reply_nterror(req, status);
7914 status = check_name(conn, smb_fname_dst->base_name);
7915 if (!NT_STATUS_IS_OK(status)) {
7916 TALLOC_FREE(dir_hnd);
7917 TALLOC_FREE(talloced);
7918 reply_nterror(req, status);
7922 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7923 smb_fname_src->base_name,
7924 smb_fname_dst->base_name));
7926 status = copy_file(ctx, conn, smb_fname_src,
7927 smb_fname_dst, ofun, count,
7928 target_is_directory);
7929 if (NT_STATUS_IS_OK(status)) {
7933 TALLOC_FREE(talloced);
7935 TALLOC_FREE(dir_hnd);
7939 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7943 reply_outbuf(req, 1, 0);
7944 SSVAL(req->outbuf,smb_vwv0,count);
7946 TALLOC_FREE(smb_fname_src);
7947 TALLOC_FREE(smb_fname_src_dir);
7948 TALLOC_FREE(smb_fname_dst);
7949 TALLOC_FREE(fname_src);
7950 TALLOC_FREE(fname_dst);
7951 TALLOC_FREE(fname_src_mask);
7952 TALLOC_FREE(fname_src_dir);
7954 END_PROFILE(SMBcopy);
7959 #define DBGC_CLASS DBGC_LOCKING
7961 /****************************************************************************
7962 Get a lock pid, dealing with large count requests.
7963 ****************************************************************************/
7965 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7966 bool large_file_format)
7968 if(!large_file_format)
7969 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7971 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7974 /****************************************************************************
7975 Get a lock count, dealing with large count requests.
7976 ****************************************************************************/
7978 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7979 bool large_file_format)
7983 if(!large_file_format) {
7984 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7987 * No BVAL, this is reversed!
7989 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7990 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7996 /****************************************************************************
7997 Get a lock offset, dealing with large offset requests.
7998 ****************************************************************************/
8000 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8001 bool large_file_format)
8003 uint64_t offset = 0;
8005 if(!large_file_format) {
8006 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8009 * No BVAL, this is reversed!
8011 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8012 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8018 NTSTATUS smbd_do_locking(struct smb_request *req,
8023 struct smbd_lock_element *locks,
8026 connection_struct *conn = req->conn;
8028 NTSTATUS status = NT_STATUS_OK;
8032 /* Setup the timeout in seconds. */
8034 if (!lp_blocking_locks(SNUM(conn))) {
8038 for(i = 0; i < (int)num_locks; i++) {
8039 struct smbd_lock_element *e = &locks[i];
8041 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8042 "%llu, file %s timeout = %d\n",
8045 (unsigned long long)e->smblctx,
8049 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8050 struct blocking_lock_record *blr = NULL;
8052 if (num_locks > 1) {
8054 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8055 * if the lock vector contains one entry. When given multiple cancel
8056 * requests in a single PDU we expect the server to return an
8057 * error. Windows servers seem to accept the request but only
8058 * cancel the first lock.
8059 * JRA - Do what Windows does (tm) :-).
8063 /* MS-CIFS (2.2.4.32.1) behavior. */
8064 return NT_STATUS_DOS(ERRDOS,
8065 ERRcancelviolation);
8067 /* Windows behavior. */
8069 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8070 "cancel request\n"));
8076 if (lp_blocking_locks(SNUM(conn))) {
8078 /* Schedule a message to ourselves to
8079 remove the blocking lock record and
8080 return the right error. */
8082 blr = blocking_lock_cancel_smb1(fsp,
8088 NT_STATUS_FILE_LOCK_CONFLICT);
8090 return NT_STATUS_DOS(
8092 ERRcancelviolation);
8095 /* Remove a matching pending lock. */
8096 status = do_lock_cancel(fsp,
8102 bool blocking_lock = timeout ? true : false;
8103 bool defer_lock = false;
8104 struct byte_range_lock *br_lck;
8105 uint64_t block_smblctx;
8107 br_lck = do_lock(req->sconn->msg_ctx,
8118 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8119 /* Windows internal resolution for blocking locks seems
8120 to be about 200ms... Don't wait for less than that. JRA. */
8121 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8122 timeout = lp_lock_spin_time();
8127 /* If a lock sent with timeout of zero would fail, and
8128 * this lock has been requested multiple times,
8129 * according to brl_lock_failed() we convert this
8130 * request to a blocking lock with a timeout of between
8131 * 150 - 300 milliseconds.
8133 * If lp_lock_spin_time() has been set to 0, we skip
8134 * this blocking retry and fail immediately.
8136 * Replacement for do_lock_spin(). JRA. */
8138 if (!req->sconn->using_smb2 &&
8139 br_lck && lp_blocking_locks(SNUM(conn)) &&
8140 lp_lock_spin_time() && !blocking_lock &&
8141 NT_STATUS_EQUAL((status),
8142 NT_STATUS_FILE_LOCK_CONFLICT))
8145 timeout = lp_lock_spin_time();
8148 if (br_lck && defer_lock) {
8150 * A blocking lock was requested. Package up
8151 * this smb into a queued request and push it
8152 * onto the blocking lock queue.
8154 if(push_blocking_lock_request(br_lck,
8165 TALLOC_FREE(br_lck);
8167 return NT_STATUS_OK;
8171 TALLOC_FREE(br_lck);
8174 if (!NT_STATUS_IS_OK(status)) {
8179 /* If any of the above locks failed, then we must unlock
8180 all of the previous locks (X/Open spec). */
8182 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8184 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8185 i = -1; /* we want to skip the for loop */
8189 * Ensure we don't do a remove on the lock that just failed,
8190 * as under POSIX rules, if we have a lock already there, we
8191 * will delete it (and we shouldn't) .....
8193 for(i--; i >= 0; i--) {
8194 struct smbd_lock_element *e = &locks[i];
8196 do_unlock(req->sconn->msg_ctx,
8206 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8207 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8209 return NT_STATUS_OK;
8212 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8214 uint16_t num_ulocks,
8215 struct smbd_lock_element *ulocks)
8219 for(i = 0; i < (int)num_ulocks; i++) {
8220 struct smbd_lock_element *e = &ulocks[i];
8223 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8224 "pid %u, file %s\n", __func__,
8227 (unsigned int)e->smblctx,
8230 if (e->brltype != UNLOCK_LOCK) {
8231 /* this can only happen with SMB2 */
8232 return NT_STATUS_INVALID_PARAMETER;
8235 status = do_unlock(req->sconn->msg_ctx,
8242 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8243 nt_errstr(status)));
8245 if (!NT_STATUS_IS_OK(status)) {
8250 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8253 return NT_STATUS_OK;
8256 /****************************************************************************
8257 Reply to a lockingX request.
8258 ****************************************************************************/
8260 void reply_lockingX(struct smb_request *req)
8262 connection_struct *conn = req->conn;
8264 unsigned char locktype;
8265 unsigned char oplocklevel;
8266 uint16_t num_ulocks;
8268 int32_t lock_timeout;
8270 const uint8_t *data;
8271 bool large_file_format;
8272 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8273 struct smbd_lock_element *ulocks;
8274 struct smbd_lock_element *locks;
8277 START_PROFILE(SMBlockingX);
8280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8281 END_PROFILE(SMBlockingX);
8285 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8286 locktype = CVAL(req->vwv+3, 0);
8287 oplocklevel = CVAL(req->vwv+3, 1);
8288 num_ulocks = SVAL(req->vwv+6, 0);
8289 num_locks = SVAL(req->vwv+7, 0);
8290 lock_timeout = IVAL(req->vwv+4, 0);
8291 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8293 if (!check_fsp(conn, req, fsp)) {
8294 END_PROFILE(SMBlockingX);
8300 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8301 /* we don't support these - and CANCEL_LOCK makes w2k
8302 and XP reboot so I don't really want to be
8303 compatible! (tridge) */
8304 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8305 END_PROFILE(SMBlockingX);
8309 /* Check if this is an oplock break on a file
8310 we have granted an oplock on.
8312 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8313 /* Client can insist on breaking to none. */
8314 bool break_to_none = (oplocklevel == 0);
8317 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8318 "for %s\n", (unsigned int)oplocklevel,
8319 fsp_fnum_dbg(fsp)));
8322 * Make sure we have granted an exclusive or batch oplock on
8326 if (fsp->oplock_type == 0) {
8328 /* The Samba4 nbench simulator doesn't understand
8329 the difference between break to level2 and break
8330 to none from level2 - it sends oplock break
8331 replies in both cases. Don't keep logging an error
8332 message here - just ignore it. JRA. */
8334 DEBUG(5,("reply_lockingX: Error : oplock break from "
8335 "client for %s (oplock=%d) and no "
8336 "oplock granted on this file (%s).\n",
8337 fsp_fnum_dbg(fsp), fsp->oplock_type,
8340 /* if this is a pure oplock break request then don't
8342 if (num_locks == 0 && num_ulocks == 0) {
8343 END_PROFILE(SMBlockingX);
8346 END_PROFILE(SMBlockingX);
8347 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8352 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8354 result = remove_oplock(fsp);
8356 result = downgrade_oplock(fsp);
8360 DEBUG(0, ("reply_lockingX: error in removing "
8361 "oplock on file %s\n", fsp_str_dbg(fsp)));
8362 /* Hmmm. Is this panic justified? */
8363 smb_panic("internal tdb error");
8366 /* if this is a pure oplock break request then don't send a
8368 if (num_locks == 0 && num_ulocks == 0) {
8369 /* Sanity check - ensure a pure oplock break is not a
8371 if (CVAL(req->vwv+0, 0) != 0xff) {
8372 DEBUG(0,("reply_lockingX: Error : pure oplock "
8373 "break is a chained %d request !\n",
8374 (unsigned int)CVAL(req->vwv+0, 0)));
8376 END_PROFILE(SMBlockingX);
8382 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8384 END_PROFILE(SMBlockingX);
8388 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8389 if (ulocks == NULL) {
8390 reply_nterror(req, NT_STATUS_NO_MEMORY);
8391 END_PROFILE(SMBlockingX);
8395 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8396 if (locks == NULL) {
8397 reply_nterror(req, NT_STATUS_NO_MEMORY);
8398 END_PROFILE(SMBlockingX);
8402 /* Data now points at the beginning of the list
8403 of smb_unlkrng structs */
8404 for(i = 0; i < (int)num_ulocks; i++) {
8405 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8406 ulocks[i].count = get_lock_count(data, i, large_file_format);
8407 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8408 ulocks[i].brltype = UNLOCK_LOCK;
8411 /* Now do any requested locks */
8412 data += ((large_file_format ? 20 : 10)*num_ulocks);
8414 /* Data now points at the beginning of the list
8415 of smb_lkrng structs */
8417 for(i = 0; i < (int)num_locks; i++) {
8418 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8419 locks[i].count = get_lock_count(data, i, large_file_format);
8420 locks[i].offset = get_lock_offset(data, i, large_file_format);
8422 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8423 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8424 locks[i].brltype = PENDING_READ_LOCK;
8426 locks[i].brltype = READ_LOCK;
8429 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8430 locks[i].brltype = PENDING_WRITE_LOCK;
8432 locks[i].brltype = WRITE_LOCK;
8437 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8438 if (!NT_STATUS_IS_OK(status)) {
8439 END_PROFILE(SMBlockingX);
8440 reply_nterror(req, status);
8444 status = smbd_do_locking(req, fsp,
8445 locktype, lock_timeout,
8448 if (!NT_STATUS_IS_OK(status)) {
8449 END_PROFILE(SMBlockingX);
8450 reply_nterror(req, status);
8454 END_PROFILE(SMBlockingX);
8458 reply_outbuf(req, 2, 0);
8459 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8460 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8462 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8463 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8465 END_PROFILE(SMBlockingX);
8469 #define DBGC_CLASS DBGC_ALL
8471 /****************************************************************************
8472 Reply to a SMBreadbmpx (read block multiplex) request.
8473 Always reply with an error, if someone has a platform really needs this,
8474 please contact vl@samba.org
8475 ****************************************************************************/
8477 void reply_readbmpx(struct smb_request *req)
8479 START_PROFILE(SMBreadBmpx);
8480 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8481 END_PROFILE(SMBreadBmpx);
8485 /****************************************************************************
8486 Reply to a SMBreadbs (read block multiplex secondary) request.
8487 Always reply with an error, if someone has a platform really needs this,
8488 please contact vl@samba.org
8489 ****************************************************************************/
8491 void reply_readbs(struct smb_request *req)
8493 START_PROFILE(SMBreadBs);
8494 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8495 END_PROFILE(SMBreadBs);
8499 /****************************************************************************
8500 Reply to a SMBsetattrE.
8501 ****************************************************************************/
8503 void reply_setattrE(struct smb_request *req)
8505 connection_struct *conn = req->conn;
8506 struct smb_file_time ft;
8510 START_PROFILE(SMBsetattrE);
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8518 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8520 if(!fsp || (fsp->conn != conn)) {
8521 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8526 * Convert the DOS times into unix times.
8529 ft.atime = convert_time_t_to_timespec(
8530 srv_make_unix_date2(req->vwv+3));
8531 ft.mtime = convert_time_t_to_timespec(
8532 srv_make_unix_date2(req->vwv+5));
8533 ft.create_time = convert_time_t_to_timespec(
8534 srv_make_unix_date2(req->vwv+1));
8536 reply_outbuf(req, 0, 0);
8539 * Patch from Ray Frush <frush@engr.colostate.edu>
8540 * Sometimes times are sent as zero - ignore them.
8543 /* Ensure we have a valid stat struct for the source. */
8544 status = vfs_stat_fsp(fsp);
8545 if (!NT_STATUS_IS_OK(status)) {
8546 reply_nterror(req, status);
8550 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8551 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8555 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8556 if (!NT_STATUS_IS_OK(status)) {
8557 reply_nterror(req, status);
8561 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8564 (unsigned int)ft.atime.tv_sec,
8565 (unsigned int)ft.mtime.tv_sec,
8566 (unsigned int)ft.create_time.tv_sec
8569 END_PROFILE(SMBsetattrE);
8574 /* Back from the dead for OS/2..... JRA. */
8576 /****************************************************************************
8577 Reply to a SMBwritebmpx (write block multiplex primary) request.
8578 Always reply with an error, if someone has a platform really needs this,
8579 please contact vl@samba.org
8580 ****************************************************************************/
8582 void reply_writebmpx(struct smb_request *req)
8584 START_PROFILE(SMBwriteBmpx);
8585 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8586 END_PROFILE(SMBwriteBmpx);
8590 /****************************************************************************
8591 Reply to a SMBwritebs (write block multiplex secondary) request.
8592 Always reply with an error, if someone has a platform really needs this,
8593 please contact vl@samba.org
8594 ****************************************************************************/
8596 void reply_writebs(struct smb_request *req)
8598 START_PROFILE(SMBwriteBs);
8599 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8600 END_PROFILE(SMBwriteBs);
8604 /****************************************************************************
8605 Reply to a SMBgetattrE.
8606 ****************************************************************************/
8608 void reply_getattrE(struct smb_request *req)
8610 connection_struct *conn = req->conn;
8613 struct timespec create_ts;
8615 START_PROFILE(SMBgetattrE);
8618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8619 END_PROFILE(SMBgetattrE);
8623 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8625 if(!fsp || (fsp->conn != conn)) {
8626 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8627 END_PROFILE(SMBgetattrE);
8631 /* Do an fstat on this file */
8633 reply_nterror(req, map_nt_error_from_unix(errno));
8634 END_PROFILE(SMBgetattrE);
8638 mode = dos_mode(conn, fsp->fsp_name);
8641 * Convert the times into dos times. Set create
8642 * date to be last modify date as UNIX doesn't save
8646 reply_outbuf(req, 11, 0);
8648 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8649 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8650 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8651 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8652 /* Should we check pending modtime here ? JRA */
8653 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8654 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8656 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8657 SIVAL(req->outbuf, smb_vwv6, 0);
8658 SIVAL(req->outbuf, smb_vwv8, 0);
8660 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8661 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8662 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8664 SSVAL(req->outbuf,smb_vwv10, mode);
8666 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8668 END_PROFILE(SMBgetattrE);