2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
266 bool posix_pathnames,
268 bool *contains_wcard)
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 *err = NT_STATUS_INVALID_PARAMETER;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
369 return srvstr_get_path_wcard_internal(ctx,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
396 return srvstr_get_path_wcard_internal(ctx,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
416 *err = NT_STATUS_INVALID_PARAMETER;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
497 if (!check_fsp_open(conn, req, fsp)) {
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
508 fsp->num_smb_operations++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
520 if (!check_fsp_open(conn, req, fsp)) {
524 if (fsp->is_directory) {
528 if (fsp->fake_file_handle == NULL) {
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 if (fsp->fake_file_handle->private_data == NULL) {
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
547 char *trim_name_type;
548 const char *retarget_parm;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
570 if (trim_name_type == NULL) {
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm == NULL) {
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
600 if (sscanf(p, "%x", &retarget_type) != 1) {
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
607 DEBUG(10, ("could not resolve %s\n", retarget));
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name);
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1, name_type2;
668 int name_len1, name_len2;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf);
755 reload_services(sconn, conn_snum_used, true);
758 xconn->transport.nbt.got_session = true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
792 /****************************************************************************
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request *req)
799 connection_struct *conn = req->conn;
801 char *service_buf = NULL;
802 char *password = NULL;
808 TALLOC_CTX *ctx = talloc_tos();
809 struct smbXsrv_connection *xconn = req->xconn;
810 NTTIME now = timeval_to_nttime(&req->request_time);
812 START_PROFILE(SMBtcon);
814 if (req->buflen < 4) {
815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
816 END_PROFILE(SMBtcon);
821 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
823 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
825 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
828 if (service_buf == NULL || password == NULL || dev == NULL) {
829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830 END_PROFILE(SMBtcon);
833 p2 = strrchr_m(service_buf,'\\');
837 service = service_buf;
840 conn = make_connection(req, now, service, dev,
841 req->vuid,&nt_status);
845 reply_nterror(req, nt_status);
846 END_PROFILE(SMBtcon);
850 reply_outbuf(req, 2, 0);
851 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
852 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
853 SSVAL(req->outbuf,smb_tid,conn->cnum);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service, conn->cnum));
858 END_PROFILE(SMBtcon);
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request *req)
869 connection_struct *conn = req->conn;
870 const char *service = NULL;
871 TALLOC_CTX *ctx = talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype = NULL;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype;
882 struct smbXsrv_session *session = NULL;
883 NTTIME now = timeval_to_nttime(&req->request_time);
884 bool session_key_updated = false;
885 uint16_t optional_support = 0;
886 struct smbXsrv_connection *xconn = req->xconn;
888 START_PROFILE(SMBtconX);
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 END_PROFILE(SMBtconX);
896 passlen = SVAL(req->vwv+3, 0);
897 tcon_flags = SVAL(req->vwv+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
901 struct smbXsrv_tcon *tcon;
909 * TODO: cancel all outstanding requests on the tcon
911 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
912 if (!NT_STATUS_IS_OK(status)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX);
921 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
928 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
929 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
930 END_PROFILE(SMBtconX);
934 if (xconn->smb1.negprot.encrypted_passwords) {
935 p = req->buf + passlen;
937 p = req->buf + passlen + 1;
940 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
943 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
944 END_PROFILE(SMBtconX);
949 * the service name can be either: \\server\share
950 * or share directly like on the DELL PowerVault 705
953 q = strchr_m(path+2,'\\');
955 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
956 END_PROFILE(SMBtconX);
964 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
965 &client_devicetype, p,
966 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
968 if (client_devicetype == NULL) {
969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 END_PROFILE(SMBtconX);
974 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
976 nt_status = smb1srv_session_lookup(xconn,
977 req->vuid, now, &session);
978 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
979 reply_force_doserror(req, ERRSRV, ERRbaduid);
980 END_PROFILE(SMBtconX);
983 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
984 reply_nterror(req, nt_status);
985 END_PROFILE(SMBtconX);
988 if (!NT_STATUS_IS_OK(nt_status)) {
989 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
990 END_PROFILE(SMBtconX);
994 if (session->global->auth_session_info == NULL) {
995 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
996 END_PROFILE(SMBtconX);
1001 * If there is no application key defined yet
1004 * This means we setup the application key on the
1005 * first tcon that happens via the given session.
1007 * Once the application key is defined, it does not
1010 if (session->global->application_key.length == 0 &&
1011 session->global->signing_key.length > 0)
1013 struct smbXsrv_session *x = session;
1014 struct auth_session_info *session_info =
1015 session->global->auth_session_info;
1016 uint8_t session_key[16];
1018 ZERO_STRUCT(session_key);
1019 memcpy(session_key, x->global->signing_key.data,
1020 MIN(x->global->signing_key.length, sizeof(session_key)));
1023 * The application key is truncated/padded to 16 bytes
1025 x->global->application_key = data_blob_talloc(x->global,
1027 sizeof(session_key));
1028 ZERO_STRUCT(session_key);
1029 if (x->global->application_key.data == NULL) {
1030 reply_nterror(req, NT_STATUS_NO_MEMORY);
1031 END_PROFILE(SMBtconX);
1035 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1036 smb_key_derivation(x->global->application_key.data,
1037 x->global->application_key.length,
1038 x->global->application_key.data);
1039 optional_support |= SMB_EXTENDED_SIGNATURES;
1043 * Place the application key into the session_info
1045 data_blob_clear_free(&session_info->session_key);
1046 session_info->session_key = data_blob_dup_talloc(session_info,
1047 x->global->application_key);
1048 if (session_info->session_key.data == NULL) {
1049 data_blob_clear_free(&x->global->application_key);
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1051 END_PROFILE(SMBtconX);
1054 session_key_updated = true;
1057 conn = make_connection(req, now, service, client_devicetype,
1058 req->vuid, &nt_status);
1062 if (session_key_updated) {
1063 struct smbXsrv_session *x = session;
1064 struct auth_session_info *session_info =
1065 session->global->auth_session_info;
1066 data_blob_clear_free(&x->global->application_key);
1067 data_blob_clear_free(&session_info->session_key);
1069 reply_nterror(req, nt_status);
1070 END_PROFILE(SMBtconX);
1075 server_devicetype = "IPC";
1076 else if ( IS_PRINT(conn) )
1077 server_devicetype = "LPT1:";
1079 server_devicetype = "A:";
1081 if (get_Protocol() < PROTOCOL_NT1) {
1082 reply_outbuf(req, 2, 0);
1083 if (message_push_string(&req->outbuf, server_devicetype,
1084 STR_TERMINATE|STR_ASCII) == -1) {
1085 reply_nterror(req, NT_STATUS_NO_MEMORY);
1086 END_PROFILE(SMBtconX);
1090 /* NT sets the fstype of IPC$ to the null string */
1091 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1093 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1094 /* Return permissions. */
1098 reply_outbuf(req, 7, 0);
1101 perm1 = FILE_ALL_ACCESS;
1102 perm2 = FILE_ALL_ACCESS;
1104 perm1 = conn->share_access;
1107 SIVAL(req->outbuf, smb_vwv3, perm1);
1108 SIVAL(req->outbuf, smb_vwv5, perm2);
1110 reply_outbuf(req, 3, 0);
1113 if ((message_push_string(&req->outbuf, server_devicetype,
1114 STR_TERMINATE|STR_ASCII) == -1)
1115 || (message_push_string(&req->outbuf, fstype,
1116 STR_TERMINATE) == -1)) {
1117 reply_nterror(req, NT_STATUS_NO_MEMORY);
1118 END_PROFILE(SMBtconX);
1122 /* what does setting this bit do? It is set by NT4 and
1123 may affect the ability to autorun mounted cdroms */
1124 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1126 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1128 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1129 DEBUG(2,("Serving %s as a Dfs root\n",
1130 lp_servicename(ctx, SNUM(conn)) ));
1131 optional_support |= SMB_SHARE_IN_DFS;
1134 SSVAL(req->outbuf, smb_vwv2, optional_support);
1137 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1138 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1140 DEBUG(3,("tconX service=%s \n",
1143 /* set the incoming and outgoing tid to the just created one */
1144 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1145 SSVAL(req->outbuf,smb_tid,conn->cnum);
1147 END_PROFILE(SMBtconX);
1149 req->tid = conn->cnum;
1152 /****************************************************************************
1153 Reply to an unknown type.
1154 ****************************************************************************/
1156 void reply_unknown_new(struct smb_request *req, uint8_t type)
1158 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1159 smb_fn_name(type), type, type));
1160 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1164 /****************************************************************************
1166 conn POINTER CAN BE NULL HERE !
1167 ****************************************************************************/
1169 void reply_ioctl(struct smb_request *req)
1171 connection_struct *conn = req->conn;
1174 uint32_t ioctl_code;
1178 START_PROFILE(SMBioctl);
1181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1182 END_PROFILE(SMBioctl);
1186 device = SVAL(req->vwv+1, 0);
1187 function = SVAL(req->vwv+2, 0);
1188 ioctl_code = (device << 16) + function;
1190 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1192 switch (ioctl_code) {
1193 case IOCTL_QUERY_JOB_INFO:
1197 reply_force_doserror(req, ERRSRV, ERRnosupport);
1198 END_PROFILE(SMBioctl);
1202 reply_outbuf(req, 8, replysize+1);
1203 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1204 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1205 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1206 p = smb_buf(req->outbuf);
1207 memset(p, '\0', replysize+1); /* valgrind-safe. */
1208 p += 1; /* Allow for alignment */
1210 switch (ioctl_code) {
1211 case IOCTL_QUERY_JOB_INFO:
1215 files_struct *fsp = file_fsp(
1216 req, SVAL(req->vwv+0, 0));
1218 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1219 END_PROFILE(SMBioctl);
1223 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1225 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1226 lp_netbios_name(), 15,
1227 STR_TERMINATE|STR_ASCII, &len);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 reply_nterror(req, status);
1230 END_PROFILE(SMBioctl);
1234 status = srvstr_push((char *)req->outbuf, req->flags2,
1236 lp_servicename(talloc_tos(),
1238 13, STR_TERMINATE|STR_ASCII, &len);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 reply_nterror(req, status);
1241 END_PROFILE(SMBioctl);
1245 memset(p+18, 0, 13);
1251 END_PROFILE(SMBioctl);
1255 /****************************************************************************
1256 Strange checkpath NTSTATUS mapping.
1257 ****************************************************************************/
1259 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1261 /* Strange DOS error code semantics only for checkpath... */
1262 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1263 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1264 /* We need to map to ERRbadpath */
1265 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1271 /****************************************************************************
1272 Reply to a checkpath.
1273 ****************************************************************************/
1275 void reply_checkpath(struct smb_request *req)
1277 connection_struct *conn = req->conn;
1278 struct smb_filename *smb_fname = NULL;
1281 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1282 TALLOC_CTX *ctx = talloc_tos();
1284 START_PROFILE(SMBcheckpath);
1286 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1287 STR_TERMINATE, &status);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 status = map_checkpath_error(req->flags2, status);
1291 reply_nterror(req, status);
1292 END_PROFILE(SMBcheckpath);
1296 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1298 status = filename_convert(ctx,
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 = ucf_flags_from_smb_request(req);
1397 status = filename_convert(ctx,
1399 req->flags2 & FLAGS2_DFS_PATHNAMES,
1404 if (!NT_STATUS_IS_OK(status)) {
1405 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1406 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1407 ERRSRV, ERRbadpath);
1410 reply_nterror(req, status);
1413 if (!VALID_STAT(smb_fname->st) &&
1414 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1415 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1416 smb_fname_str_dbg(smb_fname),
1418 reply_nterror(req, map_nt_error_from_unix(errno));
1422 mode = dos_mode(conn, smb_fname);
1423 size = smb_fname->st.st_ex_size;
1425 if (ask_sharemode) {
1426 struct timespec write_time_ts;
1427 struct file_id fileid;
1429 ZERO_STRUCT(write_time_ts);
1430 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1431 get_file_infos(fileid, 0, NULL, &write_time_ts);
1432 if (!null_timespec(write_time_ts)) {
1433 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1437 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1438 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1443 reply_outbuf(req, 10, 0);
1445 SSVAL(req->outbuf,smb_vwv0,mode);
1446 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1447 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1449 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1451 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1453 if (get_Protocol() >= PROTOCOL_NT1) {
1454 SSVAL(req->outbuf, smb_flg2,
1455 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1458 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1459 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1462 TALLOC_FREE(smb_fname);
1464 END_PROFILE(SMBgetatr);
1468 /****************************************************************************
1470 ****************************************************************************/
1472 void reply_setatr(struct smb_request *req)
1474 struct smb_file_time ft;
1475 connection_struct *conn = req->conn;
1476 struct smb_filename *smb_fname = NULL;
1482 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1483 TALLOC_CTX *ctx = talloc_tos();
1485 START_PROFILE(SMBsetatr);
1490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1494 p = (const char *)req->buf + 1;
1495 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 reply_nterror(req, status);
1501 status = filename_convert(ctx,
1503 req->flags2 & FLAGS2_DFS_PATHNAMES,
1508 if (!NT_STATUS_IS_OK(status)) {
1509 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1510 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1511 ERRSRV, ERRbadpath);
1514 reply_nterror(req, status);
1518 if (smb_fname->base_name[0] == '.' &&
1519 smb_fname->base_name[1] == '\0') {
1521 * Not sure here is the right place to catch this
1522 * condition. Might be moved to somewhere else later -- vl
1524 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1528 mode = SVAL(req->vwv+0, 0);
1529 mtime = srv_make_unix_date3(req->vwv+1);
1531 if (mode != FILE_ATTRIBUTE_NORMAL) {
1532 if (VALID_STAT_OF_DIR(smb_fname->st))
1533 mode |= FILE_ATTRIBUTE_DIRECTORY;
1535 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1537 status = check_access(conn, NULL, smb_fname,
1538 FILE_WRITE_ATTRIBUTES);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 reply_nterror(req, status);
1544 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1546 reply_nterror(req, map_nt_error_from_unix(errno));
1551 ft.mtime = convert_time_t_to_timespec(mtime);
1552 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1553 if (!NT_STATUS_IS_OK(status)) {
1554 reply_nterror(req, status);
1558 reply_outbuf(req, 0, 0);
1560 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1563 TALLOC_FREE(smb_fname);
1564 END_PROFILE(SMBsetatr);
1568 /****************************************************************************
1570 ****************************************************************************/
1572 void reply_dskattr(struct smb_request *req)
1574 connection_struct *conn = req->conn;
1576 uint64_t dfree,dsize,bsize;
1577 struct smb_filename smb_fname;
1578 START_PROFILE(SMBdskattr);
1580 ZERO_STRUCT(smb_fname);
1581 smb_fname.base_name = discard_const_p(char, ".");
1583 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1584 reply_nterror(req, map_nt_error_from_unix(errno));
1585 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1586 END_PROFILE(SMBdskattr);
1590 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1591 if (ret == (uint64_t)-1) {
1592 reply_nterror(req, map_nt_error_from_unix(errno));
1593 END_PROFILE(SMBdskattr);
1598 * Force max to fit in 16 bit fields.
1600 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1604 if (bsize > (WORDMAX*512)) {
1605 bsize = (WORDMAX*512);
1606 if (dsize > WORDMAX)
1608 if (dfree > WORDMAX)
1614 reply_outbuf(req, 5, 0);
1616 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1617 double total_space, free_space;
1618 /* we need to scale this to a number that DOS6 can handle. We
1619 use floating point so we can handle large drives on systems
1620 that don't have 64 bit integers
1622 we end up displaying a maximum of 2G to DOS systems
1624 total_space = dsize * (double)bsize;
1625 free_space = dfree * (double)bsize;
1627 dsize = (uint64_t)((total_space+63*512) / (64*512));
1628 dfree = (uint64_t)((free_space+63*512) / (64*512));
1630 if (dsize > 0xFFFF) dsize = 0xFFFF;
1631 if (dfree > 0xFFFF) dfree = 0xFFFF;
1633 SSVAL(req->outbuf,smb_vwv0,dsize);
1634 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1635 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1636 SSVAL(req->outbuf,smb_vwv3,dfree);
1638 SSVAL(req->outbuf,smb_vwv0,dsize);
1639 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1640 SSVAL(req->outbuf,smb_vwv2,512);
1641 SSVAL(req->outbuf,smb_vwv3,dfree);
1644 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1646 END_PROFILE(SMBdskattr);
1651 * Utility function to split the filename from the directory.
1653 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1654 char **fname_dir_out,
1655 char **fname_mask_out)
1657 const char *p = NULL;
1658 char *fname_dir = NULL;
1659 char *fname_mask = NULL;
1661 p = strrchr_m(fname_in, '/');
1663 fname_dir = talloc_strdup(ctx, ".");
1664 fname_mask = talloc_strdup(ctx, fname_in);
1666 fname_dir = talloc_strndup(ctx, fname_in,
1667 PTR_DIFF(p, fname_in));
1668 fname_mask = talloc_strdup(ctx, p+1);
1671 if (!fname_dir || !fname_mask) {
1672 TALLOC_FREE(fname_dir);
1673 TALLOC_FREE(fname_mask);
1674 return NT_STATUS_NO_MEMORY;
1677 *fname_dir_out = fname_dir;
1678 *fname_mask_out = fname_mask;
1679 return NT_STATUS_OK;
1682 /****************************************************************************
1684 ****************************************************************************/
1686 static bool make_dir_struct(TALLOC_CTX *ctx,
1696 char *mask2 = talloc_strdup(ctx, mask);
1702 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1706 memset(buf+1,' ',11);
1707 if ((p = strchr_m(mask2,'.')) != NULL) {
1709 push_ascii(buf+1,mask2,8, 0);
1710 push_ascii(buf+9,p+1,3, 0);
1713 push_ascii(buf+1,mask2,11, 0);
1716 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1718 srv_put_dos_date(buf,22,date);
1719 SSVAL(buf,26,size & 0xFFFF);
1720 SSVAL(buf,28,(size >> 16)&0xFFFF);
1721 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1722 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1723 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1724 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1728 /****************************************************************************
1730 Can be called from SMBsearch, SMBffirst or SMBfunique.
1731 ****************************************************************************/
1733 void reply_search(struct smb_request *req)
1735 connection_struct *conn = req->conn;
1738 char *directory = NULL;
1739 struct smb_filename *smb_fname = NULL;
1743 struct timespec date;
1745 unsigned int numentries = 0;
1746 unsigned int maxentries = 0;
1747 bool finished = False;
1752 bool check_descend = False;
1753 bool expect_close = False;
1755 bool mask_contains_wcard = False;
1756 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1757 TALLOC_CTX *ctx = talloc_tos();
1758 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1759 struct dptr_struct *dirptr = NULL;
1760 struct smbXsrv_connection *xconn = req->xconn;
1761 struct smbd_server_connection *sconn = req->sconn;
1763 START_PROFILE(SMBsearch);
1766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1770 if (req->posix_pathnames) {
1771 reply_unknown_new(req, req->cmd);
1775 /* If we were called as SMBffirst then we must expect close. */
1776 if(req->cmd == SMBffirst) {
1777 expect_close = True;
1780 reply_outbuf(req, 1, 3);
1781 maxentries = SVAL(req->vwv+0, 0);
1782 dirtype = SVAL(req->vwv+1, 0);
1783 p = (const char *)req->buf + 1;
1784 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1785 &nt_status, &mask_contains_wcard);
1786 if (!NT_STATUS_IS_OK(nt_status)) {
1787 reply_nterror(req, nt_status);
1792 status_len = SVAL(p, 0);
1795 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1797 if (status_len == 0) {
1798 struct smb_filename *smb_dname = NULL;
1799 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1800 ucf_flags_from_smb_request(req);
1801 nt_status = filename_convert(ctx, conn,
1802 req->flags2 & FLAGS2_DFS_PATHNAMES,
1805 &mask_contains_wcard,
1807 if (!NT_STATUS_IS_OK(nt_status)) {
1808 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1809 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1810 ERRSRV, ERRbadpath);
1813 reply_nterror(req, nt_status);
1817 directory = smb_fname->base_name;
1819 p = strrchr_m(directory,'/');
1820 if ((p != NULL) && (*directory != '/')) {
1821 mask = talloc_strdup(ctx, p + 1);
1822 directory = talloc_strndup(ctx, directory,
1823 PTR_DIFF(p, directory));
1825 mask = talloc_strdup(ctx, directory);
1826 directory = talloc_strdup(ctx,".");
1830 reply_nterror(req, NT_STATUS_NO_MEMORY);
1834 memset((char *)status,'\0',21);
1835 SCVAL(status,0,(dirtype & 0x1F));
1837 smb_dname = synthetic_smb_fname(talloc_tos(),
1842 if (smb_dname == NULL) {
1843 reply_nterror(req, NT_STATUS_NO_MEMORY);
1847 nt_status = dptr_create(conn,
1855 mask_contains_wcard,
1859 TALLOC_FREE(smb_dname);
1861 if (!NT_STATUS_IS_OK(nt_status)) {
1862 reply_nterror(req, nt_status);
1865 dptr_num = dptr_dnum(dirptr);
1868 const char *dirpath;
1870 memcpy(status,p,21);
1871 status_dirtype = CVAL(status,0) & 0x1F;
1872 if (status_dirtype != (dirtype & 0x1F)) {
1873 dirtype = status_dirtype;
1876 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1880 dirpath = dptr_path(sconn, dptr_num);
1881 directory = talloc_strdup(ctx, dirpath);
1883 reply_nterror(req, NT_STATUS_NO_MEMORY);
1887 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1892 * For a 'continue' search we have no string. So
1893 * check from the initial saved string.
1895 if (!req->posix_pathnames) {
1896 mask_contains_wcard = ms_has_wild(mask);
1898 dirtype = dptr_attr(sconn, dptr_num);
1901 DEBUG(4,("dptr_num is %d\n",dptr_num));
1903 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1904 dptr_init_search_op(dirptr);
1906 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1907 char buf[DIR_STRUCT_SIZE];
1908 memcpy(buf,status,21);
1909 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1910 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1911 reply_nterror(req, NT_STATUS_NO_MEMORY);
1914 dptr_fill(sconn, buf+12,dptr_num);
1915 if (dptr_zero(buf+12) && (status_len==0)) {
1920 if (message_push_blob(&req->outbuf,
1921 data_blob_const(buf, sizeof(buf)))
1923 reply_nterror(req, NT_STATUS_NO_MEMORY);
1928 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1929 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1931 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1933 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1934 directory,lp_dont_descend(ctx, SNUM(conn))));
1935 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1936 check_descend = True;
1939 for (i=numentries;(i<maxentries) && !finished;i++) {
1940 finished = !get_dir_entry(ctx,
1951 char buf[DIR_STRUCT_SIZE];
1952 memcpy(buf,status,21);
1953 if (!make_dir_struct(ctx,
1959 convert_timespec_to_time_t(date),
1960 !allow_long_path_components)) {
1961 reply_nterror(req, NT_STATUS_NO_MEMORY);
1964 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1967 if (message_push_blob(&req->outbuf,
1968 data_blob_const(buf, sizeof(buf)))
1970 reply_nterror(req, NT_STATUS_NO_MEMORY);
1980 /* If we were called as SMBffirst with smb_search_id == NULL
1981 and no entries were found then return error and close dirptr
1984 if (numentries == 0) {
1985 dptr_close(sconn, &dptr_num);
1986 } else if(expect_close && status_len == 0) {
1987 /* Close the dptr - we know it's gone */
1988 dptr_close(sconn, &dptr_num);
1991 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1992 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1993 dptr_close(sconn, &dptr_num);
1996 if ((numentries == 0) && !mask_contains_wcard) {
1997 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2001 SSVAL(req->outbuf,smb_vwv0,numentries);
2002 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2003 SCVAL(smb_buf(req->outbuf),0,5);
2004 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2006 /* The replies here are never long name. */
2007 SSVAL(req->outbuf, smb_flg2,
2008 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2009 if (!allow_long_path_components) {
2010 SSVAL(req->outbuf, smb_flg2,
2011 SVAL(req->outbuf, smb_flg2)
2012 & (~FLAGS2_LONG_PATH_COMPONENTS));
2015 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2016 SSVAL(req->outbuf, smb_flg2,
2017 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2019 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2020 smb_fn_name(req->cmd),
2027 TALLOC_FREE(directory);
2029 TALLOC_FREE(smb_fname);
2030 END_PROFILE(SMBsearch);
2034 /****************************************************************************
2035 Reply to a fclose (stop directory search).
2036 ****************************************************************************/
2038 void reply_fclose(struct smb_request *req)
2046 bool path_contains_wcard = False;
2047 TALLOC_CTX *ctx = talloc_tos();
2048 struct smbd_server_connection *sconn = req->sconn;
2050 START_PROFILE(SMBfclose);
2052 if (req->posix_pathnames) {
2053 reply_unknown_new(req, req->cmd);
2054 END_PROFILE(SMBfclose);
2058 p = (const char *)req->buf + 1;
2059 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2060 &err, &path_contains_wcard);
2061 if (!NT_STATUS_IS_OK(err)) {
2062 reply_nterror(req, err);
2063 END_PROFILE(SMBfclose);
2067 status_len = SVAL(p,0);
2070 if (status_len == 0) {
2071 reply_force_doserror(req, ERRSRV, ERRsrverror);
2072 END_PROFILE(SMBfclose);
2076 memcpy(status,p,21);
2078 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2079 /* Close the dptr - we know it's gone */
2080 dptr_close(sconn, &dptr_num);
2083 reply_outbuf(req, 1, 0);
2084 SSVAL(req->outbuf,smb_vwv0,0);
2086 DEBUG(3,("search close\n"));
2088 END_PROFILE(SMBfclose);
2092 /****************************************************************************
2094 ****************************************************************************/
2096 void reply_open(struct smb_request *req)
2098 connection_struct *conn = req->conn;
2099 struct smb_filename *smb_fname = NULL;
2109 uint32_t access_mask;
2110 uint32_t share_mode;
2111 uint32_t create_disposition;
2112 uint32_t create_options = 0;
2113 uint32_t private_flags = 0;
2116 TALLOC_CTX *ctx = talloc_tos();
2118 START_PROFILE(SMBopen);
2121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2125 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2126 deny_mode = SVAL(req->vwv+0, 0);
2127 dos_attr = SVAL(req->vwv+1, 0);
2129 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2130 STR_TERMINATE, &status);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 reply_nterror(req, status);
2136 if (!map_open_params_to_ntcreate(fname, deny_mode,
2137 OPENX_FILE_EXISTS_OPEN, &access_mask,
2138 &share_mode, &create_disposition,
2139 &create_options, &private_flags)) {
2140 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2144 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2146 status = filename_convert(ctx,
2148 req->flags2 & FLAGS2_DFS_PATHNAMES,
2153 if (!NT_STATUS_IS_OK(status)) {
2154 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2155 reply_botherror(req,
2156 NT_STATUS_PATH_NOT_COVERED,
2157 ERRSRV, ERRbadpath);
2160 reply_nterror(req, status);
2164 status = SMB_VFS_CREATE_FILE(
2167 0, /* root_dir_fid */
2168 smb_fname, /* fname */
2169 access_mask, /* access_mask */
2170 share_mode, /* share_access */
2171 create_disposition, /* create_disposition*/
2172 create_options, /* create_options */
2173 dos_attr, /* file_attributes */
2174 oplock_request, /* oplock_request */
2176 0, /* allocation_size */
2182 NULL, NULL); /* create context */
2184 if (!NT_STATUS_IS_OK(status)) {
2185 if (open_was_deferred(req->xconn, req->mid)) {
2186 /* We have re-scheduled this call. */
2189 reply_openerror(req, status);
2193 /* Ensure we're pointing at the correct stat struct. */
2194 TALLOC_FREE(smb_fname);
2195 smb_fname = fsp->fsp_name;
2197 size = smb_fname->st.st_ex_size;
2198 fattr = dos_mode(conn, smb_fname);
2200 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2202 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2203 DEBUG(3,("attempt to open a directory %s\n",
2205 close_file(req, fsp, ERROR_CLOSE);
2206 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2207 ERRDOS, ERRnoaccess);
2211 reply_outbuf(req, 7, 0);
2212 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2213 SSVAL(req->outbuf,smb_vwv1,fattr);
2214 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2215 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2217 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2219 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2220 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2222 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2223 SCVAL(req->outbuf,smb_flg,
2224 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2227 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2228 SCVAL(req->outbuf,smb_flg,
2229 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2232 END_PROFILE(SMBopen);
2236 /****************************************************************************
2237 Reply to an open and X.
2238 ****************************************************************************/
2240 void reply_open_and_X(struct smb_request *req)
2242 connection_struct *conn = req->conn;
2243 struct smb_filename *smb_fname = NULL;
2245 uint16_t open_flags;
2248 /* Breakout the oplock request bits so we can set the
2249 reply bits separately. */
2250 int ex_oplock_request;
2251 int core_oplock_request;
2254 int smb_sattr = SVAL(req->vwv+4, 0);
2255 uint32_t smb_time = make_unix_date3(req->vwv+6);
2263 uint64_t allocation_size;
2264 ssize_t retval = -1;
2265 uint32_t access_mask;
2266 uint32_t share_mode;
2267 uint32_t create_disposition;
2268 uint32_t create_options = 0;
2269 uint32_t private_flags = 0;
2271 TALLOC_CTX *ctx = talloc_tos();
2273 START_PROFILE(SMBopenX);
2275 if (req->wct < 15) {
2276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2280 open_flags = SVAL(req->vwv+2, 0);
2281 deny_mode = SVAL(req->vwv+3, 0);
2282 smb_attr = SVAL(req->vwv+5, 0);
2283 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2284 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2285 oplock_request = ex_oplock_request | core_oplock_request;
2286 smb_ofun = SVAL(req->vwv+8, 0);
2287 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2289 /* If it's an IPC, pass off the pipe handler. */
2291 if (lp_nt_pipe_support()) {
2292 reply_open_pipe_and_X(conn, req);
2294 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2299 /* XXXX we need to handle passed times, sattr and flags */
2300 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2301 STR_TERMINATE, &status);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 reply_nterror(req, status);
2307 if (!map_open_params_to_ntcreate(fname, deny_mode,
2309 &access_mask, &share_mode,
2310 &create_disposition,
2313 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2317 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2319 status = filename_convert(ctx,
2321 req->flags2 & FLAGS2_DFS_PATHNAMES,
2326 if (!NT_STATUS_IS_OK(status)) {
2327 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2328 reply_botherror(req,
2329 NT_STATUS_PATH_NOT_COVERED,
2330 ERRSRV, ERRbadpath);
2333 reply_nterror(req, status);
2337 status = SMB_VFS_CREATE_FILE(
2340 0, /* root_dir_fid */
2341 smb_fname, /* fname */
2342 access_mask, /* access_mask */
2343 share_mode, /* share_access */
2344 create_disposition, /* create_disposition*/
2345 create_options, /* create_options */
2346 smb_attr, /* file_attributes */
2347 oplock_request, /* oplock_request */
2349 0, /* allocation_size */
2354 &smb_action, /* pinfo */
2355 NULL, NULL); /* create context */
2357 if (!NT_STATUS_IS_OK(status)) {
2358 if (open_was_deferred(req->xconn, req->mid)) {
2359 /* We have re-scheduled this call. */
2362 reply_openerror(req, status);
2366 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2367 if the file is truncated or created. */
2368 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2369 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2370 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2371 close_file(req, fsp, ERROR_CLOSE);
2372 reply_nterror(req, NT_STATUS_DISK_FULL);
2375 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2377 close_file(req, fsp, ERROR_CLOSE);
2378 reply_nterror(req, NT_STATUS_DISK_FULL);
2381 status = vfs_stat_fsp(fsp);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 close_file(req, fsp, ERROR_CLOSE);
2384 reply_nterror(req, status);
2389 fattr = dos_mode(conn, fsp->fsp_name);
2390 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2391 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2392 close_file(req, fsp, ERROR_CLOSE);
2393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2397 /* If the caller set the extended oplock request bit
2398 and we granted one (by whatever means) - set the
2399 correct bit for extended oplock reply.
2402 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2403 smb_action |= EXTENDED_OPLOCK_GRANTED;
2406 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2407 smb_action |= EXTENDED_OPLOCK_GRANTED;
2410 /* If the caller set the core oplock request bit
2411 and we granted one (by whatever means) - set the
2412 correct bit for core oplock reply.
2415 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2416 reply_outbuf(req, 19, 0);
2418 reply_outbuf(req, 15, 0);
2421 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2422 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2424 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2425 SCVAL(req->outbuf, smb_flg,
2426 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2429 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2430 SCVAL(req->outbuf, smb_flg,
2431 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2434 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2435 SSVAL(req->outbuf,smb_vwv3,fattr);
2436 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2437 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2439 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2441 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2442 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2443 SSVAL(req->outbuf,smb_vwv11,smb_action);
2445 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2446 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2450 TALLOC_FREE(smb_fname);
2451 END_PROFILE(SMBopenX);
2455 /****************************************************************************
2456 Reply to a SMBulogoffX.
2457 ****************************************************************************/
2459 void reply_ulogoffX(struct smb_request *req)
2461 struct smbd_server_connection *sconn = req->sconn;
2462 struct user_struct *vuser;
2463 struct smbXsrv_session *session = NULL;
2466 START_PROFILE(SMBulogoffX);
2468 vuser = get_valid_user_struct(sconn, req->vuid);
2471 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2472 (unsigned long long)req->vuid));
2474 req->vuid = UID_FIELD_INVALID;
2475 reply_force_doserror(req, ERRSRV, ERRbaduid);
2476 END_PROFILE(SMBulogoffX);
2480 session = vuser->session;
2484 * TODO: cancel all outstanding requests on the session
2486 status = smbXsrv_session_logoff(session);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 DEBUG(0, ("reply_ulogoff: "
2489 "smbXsrv_session_logoff() failed: %s\n",
2490 nt_errstr(status)));
2492 * If we hit this case, there is something completely
2493 * wrong, so we better disconnect the transport connection.
2495 END_PROFILE(SMBulogoffX);
2496 exit_server(__location__ ": smbXsrv_session_logoff failed");
2500 TALLOC_FREE(session);
2502 reply_outbuf(req, 2, 0);
2503 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2504 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2506 DEBUG(3, ("ulogoffX vuid=%llu\n",
2507 (unsigned long long)req->vuid));
2509 END_PROFILE(SMBulogoffX);
2510 req->vuid = UID_FIELD_INVALID;
2513 /****************************************************************************
2514 Reply to a mknew or a create.
2515 ****************************************************************************/
2517 void reply_mknew(struct smb_request *req)
2519 connection_struct *conn = req->conn;
2520 struct smb_filename *smb_fname = NULL;
2523 struct smb_file_time ft;
2525 int oplock_request = 0;
2527 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2528 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2529 uint32_t create_disposition;
2530 uint32_t create_options = 0;
2532 TALLOC_CTX *ctx = talloc_tos();
2534 START_PROFILE(SMBcreate);
2538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2542 fattr = SVAL(req->vwv+0, 0);
2543 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2545 if (req->cmd == SMBmknew) {
2546 /* We should fail if file exists. */
2547 create_disposition = FILE_CREATE;
2549 /* Create if file doesn't exist, truncate if it does. */
2550 create_disposition = FILE_OVERWRITE_IF;
2554 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2556 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2557 STR_TERMINATE, &status);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 reply_nterror(req, status);
2563 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2564 status = filename_convert(ctx,
2566 req->flags2 & FLAGS2_DFS_PATHNAMES,
2571 if (!NT_STATUS_IS_OK(status)) {
2572 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2573 reply_botherror(req,
2574 NT_STATUS_PATH_NOT_COVERED,
2575 ERRSRV, ERRbadpath);
2578 reply_nterror(req, status);
2582 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2583 DEBUG(0,("Attempt to create file (%s) with volid set - "
2584 "please report this\n",
2585 smb_fname_str_dbg(smb_fname)));
2588 status = SMB_VFS_CREATE_FILE(
2591 0, /* root_dir_fid */
2592 smb_fname, /* fname */
2593 access_mask, /* access_mask */
2594 share_mode, /* share_access */
2595 create_disposition, /* create_disposition*/
2596 create_options, /* create_options */
2597 fattr, /* file_attributes */
2598 oplock_request, /* oplock_request */
2600 0, /* allocation_size */
2601 0, /* private_flags */
2606 NULL, NULL); /* create context */
2608 if (!NT_STATUS_IS_OK(status)) {
2609 if (open_was_deferred(req->xconn, req->mid)) {
2610 /* We have re-scheduled this call. */
2613 reply_openerror(req, status);
2617 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2618 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2619 if (!NT_STATUS_IS_OK(status)) {
2620 END_PROFILE(SMBcreate);
2624 reply_outbuf(req, 1, 0);
2625 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2627 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2628 SCVAL(req->outbuf,smb_flg,
2629 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2632 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2633 SCVAL(req->outbuf,smb_flg,
2634 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2637 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2638 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2639 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2640 (unsigned int)fattr));
2643 TALLOC_FREE(smb_fname);
2644 END_PROFILE(SMBcreate);
2648 /****************************************************************************
2649 Reply to a create temporary file.
2650 ****************************************************************************/
2652 void reply_ctemp(struct smb_request *req)
2654 connection_struct *conn = req->conn;
2655 struct smb_filename *smb_fname = NULL;
2656 char *wire_name = NULL;
2665 TALLOC_CTX *ctx = talloc_tos();
2667 START_PROFILE(SMBctemp);
2670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2674 fattr = SVAL(req->vwv+0, 0);
2675 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2677 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2678 STR_TERMINATE, &status);
2679 if (!NT_STATUS_IS_OK(status)) {
2680 reply_nterror(req, status);
2684 for (i = 0; i < 10; i++) {
2686 fname = talloc_asprintf(ctx,
2689 generate_random_str_list(ctx, 5, "0123456789"));
2691 fname = talloc_asprintf(ctx,
2693 generate_random_str_list(ctx, 5, "0123456789"));
2697 reply_nterror(req, NT_STATUS_NO_MEMORY);
2701 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2702 status = filename_convert(ctx, conn,
2703 req->flags2 & FLAGS2_DFS_PATHNAMES,
2708 if (!NT_STATUS_IS_OK(status)) {
2709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2710 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2711 ERRSRV, ERRbadpath);
2714 reply_nterror(req, status);
2718 /* Create the file. */
2719 status = SMB_VFS_CREATE_FILE(
2722 0, /* root_dir_fid */
2723 smb_fname, /* fname */
2724 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2725 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2726 FILE_CREATE, /* create_disposition*/
2727 0, /* create_options */
2728 fattr, /* file_attributes */
2729 oplock_request, /* oplock_request */
2731 0, /* allocation_size */
2732 0, /* private_flags */
2737 NULL, NULL); /* create context */
2739 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2741 TALLOC_FREE(smb_fname);
2745 if (!NT_STATUS_IS_OK(status)) {
2746 if (open_was_deferred(req->xconn, req->mid)) {
2747 /* We have re-scheduled this call. */
2750 reply_openerror(req, status);
2758 /* Collision after 10 times... */
2759 reply_nterror(req, status);
2763 reply_outbuf(req, 1, 0);
2764 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2766 /* the returned filename is relative to the directory */
2767 s = strrchr_m(fsp->fsp_name->base_name, '/');
2769 s = fsp->fsp_name->base_name;
2775 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2776 thing in the byte section. JRA */
2777 SSVALS(p, 0, -1); /* what is this? not in spec */
2779 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2781 reply_nterror(req, NT_STATUS_NO_MEMORY);
2785 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2786 SCVAL(req->outbuf, smb_flg,
2787 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2790 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2791 SCVAL(req->outbuf, smb_flg,
2792 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2795 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2796 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2797 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2799 TALLOC_FREE(smb_fname);
2800 TALLOC_FREE(wire_name);
2801 END_PROFILE(SMBctemp);
2805 /*******************************************************************
2806 Check if a user is allowed to rename a file.
2807 ********************************************************************/
2809 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2812 if (!CAN_WRITE(conn)) {
2813 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2816 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2817 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2818 /* Only bother to read the DOS attribute if we might deny the
2819 rename on the grounds of attribute mismatch. */
2820 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2821 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2822 return NT_STATUS_NO_SUCH_FILE;
2826 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2827 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2828 return NT_STATUS_OK;
2831 /* If no pathnames are open below this
2832 directory, allow the rename. */
2834 if (lp_strict_rename(SNUM(conn))) {
2836 * Strict rename, check open file db.
2838 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2839 return NT_STATUS_ACCESS_DENIED;
2841 } else if (file_find_subpath(fsp)) {
2843 * No strict rename, just look in local process.
2845 return NT_STATUS_ACCESS_DENIED;
2847 return NT_STATUS_OK;
2850 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2851 return NT_STATUS_OK;
2854 return NT_STATUS_ACCESS_DENIED;
2857 /*******************************************************************
2858 * unlink a file with all relevant access checks
2859 *******************************************************************/
2861 static NTSTATUS do_unlink(connection_struct *conn,
2862 struct smb_request *req,
2863 struct smb_filename *smb_fname,
2868 uint32_t dirtype_orig = dirtype;
2871 bool posix_paths = (req != NULL && req->posix_pathnames);
2873 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2874 smb_fname_str_dbg(smb_fname),
2877 if (!CAN_WRITE(conn)) {
2878 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2882 ret = SMB_VFS_LSTAT(conn, smb_fname);
2884 ret = SMB_VFS_STAT(conn, smb_fname);
2887 return map_nt_error_from_unix(errno);
2890 fattr = dos_mode(conn, smb_fname);
2892 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2893 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2896 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2898 return NT_STATUS_NO_SUCH_FILE;
2901 if (!dir_check_ftype(fattr, dirtype)) {
2902 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2903 return NT_STATUS_FILE_IS_A_DIRECTORY;
2905 return NT_STATUS_NO_SUCH_FILE;
2908 if (dirtype_orig & 0x8000) {
2909 /* These will never be set for POSIX. */
2910 return NT_STATUS_NO_SUCH_FILE;
2914 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2915 return NT_STATUS_FILE_IS_A_DIRECTORY;
2918 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2919 return NT_STATUS_NO_SUCH_FILE;
2922 if (dirtype & 0xFF00) {
2923 /* These will never be set for POSIX. */
2924 return NT_STATUS_NO_SUCH_FILE;
2929 return NT_STATUS_NO_SUCH_FILE;
2932 /* Can't delete a directory. */
2933 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2934 return NT_STATUS_FILE_IS_A_DIRECTORY;
2939 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2940 return NT_STATUS_OBJECT_NAME_INVALID;
2941 #endif /* JRATEST */
2943 /* On open checks the open itself will check the share mode, so
2944 don't do it here as we'll get it wrong. */
2946 status = SMB_VFS_CREATE_FILE
2949 0, /* root_dir_fid */
2950 smb_fname, /* fname */
2951 DELETE_ACCESS, /* access_mask */
2952 FILE_SHARE_NONE, /* share_access */
2953 FILE_OPEN, /* create_disposition*/
2954 FILE_NON_DIRECTORY_FILE, /* create_options */
2955 /* file_attributes */
2956 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2957 FILE_ATTRIBUTE_NORMAL,
2958 0, /* oplock_request */
2960 0, /* allocation_size */
2961 0, /* private_flags */
2966 NULL, NULL); /* create context */
2968 if (!NT_STATUS_IS_OK(status)) {
2969 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2970 nt_errstr(status)));
2974 status = can_set_delete_on_close(fsp, fattr);
2975 if (!NT_STATUS_IS_OK(status)) {
2976 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2978 smb_fname_str_dbg(smb_fname),
2979 nt_errstr(status)));
2980 close_file(req, fsp, NORMAL_CLOSE);
2984 /* The set is across all open files on this dev/inode pair. */
2985 if (!set_delete_on_close(fsp, True,
2986 conn->session_info->security_token,
2987 conn->session_info->unix_token)) {
2988 close_file(req, fsp, NORMAL_CLOSE);
2989 return NT_STATUS_ACCESS_DENIED;
2992 return close_file(req, fsp, NORMAL_CLOSE);
2995 /****************************************************************************
2996 The guts of the unlink command, split out so it may be called by the NT SMB
2998 ****************************************************************************/
3000 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3001 uint32_t dirtype, struct smb_filename *smb_fname,
3004 char *fname_dir = NULL;
3005 char *fname_mask = NULL;
3007 NTSTATUS status = NT_STATUS_OK;
3008 struct smb_filename *smb_fname_dir = NULL;
3009 TALLOC_CTX *ctx = talloc_tos();
3011 /* Split up the directory from the filename/mask. */
3012 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3013 &fname_dir, &fname_mask);
3014 if (!NT_STATUS_IS_OK(status)) {
3019 * We should only check the mangled cache
3020 * here if unix_convert failed. This means
3021 * that the path in 'mask' doesn't exist
3022 * on the file system and so we need to look
3023 * for a possible mangle. This patch from
3024 * Tine Smukavec <valentin.smukavec@hermes.si>.
3027 if (!VALID_STAT(smb_fname->st) &&
3028 mangle_is_mangled(fname_mask, conn->params)) {
3029 char *new_mask = NULL;
3030 mangle_lookup_name_from_8_3(ctx, fname_mask,
3031 &new_mask, conn->params);
3033 TALLOC_FREE(fname_mask);
3034 fname_mask = new_mask;
3041 * Only one file needs to be unlinked. Append the mask back
3042 * onto the directory.
3044 TALLOC_FREE(smb_fname->base_name);
3045 if (ISDOT(fname_dir)) {
3046 /* Ensure we use canonical names on open. */
3047 smb_fname->base_name = talloc_asprintf(smb_fname,
3051 smb_fname->base_name = talloc_asprintf(smb_fname,
3056 if (!smb_fname->base_name) {
3057 status = NT_STATUS_NO_MEMORY;
3061 dirtype = FILE_ATTRIBUTE_NORMAL;
3064 status = check_name(conn, smb_fname->base_name);
3065 if (!NT_STATUS_IS_OK(status)) {
3069 status = do_unlink(conn, req, smb_fname, dirtype);
3070 if (!NT_STATUS_IS_OK(status)) {
3076 struct smb_Dir *dir_hnd = NULL;
3078 const char *dname = NULL;
3079 char *talloced = NULL;
3081 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3082 status = NT_STATUS_OBJECT_NAME_INVALID;
3086 dirtype = FILE_ATTRIBUTE_NORMAL;
3089 if (strequal(fname_mask,"????????.???")) {
3090 TALLOC_FREE(fname_mask);
3091 fname_mask = talloc_strdup(ctx, "*");
3093 status = NT_STATUS_NO_MEMORY;
3098 status = check_name(conn, fname_dir);
3099 if (!NT_STATUS_IS_OK(status)) {
3103 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3108 if (smb_fname_dir == NULL) {
3109 status = NT_STATUS_NO_MEMORY;
3113 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3115 if (dir_hnd == NULL) {
3116 status = map_nt_error_from_unix(errno);
3120 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3121 the pattern matches against the long name, otherwise the short name
3122 We don't implement this yet XXXX
3125 status = NT_STATUS_NO_SUCH_FILE;
3127 while ((dname = ReadDirName(dir_hnd, &offset,
3128 &smb_fname->st, &talloced))) {
3129 TALLOC_CTX *frame = talloc_stackframe();
3131 if (!is_visible_file(conn, fname_dir, dname,
3132 &smb_fname->st, true)) {
3134 TALLOC_FREE(talloced);
3138 /* Quick check for "." and ".." */
3139 if (ISDOT(dname) || ISDOTDOT(dname)) {
3141 TALLOC_FREE(talloced);
3145 if(!mask_match(dname, fname_mask,
3146 conn->case_sensitive)) {
3148 TALLOC_FREE(talloced);
3152 TALLOC_FREE(smb_fname->base_name);
3153 if (ISDOT(fname_dir)) {
3154 /* Ensure we use canonical names on open. */
3155 smb_fname->base_name =
3156 talloc_asprintf(smb_fname, "%s",
3159 smb_fname->base_name =
3160 talloc_asprintf(smb_fname, "%s/%s",
3164 if (!smb_fname->base_name) {
3165 TALLOC_FREE(dir_hnd);
3166 status = NT_STATUS_NO_MEMORY;
3168 TALLOC_FREE(talloced);
3172 status = check_name(conn, smb_fname->base_name);
3173 if (!NT_STATUS_IS_OK(status)) {
3174 TALLOC_FREE(dir_hnd);
3176 TALLOC_FREE(talloced);
3180 status = do_unlink(conn, req, smb_fname, dirtype);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 TALLOC_FREE(dir_hnd);
3184 TALLOC_FREE(talloced);
3189 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3190 smb_fname->base_name));
3193 TALLOC_FREE(talloced);
3195 TALLOC_FREE(dir_hnd);
3198 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3199 status = map_nt_error_from_unix(errno);
3203 TALLOC_FREE(smb_fname_dir);
3204 TALLOC_FREE(fname_dir);
3205 TALLOC_FREE(fname_mask);
3209 /****************************************************************************
3211 ****************************************************************************/
3213 void reply_unlink(struct smb_request *req)
3215 connection_struct *conn = req->conn;
3217 struct smb_filename *smb_fname = NULL;
3220 bool path_contains_wcard = False;
3221 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3222 ucf_flags_from_smb_request(req);
3223 TALLOC_CTX *ctx = talloc_tos();
3225 START_PROFILE(SMBunlink);
3228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3232 dirtype = SVAL(req->vwv+0, 0);
3234 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3235 STR_TERMINATE, &status,
3236 &path_contains_wcard);
3237 if (!NT_STATUS_IS_OK(status)) {
3238 reply_nterror(req, status);
3242 status = filename_convert(ctx, conn,
3243 req->flags2 & FLAGS2_DFS_PATHNAMES,
3246 &path_contains_wcard,
3248 if (!NT_STATUS_IS_OK(status)) {
3249 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3250 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3251 ERRSRV, ERRbadpath);
3254 reply_nterror(req, status);
3258 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3260 status = unlink_internals(conn, req, dirtype, smb_fname,
3261 path_contains_wcard);
3262 if (!NT_STATUS_IS_OK(status)) {
3263 if (open_was_deferred(req->xconn, req->mid)) {
3264 /* We have re-scheduled this call. */
3267 reply_nterror(req, status);
3271 reply_outbuf(req, 0, 0);
3273 TALLOC_FREE(smb_fname);
3274 END_PROFILE(SMBunlink);
3278 /****************************************************************************
3280 ****************************************************************************/
3282 static void fail_readraw(void)
3284 const char *errstr = talloc_asprintf(talloc_tos(),
3285 "FAIL ! reply_readbraw: socket write fail (%s)",
3290 exit_server_cleanly(errstr);
3293 /****************************************************************************
3294 Fake (read/write) sendfile. Returns -1 on read or write fail.
3295 ****************************************************************************/
3297 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3298 off_t startpos, size_t nread)
3301 size_t tosend = nread;
3308 bufsize = MIN(nread, 65536);
3310 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3314 while (tosend > 0) {
3318 cur_read = MIN(tosend, bufsize);
3319 ret = read_file(fsp,buf,startpos,cur_read);
3325 /* If we had a short read, fill with zeros. */
3326 if (ret < cur_read) {
3327 memset(buf + ret, '\0', cur_read - ret);
3330 ret = write_data(xconn->transport.sock, buf, cur_read);
3331 if (ret != cur_read) {
3332 int saved_errno = errno;
3334 * Try and give an error message saying what
3337 DEBUG(0, ("write_data failed for client %s. "
3339 smbXsrv_connection_dbg(xconn),
3340 strerror(saved_errno)));
3342 errno = saved_errno;
3346 startpos += cur_read;
3350 return (ssize_t)nread;
3353 /****************************************************************************
3354 Deal with the case of sendfile reading less bytes from the file than
3355 requested. Fill with zeros (all we can do). Returns 0 on success
3356 ****************************************************************************/
3358 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3364 #define SHORT_SEND_BUFSIZE 1024
3365 if (nread < headersize) {
3366 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3367 "header for file %s (%s). Terminating\n",
3368 fsp_str_dbg(fsp), strerror(errno)));
3372 nread -= headersize;
3374 if (nread < smb_maxcnt) {
3375 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3377 DEBUG(0,("sendfile_short_send: malloc failed "
3378 "for file %s (%s). Terminating\n",
3379 fsp_str_dbg(fsp), strerror(errno)));
3383 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3384 "with zeros !\n", fsp_str_dbg(fsp)));
3386 while (nread < smb_maxcnt) {
3388 * We asked for the real file size and told sendfile
3389 * to not go beyond the end of the file. But it can
3390 * happen that in between our fstat call and the
3391 * sendfile call the file was truncated. This is very
3392 * bad because we have already announced the larger
3393 * number of bytes to the client.
3395 * The best we can do now is to send 0-bytes, just as
3396 * a read from a hole in a sparse file would do.
3398 * This should happen rarely enough that I don't care
3399 * about efficiency here :-)
3404 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3405 ret = write_data(xconn->transport.sock, buf, to_write);
3406 if (ret != to_write) {
3407 int saved_errno = errno;
3409 * Try and give an error message saying what
3412 DEBUG(0, ("write_data failed for client %s. "
3414 smbXsrv_connection_dbg(xconn),
3415 strerror(saved_errno)));
3416 errno = saved_errno;
3427 /****************************************************************************
3428 Return a readbraw error (4 bytes of zero).
3429 ****************************************************************************/
3431 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3437 smbd_lock_socket(xconn);
3438 if (write_data(xconn->transport.sock,header,4) != 4) {
3439 int saved_errno = errno;
3441 * Try and give an error message saying what
3444 DEBUG(0, ("write_data failed for client %s. "
3446 smbXsrv_connection_dbg(xconn),
3447 strerror(saved_errno)));
3448 errno = saved_errno;
3452 smbd_unlock_socket(xconn);
3455 /****************************************************************************
3456 Use sendfile in readbraw.
3457 ****************************************************************************/
3459 static void send_file_readbraw(connection_struct *conn,
3460 struct smb_request *req,
3466 struct smbXsrv_connection *xconn = req->xconn;
3467 char *outbuf = NULL;
3471 * We can only use sendfile on a non-chained packet
3472 * but we can use on a non-oplocked file. tridge proved this
3473 * on a train in Germany :-). JRA.
3474 * reply_readbraw has already checked the length.
3477 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3478 (fsp->wcp == NULL) &&
3479 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3480 ssize_t sendfile_read = -1;
3482 DATA_BLOB header_blob;
3484 _smb_setlen(header,nread);
3485 header_blob = data_blob_const(header, 4);
3487 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3488 &header_blob, startpos,
3490 if (sendfile_read == -1) {
3491 /* Returning ENOSYS means no data at all was sent.
3492 * Do this as a normal read. */
3493 if (errno == ENOSYS) {
3494 goto normal_readbraw;
3498 * Special hack for broken Linux with no working sendfile. If we
3499 * return EINTR we sent the header but not the rest of the data.
3500 * Fake this up by doing read/write calls.
3502 if (errno == EINTR) {
3503 /* Ensure we don't do this again. */
3504 set_use_sendfile(SNUM(conn), False);
3505 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3507 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3508 DEBUG(0,("send_file_readbraw: "
3509 "fake_sendfile failed for "
3513 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3518 DEBUG(0,("send_file_readbraw: sendfile failed for "
3519 "file %s (%s). Terminating\n",
3520 fsp_str_dbg(fsp), strerror(errno)));
3521 exit_server_cleanly("send_file_readbraw sendfile failed");
3522 } else if (sendfile_read == 0) {
3524 * Some sendfile implementations return 0 to indicate
3525 * that there was a short read, but nothing was
3526 * actually written to the socket. In this case,
3527 * fallback to the normal read path so the header gets
3528 * the correct byte count.
3530 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3531 "bytes falling back to the normal read: "
3532 "%s\n", fsp_str_dbg(fsp)));
3533 goto normal_readbraw;
3536 /* Deal with possible short send. */
3537 if (sendfile_read != 4+nread) {
3538 ret = sendfile_short_send(xconn, fsp,
3539 sendfile_read, 4, nread);
3549 outbuf = talloc_array(NULL, char, nread+4);
3551 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3552 (unsigned)(nread+4)));
3553 reply_readbraw_error(xconn);
3558 ret = read_file(fsp,outbuf+4,startpos,nread);
3559 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3568 _smb_setlen(outbuf,ret);
3569 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3570 int saved_errno = errno;
3572 * Try and give an error message saying what
3575 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3576 smbXsrv_connection_dbg(xconn),
3577 strerror(saved_errno)));
3578 errno = saved_errno;
3583 TALLOC_FREE(outbuf);
3586 /****************************************************************************
3587 Reply to a readbraw (core+ protocol).
3588 ****************************************************************************/
3590 void reply_readbraw(struct smb_request *req)
3592 connection_struct *conn = req->conn;
3593 struct smbXsrv_connection *xconn = req->xconn;
3594 ssize_t maxcount,mincount;
3598 struct lock_struct lock;
3601 START_PROFILE(SMBreadbraw);
3603 if (srv_is_signing_active(xconn) || req->encrypted) {
3604 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3605 "raw reads/writes are disallowed.");
3609 reply_readbraw_error(xconn);
3610 END_PROFILE(SMBreadbraw);
3614 if (xconn->smb1.echo_handler.trusted_fde) {
3615 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3616 "'async smb echo handler = yes'\n"));
3617 reply_readbraw_error(xconn);
3618 END_PROFILE(SMBreadbraw);
3623 * Special check if an oplock break has been issued
3624 * and the readraw request croses on the wire, we must
3625 * return a zero length response here.
3628 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3631 * We have to do a check_fsp by hand here, as
3632 * we must always return 4 zero bytes on error,
3636 if (!fsp || !conn || conn != fsp->conn ||
3637 req->vuid != fsp->vuid ||
3638 fsp->is_directory || fsp->fh->fd == -1) {
3640 * fsp could be NULL here so use the value from the packet. JRA.
3642 DEBUG(3,("reply_readbraw: fnum %d not valid "
3644 (int)SVAL(req->vwv+0, 0)));
3645 reply_readbraw_error(xconn);
3646 END_PROFILE(SMBreadbraw);
3650 /* Do a "by hand" version of CHECK_READ. */
3651 if (!(fsp->can_read ||
3652 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3653 (fsp->access_mask & FILE_EXECUTE)))) {
3654 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3655 (int)SVAL(req->vwv+0, 0)));
3656 reply_readbraw_error(xconn);
3657 END_PROFILE(SMBreadbraw);
3661 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3663 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3664 if(req->wct == 10) {
3666 * This is a large offset (64 bit) read.
3669 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3672 DEBUG(0,("reply_readbraw: negative 64 bit "
3673 "readraw offset (%.0f) !\n",
3674 (double)startpos ));
3675 reply_readbraw_error(xconn);
3676 END_PROFILE(SMBreadbraw);
3681 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3682 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3684 /* ensure we don't overrun the packet size */
3685 maxcount = MIN(65535,maxcount);
3687 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3688 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3691 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3692 reply_readbraw_error(xconn);
3693 END_PROFILE(SMBreadbraw);
3697 if (fsp_stat(fsp) == 0) {
3698 size = fsp->fsp_name->st.st_ex_size;
3701 if (startpos >= size) {
3704 nread = MIN(maxcount,(size - startpos));
3707 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3708 if (nread < mincount)
3712 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3713 "min=%lu nread=%lu\n",
3714 fsp_fnum_dbg(fsp), (double)startpos,
3715 (unsigned long)maxcount,
3716 (unsigned long)mincount,
3717 (unsigned long)nread ) );
3719 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3721 DEBUG(5,("reply_readbraw finished\n"));
3723 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3725 END_PROFILE(SMBreadbraw);
3730 #define DBGC_CLASS DBGC_LOCKING
3732 /****************************************************************************
3733 Reply to a lockread (core+ protocol).
3734 ****************************************************************************/
3736 void reply_lockread(struct smb_request *req)
3738 connection_struct *conn = req->conn;
3746 struct byte_range_lock *br_lck = NULL;
3748 struct smbXsrv_connection *xconn = req->xconn;
3750 START_PROFILE(SMBlockread);
3753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3754 END_PROFILE(SMBlockread);
3758 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3760 if (!check_fsp(conn, req, fsp)) {
3761 END_PROFILE(SMBlockread);
3765 if (!CHECK_READ(fsp,req)) {
3766 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3767 END_PROFILE(SMBlockread);
3771 numtoread = SVAL(req->vwv+1, 0);
3772 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3775 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3776 * protocol request that predates the read/write lock concept.
3777 * Thus instead of asking for a read lock here we need to ask
3778 * for a write lock. JRA.
3779 * Note that the requested lock size is unaffected by max_send.
3782 br_lck = do_lock(req->sconn->msg_ctx,
3784 (uint64_t)req->smbpid,
3785 (uint64_t)numtoread,
3789 False, /* Non-blocking lock. */
3792 TALLOC_FREE(br_lck);
3794 if (NT_STATUS_V(status)) {
3795 reply_nterror(req, status);
3796 END_PROFILE(SMBlockread);
3801 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3803 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3805 if (numtoread > maxtoread) {
3806 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3807 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3808 (unsigned int)numtoread, (unsigned int)maxtoread,
3809 (unsigned int)xconn->smb1.sessions.max_send));
3810 numtoread = maxtoread;
3813 reply_outbuf(req, 5, numtoread + 3);
3815 data = smb_buf(req->outbuf) + 3;
3817 nread = read_file(fsp,data,startpos,numtoread);
3820 reply_nterror(req, map_nt_error_from_unix(errno));
3821 END_PROFILE(SMBlockread);
3825 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3827 SSVAL(req->outbuf,smb_vwv0,nread);
3828 SSVAL(req->outbuf,smb_vwv5,nread+3);
3829 p = smb_buf(req->outbuf);
3830 SCVAL(p,0,0); /* pad byte. */
3833 DEBUG(3,("lockread %s num=%d nread=%d\n",
3834 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3836 END_PROFILE(SMBlockread);
3841 #define DBGC_CLASS DBGC_ALL
3843 /****************************************************************************
3845 ****************************************************************************/
3847 void reply_read(struct smb_request *req)
3849 connection_struct *conn = req->conn;
3856 struct lock_struct lock;
3857 struct smbXsrv_connection *xconn = req->xconn;
3859 START_PROFILE(SMBread);
3862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3863 END_PROFILE(SMBread);
3867 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3869 if (!check_fsp(conn, req, fsp)) {
3870 END_PROFILE(SMBread);
3874 if (!CHECK_READ(fsp,req)) {
3875 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3876 END_PROFILE(SMBread);
3880 numtoread = SVAL(req->vwv+1, 0);
3881 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3884 * The requested read size cannot be greater than max_send. JRA.
3886 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3888 if (numtoread > maxtoread) {
3889 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3890 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3891 (unsigned int)numtoread, (unsigned int)maxtoread,
3892 (unsigned int)xconn->smb1.sessions.max_send));
3893 numtoread = maxtoread;
3896 reply_outbuf(req, 5, numtoread+3);
3898 data = smb_buf(req->outbuf) + 3;
3900 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3901 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3904 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3905 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3906 END_PROFILE(SMBread);
3911 nread = read_file(fsp,data,startpos,numtoread);
3914 reply_nterror(req, map_nt_error_from_unix(errno));
3918 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3920 SSVAL(req->outbuf,smb_vwv0,nread);
3921 SSVAL(req->outbuf,smb_vwv5,nread+3);
3922 SCVAL(smb_buf(req->outbuf),0,1);
3923 SSVAL(smb_buf(req->outbuf),1,nread);
3925 DEBUG(3, ("read %s num=%d nread=%d\n",
3926 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3929 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3931 END_PROFILE(SMBread);
3935 /****************************************************************************
3937 ****************************************************************************/
3939 int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3943 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3946 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3948 SCVAL(outbuf,smb_vwv0,0xFF);
3949 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3950 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3951 SSVAL(outbuf,smb_vwv6,
3952 (smb_wct - 4) /* offset from smb header to wct */
3953 + 1 /* the wct field */
3954 + 12 * sizeof(uint16_t) /* vwv */
3955 + 2 /* the buflen field */
3956 + 1); /* padding byte */
3957 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3958 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3959 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3960 _smb_setlen_large(outbuf,
3961 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3965 /****************************************************************************
3966 Reply to a read and X - possibly using sendfile.
3967 ****************************************************************************/
3969 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3970 files_struct *fsp, off_t startpos,
3973 struct smbXsrv_connection *xconn = req->xconn;
3975 struct lock_struct lock;
3976 int saved_errno = 0;
3978 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3979 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3982 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3983 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3988 * We can only use sendfile on a non-chained packet
3989 * but we can use on a non-oplocked file. tridge proved this
3990 * on a train in Germany :-). JRA.
3993 if (!req_is_in_chain(req) &&
3995 (fsp->base_fsp == NULL) &&
3996 (fsp->wcp == NULL) &&
3997 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3998 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4001 if(fsp_stat(fsp) == -1) {
4002 reply_nterror(req, map_nt_error_from_unix(errno));
4006 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4007 (startpos > fsp->fsp_name->st.st_ex_size) ||
4008 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4010 * We already know that we would do a short read, so don't
4011 * try the sendfile() path.
4013 goto nosendfile_read;
4017 * Set up the packet header before send. We
4018 * assume here the sendfile will work (get the
4019 * correct amount of data).
4022 header = data_blob_const(headerbuf, sizeof(headerbuf));
4024 construct_reply_common_req(req, (char *)headerbuf);
4025 setup_readX_header((char *)headerbuf, smb_maxcnt);
4027 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4028 startpos, smb_maxcnt);
4030 saved_errno = errno;
4032 /* Returning ENOSYS means no data at all was sent.
4033 Do this as a normal read. */
4034 if (errno == ENOSYS) {
4039 * Special hack for broken Linux with no working sendfile. If we
4040 * return EINTR we sent the header but not the rest of the data.
4041 * Fake this up by doing read/write calls.
4044 if (errno == EINTR) {
4045 /* Ensure we don't do this again. */
4046 set_use_sendfile(SNUM(conn), False);
4047 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4048 nread = fake_sendfile(xconn, fsp, startpos,
4051 saved_errno = errno;
4052 DEBUG(0,("send_file_readX: "
4053 "fake_sendfile failed for "
4054 "file %s (%s) for client %s. "
4057 smbXsrv_connection_dbg(xconn),
4058 strerror(saved_errno)));
4059 errno = saved_errno;
4060 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4062 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4063 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4064 /* No outbuf here means successful sendfile. */
4068 DEBUG(0,("send_file_readX: sendfile failed for file "
4069 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4071 exit_server_cleanly("send_file_readX sendfile failed");
4072 } else if (nread == 0) {
4074 * Some sendfile implementations return 0 to indicate
4075 * that there was a short read, but nothing was
4076 * actually written to the socket. In this case,
4077 * fallback to the normal read path so the header gets
4078 * the correct byte count.
4080 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4081 "falling back to the normal read: %s\n",
4086 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4087 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4089 /* Deal with possible short send. */
4090 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4093 ret = sendfile_short_send(xconn, fsp, nread,
4094 sizeof(headerbuf), smb_maxcnt);
4097 r = "send_file_readX: sendfile_short_send failed";
4098 DEBUG(0,("%s for file %s (%s).\n",
4099 r, fsp_str_dbg(fsp), strerror(errno)));
4100 exit_server_cleanly(r);
4103 /* No outbuf here means successful sendfile. */
4104 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4105 SMB_PERFCOUNT_END(&req->pcd);
4111 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4112 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4115 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4116 (startpos > fsp->fsp_name->st.st_ex_size) ||
4117 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4119 * We already know that we would do a short
4120 * read, so don't try the sendfile() path.
4122 goto nosendfile_read;
4125 construct_reply_common_req(req, (char *)headerbuf);
4126 setup_readX_header((char *)headerbuf, smb_maxcnt);
4128 /* Send out the header. */
4129 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4131 if (ret != sizeof(headerbuf)) {
4132 saved_errno = errno;
4134 * Try and give an error message saying what
4137 DEBUG(0,("send_file_readX: write_data failed for file "
4138 "%s (%s) for client %s. Terminating\n",
4140 smbXsrv_connection_dbg(xconn),
4141 strerror(saved_errno)));
4142 errno = saved_errno;
4143 exit_server_cleanly("send_file_readX sendfile failed");
4145 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4147 saved_errno = errno;
4148 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4149 "%s (%s) for client %s. Terminating\n",
4151 smbXsrv_connection_dbg(xconn),
4152 strerror(saved_errno)));
4153 errno = saved_errno;
4154 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4161 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4162 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4163 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4165 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4166 startpos, smb_maxcnt);
4167 saved_errno = errno;
4169 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4172 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4176 setup_readX_header((char *)req->outbuf, nread);
4178 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4179 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4183 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4184 TALLOC_FREE(req->outbuf);
4188 /****************************************************************************
4189 Work out how much space we have for a read return.
4190 ****************************************************************************/
4192 static size_t calc_max_read_pdu(const struct smb_request *req)
4194 struct smbXsrv_connection *xconn = req->xconn;
4196 if (xconn->protocol < PROTOCOL_NT1) {
4197 return xconn->smb1.sessions.max_send;
4200 if (!lp_large_readwrite()) {
4201 return xconn->smb1.sessions.max_send;
4204 if (req_is_in_chain(req)) {
4205 return xconn->smb1.sessions.max_send;
4208 if (req->encrypted) {
4210 * Don't take encrypted traffic up to the
4211 * limit. There are padding considerations
4212 * that make that tricky.
4214 return xconn->smb1.sessions.max_send;
4217 if (srv_is_signing_active(xconn)) {
4221 if (!lp_unix_extensions()) {
4226 * We can do ultra-large POSIX reads.
4231 /****************************************************************************
4232 Calculate how big a read can be. Copes with all clients. It's always
4233 safe to return a short read - Windows does this.
4234 ****************************************************************************/
4236 static size_t calc_read_size(const struct smb_request *req,
4240 struct smbXsrv_connection *xconn = req->xconn;
4241 size_t max_pdu = calc_max_read_pdu(req);
4242 size_t total_size = 0;
4243 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4244 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4247 * Windows explicitly ignores upper size of 0xFFFF.
4248 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4249 * We must do the same as these will never fit even in
4250 * an extended size NetBIOS packet.
4252 if (upper_size == 0xFFFF) {
4256 if (xconn->protocol < PROTOCOL_NT1) {
4260 total_size = ((upper_size<<16) | lower_size);
4263 * LARGE_READX test shows it's always safe to return
4264 * a short read. Windows does so.
4266 return MIN(total_size, max_len);
4269 /****************************************************************************
4270 Reply to a read and X.
4271 ****************************************************************************/
4273 void reply_read_and_X(struct smb_request *req)
4275 connection_struct *conn = req->conn;
4280 bool big_readX = False;
4282 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4285 START_PROFILE(SMBreadX);
4287 if ((req->wct != 10) && (req->wct != 12)) {
4288 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4292 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4293 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4294 smb_maxcnt = SVAL(req->vwv+5, 0);
4296 /* If it's an IPC, pass off the pipe handler. */
4298 reply_pipe_read_and_X(req);
4299 END_PROFILE(SMBreadX);
4303 if (!check_fsp(conn, req, fsp)) {
4304 END_PROFILE(SMBreadX);
4308 if (!CHECK_READ(fsp,req)) {
4309 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4310 END_PROFILE(SMBreadX);
4314 upper_size = SVAL(req->vwv+7, 0);
4315 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4316 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4318 * This is a heuristic to avoid keeping large
4319 * outgoing buffers around over long-lived aio
4325 if (req->wct == 12) {
4327 * This is a large offset (64 bit) read.
4329 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4334 NTSTATUS status = schedule_aio_read_and_X(conn,
4339 if (NT_STATUS_IS_OK(status)) {
4340 /* Read scheduled - we're done. */
4343 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4344 /* Real error - report to client. */
4345 END_PROFILE(SMBreadX);
4346 reply_nterror(req, status);
4349 /* NT_STATUS_RETRY - fall back to sync read. */
4352 smbd_lock_socket(req->xconn);
4353 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4354 smbd_unlock_socket(req->xconn);
4357 END_PROFILE(SMBreadX);
4361 /****************************************************************************
4362 Error replies to writebraw must have smb_wct == 1. Fix this up.
4363 ****************************************************************************/
4365 void error_to_writebrawerr(struct smb_request *req)
4367 uint8_t *old_outbuf = req->outbuf;
4369 reply_outbuf(req, 1, 0);
4371 memcpy(req->outbuf, old_outbuf, smb_size);
4372 TALLOC_FREE(old_outbuf);
4375 /****************************************************************************
4376 Read 4 bytes of a smb packet and return the smb length of the packet.
4377 Store the result in the buffer. This version of the function will
4378 never return a session keepalive (length of zero).
4379 Timeout is in milliseconds.
4380 ****************************************************************************/
4382 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4385 uint8_t msgtype = NBSSkeepalive;
4387 while (msgtype == NBSSkeepalive) {
4390 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4392 if (!NT_STATUS_IS_OK(status)) {
4393 char addr[INET6_ADDRSTRLEN];
4394 /* Try and give an error message
4395 * saying what client failed. */
4396 DEBUG(0, ("read_fd_with_timeout failed for "
4397 "client %s read error = %s.\n",
4398 get_peer_addr(fd,addr,sizeof(addr)),
4399 nt_errstr(status)));
4403 msgtype = CVAL(inbuf, 0);
4406 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4407 (unsigned long)len));
4409 return NT_STATUS_OK;
4412 /****************************************************************************
4413 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4414 ****************************************************************************/
4416 void reply_writebraw(struct smb_request *req)
4418 connection_struct *conn = req->conn;
4419 struct smbXsrv_connection *xconn = req->xconn;
4422 ssize_t total_written=0;
4423 size_t numtowrite=0;
4426 const char *data=NULL;
4429 struct lock_struct lock;
4432 START_PROFILE(SMBwritebraw);
4435 * If we ever reply with an error, it must have the SMB command
4436 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4439 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4441 if (srv_is_signing_active(xconn)) {
4442 END_PROFILE(SMBwritebraw);
4443 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4444 "raw reads/writes are disallowed.");
4447 if (req->wct < 12) {
4448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4449 error_to_writebrawerr(req);
4450 END_PROFILE(SMBwritebraw);
4454 if (xconn->smb1.echo_handler.trusted_fde) {
4455 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4456 "'async smb echo handler = yes'\n"));
4457 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4458 error_to_writebrawerr(req);
4459 END_PROFILE(SMBwritebraw);
4463 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4464 if (!check_fsp(conn, req, fsp)) {
4465 error_to_writebrawerr(req);
4466 END_PROFILE(SMBwritebraw);
4470 if (!CHECK_WRITE(fsp)) {
4471 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4472 error_to_writebrawerr(req);
4473 END_PROFILE(SMBwritebraw);
4477 tcount = IVAL(req->vwv+1, 0);
4478 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4479 write_through = BITSETW(req->vwv+7,0);
4481 /* We have to deal with slightly different formats depending
4482 on whether we are using the core+ or lanman1.0 protocol */
4484 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4485 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4486 data = smb_buf_const(req->inbuf);
4488 numtowrite = SVAL(req->vwv+10, 0);
4489 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4492 /* Ensure we don't write bytes past the end of this packet. */
4493 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4495 error_to_writebrawerr(req);
4496 END_PROFILE(SMBwritebraw);
4500 if (!fsp->print_file) {
4501 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4502 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4505 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4506 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4507 error_to_writebrawerr(req);
4508 END_PROFILE(SMBwritebraw);
4514 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4517 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4518 "wrote=%d sync=%d\n",
4519 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4520 (int)nwritten, (int)write_through));
4522 if (nwritten < (ssize_t)numtowrite) {
4523 reply_nterror(req, NT_STATUS_DISK_FULL);
4524 error_to_writebrawerr(req);
4528 total_written = nwritten;
4530 /* Allocate a buffer of 64k + length. */
4531 buf = talloc_array(NULL, char, 65540);
4533 reply_nterror(req, NT_STATUS_NO_MEMORY);
4534 error_to_writebrawerr(req);
4538 /* Return a SMBwritebraw message to the redirector to tell
4539 * it to send more bytes */
4541 memcpy(buf, req->inbuf, smb_size);
4542 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4543 SCVAL(buf,smb_com,SMBwritebraw);
4544 SSVALS(buf,smb_vwv0,0xFFFF);
4546 if (!srv_send_smb(req->xconn,
4548 false, 0, /* no signing */
4549 IS_CONN_ENCRYPTED(conn),
4551 exit_server_cleanly("reply_writebraw: srv_send_smb "
4555 /* Now read the raw data into the buffer and write it */
4556 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4558 if (!NT_STATUS_IS_OK(status)) {
4559 exit_server_cleanly("secondary writebraw failed");
4562 /* Set up outbuf to return the correct size */
4563 reply_outbuf(req, 1, 0);
4565 if (numtowrite != 0) {
4567 if (numtowrite > 0xFFFF) {
4568 DEBUG(0,("reply_writebraw: Oversize secondary write "
4569 "raw requested (%u). Terminating\n",
4570 (unsigned int)numtowrite ));
4571 exit_server_cleanly("secondary writebraw failed");
4574 if (tcount > nwritten+numtowrite) {
4575 DEBUG(3,("reply_writebraw: Client overestimated the "
4577 (int)tcount,(int)nwritten,(int)numtowrite));
4580 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4583 if (!NT_STATUS_IS_OK(status)) {
4584 /* Try and give an error message
4585 * saying what client failed. */
4586 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4587 "raw read failed (%s) for client %s. "
4588 "Terminating\n", nt_errstr(status),
4589 smbXsrv_connection_dbg(xconn)));
4590 exit_server_cleanly("secondary writebraw failed");
4593 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4594 if (nwritten == -1) {
4596 reply_nterror(req, map_nt_error_from_unix(errno));
4597 error_to_writebrawerr(req);
4601 if (nwritten < (ssize_t)numtowrite) {
4602 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4603 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4607 total_written += nwritten;
4612 SSVAL(req->outbuf,smb_vwv0,total_written);
4614 status = sync_file(conn, fsp, write_through);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4617 fsp_str_dbg(fsp), nt_errstr(status)));
4618 reply_nterror(req, status);
4619 error_to_writebrawerr(req);
4623 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4625 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4626 (int)total_written));
4628 if (!fsp->print_file) {
4629 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4632 /* We won't return a status if write through is not selected - this
4633 * follows what WfWg does */
4634 END_PROFILE(SMBwritebraw);
4636 if (!write_through && total_written==tcount) {
4638 #if RABBIT_PELLET_FIX
4640 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4641 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4644 if (!send_keepalive(xconn->transport.sock)) {
4645 exit_server_cleanly("reply_writebraw: send of "
4646 "keepalive failed");
4649 TALLOC_FREE(req->outbuf);
4654 if (!fsp->print_file) {
4655 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4658 END_PROFILE(SMBwritebraw);
4663 #define DBGC_CLASS DBGC_LOCKING
4665 /****************************************************************************
4666 Reply to a writeunlock (core+).
4667 ****************************************************************************/
4669 void reply_writeunlock(struct smb_request *req)
4671 connection_struct *conn = req->conn;
4672 ssize_t nwritten = -1;
4676 NTSTATUS status = NT_STATUS_OK;
4678 struct lock_struct lock;
4679 int saved_errno = 0;
4681 START_PROFILE(SMBwriteunlock);
4684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4685 END_PROFILE(SMBwriteunlock);
4689 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4691 if (!check_fsp(conn, req, fsp)) {
4692 END_PROFILE(SMBwriteunlock);
4696 if (!CHECK_WRITE(fsp)) {
4697 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4698 END_PROFILE(SMBwriteunlock);
4702 numtowrite = SVAL(req->vwv+1, 0);
4703 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4704 data = (const char *)req->buf + 3;
4706 if (!fsp->print_file && numtowrite > 0) {
4707 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4708 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4711 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4712 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4713 END_PROFILE(SMBwriteunlock);
4718 /* The special X/Open SMB protocol handling of
4719 zero length writes is *NOT* done for
4721 if(numtowrite == 0) {
4724 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4725 saved_errno = errno;
4728 status = sync_file(conn, fsp, False /* write through */);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4731 fsp_str_dbg(fsp), nt_errstr(status)));
4732 reply_nterror(req, status);
4737 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4741 if((nwritten < numtowrite) && (numtowrite != 0)) {
4742 reply_nterror(req, NT_STATUS_DISK_FULL);
4746 if (numtowrite && !fsp->print_file) {
4747 status = do_unlock(req->sconn->msg_ctx,
4749 (uint64_t)req->smbpid,
4750 (uint64_t)numtowrite,
4754 if (NT_STATUS_V(status)) {
4755 reply_nterror(req, status);
4760 reply_outbuf(req, 1, 0);
4762 SSVAL(req->outbuf,smb_vwv0,nwritten);
4764 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4765 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4768 if (numtowrite && !fsp->print_file) {
4769 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4772 END_PROFILE(SMBwriteunlock);
4777 #define DBGC_CLASS DBGC_ALL
4779 /****************************************************************************
4781 ****************************************************************************/
4783 void reply_write(struct smb_request *req)
4785 connection_struct *conn = req->conn;
4787 ssize_t nwritten = -1;
4791 struct lock_struct lock;
4793 int saved_errno = 0;
4795 START_PROFILE(SMBwrite);
4798 END_PROFILE(SMBwrite);
4799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4803 /* If it's an IPC, pass off the pipe handler. */
4805 reply_pipe_write(req);
4806 END_PROFILE(SMBwrite);
4810 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4812 if (!check_fsp(conn, req, fsp)) {
4813 END_PROFILE(SMBwrite);
4817 if (!CHECK_WRITE(fsp)) {
4818 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4819 END_PROFILE(SMBwrite);
4823 numtowrite = SVAL(req->vwv+1, 0);
4824 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4825 data = (const char *)req->buf + 3;
4827 if (!fsp->print_file) {
4828 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4829 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4832 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4833 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4834 END_PROFILE(SMBwrite);
4840 * X/Open SMB protocol says that if smb_vwv1 is
4841 * zero then the file size should be extended or
4842 * truncated to the size given in smb_vwv[2-3].
4845 if(numtowrite == 0) {
4847 * This is actually an allocate call, and set EOF. JRA.
4849 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4851 reply_nterror(req, NT_STATUS_DISK_FULL);
4854 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4856 reply_nterror(req, NT_STATUS_DISK_FULL);
4859 trigger_write_time_update_immediate(fsp);
4861 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4864 status = sync_file(conn, fsp, False);
4865 if (!NT_STATUS_IS_OK(status)) {
4866 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4867 fsp_str_dbg(fsp), nt_errstr(status)));
4868 reply_nterror(req, status);
4873 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4877 if((nwritten == 0) && (numtowrite != 0)) {
4878 reply_nterror(req, NT_STATUS_DISK_FULL);
4882 reply_outbuf(req, 1, 0);
4884 SSVAL(req->outbuf,smb_vwv0,nwritten);
4886 if (nwritten < (ssize_t)numtowrite) {
4887 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4888 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4891 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4894 if (!fsp->print_file) {
4895 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4898 END_PROFILE(SMBwrite);
4902 /****************************************************************************
4903 Ensure a buffer is a valid writeX for recvfile purposes.
4904 ****************************************************************************/
4906 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4907 (2*14) + /* word count (including bcc) */ \
4910 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4911 const uint8_t *inbuf)
4914 unsigned int doff = 0;
4915 size_t len = smb_len_large(inbuf);
4917 struct smbXsrv_open *op = NULL;
4918 struct files_struct *fsp = NULL;
4921 if (is_encrypted_packet(inbuf)) {
4922 /* Can't do this on encrypted
4927 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4931 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4932 CVAL(inbuf,smb_wct) != 14) {
4933 DEBUG(10,("is_valid_writeX_buffer: chained or "
4934 "invalid word length.\n"));
4938 fnum = SVAL(inbuf, smb_vwv2);
4939 status = smb1srv_open_lookup(xconn,
4943 if (!NT_STATUS_IS_OK(status)) {
4944 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4949 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4952 if (fsp->conn == NULL) {
4953 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4957 if (IS_IPC(fsp->conn)) {
4958 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4961 if (IS_PRINT(fsp->conn)) {
4962 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4965 doff = SVAL(inbuf,smb_vwv11);
4967 numtowrite = SVAL(inbuf,smb_vwv10);
4969 if (len > doff && len - doff > 0xFFFF) {
4970 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4973 if (numtowrite == 0) {
4974 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4978 /* Ensure the sizes match up. */
4979 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4980 /* no pad byte...old smbclient :-( */
4981 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4983 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4987 if (len - doff != numtowrite) {
4988 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4989 "len = %u, doff = %u, numtowrite = %u\n",
4992 (unsigned int)numtowrite ));
4996 DEBUG(10,("is_valid_writeX_buffer: true "
4997 "len = %u, doff = %u, numtowrite = %u\n",
5000 (unsigned int)numtowrite ));
5005 /****************************************************************************
5006 Reply to a write and X.
5007 ****************************************************************************/
5009 void reply_write_and_X(struct smb_request *req)
5011 connection_struct *conn = req->conn;
5012 struct smbXsrv_connection *xconn = req->xconn;
5014 struct lock_struct lock;
5019 unsigned int smb_doff;
5020 unsigned int smblen;
5023 int saved_errno = 0;
5025 START_PROFILE(SMBwriteX);
5027 if ((req->wct != 12) && (req->wct != 14)) {
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 numtowrite = SVAL(req->vwv+10, 0);
5033 smb_doff = SVAL(req->vwv+11, 0);
5034 smblen = smb_len(req->inbuf);
5036 if (req->unread_bytes > 0xFFFF ||
5037 (smblen > smb_doff &&
5038 smblen - smb_doff > 0xFFFF)) {
5039 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5042 if (req->unread_bytes) {
5043 /* Can't do a recvfile write on IPC$ */
5045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5048 if (numtowrite != req->unread_bytes) {
5049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5053 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5054 smb_doff + numtowrite > smblen) {
5055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5060 /* If it's an IPC, pass off the pipe handler. */
5062 if (req->unread_bytes) {
5063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5066 reply_pipe_write_and_X(req);
5070 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5071 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5072 write_through = BITSETW(req->vwv+7,0);
5074 if (!check_fsp(conn, req, fsp)) {
5078 if (!CHECK_WRITE(fsp)) {
5079 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5083 data = smb_base(req->inbuf) + smb_doff;
5085 if(req->wct == 14) {
5087 * This is a large offset (64 bit) write.
5089 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5093 /* X/Open SMB protocol says that, unlike SMBwrite
5094 if the length is zero then NO truncation is
5095 done, just a write of zero. To truncate a file,
5098 if(numtowrite == 0) {
5101 if (req->unread_bytes == 0) {
5102 status = schedule_aio_write_and_X(conn,
5109 if (NT_STATUS_IS_OK(status)) {
5110 /* write scheduled - we're done. */
5113 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5114 /* Real error - report to client. */
5115 reply_nterror(req, status);
5118 /* NT_STATUS_RETRY - fall through to sync write. */
5121 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5122 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5125 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5126 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5130 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5131 saved_errno = errno;
5133 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5137 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5141 if((nwritten == 0) && (numtowrite != 0)) {
5142 reply_nterror(req, NT_STATUS_DISK_FULL);
5146 reply_outbuf(req, 6, 0);
5147 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5148 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5149 SSVAL(req->outbuf,smb_vwv2,nwritten);
5150 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5152 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5153 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5155 status = sync_file(conn, fsp, write_through);
5156 if (!NT_STATUS_IS_OK(status)) {
5157 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5158 fsp_str_dbg(fsp), nt_errstr(status)));
5159 reply_nterror(req, status);
5163 END_PROFILE(SMBwriteX);
5167 if (req->unread_bytes) {
5168 /* writeX failed. drain socket. */
5169 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5170 req->unread_bytes) {
5171 smb_panic("failed to drain pending bytes");
5173 req->unread_bytes = 0;
5176 END_PROFILE(SMBwriteX);
5180 /****************************************************************************
5182 ****************************************************************************/
5184 void reply_lseek(struct smb_request *req)
5186 connection_struct *conn = req->conn;
5192 START_PROFILE(SMBlseek);
5195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5196 END_PROFILE(SMBlseek);
5200 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5202 if (!check_fsp(conn, req, fsp)) {
5206 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5208 mode = SVAL(req->vwv+1, 0) & 3;
5209 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5210 startpos = (off_t)IVALS(req->vwv+2, 0);
5219 res = fsp->fh->pos + startpos;
5230 if (umode == SEEK_END) {
5231 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5232 if(errno == EINVAL) {
5233 off_t current_pos = startpos;
5235 if(fsp_stat(fsp) == -1) {
5237 map_nt_error_from_unix(errno));
5238 END_PROFILE(SMBlseek);
5242 current_pos += fsp->fsp_name->st.st_ex_size;
5244 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5249 reply_nterror(req, map_nt_error_from_unix(errno));
5250 END_PROFILE(SMBlseek);
5257 reply_outbuf(req, 2, 0);
5258 SIVAL(req->outbuf,smb_vwv0,res);
5260 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5261 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5263 END_PROFILE(SMBlseek);
5267 /****************************************************************************
5269 ****************************************************************************/
5271 void reply_flush(struct smb_request *req)
5273 connection_struct *conn = req->conn;
5277 START_PROFILE(SMBflush);
5280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284 fnum = SVAL(req->vwv+0, 0);
5285 fsp = file_fsp(req, fnum);
5287 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5292 file_sync_all(conn);
5294 NTSTATUS status = sync_file(conn, fsp, True);
5295 if (!NT_STATUS_IS_OK(status)) {
5296 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5297 fsp_str_dbg(fsp), nt_errstr(status)));
5298 reply_nterror(req, status);
5299 END_PROFILE(SMBflush);
5304 reply_outbuf(req, 0, 0);
5306 DEBUG(3,("flush\n"));
5307 END_PROFILE(SMBflush);
5311 /****************************************************************************
5313 conn POINTER CAN BE NULL HERE !
5314 ****************************************************************************/
5316 void reply_exit(struct smb_request *req)
5318 START_PROFILE(SMBexit);
5320 file_close_pid(req->sconn, req->smbpid, req->vuid);
5322 reply_outbuf(req, 0, 0);
5324 DEBUG(3,("exit\n"));
5326 END_PROFILE(SMBexit);
5330 struct reply_close_state {
5332 struct smb_request *smbreq;
5335 static void do_smb1_close(struct tevent_req *req);
5337 void reply_close(struct smb_request *req)
5339 connection_struct *conn = req->conn;
5340 NTSTATUS status = NT_STATUS_OK;
5341 files_struct *fsp = NULL;
5342 START_PROFILE(SMBclose);
5345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5346 END_PROFILE(SMBclose);
5350 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5353 * We can only use check_fsp if we know it's not a directory.
5356 if (!check_fsp_open(conn, req, fsp)) {
5357 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5358 END_PROFILE(SMBclose);
5362 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5363 fsp->is_directory ? "directory" : "file",
5364 fsp->fh->fd, fsp_fnum_dbg(fsp),
5365 conn->num_files_open));
5367 if (!fsp->is_directory) {
5371 * Take care of any time sent in the close.
5374 t = srv_make_unix_date3(req->vwv+1);
5375 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5378 if (fsp->num_aio_requests != 0) {
5380 struct reply_close_state *state;
5382 DEBUG(10, ("closing with aio %u requests pending\n",
5383 fsp->num_aio_requests));
5386 * We depend on the aio_extra destructor to take care of this
5387 * close request once fsp->num_aio_request drops to 0.
5390 fsp->deferred_close = tevent_wait_send(
5391 fsp, fsp->conn->sconn->ev_ctx);
5392 if (fsp->deferred_close == NULL) {
5393 status = NT_STATUS_NO_MEMORY;
5397 state = talloc(fsp, struct reply_close_state);
5398 if (state == NULL) {
5399 TALLOC_FREE(fsp->deferred_close);
5400 status = NT_STATUS_NO_MEMORY;
5404 state->smbreq = talloc_move(fsp, &req);
5405 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5407 END_PROFILE(SMBclose);
5412 * close_file() returns the unix errno if an error was detected on
5413 * close - normally this is due to a disk full error. If not then it
5414 * was probably an I/O error.
5417 status = close_file(req, fsp, NORMAL_CLOSE);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 reply_nterror(req, status);
5421 END_PROFILE(SMBclose);
5425 reply_outbuf(req, 0, 0);
5426 END_PROFILE(SMBclose);
5430 static void do_smb1_close(struct tevent_req *req)
5432 struct reply_close_state *state = tevent_req_callback_data(
5433 req, struct reply_close_state);
5434 struct smb_request *smbreq;
5438 ret = tevent_wait_recv(req);
5441 DEBUG(10, ("tevent_wait_recv returned %s\n",
5444 * Continue anyway, this should never happen
5449 * fsp->smb2_close_request right now is a talloc grandchild of
5450 * fsp. When we close_file(fsp), it would go with it. No chance to
5453 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5455 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5456 if (NT_STATUS_IS_OK(status)) {
5457 reply_outbuf(smbreq, 0, 0);
5459 reply_nterror(smbreq, status);
5461 if (!srv_send_smb(smbreq->xconn,
5462 (char *)smbreq->outbuf,
5465 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5467 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5470 TALLOC_FREE(smbreq);
5473 /****************************************************************************
5474 Reply to a writeclose (Core+ protocol).
5475 ****************************************************************************/
5477 void reply_writeclose(struct smb_request *req)
5479 connection_struct *conn = req->conn;
5481 ssize_t nwritten = -1;
5482 NTSTATUS close_status = NT_STATUS_OK;
5485 struct timespec mtime;
5487 struct lock_struct lock;
5489 START_PROFILE(SMBwriteclose);
5492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5493 END_PROFILE(SMBwriteclose);
5497 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5499 if (!check_fsp(conn, req, fsp)) {
5500 END_PROFILE(SMBwriteclose);
5503 if (!CHECK_WRITE(fsp)) {
5504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5505 END_PROFILE(SMBwriteclose);
5509 numtowrite = SVAL(req->vwv+1, 0);
5510 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5511 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5512 data = (const char *)req->buf + 1;
5514 if (fsp->print_file == NULL) {
5515 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5516 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5519 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5520 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5521 END_PROFILE(SMBwriteclose);
5526 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5528 if (fsp->print_file == NULL) {
5529 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5532 set_close_write_time(fsp, mtime);
5535 * More insanity. W2K only closes the file if writelen > 0.
5539 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5540 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5541 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5544 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5545 "file %s\n", fsp_str_dbg(fsp)));
5546 close_status = close_file(req, fsp, NORMAL_CLOSE);
5550 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5551 reply_nterror(req, NT_STATUS_DISK_FULL);
5555 if(!NT_STATUS_IS_OK(close_status)) {
5556 reply_nterror(req, close_status);
5560 reply_outbuf(req, 1, 0);
5562 SSVAL(req->outbuf,smb_vwv0,nwritten);
5566 END_PROFILE(SMBwriteclose);
5571 #define DBGC_CLASS DBGC_LOCKING
5573 /****************************************************************************
5575 ****************************************************************************/
5577 void reply_lock(struct smb_request *req)
5579 connection_struct *conn = req->conn;
5580 uint64_t count,offset;
5583 struct byte_range_lock *br_lck = NULL;
5585 START_PROFILE(SMBlock);
5588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5589 END_PROFILE(SMBlock);
5593 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5595 if (!check_fsp(conn, req, fsp)) {
5596 END_PROFILE(SMBlock);
5600 count = (uint64_t)IVAL(req->vwv+1, 0);
5601 offset = (uint64_t)IVAL(req->vwv+3, 0);
5603 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5604 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5606 br_lck = do_lock(req->sconn->msg_ctx,
5608 (uint64_t)req->smbpid,
5613 False, /* Non-blocking lock. */
5617 TALLOC_FREE(br_lck);
5619 if (NT_STATUS_V(status)) {
5620 reply_nterror(req, status);
5621 END_PROFILE(SMBlock);
5625 reply_outbuf(req, 0, 0);
5627 END_PROFILE(SMBlock);
5631 /****************************************************************************
5633 ****************************************************************************/
5635 void reply_unlock(struct smb_request *req)
5637 connection_struct *conn = req->conn;
5638 uint64_t count,offset;
5642 START_PROFILE(SMBunlock);
5645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5646 END_PROFILE(SMBunlock);
5650 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5652 if (!check_fsp(conn, req, fsp)) {
5653 END_PROFILE(SMBunlock);
5657 count = (uint64_t)IVAL(req->vwv+1, 0);
5658 offset = (uint64_t)IVAL(req->vwv+3, 0);
5660 status = do_unlock(req->sconn->msg_ctx,
5662 (uint64_t)req->smbpid,
5667 if (NT_STATUS_V(status)) {
5668 reply_nterror(req, status);
5669 END_PROFILE(SMBunlock);
5673 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5674 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5676 reply_outbuf(req, 0, 0);
5678 END_PROFILE(SMBunlock);
5683 #define DBGC_CLASS DBGC_ALL
5685 /****************************************************************************
5687 conn POINTER CAN BE NULL HERE !
5688 ****************************************************************************/
5690 void reply_tdis(struct smb_request *req)
5693 connection_struct *conn = req->conn;
5694 struct smbXsrv_tcon *tcon;
5696 START_PROFILE(SMBtdis);
5699 DEBUG(4,("Invalid connection in tdis\n"));
5700 reply_force_doserror(req, ERRSRV, ERRinvnid);
5701 END_PROFILE(SMBtdis);
5709 * TODO: cancel all outstanding requests on the tcon
5711 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5712 if (!NT_STATUS_IS_OK(status)) {
5713 DEBUG(0, ("reply_tdis: "
5714 "smbXsrv_tcon_disconnect() failed: %s\n",
5715 nt_errstr(status)));
5717 * If we hit this case, there is something completely
5718 * wrong, so we better disconnect the transport connection.
5720 END_PROFILE(SMBtdis);
5721 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5727 reply_outbuf(req, 0, 0);
5728 END_PROFILE(SMBtdis);
5732 /****************************************************************************
5734 conn POINTER CAN BE NULL HERE !
5735 ****************************************************************************/
5737 void reply_echo(struct smb_request *req)
5739 connection_struct *conn = req->conn;
5740 struct smb_perfcount_data local_pcd;
5741 struct smb_perfcount_data *cur_pcd;
5745 START_PROFILE(SMBecho);
5747 smb_init_perfcount_data(&local_pcd);
5750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5751 END_PROFILE(SMBecho);
5755 smb_reverb = SVAL(req->vwv+0, 0);
5757 reply_outbuf(req, 1, req->buflen);
5759 /* copy any incoming data back out */
5760 if (req->buflen > 0) {
5761 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5764 if (smb_reverb > 100) {
5765 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5769 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5771 /* this makes sure we catch the request pcd */
5772 if (seq_num == smb_reverb) {
5773 cur_pcd = &req->pcd;
5775 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5776 cur_pcd = &local_pcd;
5779 SSVAL(req->outbuf,smb_vwv0,seq_num);
5781 show_msg((char *)req->outbuf);
5782 if (!srv_send_smb(req->xconn,
5783 (char *)req->outbuf,
5784 true, req->seqnum+1,
5785 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5787 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5790 DEBUG(3,("echo %d times\n", smb_reverb));
5792 TALLOC_FREE(req->outbuf);
5794 END_PROFILE(SMBecho);
5798 /****************************************************************************
5799 Reply to a printopen.
5800 ****************************************************************************/
5802 void reply_printopen(struct smb_request *req)
5804 connection_struct *conn = req->conn;
5808 START_PROFILE(SMBsplopen);
5811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5812 END_PROFILE(SMBsplopen);
5816 if (!CAN_PRINT(conn)) {
5817 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5818 END_PROFILE(SMBsplopen);
5822 status = file_new(req, conn, &fsp);
5823 if(!NT_STATUS_IS_OK(status)) {
5824 reply_nterror(req, status);
5825 END_PROFILE(SMBsplopen);
5829 /* Open for exclusive use, write only. */
5830 status = print_spool_open(fsp, NULL, req->vuid);
5832 if (!NT_STATUS_IS_OK(status)) {
5833 file_free(req, fsp);
5834 reply_nterror(req, status);
5835 END_PROFILE(SMBsplopen);
5839 reply_outbuf(req, 1, 0);
5840 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5842 DEBUG(3,("openprint fd=%d %s\n",
5843 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5845 END_PROFILE(SMBsplopen);
5849 /****************************************************************************
5850 Reply to a printclose.
5851 ****************************************************************************/
5853 void reply_printclose(struct smb_request *req)
5855 connection_struct *conn = req->conn;
5859 START_PROFILE(SMBsplclose);
5862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5863 END_PROFILE(SMBsplclose);
5867 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5869 if (!check_fsp(conn, req, fsp)) {
5870 END_PROFILE(SMBsplclose);
5874 if (!CAN_PRINT(conn)) {
5875 reply_force_doserror(req, ERRSRV, ERRerror);
5876 END_PROFILE(SMBsplclose);
5880 DEBUG(3,("printclose fd=%d %s\n",
5881 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5883 status = close_file(req, fsp, NORMAL_CLOSE);
5885 if(!NT_STATUS_IS_OK(status)) {
5886 reply_nterror(req, status);
5887 END_PROFILE(SMBsplclose);
5891 reply_outbuf(req, 0, 0);
5893 END_PROFILE(SMBsplclose);
5897 /****************************************************************************
5898 Reply to a printqueue.
5899 ****************************************************************************/
5901 void reply_printqueue(struct smb_request *req)
5903 connection_struct *conn = req->conn;
5907 START_PROFILE(SMBsplretq);
5910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5911 END_PROFILE(SMBsplretq);
5915 max_count = SVAL(req->vwv+0, 0);
5916 start_index = SVAL(req->vwv+1, 0);
5918 /* we used to allow the client to get the cnum wrong, but that
5919 is really quite gross and only worked when there was only
5920 one printer - I think we should now only accept it if they
5921 get it right (tridge) */
5922 if (!CAN_PRINT(conn)) {
5923 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5924 END_PROFILE(SMBsplretq);
5928 reply_outbuf(req, 2, 3);
5929 SSVAL(req->outbuf,smb_vwv0,0);
5930 SSVAL(req->outbuf,smb_vwv1,0);
5931 SCVAL(smb_buf(req->outbuf),0,1);
5932 SSVAL(smb_buf(req->outbuf),1,0);
5934 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5935 start_index, max_count));
5938 TALLOC_CTX *mem_ctx = talloc_tos();
5941 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5942 struct rpc_pipe_client *cli = NULL;
5943 struct dcerpc_binding_handle *b = NULL;
5944 struct policy_handle handle;
5945 struct spoolss_DevmodeContainer devmode_ctr;
5946 union spoolss_JobInfo *info;
5948 uint32_t num_to_get;
5952 ZERO_STRUCT(handle);
5954 status = rpc_pipe_open_interface(conn,
5957 conn->sconn->remote_address,
5958 conn->sconn->local_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 = ucf_flags_from_smb_request(req);
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 = ucf_flags_from_smb_request(req) |
7297 (req->posix_pathnames ?
7298 UCF_UNIX_NAME_LOOKUP :
7299 UCF_COND_ALLOW_WCARD_LCOMP);
7300 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7302 (req->posix_pathnames ?
7304 UCF_COND_ALLOW_WCARD_LCOMP);
7305 bool stream_rename = false;
7307 START_PROFILE(SMBmv);
7310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7314 attrs = SVAL(req->vwv+0, 0);
7316 p = (const char *)req->buf + 1;
7317 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7318 &status, &src_has_wcard);
7319 if (!NT_STATUS_IS_OK(status)) {
7320 reply_nterror(req, status);
7324 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7325 &status, &dest_has_wcard);
7326 if (!NT_STATUS_IS_OK(status)) {
7327 reply_nterror(req, status);
7331 if (!req->posix_pathnames) {
7332 /* The newname must begin with a ':' if the
7333 name contains a ':'. */
7334 if (strchr_m(name, ':')) {
7335 if (newname[0] != ':') {
7336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7339 stream_rename = true;
7343 status = filename_convert(ctx,
7345 req->flags2 & FLAGS2_DFS_PATHNAMES,
7351 if (!NT_STATUS_IS_OK(status)) {
7352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7353 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7354 ERRSRV, ERRbadpath);
7357 reply_nterror(req, status);
7361 status = filename_convert(ctx,
7363 req->flags2 & FLAGS2_DFS_PATHNAMES,
7369 if (!NT_STATUS_IS_OK(status)) {
7370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7371 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7372 ERRSRV, ERRbadpath);
7375 reply_nterror(req, status);
7379 if (stream_rename) {
7380 /* smb_fname_dst->base_name must be the same as
7381 smb_fname_src->base_name. */
7382 TALLOC_FREE(smb_fname_dst->base_name);
7383 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7384 smb_fname_src->base_name);
7385 if (!smb_fname_dst->base_name) {
7386 reply_nterror(req, NT_STATUS_NO_MEMORY);
7391 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7392 smb_fname_str_dbg(smb_fname_dst)));
7394 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7395 attrs, False, src_has_wcard, dest_has_wcard,
7397 if (!NT_STATUS_IS_OK(status)) {
7398 if (open_was_deferred(req->xconn, req->mid)) {
7399 /* We have re-scheduled this call. */
7402 reply_nterror(req, status);
7406 reply_outbuf(req, 0, 0);
7408 TALLOC_FREE(smb_fname_src);
7409 TALLOC_FREE(smb_fname_dst);
7414 /*******************************************************************
7415 Copy a file as part of a reply_copy.
7416 ******************************************************************/
7419 * TODO: check error codes on all callers
7422 NTSTATUS copy_file(TALLOC_CTX *ctx,
7423 connection_struct *conn,
7424 struct smb_filename *smb_fname_src,
7425 struct smb_filename *smb_fname_dst,
7428 bool target_is_directory)
7430 struct smb_filename *smb_fname_dst_tmp = NULL;
7432 files_struct *fsp1,*fsp2;
7434 uint32_t new_create_disposition;
7438 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7439 if (smb_fname_dst_tmp == NULL) {
7440 return NT_STATUS_NO_MEMORY;
7444 * If the target is a directory, extract the last component from the
7445 * src filename and append it to the dst filename
7447 if (target_is_directory) {
7450 /* dest/target can't be a stream if it's a directory. */
7451 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7453 p = strrchr_m(smb_fname_src->base_name,'/');
7457 p = smb_fname_src->base_name;
7459 smb_fname_dst_tmp->base_name =
7460 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7462 if (!smb_fname_dst_tmp->base_name) {
7463 status = NT_STATUS_NO_MEMORY;
7468 status = vfs_file_exist(conn, smb_fname_src);
7469 if (!NT_STATUS_IS_OK(status)) {
7473 if (!target_is_directory && count) {
7474 new_create_disposition = FILE_OPEN;
7476 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7479 &new_create_disposition,
7482 status = NT_STATUS_INVALID_PARAMETER;
7487 /* Open the src file for reading. */
7488 status = SMB_VFS_CREATE_FILE(
7491 0, /* root_dir_fid */
7492 smb_fname_src, /* fname */
7493 FILE_GENERIC_READ, /* access_mask */
7494 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7495 FILE_OPEN, /* create_disposition*/
7496 0, /* create_options */
7497 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7498 INTERNAL_OPEN_ONLY, /* oplock_request */
7500 0, /* allocation_size */
7501 0, /* private_flags */
7506 NULL, NULL); /* create context */
7508 if (!NT_STATUS_IS_OK(status)) {
7512 dosattrs = dos_mode(conn, smb_fname_src);
7514 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7515 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7518 /* Open the dst file for writing. */
7519 status = SMB_VFS_CREATE_FILE(
7522 0, /* root_dir_fid */
7523 smb_fname_dst, /* fname */
7524 FILE_GENERIC_WRITE, /* access_mask */
7525 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7526 new_create_disposition, /* create_disposition*/
7527 0, /* create_options */
7528 dosattrs, /* file_attributes */
7529 INTERNAL_OPEN_ONLY, /* oplock_request */
7531 0, /* allocation_size */
7532 0, /* private_flags */
7537 NULL, NULL); /* create context */
7539 if (!NT_STATUS_IS_OK(status)) {
7540 close_file(NULL, fsp1, ERROR_CLOSE);
7544 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7545 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7547 DEBUG(0, ("error - vfs lseek returned error %s\n",
7549 status = map_nt_error_from_unix(errno);
7550 close_file(NULL, fsp1, ERROR_CLOSE);
7551 close_file(NULL, fsp2, ERROR_CLOSE);
7556 /* Do the actual copy. */
7557 if (smb_fname_src->st.st_ex_size) {
7558 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7563 close_file(NULL, fsp1, NORMAL_CLOSE);
7565 /* Ensure the modtime is set correctly on the destination file. */
7566 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7569 * As we are opening fsp1 read-only we only expect
7570 * an error on close on fsp2 if we are out of space.
7571 * Thus we don't look at the error return from the
7574 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7576 if (!NT_STATUS_IS_OK(status)) {
7580 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7581 status = NT_STATUS_DISK_FULL;
7585 status = NT_STATUS_OK;
7588 TALLOC_FREE(smb_fname_dst_tmp);
7592 /****************************************************************************
7593 Reply to a file copy.
7594 ****************************************************************************/
7596 void reply_copy(struct smb_request *req)
7598 connection_struct *conn = req->conn;
7599 struct smb_filename *smb_fname_src = NULL;
7600 struct smb_filename *smb_fname_src_dir = NULL;
7601 struct smb_filename *smb_fname_dst = NULL;
7602 char *fname_src = NULL;
7603 char *fname_dst = NULL;
7604 char *fname_src_mask = NULL;
7605 char *fname_src_dir = NULL;
7608 int error = ERRnoaccess;
7612 bool target_is_directory=False;
7613 bool source_has_wild = False;
7614 bool dest_has_wild = False;
7616 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7617 ucf_flags_from_smb_request(req);
7618 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7619 ucf_flags_from_smb_request(req);
7620 TALLOC_CTX *ctx = talloc_tos();
7622 START_PROFILE(SMBcopy);
7625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7629 tid2 = SVAL(req->vwv+0, 0);
7630 ofun = SVAL(req->vwv+1, 0);
7631 flags = SVAL(req->vwv+2, 0);
7633 p = (const char *)req->buf;
7634 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7635 &status, &source_has_wild);
7636 if (!NT_STATUS_IS_OK(status)) {
7637 reply_nterror(req, status);
7640 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7641 &status, &dest_has_wild);
7642 if (!NT_STATUS_IS_OK(status)) {
7643 reply_nterror(req, status);
7647 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7649 if (tid2 != conn->cnum) {
7650 /* can't currently handle inter share copies XXXX */
7651 DEBUG(3,("Rejecting inter-share copy\n"));
7652 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7656 status = filename_convert(ctx, conn,
7657 req->flags2 & FLAGS2_DFS_PATHNAMES,
7662 if (!NT_STATUS_IS_OK(status)) {
7663 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7664 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7665 ERRSRV, ERRbadpath);
7668 reply_nterror(req, status);
7672 status = filename_convert(ctx, conn,
7673 req->flags2 & FLAGS2_DFS_PATHNAMES,
7678 if (!NT_STATUS_IS_OK(status)) {
7679 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7680 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7681 ERRSRV, ERRbadpath);
7684 reply_nterror(req, status);
7688 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7690 if ((flags&1) && target_is_directory) {
7691 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7695 if ((flags&2) && !target_is_directory) {
7696 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7700 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7701 /* wants a tree copy! XXXX */
7702 DEBUG(3,("Rejecting tree copy\n"));
7703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7707 /* Split up the directory from the filename/mask. */
7708 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7709 &fname_src_dir, &fname_src_mask);
7710 if (!NT_STATUS_IS_OK(status)) {
7711 reply_nterror(req, NT_STATUS_NO_MEMORY);
7716 * We should only check the mangled cache
7717 * here if unix_convert failed. This means
7718 * that the path in 'mask' doesn't exist
7719 * on the file system and so we need to look
7720 * for a possible mangle. This patch from
7721 * Tine Smukavec <valentin.smukavec@hermes.si>.
7723 if (!VALID_STAT(smb_fname_src->st) &&
7724 mangle_is_mangled(fname_src_mask, conn->params)) {
7725 char *new_mask = NULL;
7726 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7727 &new_mask, conn->params);
7729 /* Use demangled name if one was successfully found. */
7731 TALLOC_FREE(fname_src_mask);
7732 fname_src_mask = new_mask;
7736 if (!source_has_wild) {
7739 * Only one file needs to be copied. Append the mask back onto
7742 TALLOC_FREE(smb_fname_src->base_name);
7743 if (ISDOT(fname_src_dir)) {
7744 /* Ensure we use canonical names on open. */
7745 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7749 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7754 if (!smb_fname_src->base_name) {
7755 reply_nterror(req, NT_STATUS_NO_MEMORY);
7759 if (dest_has_wild) {
7760 char *fname_dst_mod = NULL;
7761 if (!resolve_wildcards(smb_fname_dst,
7762 smb_fname_src->base_name,
7763 smb_fname_dst->base_name,
7765 reply_nterror(req, NT_STATUS_NO_MEMORY);
7768 TALLOC_FREE(smb_fname_dst->base_name);
7769 smb_fname_dst->base_name = fname_dst_mod;
7772 status = check_name(conn, smb_fname_src->base_name);
7773 if (!NT_STATUS_IS_OK(status)) {
7774 reply_nterror(req, status);
7778 status = check_name(conn, smb_fname_dst->base_name);
7779 if (!NT_STATUS_IS_OK(status)) {
7780 reply_nterror(req, status);
7784 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7785 ofun, count, target_is_directory);
7787 if(!NT_STATUS_IS_OK(status)) {
7788 reply_nterror(req, status);
7794 struct smb_Dir *dir_hnd = NULL;
7795 const char *dname = NULL;
7796 char *talloced = NULL;
7800 * There is a wildcard that requires us to actually read the
7801 * src dir and copy each file matching the mask to the dst.
7802 * Right now streams won't be copied, but this could
7803 * presumably be added with a nested loop for reach dir entry.
7805 SMB_ASSERT(!smb_fname_src->stream_name);
7806 SMB_ASSERT(!smb_fname_dst->stream_name);
7808 smb_fname_src->stream_name = NULL;
7809 smb_fname_dst->stream_name = NULL;
7811 if (strequal(fname_src_mask,"????????.???")) {
7812 TALLOC_FREE(fname_src_mask);
7813 fname_src_mask = talloc_strdup(ctx, "*");
7814 if (!fname_src_mask) {
7815 reply_nterror(req, NT_STATUS_NO_MEMORY);
7820 status = check_name(conn, fname_src_dir);
7821 if (!NT_STATUS_IS_OK(status)) {
7822 reply_nterror(req, status);
7826 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7830 smb_fname_src->flags);
7831 if (smb_fname_src_dir == NULL) {
7832 reply_nterror(req, NT_STATUS_NO_MEMORY);
7836 dir_hnd = OpenDir(ctx,
7841 if (dir_hnd == NULL) {
7842 status = map_nt_error_from_unix(errno);
7843 reply_nterror(req, status);
7849 /* Iterate over the src dir copying each entry to the dst. */
7850 while ((dname = ReadDirName(dir_hnd, &offset,
7851 &smb_fname_src->st, &talloced))) {
7852 char *destname = NULL;
7854 if (ISDOT(dname) || ISDOTDOT(dname)) {
7855 TALLOC_FREE(talloced);
7859 if (!is_visible_file(conn, fname_src_dir, dname,
7860 &smb_fname_src->st, false)) {
7861 TALLOC_FREE(talloced);
7865 if(!mask_match(dname, fname_src_mask,
7866 conn->case_sensitive)) {
7867 TALLOC_FREE(talloced);
7871 error = ERRnoaccess;
7873 /* Get the src smb_fname struct setup. */
7874 TALLOC_FREE(smb_fname_src->base_name);
7875 if (ISDOT(fname_src_dir)) {
7876 /* Ensure we use canonical names on open. */
7877 smb_fname_src->base_name =
7878 talloc_asprintf(smb_fname_src, "%s",
7881 smb_fname_src->base_name =
7882 talloc_asprintf(smb_fname_src, "%s/%s",
7883 fname_src_dir, dname);
7886 if (!smb_fname_src->base_name) {
7887 TALLOC_FREE(dir_hnd);
7888 TALLOC_FREE(talloced);
7889 reply_nterror(req, NT_STATUS_NO_MEMORY);
7893 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7894 smb_fname_dst->base_name,
7896 TALLOC_FREE(talloced);
7900 TALLOC_FREE(dir_hnd);
7901 TALLOC_FREE(talloced);
7902 reply_nterror(req, NT_STATUS_NO_MEMORY);
7906 TALLOC_FREE(smb_fname_dst->base_name);
7907 smb_fname_dst->base_name = destname;
7909 status = check_name(conn, smb_fname_src->base_name);
7910 if (!NT_STATUS_IS_OK(status)) {
7911 TALLOC_FREE(dir_hnd);
7912 TALLOC_FREE(talloced);
7913 reply_nterror(req, status);
7917 status = check_name(conn, smb_fname_dst->base_name);
7918 if (!NT_STATUS_IS_OK(status)) {
7919 TALLOC_FREE(dir_hnd);
7920 TALLOC_FREE(talloced);
7921 reply_nterror(req, status);
7925 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7926 smb_fname_src->base_name,
7927 smb_fname_dst->base_name));
7929 status = copy_file(ctx, conn, smb_fname_src,
7930 smb_fname_dst, ofun, count,
7931 target_is_directory);
7932 if (NT_STATUS_IS_OK(status)) {
7936 TALLOC_FREE(talloced);
7938 TALLOC_FREE(dir_hnd);
7942 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7946 reply_outbuf(req, 1, 0);
7947 SSVAL(req->outbuf,smb_vwv0,count);
7949 TALLOC_FREE(smb_fname_src);
7950 TALLOC_FREE(smb_fname_src_dir);
7951 TALLOC_FREE(smb_fname_dst);
7952 TALLOC_FREE(fname_src);
7953 TALLOC_FREE(fname_dst);
7954 TALLOC_FREE(fname_src_mask);
7955 TALLOC_FREE(fname_src_dir);
7957 END_PROFILE(SMBcopy);
7962 #define DBGC_CLASS DBGC_LOCKING
7964 /****************************************************************************
7965 Get a lock pid, dealing with large count requests.
7966 ****************************************************************************/
7968 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7969 bool large_file_format)
7971 if(!large_file_format)
7972 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7974 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7977 /****************************************************************************
7978 Get a lock count, dealing with large count requests.
7979 ****************************************************************************/
7981 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7982 bool large_file_format)
7986 if(!large_file_format) {
7987 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7990 * No BVAL, this is reversed!
7992 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7993 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7999 /****************************************************************************
8000 Get a lock offset, dealing with large offset requests.
8001 ****************************************************************************/
8003 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8004 bool large_file_format)
8006 uint64_t offset = 0;
8008 if(!large_file_format) {
8009 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8012 * No BVAL, this is reversed!
8014 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8015 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8021 NTSTATUS smbd_do_locking(struct smb_request *req,
8026 struct smbd_lock_element *locks,
8029 connection_struct *conn = req->conn;
8031 NTSTATUS status = NT_STATUS_OK;
8035 /* Setup the timeout in seconds. */
8037 if (!lp_blocking_locks(SNUM(conn))) {
8041 for(i = 0; i < (int)num_locks; i++) {
8042 struct smbd_lock_element *e = &locks[i];
8044 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8045 "%llu, file %s timeout = %d\n",
8048 (unsigned long long)e->smblctx,
8052 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8053 struct blocking_lock_record *blr = NULL;
8055 if (num_locks > 1) {
8057 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8058 * if the lock vector contains one entry. When given multiple cancel
8059 * requests in a single PDU we expect the server to return an
8060 * error. Windows servers seem to accept the request but only
8061 * cancel the first lock.
8062 * JRA - Do what Windows does (tm) :-).
8066 /* MS-CIFS (2.2.4.32.1) behavior. */
8067 return NT_STATUS_DOS(ERRDOS,
8068 ERRcancelviolation);
8070 /* Windows behavior. */
8072 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8073 "cancel request\n"));
8079 if (lp_blocking_locks(SNUM(conn))) {
8081 /* Schedule a message to ourselves to
8082 remove the blocking lock record and
8083 return the right error. */
8085 blr = blocking_lock_cancel_smb1(fsp,
8091 NT_STATUS_FILE_LOCK_CONFLICT);
8093 return NT_STATUS_DOS(
8095 ERRcancelviolation);
8098 /* Remove a matching pending lock. */
8099 status = do_lock_cancel(fsp,
8105 bool blocking_lock = timeout ? true : false;
8106 bool defer_lock = false;
8107 struct byte_range_lock *br_lck;
8108 uint64_t block_smblctx;
8110 br_lck = do_lock(req->sconn->msg_ctx,
8121 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8122 /* Windows internal resolution for blocking locks seems
8123 to be about 200ms... Don't wait for less than that. JRA. */
8124 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8125 timeout = lp_lock_spin_time();
8130 /* If a lock sent with timeout of zero would fail, and
8131 * this lock has been requested multiple times,
8132 * according to brl_lock_failed() we convert this
8133 * request to a blocking lock with a timeout of between
8134 * 150 - 300 milliseconds.
8136 * If lp_lock_spin_time() has been set to 0, we skip
8137 * this blocking retry and fail immediately.
8139 * Replacement for do_lock_spin(). JRA. */
8141 if (!req->sconn->using_smb2 &&
8142 br_lck && lp_blocking_locks(SNUM(conn)) &&
8143 lp_lock_spin_time() && !blocking_lock &&
8144 NT_STATUS_EQUAL((status),
8145 NT_STATUS_FILE_LOCK_CONFLICT))
8148 timeout = lp_lock_spin_time();
8151 if (br_lck && defer_lock) {
8153 * A blocking lock was requested. Package up
8154 * this smb into a queued request and push it
8155 * onto the blocking lock queue.
8157 if(push_blocking_lock_request(br_lck,
8168 TALLOC_FREE(br_lck);
8170 return NT_STATUS_OK;
8174 TALLOC_FREE(br_lck);
8177 if (!NT_STATUS_IS_OK(status)) {
8182 /* If any of the above locks failed, then we must unlock
8183 all of the previous locks (X/Open spec). */
8185 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8187 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8188 i = -1; /* we want to skip the for loop */
8192 * Ensure we don't do a remove on the lock that just failed,
8193 * as under POSIX rules, if we have a lock already there, we
8194 * will delete it (and we shouldn't) .....
8196 for(i--; i >= 0; i--) {
8197 struct smbd_lock_element *e = &locks[i];
8199 do_unlock(req->sconn->msg_ctx,
8209 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8210 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8212 return NT_STATUS_OK;
8215 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8217 uint16_t num_ulocks,
8218 struct smbd_lock_element *ulocks)
8222 for(i = 0; i < (int)num_ulocks; i++) {
8223 struct smbd_lock_element *e = &ulocks[i];
8226 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8227 "pid %u, file %s\n", __func__,
8230 (unsigned int)e->smblctx,
8233 if (e->brltype != UNLOCK_LOCK) {
8234 /* this can only happen with SMB2 */
8235 return NT_STATUS_INVALID_PARAMETER;
8238 status = do_unlock(req->sconn->msg_ctx,
8245 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8246 nt_errstr(status)));
8248 if (!NT_STATUS_IS_OK(status)) {
8253 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8256 return NT_STATUS_OK;
8259 /****************************************************************************
8260 Reply to a lockingX request.
8261 ****************************************************************************/
8263 void reply_lockingX(struct smb_request *req)
8265 connection_struct *conn = req->conn;
8267 unsigned char locktype;
8268 unsigned char oplocklevel;
8269 uint16_t num_ulocks;
8271 int32_t lock_timeout;
8273 const uint8_t *data;
8274 bool large_file_format;
8275 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8276 struct smbd_lock_element *ulocks;
8277 struct smbd_lock_element *locks;
8280 START_PROFILE(SMBlockingX);
8283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8284 END_PROFILE(SMBlockingX);
8288 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8289 locktype = CVAL(req->vwv+3, 0);
8290 oplocklevel = CVAL(req->vwv+3, 1);
8291 num_ulocks = SVAL(req->vwv+6, 0);
8292 num_locks = SVAL(req->vwv+7, 0);
8293 lock_timeout = IVAL(req->vwv+4, 0);
8294 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8296 if (!check_fsp(conn, req, fsp)) {
8297 END_PROFILE(SMBlockingX);
8303 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8304 /* we don't support these - and CANCEL_LOCK makes w2k
8305 and XP reboot so I don't really want to be
8306 compatible! (tridge) */
8307 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8308 END_PROFILE(SMBlockingX);
8312 /* Check if this is an oplock break on a file
8313 we have granted an oplock on.
8315 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8316 /* Client can insist on breaking to none. */
8317 bool break_to_none = (oplocklevel == 0);
8320 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8321 "for %s\n", (unsigned int)oplocklevel,
8322 fsp_fnum_dbg(fsp)));
8325 * Make sure we have granted an exclusive or batch oplock on
8329 if (fsp->oplock_type == 0) {
8331 /* The Samba4 nbench simulator doesn't understand
8332 the difference between break to level2 and break
8333 to none from level2 - it sends oplock break
8334 replies in both cases. Don't keep logging an error
8335 message here - just ignore it. JRA. */
8337 DEBUG(5,("reply_lockingX: Error : oplock break from "
8338 "client for %s (oplock=%d) and no "
8339 "oplock granted on this file (%s).\n",
8340 fsp_fnum_dbg(fsp), fsp->oplock_type,
8343 /* if this is a pure oplock break request then don't
8345 if (num_locks == 0 && num_ulocks == 0) {
8346 END_PROFILE(SMBlockingX);
8349 END_PROFILE(SMBlockingX);
8350 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8355 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8357 result = remove_oplock(fsp);
8359 result = downgrade_oplock(fsp);
8363 DEBUG(0, ("reply_lockingX: error in removing "
8364 "oplock on file %s\n", fsp_str_dbg(fsp)));
8365 /* Hmmm. Is this panic justified? */
8366 smb_panic("internal tdb error");
8369 /* if this is a pure oplock break request then don't send a
8371 if (num_locks == 0 && num_ulocks == 0) {
8372 /* Sanity check - ensure a pure oplock break is not a
8374 if (CVAL(req->vwv+0, 0) != 0xff) {
8375 DEBUG(0,("reply_lockingX: Error : pure oplock "
8376 "break is a chained %d request !\n",
8377 (unsigned int)CVAL(req->vwv+0, 0)));
8379 END_PROFILE(SMBlockingX);
8385 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8387 END_PROFILE(SMBlockingX);
8391 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8392 if (ulocks == NULL) {
8393 reply_nterror(req, NT_STATUS_NO_MEMORY);
8394 END_PROFILE(SMBlockingX);
8398 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8399 if (locks == NULL) {
8400 reply_nterror(req, NT_STATUS_NO_MEMORY);
8401 END_PROFILE(SMBlockingX);
8405 /* Data now points at the beginning of the list
8406 of smb_unlkrng structs */
8407 for(i = 0; i < (int)num_ulocks; i++) {
8408 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8409 ulocks[i].count = get_lock_count(data, i, large_file_format);
8410 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8411 ulocks[i].brltype = UNLOCK_LOCK;
8414 /* Now do any requested locks */
8415 data += ((large_file_format ? 20 : 10)*num_ulocks);
8417 /* Data now points at the beginning of the list
8418 of smb_lkrng structs */
8420 for(i = 0; i < (int)num_locks; i++) {
8421 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8422 locks[i].count = get_lock_count(data, i, large_file_format);
8423 locks[i].offset = get_lock_offset(data, i, large_file_format);
8425 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8426 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8427 locks[i].brltype = PENDING_READ_LOCK;
8429 locks[i].brltype = READ_LOCK;
8432 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8433 locks[i].brltype = PENDING_WRITE_LOCK;
8435 locks[i].brltype = WRITE_LOCK;
8440 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8441 if (!NT_STATUS_IS_OK(status)) {
8442 END_PROFILE(SMBlockingX);
8443 reply_nterror(req, status);
8447 status = smbd_do_locking(req, fsp,
8448 locktype, lock_timeout,
8451 if (!NT_STATUS_IS_OK(status)) {
8452 END_PROFILE(SMBlockingX);
8453 reply_nterror(req, status);
8457 END_PROFILE(SMBlockingX);
8461 reply_outbuf(req, 2, 0);
8462 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8463 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8465 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8466 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8468 END_PROFILE(SMBlockingX);
8472 #define DBGC_CLASS DBGC_ALL
8474 /****************************************************************************
8475 Reply to a SMBreadbmpx (read block multiplex) request.
8476 Always reply with an error, if someone has a platform really needs this,
8477 please contact vl@samba.org
8478 ****************************************************************************/
8480 void reply_readbmpx(struct smb_request *req)
8482 START_PROFILE(SMBreadBmpx);
8483 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8484 END_PROFILE(SMBreadBmpx);
8488 /****************************************************************************
8489 Reply to a SMBreadbs (read block multiplex secondary) request.
8490 Always reply with an error, if someone has a platform really needs this,
8491 please contact vl@samba.org
8492 ****************************************************************************/
8494 void reply_readbs(struct smb_request *req)
8496 START_PROFILE(SMBreadBs);
8497 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8498 END_PROFILE(SMBreadBs);
8502 /****************************************************************************
8503 Reply to a SMBsetattrE.
8504 ****************************************************************************/
8506 void reply_setattrE(struct smb_request *req)
8508 connection_struct *conn = req->conn;
8509 struct smb_file_time ft;
8513 START_PROFILE(SMBsetattrE);
8517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8521 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8523 if(!fsp || (fsp->conn != conn)) {
8524 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8529 * Convert the DOS times into unix times.
8532 ft.atime = convert_time_t_to_timespec(
8533 srv_make_unix_date2(req->vwv+3));
8534 ft.mtime = convert_time_t_to_timespec(
8535 srv_make_unix_date2(req->vwv+5));
8536 ft.create_time = convert_time_t_to_timespec(
8537 srv_make_unix_date2(req->vwv+1));
8539 reply_outbuf(req, 0, 0);
8542 * Patch from Ray Frush <frush@engr.colostate.edu>
8543 * Sometimes times are sent as zero - ignore them.
8546 /* Ensure we have a valid stat struct for the source. */
8547 status = vfs_stat_fsp(fsp);
8548 if (!NT_STATUS_IS_OK(status)) {
8549 reply_nterror(req, status);
8553 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8554 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8558 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8559 if (!NT_STATUS_IS_OK(status)) {
8560 reply_nterror(req, status);
8564 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8567 (unsigned int)ft.atime.tv_sec,
8568 (unsigned int)ft.mtime.tv_sec,
8569 (unsigned int)ft.create_time.tv_sec
8572 END_PROFILE(SMBsetattrE);
8577 /* Back from the dead for OS/2..... JRA. */
8579 /****************************************************************************
8580 Reply to a SMBwritebmpx (write block multiplex primary) request.
8581 Always reply with an error, if someone has a platform really needs this,
8582 please contact vl@samba.org
8583 ****************************************************************************/
8585 void reply_writebmpx(struct smb_request *req)
8587 START_PROFILE(SMBwriteBmpx);
8588 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8589 END_PROFILE(SMBwriteBmpx);
8593 /****************************************************************************
8594 Reply to a SMBwritebs (write block multiplex secondary) request.
8595 Always reply with an error, if someone has a platform really needs this,
8596 please contact vl@samba.org
8597 ****************************************************************************/
8599 void reply_writebs(struct smb_request *req)
8601 START_PROFILE(SMBwriteBs);
8602 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8603 END_PROFILE(SMBwriteBs);
8607 /****************************************************************************
8608 Reply to a SMBgetattrE.
8609 ****************************************************************************/
8611 void reply_getattrE(struct smb_request *req)
8613 connection_struct *conn = req->conn;
8616 struct timespec create_ts;
8618 START_PROFILE(SMBgetattrE);
8621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8622 END_PROFILE(SMBgetattrE);
8626 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8628 if(!fsp || (fsp->conn != conn)) {
8629 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8630 END_PROFILE(SMBgetattrE);
8634 /* Do an fstat on this file */
8636 reply_nterror(req, map_nt_error_from_unix(errno));
8637 END_PROFILE(SMBgetattrE);
8641 mode = dos_mode(conn, fsp->fsp_name);
8644 * Convert the times into dos times. Set create
8645 * date to be last modify date as UNIX doesn't save
8649 reply_outbuf(req, 11, 0);
8651 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8652 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8653 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8654 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8655 /* Should we check pending modtime here ? JRA */
8656 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8657 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8659 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8660 SIVAL(req->outbuf, smb_vwv6, 0);
8661 SIVAL(req->outbuf, smb_vwv8, 0);
8663 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8664 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8665 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8667 SSVAL(req->outbuf,smb_vwv10, mode);
8669 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8671 END_PROFILE(SMBgetattrE);