2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
266 bool posix_pathnames,
268 bool *contains_wcard)
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 *err = NT_STATUS_INVALID_PARAMETER;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
369 return srvstr_get_path_wcard_internal(ctx,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
396 return srvstr_get_path_wcard_internal(ctx,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
416 *err = NT_STATUS_INVALID_PARAMETER;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
497 if (!check_fsp_open(conn, req, fsp)) {
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
508 fsp->num_smb_operations++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
520 if (!check_fsp_open(conn, req, fsp)) {
524 if (fsp->is_directory) {
528 if (fsp->fake_file_handle == NULL) {
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 if (fsp->fake_file_handle->private_data == NULL) {
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
547 char *trim_name_type;
548 const char *retarget_parm;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
570 if (trim_name_type == NULL) {
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm == NULL) {
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
600 if (sscanf(p, "%x", &retarget_type) != 1) {
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
607 DEBUG(10, ("could not resolve %s\n", retarget));
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name);
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1, name_type2;
668 int name_len1, name_len2;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf);
755 reload_services(sconn, conn_snum_used, true);
758 xconn->transport.nbt.got_session = true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
784 if (CVAL(outbuf, 0) != 0x82) {
785 exit_server_cleanly("invalid netbios session");
790 /****************************************************************************
792 conn POINTER CAN BE NULL HERE !
793 ****************************************************************************/
795 void reply_tcon(struct smb_request *req)
797 connection_struct *conn = req->conn;
799 char *service_buf = NULL;
800 char *password = NULL;
806 TALLOC_CTX *ctx = talloc_tos();
807 struct smbXsrv_connection *xconn = req->xconn;
808 NTTIME now = timeval_to_nttime(&req->request_time);
810 START_PROFILE(SMBtcon);
812 if (req->buflen < 4) {
813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
814 END_PROFILE(SMBtcon);
819 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
821 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
823 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
826 if (service_buf == NULL || password == NULL || dev == NULL) {
827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
828 END_PROFILE(SMBtcon);
831 p2 = strrchr_m(service_buf,'\\');
835 service = service_buf;
838 conn = make_connection(req, now, service, dev,
839 req->vuid,&nt_status);
843 reply_nterror(req, nt_status);
844 END_PROFILE(SMBtcon);
848 reply_outbuf(req, 2, 0);
849 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
850 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
853 DEBUG(3,("tcon service=%s cnum=%d\n",
854 service, conn->cnum));
856 END_PROFILE(SMBtcon);
860 /****************************************************************************
861 Reply to a tcon and X.
862 conn POINTER CAN BE NULL HERE !
863 ****************************************************************************/
865 void reply_tcon_and_X(struct smb_request *req)
867 connection_struct *conn = req->conn;
868 const char *service = NULL;
869 TALLOC_CTX *ctx = talloc_tos();
870 /* what the cleint thinks the device is */
871 char *client_devicetype = NULL;
872 /* what the server tells the client the share represents */
873 const char *server_devicetype;
880 struct smbXsrv_session *session = NULL;
881 NTTIME now = timeval_to_nttime(&req->request_time);
882 bool session_key_updated = false;
883 uint16_t optional_support = 0;
884 struct smbXsrv_connection *xconn = req->xconn;
886 START_PROFILE(SMBtconX);
889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
890 END_PROFILE(SMBtconX);
894 passlen = SVAL(req->vwv+3, 0);
895 tcon_flags = SVAL(req->vwv+2, 0);
897 /* we might have to close an old one */
898 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
899 struct smbXsrv_tcon *tcon;
907 * TODO: cancel all outstanding requests on the tcon
909 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(0, ("reply_tcon_and_X: "
912 "smbXsrv_tcon_disconnect() failed: %s\n",
915 * If we hit this case, there is something completely
916 * wrong, so we better disconnect the transport connection.
918 END_PROFILE(SMBtconX);
919 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
926 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
927 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
928 END_PROFILE(SMBtconX);
932 if (xconn->smb1.negprot.encrypted_passwords) {
933 p = req->buf + passlen;
935 p = req->buf + passlen + 1;
938 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
942 END_PROFILE(SMBtconX);
947 * the service name can be either: \\server\share
948 * or share directly like on the DELL PowerVault 705
951 q = strchr_m(path+2,'\\');
953 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
954 END_PROFILE(SMBtconX);
962 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
963 &client_devicetype, p,
964 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
966 if (client_devicetype == NULL) {
967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
968 END_PROFILE(SMBtconX);
972 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
974 nt_status = smb1srv_session_lookup(xconn,
975 req->vuid, now, &session);
976 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
977 reply_force_doserror(req, ERRSRV, ERRbaduid);
978 END_PROFILE(SMBtconX);
981 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
982 reply_nterror(req, nt_status);
983 END_PROFILE(SMBtconX);
986 if (!NT_STATUS_IS_OK(nt_status)) {
987 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
988 END_PROFILE(SMBtconX);
992 if (session->global->auth_session_info == NULL) {
993 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
994 END_PROFILE(SMBtconX);
999 * If there is no application key defined yet
1002 * This means we setup the application key on the
1003 * first tcon that happens via the given session.
1005 * Once the application key is defined, it does not
1008 if (session->global->application_key.length == 0 &&
1009 session->global->signing_key.length > 0)
1011 struct smbXsrv_session *x = session;
1012 struct auth_session_info *session_info =
1013 session->global->auth_session_info;
1014 uint8_t session_key[16];
1016 ZERO_STRUCT(session_key);
1017 memcpy(session_key, x->global->signing_key.data,
1018 MIN(x->global->signing_key.length, sizeof(session_key)));
1021 * The application key is truncated/padded to 16 bytes
1023 x->global->application_key = data_blob_talloc(x->global,
1025 sizeof(session_key));
1026 ZERO_STRUCT(session_key);
1027 if (x->global->application_key.data == NULL) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 END_PROFILE(SMBtconX);
1033 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1034 smb_key_derivation(x->global->application_key.data,
1035 x->global->application_key.length,
1036 x->global->application_key.data);
1037 optional_support |= SMB_EXTENDED_SIGNATURES;
1041 * Place the application key into the session_info
1043 data_blob_clear_free(&session_info->session_key);
1044 session_info->session_key = data_blob_dup_talloc(session_info,
1045 x->global->application_key);
1046 if (session_info->session_key.data == NULL) {
1047 data_blob_clear_free(&x->global->application_key);
1048 reply_nterror(req, NT_STATUS_NO_MEMORY);
1049 END_PROFILE(SMBtconX);
1052 session_key_updated = true;
1055 conn = make_connection(req, now, service, client_devicetype,
1056 req->vuid, &nt_status);
1060 if (session_key_updated) {
1061 struct smbXsrv_session *x = session;
1062 struct auth_session_info *session_info =
1063 session->global->auth_session_info;
1064 data_blob_clear_free(&x->global->application_key);
1065 data_blob_clear_free(&session_info->session_key);
1067 reply_nterror(req, nt_status);
1068 END_PROFILE(SMBtconX);
1073 server_devicetype = "IPC";
1074 else if ( IS_PRINT(conn) )
1075 server_devicetype = "LPT1:";
1077 server_devicetype = "A:";
1079 if (get_Protocol() < PROTOCOL_NT1) {
1080 reply_outbuf(req, 2, 0);
1081 if (message_push_string(&req->outbuf, server_devicetype,
1082 STR_TERMINATE|STR_ASCII) == -1) {
1083 reply_nterror(req, NT_STATUS_NO_MEMORY);
1084 END_PROFILE(SMBtconX);
1088 /* NT sets the fstype of IPC$ to the null string */
1089 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1091 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1092 /* Return permissions. */
1096 reply_outbuf(req, 7, 0);
1099 perm1 = FILE_ALL_ACCESS;
1100 perm2 = FILE_ALL_ACCESS;
1102 perm1 = conn->share_access;
1105 SIVAL(req->outbuf, smb_vwv3, perm1);
1106 SIVAL(req->outbuf, smb_vwv5, perm2);
1108 reply_outbuf(req, 3, 0);
1111 if ((message_push_string(&req->outbuf, server_devicetype,
1112 STR_TERMINATE|STR_ASCII) == -1)
1113 || (message_push_string(&req->outbuf, fstype,
1114 STR_TERMINATE) == -1)) {
1115 reply_nterror(req, NT_STATUS_NO_MEMORY);
1116 END_PROFILE(SMBtconX);
1120 /* what does setting this bit do? It is set by NT4 and
1121 may affect the ability to autorun mounted cdroms */
1122 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1124 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1126 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1127 DEBUG(2,("Serving %s as a Dfs root\n",
1128 lp_servicename(ctx, SNUM(conn)) ));
1129 optional_support |= SMB_SHARE_IN_DFS;
1132 SSVAL(req->outbuf, smb_vwv2, optional_support);
1135 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1136 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1138 DEBUG(3,("tconX service=%s \n",
1141 /* set the incoming and outgoing tid to the just created one */
1142 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1143 SSVAL(req->outbuf,smb_tid,conn->cnum);
1145 END_PROFILE(SMBtconX);
1147 req->tid = conn->cnum;
1150 /****************************************************************************
1151 Reply to an unknown type.
1152 ****************************************************************************/
1154 void reply_unknown_new(struct smb_request *req, uint8_t type)
1156 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1157 smb_fn_name(type), type, type));
1158 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1162 /****************************************************************************
1164 conn POINTER CAN BE NULL HERE !
1165 ****************************************************************************/
1167 void reply_ioctl(struct smb_request *req)
1169 connection_struct *conn = req->conn;
1172 uint32_t ioctl_code;
1176 START_PROFILE(SMBioctl);
1179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1180 END_PROFILE(SMBioctl);
1184 device = SVAL(req->vwv+1, 0);
1185 function = SVAL(req->vwv+2, 0);
1186 ioctl_code = (device << 16) + function;
1188 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1190 switch (ioctl_code) {
1191 case IOCTL_QUERY_JOB_INFO:
1195 reply_force_doserror(req, ERRSRV, ERRnosupport);
1196 END_PROFILE(SMBioctl);
1200 reply_outbuf(req, 8, replysize+1);
1201 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1202 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1203 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1204 p = smb_buf(req->outbuf);
1205 memset(p, '\0', replysize+1); /* valgrind-safe. */
1206 p += 1; /* Allow for alignment */
1208 switch (ioctl_code) {
1209 case IOCTL_QUERY_JOB_INFO:
1213 files_struct *fsp = file_fsp(
1214 req, SVAL(req->vwv+0, 0));
1216 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1217 END_PROFILE(SMBioctl);
1221 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1223 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1224 lp_netbios_name(), 15,
1225 STR_TERMINATE|STR_ASCII, &len);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 reply_nterror(req, status);
1228 END_PROFILE(SMBioctl);
1232 status = srvstr_push((char *)req->outbuf, req->flags2,
1234 lp_servicename(talloc_tos(),
1236 13, STR_TERMINATE|STR_ASCII, &len);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_nterror(req, status);
1239 END_PROFILE(SMBioctl);
1243 memset(p+18, 0, 13);
1249 END_PROFILE(SMBioctl);
1253 /****************************************************************************
1254 Strange checkpath NTSTATUS mapping.
1255 ****************************************************************************/
1257 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1259 /* Strange DOS error code semantics only for checkpath... */
1260 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1261 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1262 /* We need to map to ERRbadpath */
1263 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1269 /****************************************************************************
1270 Reply to a checkpath.
1271 ****************************************************************************/
1273 void reply_checkpath(struct smb_request *req)
1275 connection_struct *conn = req->conn;
1276 struct smb_filename *smb_fname = NULL;
1279 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1280 TALLOC_CTX *ctx = talloc_tos();
1282 START_PROFILE(SMBcheckpath);
1284 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1285 STR_TERMINATE, &status);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 status = map_checkpath_error(req->flags2, status);
1289 reply_nterror(req, status);
1290 END_PROFILE(SMBcheckpath);
1294 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1296 status = filename_convert(ctx,
1298 req->flags2 & FLAGS2_DFS_PATHNAMES,
1304 if (!NT_STATUS_IS_OK(status)) {
1305 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1306 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1307 ERRSRV, ERRbadpath);
1308 END_PROFILE(SMBcheckpath);
1314 if (!VALID_STAT(smb_fname->st) &&
1315 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1316 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1317 smb_fname_str_dbg(smb_fname), strerror(errno)));
1318 status = map_nt_error_from_unix(errno);
1322 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1323 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1324 ERRDOS, ERRbadpath);
1328 reply_outbuf(req, 0, 0);
1331 /* We special case this - as when a Windows machine
1332 is parsing a path is steps through the components
1333 one at a time - if a component fails it expects
1334 ERRbadpath, not ERRbadfile.
1336 status = map_checkpath_error(req->flags2, status);
1337 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1339 * Windows returns different error codes if
1340 * the parent directory is valid but not the
1341 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1342 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1343 * if the path is invalid.
1345 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1346 ERRDOS, ERRbadpath);
1350 reply_nterror(req, status);
1353 TALLOC_FREE(smb_fname);
1354 END_PROFILE(SMBcheckpath);
1358 /****************************************************************************
1360 ****************************************************************************/
1362 void reply_getatr(struct smb_request *req)
1364 connection_struct *conn = req->conn;
1365 struct smb_filename *smb_fname = NULL;
1372 TALLOC_CTX *ctx = talloc_tos();
1373 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1375 START_PROFILE(SMBgetatr);
1377 p = (const char *)req->buf + 1;
1378 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 reply_nterror(req, status);
1384 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1385 under WfWg - weird! */
1386 if (*fname == '\0') {
1387 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1388 if (!CAN_WRITE(conn)) {
1389 mode |= FILE_ATTRIBUTE_READONLY;
1394 uint32_t ucf_flags = (req->posix_pathnames ?
1395 UCF_POSIX_PATHNAMES : 0);
1396 status = filename_convert(ctx,
1398 req->flags2 & FLAGS2_DFS_PATHNAMES,
1403 if (!NT_STATUS_IS_OK(status)) {
1404 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1405 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1406 ERRSRV, ERRbadpath);
1409 reply_nterror(req, status);
1412 if (!VALID_STAT(smb_fname->st) &&
1413 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1414 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1415 smb_fname_str_dbg(smb_fname),
1417 reply_nterror(req, map_nt_error_from_unix(errno));
1421 mode = dos_mode(conn, smb_fname);
1422 size = smb_fname->st.st_ex_size;
1424 if (ask_sharemode) {
1425 struct timespec write_time_ts;
1426 struct file_id fileid;
1428 ZERO_STRUCT(write_time_ts);
1429 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1430 get_file_infos(fileid, 0, NULL, &write_time_ts);
1431 if (!null_timespec(write_time_ts)) {
1432 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1436 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1437 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1442 reply_outbuf(req, 10, 0);
1444 SSVAL(req->outbuf,smb_vwv0,mode);
1445 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1446 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1448 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1450 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1452 if (get_Protocol() >= PROTOCOL_NT1) {
1453 SSVAL(req->outbuf, smb_flg2,
1454 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1457 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1458 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1461 TALLOC_FREE(smb_fname);
1463 END_PROFILE(SMBgetatr);
1467 /****************************************************************************
1469 ****************************************************************************/
1471 void reply_setatr(struct smb_request *req)
1473 struct smb_file_time ft;
1474 connection_struct *conn = req->conn;
1475 struct smb_filename *smb_fname = NULL;
1481 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1482 TALLOC_CTX *ctx = talloc_tos();
1484 START_PROFILE(SMBsetatr);
1489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1493 p = (const char *)req->buf + 1;
1494 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 reply_nterror(req, status);
1500 status = filename_convert(ctx,
1502 req->flags2 & FLAGS2_DFS_PATHNAMES,
1507 if (!NT_STATUS_IS_OK(status)) {
1508 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1509 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1510 ERRSRV, ERRbadpath);
1513 reply_nterror(req, status);
1517 if (smb_fname->base_name[0] == '.' &&
1518 smb_fname->base_name[1] == '\0') {
1520 * Not sure here is the right place to catch this
1521 * condition. Might be moved to somewhere else later -- vl
1523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1527 mode = SVAL(req->vwv+0, 0);
1528 mtime = srv_make_unix_date3(req->vwv+1);
1530 if (mode != FILE_ATTRIBUTE_NORMAL) {
1531 if (VALID_STAT_OF_DIR(smb_fname->st))
1532 mode |= FILE_ATTRIBUTE_DIRECTORY;
1534 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1536 status = check_access(conn, NULL, smb_fname,
1537 FILE_WRITE_ATTRIBUTES);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 reply_nterror(req, status);
1543 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1545 reply_nterror(req, map_nt_error_from_unix(errno));
1550 ft.mtime = convert_time_t_to_timespec(mtime);
1551 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 reply_nterror(req, status);
1557 reply_outbuf(req, 0, 0);
1559 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1562 TALLOC_FREE(smb_fname);
1563 END_PROFILE(SMBsetatr);
1567 /****************************************************************************
1569 ****************************************************************************/
1571 void reply_dskattr(struct smb_request *req)
1573 connection_struct *conn = req->conn;
1575 uint64_t dfree,dsize,bsize;
1576 struct smb_filename smb_fname;
1577 START_PROFILE(SMBdskattr);
1579 ZERO_STRUCT(smb_fname);
1580 smb_fname.base_name = discard_const_p(char, ".");
1582 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1583 reply_nterror(req, map_nt_error_from_unix(errno));
1584 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1585 END_PROFILE(SMBdskattr);
1589 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1590 if (ret == (uint64_t)-1) {
1591 reply_nterror(req, map_nt_error_from_unix(errno));
1592 END_PROFILE(SMBdskattr);
1597 * Force max to fit in 16 bit fields.
1599 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1603 if (bsize > (WORDMAX*512)) {
1604 bsize = (WORDMAX*512);
1605 if (dsize > WORDMAX)
1607 if (dfree > WORDMAX)
1613 reply_outbuf(req, 5, 0);
1615 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1616 double total_space, free_space;
1617 /* we need to scale this to a number that DOS6 can handle. We
1618 use floating point so we can handle large drives on systems
1619 that don't have 64 bit integers
1621 we end up displaying a maximum of 2G to DOS systems
1623 total_space = dsize * (double)bsize;
1624 free_space = dfree * (double)bsize;
1626 dsize = (uint64_t)((total_space+63*512) / (64*512));
1627 dfree = (uint64_t)((free_space+63*512) / (64*512));
1629 if (dsize > 0xFFFF) dsize = 0xFFFF;
1630 if (dfree > 0xFFFF) dfree = 0xFFFF;
1632 SSVAL(req->outbuf,smb_vwv0,dsize);
1633 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1634 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1635 SSVAL(req->outbuf,smb_vwv3,dfree);
1637 SSVAL(req->outbuf,smb_vwv0,dsize);
1638 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1639 SSVAL(req->outbuf,smb_vwv2,512);
1640 SSVAL(req->outbuf,smb_vwv3,dfree);
1643 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1645 END_PROFILE(SMBdskattr);
1650 * Utility function to split the filename from the directory.
1652 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1653 char **fname_dir_out,
1654 char **fname_mask_out)
1656 const char *p = NULL;
1657 char *fname_dir = NULL;
1658 char *fname_mask = NULL;
1660 p = strrchr_m(fname_in, '/');
1662 fname_dir = talloc_strdup(ctx, ".");
1663 fname_mask = talloc_strdup(ctx, fname_in);
1665 fname_dir = talloc_strndup(ctx, fname_in,
1666 PTR_DIFF(p, fname_in));
1667 fname_mask = talloc_strdup(ctx, p+1);
1670 if (!fname_dir || !fname_mask) {
1671 TALLOC_FREE(fname_dir);
1672 TALLOC_FREE(fname_mask);
1673 return NT_STATUS_NO_MEMORY;
1676 *fname_dir_out = fname_dir;
1677 *fname_mask_out = fname_mask;
1678 return NT_STATUS_OK;
1681 /****************************************************************************
1683 ****************************************************************************/
1685 static bool make_dir_struct(TALLOC_CTX *ctx,
1695 char *mask2 = talloc_strdup(ctx, mask);
1701 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1705 memset(buf+1,' ',11);
1706 if ((p = strchr_m(mask2,'.')) != NULL) {
1708 push_ascii(buf+1,mask2,8, 0);
1709 push_ascii(buf+9,p+1,3, 0);
1712 push_ascii(buf+1,mask2,11, 0);
1715 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1717 srv_put_dos_date(buf,22,date);
1718 SSVAL(buf,26,size & 0xFFFF);
1719 SSVAL(buf,28,(size >> 16)&0xFFFF);
1720 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1721 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1722 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1723 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1727 /****************************************************************************
1729 Can be called from SMBsearch, SMBffirst or SMBfunique.
1730 ****************************************************************************/
1732 void reply_search(struct smb_request *req)
1734 connection_struct *conn = req->conn;
1737 char *directory = NULL;
1738 struct smb_filename *smb_fname = NULL;
1742 struct timespec date;
1744 unsigned int numentries = 0;
1745 unsigned int maxentries = 0;
1746 bool finished = False;
1751 bool check_descend = False;
1752 bool expect_close = False;
1754 bool mask_contains_wcard = False;
1755 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1756 TALLOC_CTX *ctx = talloc_tos();
1757 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1758 struct dptr_struct *dirptr = NULL;
1759 struct smbXsrv_connection *xconn = req->xconn;
1760 struct smbd_server_connection *sconn = req->sconn;
1762 START_PROFILE(SMBsearch);
1765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1769 if (req->posix_pathnames) {
1770 reply_unknown_new(req, req->cmd);
1774 /* If we were called as SMBffirst then we must expect close. */
1775 if(req->cmd == SMBffirst) {
1776 expect_close = True;
1779 reply_outbuf(req, 1, 3);
1780 maxentries = SVAL(req->vwv+0, 0);
1781 dirtype = SVAL(req->vwv+1, 0);
1782 p = (const char *)req->buf + 1;
1783 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1784 &nt_status, &mask_contains_wcard);
1785 if (!NT_STATUS_IS_OK(nt_status)) {
1786 reply_nterror(req, nt_status);
1791 status_len = SVAL(p, 0);
1794 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1796 if (status_len == 0) {
1797 struct smb_filename *smb_dname = NULL;
1798 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1799 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1800 nt_status = filename_convert(ctx, conn,
1801 req->flags2 & FLAGS2_DFS_PATHNAMES,
1804 &mask_contains_wcard,
1806 if (!NT_STATUS_IS_OK(nt_status)) {
1807 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1808 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1809 ERRSRV, ERRbadpath);
1812 reply_nterror(req, nt_status);
1816 directory = smb_fname->base_name;
1818 p = strrchr_m(directory,'/');
1819 if ((p != NULL) && (*directory != '/')) {
1820 mask = talloc_strdup(ctx, p + 1);
1821 directory = talloc_strndup(ctx, directory,
1822 PTR_DIFF(p, directory));
1824 mask = talloc_strdup(ctx, directory);
1825 directory = talloc_strdup(ctx,".");
1829 reply_nterror(req, NT_STATUS_NO_MEMORY);
1833 memset((char *)status,'\0',21);
1834 SCVAL(status,0,(dirtype & 0x1F));
1836 smb_dname = synthetic_smb_fname(talloc_tos(),
1841 if (smb_dname == NULL) {
1842 reply_nterror(req, NT_STATUS_NO_MEMORY);
1846 nt_status = dptr_create(conn,
1854 mask_contains_wcard,
1858 TALLOC_FREE(smb_dname);
1860 if (!NT_STATUS_IS_OK(nt_status)) {
1861 reply_nterror(req, nt_status);
1864 dptr_num = dptr_dnum(dirptr);
1867 const char *dirpath;
1869 memcpy(status,p,21);
1870 status_dirtype = CVAL(status,0) & 0x1F;
1871 if (status_dirtype != (dirtype & 0x1F)) {
1872 dirtype = status_dirtype;
1875 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1879 dirpath = dptr_path(sconn, dptr_num);
1880 directory = talloc_strdup(ctx, dirpath);
1882 reply_nterror(req, NT_STATUS_NO_MEMORY);
1886 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1891 * For a 'continue' search we have no string. So
1892 * check from the initial saved string.
1894 if (!req->posix_pathnames) {
1895 mask_contains_wcard = ms_has_wild(mask);
1897 dirtype = dptr_attr(sconn, dptr_num);
1900 DEBUG(4,("dptr_num is %d\n",dptr_num));
1902 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1903 dptr_init_search_op(dirptr);
1905 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1906 char buf[DIR_STRUCT_SIZE];
1907 memcpy(buf,status,21);
1908 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1909 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1910 reply_nterror(req, NT_STATUS_NO_MEMORY);
1913 dptr_fill(sconn, buf+12,dptr_num);
1914 if (dptr_zero(buf+12) && (status_len==0)) {
1919 if (message_push_blob(&req->outbuf,
1920 data_blob_const(buf, sizeof(buf)))
1922 reply_nterror(req, NT_STATUS_NO_MEMORY);
1927 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1928 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1930 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1932 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1933 directory,lp_dont_descend(ctx, SNUM(conn))));
1934 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1935 check_descend = True;
1938 for (i=numentries;(i<maxentries) && !finished;i++) {
1939 finished = !get_dir_entry(ctx,
1950 char buf[DIR_STRUCT_SIZE];
1951 memcpy(buf,status,21);
1952 if (!make_dir_struct(ctx,
1958 convert_timespec_to_time_t(date),
1959 !allow_long_path_components)) {
1960 reply_nterror(req, NT_STATUS_NO_MEMORY);
1963 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1966 if (message_push_blob(&req->outbuf,
1967 data_blob_const(buf, sizeof(buf)))
1969 reply_nterror(req, NT_STATUS_NO_MEMORY);
1979 /* If we were called as SMBffirst with smb_search_id == NULL
1980 and no entries were found then return error and close dirptr
1983 if (numentries == 0) {
1984 dptr_close(sconn, &dptr_num);
1985 } else if(expect_close && status_len == 0) {
1986 /* Close the dptr - we know it's gone */
1987 dptr_close(sconn, &dptr_num);
1990 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1991 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1992 dptr_close(sconn, &dptr_num);
1995 if ((numentries == 0) && !mask_contains_wcard) {
1996 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2000 SSVAL(req->outbuf,smb_vwv0,numentries);
2001 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2002 SCVAL(smb_buf(req->outbuf),0,5);
2003 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2005 /* The replies here are never long name. */
2006 SSVAL(req->outbuf, smb_flg2,
2007 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2008 if (!allow_long_path_components) {
2009 SSVAL(req->outbuf, smb_flg2,
2010 SVAL(req->outbuf, smb_flg2)
2011 & (~FLAGS2_LONG_PATH_COMPONENTS));
2014 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2015 SSVAL(req->outbuf, smb_flg2,
2016 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2018 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2019 smb_fn_name(req->cmd),
2026 TALLOC_FREE(directory);
2028 TALLOC_FREE(smb_fname);
2029 END_PROFILE(SMBsearch);
2033 /****************************************************************************
2034 Reply to a fclose (stop directory search).
2035 ****************************************************************************/
2037 void reply_fclose(struct smb_request *req)
2045 bool path_contains_wcard = False;
2046 TALLOC_CTX *ctx = talloc_tos();
2047 struct smbd_server_connection *sconn = req->sconn;
2049 START_PROFILE(SMBfclose);
2051 if (req->posix_pathnames) {
2052 reply_unknown_new(req, req->cmd);
2053 END_PROFILE(SMBfclose);
2057 p = (const char *)req->buf + 1;
2058 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2059 &err, &path_contains_wcard);
2060 if (!NT_STATUS_IS_OK(err)) {
2061 reply_nterror(req, err);
2062 END_PROFILE(SMBfclose);
2066 status_len = SVAL(p,0);
2069 if (status_len == 0) {
2070 reply_force_doserror(req, ERRSRV, ERRsrverror);
2071 END_PROFILE(SMBfclose);
2075 memcpy(status,p,21);
2077 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2078 /* Close the dptr - we know it's gone */
2079 dptr_close(sconn, &dptr_num);
2082 reply_outbuf(req, 1, 0);
2083 SSVAL(req->outbuf,smb_vwv0,0);
2085 DEBUG(3,("search close\n"));
2087 END_PROFILE(SMBfclose);
2091 /****************************************************************************
2093 ****************************************************************************/
2095 void reply_open(struct smb_request *req)
2097 connection_struct *conn = req->conn;
2098 struct smb_filename *smb_fname = NULL;
2108 uint32_t access_mask;
2109 uint32_t share_mode;
2110 uint32_t create_disposition;
2111 uint32_t create_options = 0;
2112 uint32_t private_flags = 0;
2115 TALLOC_CTX *ctx = talloc_tos();
2117 START_PROFILE(SMBopen);
2120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2124 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2125 deny_mode = SVAL(req->vwv+0, 0);
2126 dos_attr = SVAL(req->vwv+1, 0);
2128 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2129 STR_TERMINATE, &status);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 reply_nterror(req, status);
2135 if (!map_open_params_to_ntcreate(fname, deny_mode,
2136 OPENX_FILE_EXISTS_OPEN, &access_mask,
2137 &share_mode, &create_disposition,
2138 &create_options, &private_flags)) {
2139 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2143 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2145 status = filename_convert(ctx,
2147 req->flags2 & FLAGS2_DFS_PATHNAMES,
2152 if (!NT_STATUS_IS_OK(status)) {
2153 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2154 reply_botherror(req,
2155 NT_STATUS_PATH_NOT_COVERED,
2156 ERRSRV, ERRbadpath);
2159 reply_nterror(req, status);
2163 status = SMB_VFS_CREATE_FILE(
2166 0, /* root_dir_fid */
2167 smb_fname, /* fname */
2168 access_mask, /* access_mask */
2169 share_mode, /* share_access */
2170 create_disposition, /* create_disposition*/
2171 create_options, /* create_options */
2172 dos_attr, /* file_attributes */
2173 oplock_request, /* oplock_request */
2175 0, /* allocation_size */
2181 NULL, NULL); /* create context */
2183 if (!NT_STATUS_IS_OK(status)) {
2184 if (open_was_deferred(req->xconn, req->mid)) {
2185 /* We have re-scheduled this call. */
2188 reply_openerror(req, status);
2192 /* Ensure we're pointing at the correct stat struct. */
2193 TALLOC_FREE(smb_fname);
2194 smb_fname = fsp->fsp_name;
2196 size = smb_fname->st.st_ex_size;
2197 fattr = dos_mode(conn, smb_fname);
2199 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2201 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2202 DEBUG(3,("attempt to open a directory %s\n",
2204 close_file(req, fsp, ERROR_CLOSE);
2205 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2206 ERRDOS, ERRnoaccess);
2210 reply_outbuf(req, 7, 0);
2211 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2212 SSVAL(req->outbuf,smb_vwv1,fattr);
2213 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2214 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2216 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2218 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2219 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2221 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2222 SCVAL(req->outbuf,smb_flg,
2223 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2226 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2227 SCVAL(req->outbuf,smb_flg,
2228 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2231 END_PROFILE(SMBopen);
2235 /****************************************************************************
2236 Reply to an open and X.
2237 ****************************************************************************/
2239 void reply_open_and_X(struct smb_request *req)
2241 connection_struct *conn = req->conn;
2242 struct smb_filename *smb_fname = NULL;
2244 uint16_t open_flags;
2247 /* Breakout the oplock request bits so we can set the
2248 reply bits separately. */
2249 int ex_oplock_request;
2250 int core_oplock_request;
2253 int smb_sattr = SVAL(req->vwv+4, 0);
2254 uint32_t smb_time = make_unix_date3(req->vwv+6);
2262 uint64_t allocation_size;
2263 ssize_t retval = -1;
2264 uint32_t access_mask;
2265 uint32_t share_mode;
2266 uint32_t create_disposition;
2267 uint32_t create_options = 0;
2268 uint32_t private_flags = 0;
2270 TALLOC_CTX *ctx = talloc_tos();
2272 START_PROFILE(SMBopenX);
2274 if (req->wct < 15) {
2275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2279 open_flags = SVAL(req->vwv+2, 0);
2280 deny_mode = SVAL(req->vwv+3, 0);
2281 smb_attr = SVAL(req->vwv+5, 0);
2282 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2283 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2284 oplock_request = ex_oplock_request | core_oplock_request;
2285 smb_ofun = SVAL(req->vwv+8, 0);
2286 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2288 /* If it's an IPC, pass off the pipe handler. */
2290 if (lp_nt_pipe_support()) {
2291 reply_open_pipe_and_X(conn, req);
2293 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2298 /* XXXX we need to handle passed times, sattr and flags */
2299 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2300 STR_TERMINATE, &status);
2301 if (!NT_STATUS_IS_OK(status)) {
2302 reply_nterror(req, status);
2306 if (!map_open_params_to_ntcreate(fname, deny_mode,
2308 &access_mask, &share_mode,
2309 &create_disposition,
2312 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2316 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2318 status = filename_convert(ctx,
2320 req->flags2 & FLAGS2_DFS_PATHNAMES,
2325 if (!NT_STATUS_IS_OK(status)) {
2326 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2327 reply_botherror(req,
2328 NT_STATUS_PATH_NOT_COVERED,
2329 ERRSRV, ERRbadpath);
2332 reply_nterror(req, status);
2336 status = SMB_VFS_CREATE_FILE(
2339 0, /* root_dir_fid */
2340 smb_fname, /* fname */
2341 access_mask, /* access_mask */
2342 share_mode, /* share_access */
2343 create_disposition, /* create_disposition*/
2344 create_options, /* create_options */
2345 smb_attr, /* file_attributes */
2346 oplock_request, /* oplock_request */
2348 0, /* allocation_size */
2353 &smb_action, /* pinfo */
2354 NULL, NULL); /* create context */
2356 if (!NT_STATUS_IS_OK(status)) {
2357 if (open_was_deferred(req->xconn, req->mid)) {
2358 /* We have re-scheduled this call. */
2361 reply_openerror(req, status);
2365 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2366 if the file is truncated or created. */
2367 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2368 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2369 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2370 close_file(req, fsp, ERROR_CLOSE);
2371 reply_nterror(req, NT_STATUS_DISK_FULL);
2374 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2376 close_file(req, fsp, ERROR_CLOSE);
2377 reply_nterror(req, NT_STATUS_DISK_FULL);
2380 status = vfs_stat_fsp(fsp);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 close_file(req, fsp, ERROR_CLOSE);
2383 reply_nterror(req, status);
2388 fattr = dos_mode(conn, fsp->fsp_name);
2389 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2390 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2391 close_file(req, fsp, ERROR_CLOSE);
2392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2396 /* If the caller set the extended oplock request bit
2397 and we granted one (by whatever means) - set the
2398 correct bit for extended oplock reply.
2401 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2402 smb_action |= EXTENDED_OPLOCK_GRANTED;
2405 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2406 smb_action |= EXTENDED_OPLOCK_GRANTED;
2409 /* If the caller set the core oplock request bit
2410 and we granted one (by whatever means) - set the
2411 correct bit for core oplock reply.
2414 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2415 reply_outbuf(req, 19, 0);
2417 reply_outbuf(req, 15, 0);
2420 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2421 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2423 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2424 SCVAL(req->outbuf, smb_flg,
2425 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2428 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2429 SCVAL(req->outbuf, smb_flg,
2430 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2433 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2434 SSVAL(req->outbuf,smb_vwv3,fattr);
2435 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2436 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2438 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2440 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2441 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2442 SSVAL(req->outbuf,smb_vwv11,smb_action);
2444 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2445 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2449 TALLOC_FREE(smb_fname);
2450 END_PROFILE(SMBopenX);
2454 /****************************************************************************
2455 Reply to a SMBulogoffX.
2456 ****************************************************************************/
2458 void reply_ulogoffX(struct smb_request *req)
2460 struct smbd_server_connection *sconn = req->sconn;
2461 struct user_struct *vuser;
2462 struct smbXsrv_session *session = NULL;
2465 START_PROFILE(SMBulogoffX);
2467 vuser = get_valid_user_struct(sconn, req->vuid);
2470 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2471 (unsigned long long)req->vuid));
2473 req->vuid = UID_FIELD_INVALID;
2474 reply_force_doserror(req, ERRSRV, ERRbaduid);
2475 END_PROFILE(SMBulogoffX);
2479 session = vuser->session;
2483 * TODO: cancel all outstanding requests on the session
2485 status = smbXsrv_session_logoff(session);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 DEBUG(0, ("reply_ulogoff: "
2488 "smbXsrv_session_logoff() failed: %s\n",
2489 nt_errstr(status)));
2491 * If we hit this case, there is something completely
2492 * wrong, so we better disconnect the transport connection.
2494 END_PROFILE(SMBulogoffX);
2495 exit_server(__location__ ": smbXsrv_session_logoff failed");
2499 TALLOC_FREE(session);
2501 reply_outbuf(req, 2, 0);
2502 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2503 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2505 DEBUG(3, ("ulogoffX vuid=%llu\n",
2506 (unsigned long long)req->vuid));
2508 END_PROFILE(SMBulogoffX);
2509 req->vuid = UID_FIELD_INVALID;
2512 /****************************************************************************
2513 Reply to a mknew or a create.
2514 ****************************************************************************/
2516 void reply_mknew(struct smb_request *req)
2518 connection_struct *conn = req->conn;
2519 struct smb_filename *smb_fname = NULL;
2522 struct smb_file_time ft;
2524 int oplock_request = 0;
2526 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2527 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2528 uint32_t create_disposition;
2529 uint32_t create_options = 0;
2531 TALLOC_CTX *ctx = talloc_tos();
2533 START_PROFILE(SMBcreate);
2537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2541 fattr = SVAL(req->vwv+0, 0);
2542 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2544 if (req->cmd == SMBmknew) {
2545 /* We should fail if file exists. */
2546 create_disposition = FILE_CREATE;
2548 /* Create if file doesn't exist, truncate if it does. */
2549 create_disposition = FILE_OVERWRITE_IF;
2553 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2555 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2556 STR_TERMINATE, &status);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 reply_nterror(req, status);
2562 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2563 status = filename_convert(ctx,
2565 req->flags2 & FLAGS2_DFS_PATHNAMES,
2570 if (!NT_STATUS_IS_OK(status)) {
2571 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2572 reply_botherror(req,
2573 NT_STATUS_PATH_NOT_COVERED,
2574 ERRSRV, ERRbadpath);
2577 reply_nterror(req, status);
2581 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2582 DEBUG(0,("Attempt to create file (%s) with volid set - "
2583 "please report this\n",
2584 smb_fname_str_dbg(smb_fname)));
2587 status = SMB_VFS_CREATE_FILE(
2590 0, /* root_dir_fid */
2591 smb_fname, /* fname */
2592 access_mask, /* access_mask */
2593 share_mode, /* share_access */
2594 create_disposition, /* create_disposition*/
2595 create_options, /* create_options */
2596 fattr, /* file_attributes */
2597 oplock_request, /* oplock_request */
2599 0, /* allocation_size */
2600 0, /* private_flags */
2605 NULL, NULL); /* create context */
2607 if (!NT_STATUS_IS_OK(status)) {
2608 if (open_was_deferred(req->xconn, req->mid)) {
2609 /* We have re-scheduled this call. */
2612 reply_openerror(req, status);
2616 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2617 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 END_PROFILE(SMBcreate);
2623 reply_outbuf(req, 1, 0);
2624 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2626 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2627 SCVAL(req->outbuf,smb_flg,
2628 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2631 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2632 SCVAL(req->outbuf,smb_flg,
2633 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2636 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2637 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2638 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2639 (unsigned int)fattr));
2642 TALLOC_FREE(smb_fname);
2643 END_PROFILE(SMBcreate);
2647 /****************************************************************************
2648 Reply to a create temporary file.
2649 ****************************************************************************/
2651 void reply_ctemp(struct smb_request *req)
2653 connection_struct *conn = req->conn;
2654 struct smb_filename *smb_fname = NULL;
2655 char *wire_name = NULL;
2664 TALLOC_CTX *ctx = talloc_tos();
2666 START_PROFILE(SMBctemp);
2669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2673 fattr = SVAL(req->vwv+0, 0);
2674 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2676 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2677 STR_TERMINATE, &status);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 reply_nterror(req, status);
2683 for (i = 0; i < 10; i++) {
2685 fname = talloc_asprintf(ctx,
2688 generate_random_str_list(ctx, 5, "0123456789"));
2690 fname = talloc_asprintf(ctx,
2692 generate_random_str_list(ctx, 5, "0123456789"));
2696 reply_nterror(req, NT_STATUS_NO_MEMORY);
2700 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2701 status = filename_convert(ctx, conn,
2702 req->flags2 & FLAGS2_DFS_PATHNAMES,
2707 if (!NT_STATUS_IS_OK(status)) {
2708 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2709 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2710 ERRSRV, ERRbadpath);
2713 reply_nterror(req, status);
2717 /* Create the file. */
2718 status = SMB_VFS_CREATE_FILE(
2721 0, /* root_dir_fid */
2722 smb_fname, /* fname */
2723 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2724 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2725 FILE_CREATE, /* create_disposition*/
2726 0, /* create_options */
2727 fattr, /* file_attributes */
2728 oplock_request, /* oplock_request */
2730 0, /* allocation_size */
2731 0, /* private_flags */
2736 NULL, NULL); /* create context */
2738 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2740 TALLOC_FREE(smb_fname);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 if (open_was_deferred(req->xconn, req->mid)) {
2746 /* We have re-scheduled this call. */
2749 reply_openerror(req, status);
2757 /* Collision after 10 times... */
2758 reply_nterror(req, status);
2762 reply_outbuf(req, 1, 0);
2763 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2765 /* the returned filename is relative to the directory */
2766 s = strrchr_m(fsp->fsp_name->base_name, '/');
2768 s = fsp->fsp_name->base_name;
2774 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2775 thing in the byte section. JRA */
2776 SSVALS(p, 0, -1); /* what is this? not in spec */
2778 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2780 reply_nterror(req, NT_STATUS_NO_MEMORY);
2784 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2785 SCVAL(req->outbuf, smb_flg,
2786 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2789 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2790 SCVAL(req->outbuf, smb_flg,
2791 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2794 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2795 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2796 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2798 TALLOC_FREE(smb_fname);
2799 TALLOC_FREE(wire_name);
2800 END_PROFILE(SMBctemp);
2804 /*******************************************************************
2805 Check if a user is allowed to rename a file.
2806 ********************************************************************/
2808 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2811 if (!CAN_WRITE(conn)) {
2812 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2815 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2816 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2817 /* Only bother to read the DOS attribute if we might deny the
2818 rename on the grounds of attribute mismatch. */
2819 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2820 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2821 return NT_STATUS_NO_SUCH_FILE;
2825 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2826 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2827 return NT_STATUS_OK;
2830 /* If no pathnames are open below this
2831 directory, allow the rename. */
2833 if (lp_strict_rename(SNUM(conn))) {
2835 * Strict rename, check open file db.
2837 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2838 return NT_STATUS_ACCESS_DENIED;
2840 } else if (file_find_subpath(fsp)) {
2842 * No strict rename, just look in local process.
2844 return NT_STATUS_ACCESS_DENIED;
2846 return NT_STATUS_OK;
2849 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2850 return NT_STATUS_OK;
2853 return NT_STATUS_ACCESS_DENIED;
2856 /*******************************************************************
2857 * unlink a file with all relevant access checks
2858 *******************************************************************/
2860 static NTSTATUS do_unlink(connection_struct *conn,
2861 struct smb_request *req,
2862 struct smb_filename *smb_fname,
2867 uint32_t dirtype_orig = dirtype;
2870 bool posix_paths = (req != NULL && req->posix_pathnames);
2872 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2873 smb_fname_str_dbg(smb_fname),
2876 if (!CAN_WRITE(conn)) {
2877 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2881 ret = SMB_VFS_LSTAT(conn, smb_fname);
2883 ret = SMB_VFS_STAT(conn, smb_fname);
2886 return map_nt_error_from_unix(errno);
2889 fattr = dos_mode(conn, smb_fname);
2891 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2892 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2895 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2897 return NT_STATUS_NO_SUCH_FILE;
2900 if (!dir_check_ftype(fattr, dirtype)) {
2901 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2902 return NT_STATUS_FILE_IS_A_DIRECTORY;
2904 return NT_STATUS_NO_SUCH_FILE;
2907 if (dirtype_orig & 0x8000) {
2908 /* These will never be set for POSIX. */
2909 return NT_STATUS_NO_SUCH_FILE;
2913 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2914 return NT_STATUS_FILE_IS_A_DIRECTORY;
2917 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2918 return NT_STATUS_NO_SUCH_FILE;
2921 if (dirtype & 0xFF00) {
2922 /* These will never be set for POSIX. */
2923 return NT_STATUS_NO_SUCH_FILE;
2928 return NT_STATUS_NO_SUCH_FILE;
2931 /* Can't delete a directory. */
2932 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2933 return NT_STATUS_FILE_IS_A_DIRECTORY;
2938 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2939 return NT_STATUS_OBJECT_NAME_INVALID;
2940 #endif /* JRATEST */
2942 /* On open checks the open itself will check the share mode, so
2943 don't do it here as we'll get it wrong. */
2945 status = SMB_VFS_CREATE_FILE
2948 0, /* root_dir_fid */
2949 smb_fname, /* fname */
2950 DELETE_ACCESS, /* access_mask */
2951 FILE_SHARE_NONE, /* share_access */
2952 FILE_OPEN, /* create_disposition*/
2953 FILE_NON_DIRECTORY_FILE, /* create_options */
2954 /* file_attributes */
2955 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2956 FILE_ATTRIBUTE_NORMAL,
2957 0, /* oplock_request */
2959 0, /* allocation_size */
2960 0, /* private_flags */
2965 NULL, NULL); /* create context */
2967 if (!NT_STATUS_IS_OK(status)) {
2968 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2969 nt_errstr(status)));
2973 status = can_set_delete_on_close(fsp, fattr);
2974 if (!NT_STATUS_IS_OK(status)) {
2975 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2977 smb_fname_str_dbg(smb_fname),
2978 nt_errstr(status)));
2979 close_file(req, fsp, NORMAL_CLOSE);
2983 /* The set is across all open files on this dev/inode pair. */
2984 if (!set_delete_on_close(fsp, True,
2985 conn->session_info->security_token,
2986 conn->session_info->unix_token)) {
2987 close_file(req, fsp, NORMAL_CLOSE);
2988 return NT_STATUS_ACCESS_DENIED;
2991 return close_file(req, fsp, NORMAL_CLOSE);
2994 /****************************************************************************
2995 The guts of the unlink command, split out so it may be called by the NT SMB
2997 ****************************************************************************/
2999 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3000 uint32_t dirtype, struct smb_filename *smb_fname,
3003 char *fname_dir = NULL;
3004 char *fname_mask = NULL;
3006 NTSTATUS status = NT_STATUS_OK;
3007 struct smb_filename *smb_fname_dir = NULL;
3008 TALLOC_CTX *ctx = talloc_tos();
3010 /* Split up the directory from the filename/mask. */
3011 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3012 &fname_dir, &fname_mask);
3013 if (!NT_STATUS_IS_OK(status)) {
3018 * We should only check the mangled cache
3019 * here if unix_convert failed. This means
3020 * that the path in 'mask' doesn't exist
3021 * on the file system and so we need to look
3022 * for a possible mangle. This patch from
3023 * Tine Smukavec <valentin.smukavec@hermes.si>.
3026 if (!VALID_STAT(smb_fname->st) &&
3027 mangle_is_mangled(fname_mask, conn->params)) {
3028 char *new_mask = NULL;
3029 mangle_lookup_name_from_8_3(ctx, fname_mask,
3030 &new_mask, conn->params);
3032 TALLOC_FREE(fname_mask);
3033 fname_mask = new_mask;
3040 * Only one file needs to be unlinked. Append the mask back
3041 * onto the directory.
3043 TALLOC_FREE(smb_fname->base_name);
3044 if (ISDOT(fname_dir)) {
3045 /* Ensure we use canonical names on open. */
3046 smb_fname->base_name = talloc_asprintf(smb_fname,
3050 smb_fname->base_name = talloc_asprintf(smb_fname,
3055 if (!smb_fname->base_name) {
3056 status = NT_STATUS_NO_MEMORY;
3060 dirtype = FILE_ATTRIBUTE_NORMAL;
3063 status = check_name(conn, smb_fname->base_name);
3064 if (!NT_STATUS_IS_OK(status)) {
3068 status = do_unlink(conn, req, smb_fname, dirtype);
3069 if (!NT_STATUS_IS_OK(status)) {
3075 struct smb_Dir *dir_hnd = NULL;
3077 const char *dname = NULL;
3078 char *talloced = NULL;
3080 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3081 status = NT_STATUS_OBJECT_NAME_INVALID;
3085 dirtype = FILE_ATTRIBUTE_NORMAL;
3088 if (strequal(fname_mask,"????????.???")) {
3089 TALLOC_FREE(fname_mask);
3090 fname_mask = talloc_strdup(ctx, "*");
3092 status = NT_STATUS_NO_MEMORY;
3097 status = check_name(conn, fname_dir);
3098 if (!NT_STATUS_IS_OK(status)) {
3102 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3107 if (smb_fname_dir == NULL) {
3108 status = NT_STATUS_NO_MEMORY;
3112 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3114 if (dir_hnd == NULL) {
3115 status = map_nt_error_from_unix(errno);
3119 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3120 the pattern matches against the long name, otherwise the short name
3121 We don't implement this yet XXXX
3124 status = NT_STATUS_NO_SUCH_FILE;
3126 while ((dname = ReadDirName(dir_hnd, &offset,
3127 &smb_fname->st, &talloced))) {
3128 TALLOC_CTX *frame = talloc_stackframe();
3130 if (!is_visible_file(conn, fname_dir, dname,
3131 &smb_fname->st, true)) {
3133 TALLOC_FREE(talloced);
3137 /* Quick check for "." and ".." */
3138 if (ISDOT(dname) || ISDOTDOT(dname)) {
3140 TALLOC_FREE(talloced);
3144 if(!mask_match(dname, fname_mask,
3145 conn->case_sensitive)) {
3147 TALLOC_FREE(talloced);
3151 TALLOC_FREE(smb_fname->base_name);
3152 if (ISDOT(fname_dir)) {
3153 /* Ensure we use canonical names on open. */
3154 smb_fname->base_name =
3155 talloc_asprintf(smb_fname, "%s",
3158 smb_fname->base_name =
3159 talloc_asprintf(smb_fname, "%s/%s",
3163 if (!smb_fname->base_name) {
3164 TALLOC_FREE(dir_hnd);
3165 status = NT_STATUS_NO_MEMORY;
3167 TALLOC_FREE(talloced);
3171 status = check_name(conn, smb_fname->base_name);
3172 if (!NT_STATUS_IS_OK(status)) {
3173 TALLOC_FREE(dir_hnd);
3175 TALLOC_FREE(talloced);
3179 status = do_unlink(conn, req, smb_fname, dirtype);
3180 if (!NT_STATUS_IS_OK(status)) {
3181 TALLOC_FREE(dir_hnd);
3183 TALLOC_FREE(talloced);
3188 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3189 smb_fname->base_name));
3192 TALLOC_FREE(talloced);
3194 TALLOC_FREE(dir_hnd);
3197 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3198 status = map_nt_error_from_unix(errno);
3202 TALLOC_FREE(smb_fname_dir);
3203 TALLOC_FREE(fname_dir);
3204 TALLOC_FREE(fname_mask);
3208 /****************************************************************************
3210 ****************************************************************************/
3212 void reply_unlink(struct smb_request *req)
3214 connection_struct *conn = req->conn;
3216 struct smb_filename *smb_fname = NULL;
3219 bool path_contains_wcard = False;
3220 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3221 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
3222 TALLOC_CTX *ctx = talloc_tos();
3224 START_PROFILE(SMBunlink);
3227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3231 dirtype = SVAL(req->vwv+0, 0);
3233 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3234 STR_TERMINATE, &status,
3235 &path_contains_wcard);
3236 if (!NT_STATUS_IS_OK(status)) {
3237 reply_nterror(req, status);
3241 status = filename_convert(ctx, conn,
3242 req->flags2 & FLAGS2_DFS_PATHNAMES,
3245 &path_contains_wcard,
3247 if (!NT_STATUS_IS_OK(status)) {
3248 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3249 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3250 ERRSRV, ERRbadpath);
3253 reply_nterror(req, status);
3257 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3259 status = unlink_internals(conn, req, dirtype, smb_fname,
3260 path_contains_wcard);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 if (open_was_deferred(req->xconn, req->mid)) {
3263 /* We have re-scheduled this call. */
3266 reply_nterror(req, status);
3270 reply_outbuf(req, 0, 0);
3272 TALLOC_FREE(smb_fname);
3273 END_PROFILE(SMBunlink);
3277 /****************************************************************************
3279 ****************************************************************************/
3281 static void fail_readraw(void)
3283 const char *errstr = talloc_asprintf(talloc_tos(),
3284 "FAIL ! reply_readbraw: socket write fail (%s)",
3289 exit_server_cleanly(errstr);
3292 /****************************************************************************
3293 Fake (read/write) sendfile. Returns -1 on read or write fail.
3294 ****************************************************************************/
3296 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3297 off_t startpos, size_t nread)
3300 size_t tosend = nread;
3307 bufsize = MIN(nread, 65536);
3309 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3313 while (tosend > 0) {
3317 cur_read = MIN(tosend, bufsize);
3318 ret = read_file(fsp,buf,startpos,cur_read);
3324 /* If we had a short read, fill with zeros. */
3325 if (ret < cur_read) {
3326 memset(buf + ret, '\0', cur_read - ret);
3329 ret = write_data(xconn->transport.sock, buf, cur_read);
3330 if (ret != cur_read) {
3331 int saved_errno = errno;
3333 * Try and give an error message saying what
3336 DEBUG(0, ("write_data failed for client %s. "
3338 smbXsrv_connection_dbg(xconn),
3339 strerror(saved_errno)));
3341 errno = saved_errno;
3345 startpos += cur_read;
3349 return (ssize_t)nread;
3352 /****************************************************************************
3353 Deal with the case of sendfile reading less bytes from the file than
3354 requested. Fill with zeros (all we can do). Returns 0 on success
3355 ****************************************************************************/
3357 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3363 #define SHORT_SEND_BUFSIZE 1024
3364 if (nread < headersize) {
3365 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3366 "header for file %s (%s). Terminating\n",
3367 fsp_str_dbg(fsp), strerror(errno)));
3371 nread -= headersize;
3373 if (nread < smb_maxcnt) {
3374 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3376 DEBUG(0,("sendfile_short_send: malloc failed "
3377 "for file %s (%s). Terminating\n",
3378 fsp_str_dbg(fsp), strerror(errno)));
3382 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3383 "with zeros !\n", fsp_str_dbg(fsp)));
3385 while (nread < smb_maxcnt) {
3387 * We asked for the real file size and told sendfile
3388 * to not go beyond the end of the file. But it can
3389 * happen that in between our fstat call and the
3390 * sendfile call the file was truncated. This is very
3391 * bad because we have already announced the larger
3392 * number of bytes to the client.
3394 * The best we can do now is to send 0-bytes, just as
3395 * a read from a hole in a sparse file would do.
3397 * This should happen rarely enough that I don't care
3398 * about efficiency here :-)
3403 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3404 ret = write_data(xconn->transport.sock, buf, to_write);
3405 if (ret != to_write) {
3406 int saved_errno = errno;
3408 * Try and give an error message saying what
3411 DEBUG(0, ("write_data failed for client %s. "
3413 smbXsrv_connection_dbg(xconn),
3414 strerror(saved_errno)));
3415 errno = saved_errno;
3426 /****************************************************************************
3427 Return a readbraw error (4 bytes of zero).
3428 ****************************************************************************/
3430 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3436 smbd_lock_socket(xconn);
3437 if (write_data(xconn->transport.sock,header,4) != 4) {
3438 int saved_errno = errno;
3440 * Try and give an error message saying what
3443 DEBUG(0, ("write_data failed for client %s. "
3445 smbXsrv_connection_dbg(xconn),
3446 strerror(saved_errno)));
3447 errno = saved_errno;
3451 smbd_unlock_socket(xconn);
3454 /****************************************************************************
3455 Use sendfile in readbraw.
3456 ****************************************************************************/
3458 static void send_file_readbraw(connection_struct *conn,
3459 struct smb_request *req,
3465 struct smbXsrv_connection *xconn = req->xconn;
3466 char *outbuf = NULL;
3470 * We can only use sendfile on a non-chained packet
3471 * but we can use on a non-oplocked file. tridge proved this
3472 * on a train in Germany :-). JRA.
3473 * reply_readbraw has already checked the length.
3476 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3477 (fsp->wcp == NULL) &&
3478 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3479 ssize_t sendfile_read = -1;
3481 DATA_BLOB header_blob;
3483 _smb_setlen(header,nread);
3484 header_blob = data_blob_const(header, 4);
3486 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3487 &header_blob, startpos,
3489 if (sendfile_read == -1) {
3490 /* Returning ENOSYS means no data at all was sent.
3491 * Do this as a normal read. */
3492 if (errno == ENOSYS) {
3493 goto normal_readbraw;
3497 * Special hack for broken Linux with no working sendfile. If we
3498 * return EINTR we sent the header but not the rest of the data.
3499 * Fake this up by doing read/write calls.
3501 if (errno == EINTR) {
3502 /* Ensure we don't do this again. */
3503 set_use_sendfile(SNUM(conn), False);
3504 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3506 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3507 DEBUG(0,("send_file_readbraw: "
3508 "fake_sendfile failed for "
3512 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3517 DEBUG(0,("send_file_readbraw: sendfile failed for "
3518 "file %s (%s). Terminating\n",
3519 fsp_str_dbg(fsp), strerror(errno)));
3520 exit_server_cleanly("send_file_readbraw sendfile failed");
3521 } else if (sendfile_read == 0) {
3523 * Some sendfile implementations return 0 to indicate
3524 * that there was a short read, but nothing was
3525 * actually written to the socket. In this case,
3526 * fallback to the normal read path so the header gets
3527 * the correct byte count.
3529 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3530 "bytes falling back to the normal read: "
3531 "%s\n", fsp_str_dbg(fsp)));
3532 goto normal_readbraw;
3535 /* Deal with possible short send. */
3536 if (sendfile_read != 4+nread) {
3537 ret = sendfile_short_send(xconn, fsp,
3538 sendfile_read, 4, nread);
3548 outbuf = talloc_array(NULL, char, nread+4);
3550 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3551 (unsigned)(nread+4)));
3552 reply_readbraw_error(xconn);
3557 ret = read_file(fsp,outbuf+4,startpos,nread);
3558 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3567 _smb_setlen(outbuf,ret);
3568 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3569 int saved_errno = errno;
3571 * Try and give an error message saying what
3574 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3575 smbXsrv_connection_dbg(xconn),
3576 strerror(saved_errno)));
3577 errno = saved_errno;
3582 TALLOC_FREE(outbuf);
3585 /****************************************************************************
3586 Reply to a readbraw (core+ protocol).
3587 ****************************************************************************/
3589 void reply_readbraw(struct smb_request *req)
3591 connection_struct *conn = req->conn;
3592 struct smbXsrv_connection *xconn = req->xconn;
3593 ssize_t maxcount,mincount;
3597 struct lock_struct lock;
3600 START_PROFILE(SMBreadbraw);
3602 if (srv_is_signing_active(xconn) || req->encrypted) {
3603 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3604 "raw reads/writes are disallowed.");
3608 reply_readbraw_error(xconn);
3609 END_PROFILE(SMBreadbraw);
3613 if (xconn->smb1.echo_handler.trusted_fde) {
3614 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3615 "'async smb echo handler = yes'\n"));
3616 reply_readbraw_error(xconn);
3617 END_PROFILE(SMBreadbraw);
3622 * Special check if an oplock break has been issued
3623 * and the readraw request croses on the wire, we must
3624 * return a zero length response here.
3627 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3630 * We have to do a check_fsp by hand here, as
3631 * we must always return 4 zero bytes on error,
3635 if (!fsp || !conn || conn != fsp->conn ||
3636 req->vuid != fsp->vuid ||
3637 fsp->is_directory || fsp->fh->fd == -1) {
3639 * fsp could be NULL here so use the value from the packet. JRA.
3641 DEBUG(3,("reply_readbraw: fnum %d not valid "
3643 (int)SVAL(req->vwv+0, 0)));
3644 reply_readbraw_error(xconn);
3645 END_PROFILE(SMBreadbraw);
3649 /* Do a "by hand" version of CHECK_READ. */
3650 if (!(fsp->can_read ||
3651 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3652 (fsp->access_mask & FILE_EXECUTE)))) {
3653 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3654 (int)SVAL(req->vwv+0, 0)));
3655 reply_readbraw_error(xconn);
3656 END_PROFILE(SMBreadbraw);
3660 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3662 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3663 if(req->wct == 10) {
3665 * This is a large offset (64 bit) read.
3668 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3671 DEBUG(0,("reply_readbraw: negative 64 bit "
3672 "readraw offset (%.0f) !\n",
3673 (double)startpos ));
3674 reply_readbraw_error(xconn);
3675 END_PROFILE(SMBreadbraw);
3680 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3681 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3683 /* ensure we don't overrun the packet size */
3684 maxcount = MIN(65535,maxcount);
3686 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3687 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3690 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3691 reply_readbraw_error(xconn);
3692 END_PROFILE(SMBreadbraw);
3696 if (fsp_stat(fsp) == 0) {
3697 size = fsp->fsp_name->st.st_ex_size;
3700 if (startpos >= size) {
3703 nread = MIN(maxcount,(size - startpos));
3706 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3707 if (nread < mincount)
3711 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3712 "min=%lu nread=%lu\n",
3713 fsp_fnum_dbg(fsp), (double)startpos,
3714 (unsigned long)maxcount,
3715 (unsigned long)mincount,
3716 (unsigned long)nread ) );
3718 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3720 DEBUG(5,("reply_readbraw finished\n"));
3722 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3724 END_PROFILE(SMBreadbraw);
3729 #define DBGC_CLASS DBGC_LOCKING
3731 /****************************************************************************
3732 Reply to a lockread (core+ protocol).
3733 ****************************************************************************/
3735 void reply_lockread(struct smb_request *req)
3737 connection_struct *conn = req->conn;
3745 struct byte_range_lock *br_lck = NULL;
3747 struct smbXsrv_connection *xconn = req->xconn;
3749 START_PROFILE(SMBlockread);
3752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 END_PROFILE(SMBlockread);
3757 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3759 if (!check_fsp(conn, req, fsp)) {
3760 END_PROFILE(SMBlockread);
3764 if (!CHECK_READ(fsp,req)) {
3765 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3766 END_PROFILE(SMBlockread);
3770 numtoread = SVAL(req->vwv+1, 0);
3771 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3774 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3775 * protocol request that predates the read/write lock concept.
3776 * Thus instead of asking for a read lock here we need to ask
3777 * for a write lock. JRA.
3778 * Note that the requested lock size is unaffected by max_send.
3781 br_lck = do_lock(req->sconn->msg_ctx,
3783 (uint64_t)req->smbpid,
3784 (uint64_t)numtoread,
3788 False, /* Non-blocking lock. */
3791 TALLOC_FREE(br_lck);
3793 if (NT_STATUS_V(status)) {
3794 reply_nterror(req, status);
3795 END_PROFILE(SMBlockread);
3800 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3802 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3804 if (numtoread > maxtoread) {
3805 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3806 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3807 (unsigned int)numtoread, (unsigned int)maxtoread,
3808 (unsigned int)xconn->smb1.sessions.max_send));
3809 numtoread = maxtoread;
3812 reply_outbuf(req, 5, numtoread + 3);
3814 data = smb_buf(req->outbuf) + 3;
3816 nread = read_file(fsp,data,startpos,numtoread);
3819 reply_nterror(req, map_nt_error_from_unix(errno));
3820 END_PROFILE(SMBlockread);
3824 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3826 SSVAL(req->outbuf,smb_vwv0,nread);
3827 SSVAL(req->outbuf,smb_vwv5,nread+3);
3828 p = smb_buf(req->outbuf);
3829 SCVAL(p,0,0); /* pad byte. */
3832 DEBUG(3,("lockread %s num=%d nread=%d\n",
3833 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3835 END_PROFILE(SMBlockread);
3840 #define DBGC_CLASS DBGC_ALL
3842 /****************************************************************************
3844 ****************************************************************************/
3846 void reply_read(struct smb_request *req)
3848 connection_struct *conn = req->conn;
3855 struct lock_struct lock;
3856 struct smbXsrv_connection *xconn = req->xconn;
3858 START_PROFILE(SMBread);
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3862 END_PROFILE(SMBread);
3866 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3868 if (!check_fsp(conn, req, fsp)) {
3869 END_PROFILE(SMBread);
3873 if (!CHECK_READ(fsp,req)) {
3874 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3875 END_PROFILE(SMBread);
3879 numtoread = SVAL(req->vwv+1, 0);
3880 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3883 * The requested read size cannot be greater than max_send. JRA.
3885 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3887 if (numtoread > maxtoread) {
3888 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3889 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3890 (unsigned int)numtoread, (unsigned int)maxtoread,
3891 (unsigned int)xconn->smb1.sessions.max_send));
3892 numtoread = maxtoread;
3895 reply_outbuf(req, 5, numtoread+3);
3897 data = smb_buf(req->outbuf) + 3;
3899 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3900 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3903 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3904 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3905 END_PROFILE(SMBread);
3910 nread = read_file(fsp,data,startpos,numtoread);
3913 reply_nterror(req, map_nt_error_from_unix(errno));
3917 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3919 SSVAL(req->outbuf,smb_vwv0,nread);
3920 SSVAL(req->outbuf,smb_vwv5,nread+3);
3921 SCVAL(smb_buf(req->outbuf),0,1);
3922 SSVAL(smb_buf(req->outbuf),1,nread);
3924 DEBUG(3, ("read %s num=%d nread=%d\n",
3925 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3928 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3930 END_PROFILE(SMBread);
3934 /****************************************************************************
3936 ****************************************************************************/
3938 int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3942 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3945 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3947 SCVAL(outbuf,smb_vwv0,0xFF);
3948 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3949 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3950 SSVAL(outbuf,smb_vwv6,
3951 (smb_wct - 4) /* offset from smb header to wct */
3952 + 1 /* the wct field */
3953 + 12 * sizeof(uint16_t) /* vwv */
3954 + 2 /* the buflen field */
3955 + 1); /* padding byte */
3956 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3957 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3958 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3959 _smb_setlen_large(outbuf,
3960 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3964 /****************************************************************************
3965 Reply to a read and X - possibly using sendfile.
3966 ****************************************************************************/
3968 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3969 files_struct *fsp, off_t startpos,
3972 struct smbXsrv_connection *xconn = req->xconn;
3974 struct lock_struct lock;
3975 int saved_errno = 0;
3977 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3978 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3981 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3982 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3987 * We can only use sendfile on a non-chained packet
3988 * but we can use on a non-oplocked file. tridge proved this
3989 * on a train in Germany :-). JRA.
3992 if (!req_is_in_chain(req) &&
3994 (fsp->base_fsp == NULL) &&
3995 (fsp->wcp == NULL) &&
3996 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3997 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4000 if(fsp_stat(fsp) == -1) {
4001 reply_nterror(req, map_nt_error_from_unix(errno));
4005 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4006 (startpos > fsp->fsp_name->st.st_ex_size) ||
4007 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4009 * We already know that we would do a short read, so don't
4010 * try the sendfile() path.
4012 goto nosendfile_read;
4016 * Set up the packet header before send. We
4017 * assume here the sendfile will work (get the
4018 * correct amount of data).
4021 header = data_blob_const(headerbuf, sizeof(headerbuf));
4023 construct_reply_common_req(req, (char *)headerbuf);
4024 setup_readX_header((char *)headerbuf, smb_maxcnt);
4026 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4027 startpos, smb_maxcnt);
4029 saved_errno = errno;
4031 /* Returning ENOSYS means no data at all was sent.
4032 Do this as a normal read. */
4033 if (errno == ENOSYS) {
4038 * Special hack for broken Linux with no working sendfile. If we
4039 * return EINTR we sent the header but not the rest of the data.
4040 * Fake this up by doing read/write calls.
4043 if (errno == EINTR) {
4044 /* Ensure we don't do this again. */
4045 set_use_sendfile(SNUM(conn), False);
4046 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4047 nread = fake_sendfile(xconn, fsp, startpos,
4050 saved_errno = errno;
4051 DEBUG(0,("send_file_readX: "
4052 "fake_sendfile failed for "
4053 "file %s (%s) for client %s. "
4056 smbXsrv_connection_dbg(xconn),
4057 strerror(saved_errno)));
4058 errno = saved_errno;
4059 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4061 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4062 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4063 /* No outbuf here means successful sendfile. */
4067 DEBUG(0,("send_file_readX: sendfile failed for file "
4068 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4070 exit_server_cleanly("send_file_readX sendfile failed");
4071 } else if (nread == 0) {
4073 * Some sendfile implementations return 0 to indicate
4074 * that there was a short read, but nothing was
4075 * actually written to the socket. In this case,
4076 * fallback to the normal read path so the header gets
4077 * the correct byte count.
4079 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4080 "falling back to the normal read: %s\n",
4085 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4086 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4088 /* Deal with possible short send. */
4089 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4092 ret = sendfile_short_send(xconn, fsp, nread,
4093 sizeof(headerbuf), smb_maxcnt);
4096 r = "send_file_readX: sendfile_short_send failed";
4097 DEBUG(0,("%s for file %s (%s).\n",
4098 r, fsp_str_dbg(fsp), strerror(errno)));
4099 exit_server_cleanly(r);
4102 /* No outbuf here means successful sendfile. */
4103 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4104 SMB_PERFCOUNT_END(&req->pcd);
4110 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4111 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4114 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4115 (startpos > fsp->fsp_name->st.st_ex_size) ||
4116 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4118 * We already know that we would do a short
4119 * read, so don't try the sendfile() path.
4121 goto nosendfile_read;
4124 construct_reply_common_req(req, (char *)headerbuf);
4125 setup_readX_header((char *)headerbuf, smb_maxcnt);
4127 /* Send out the header. */
4128 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4130 if (ret != sizeof(headerbuf)) {
4131 saved_errno = errno;
4133 * Try and give an error message saying what
4136 DEBUG(0,("send_file_readX: write_data failed for file "
4137 "%s (%s) for client %s. Terminating\n",
4139 smbXsrv_connection_dbg(xconn),
4140 strerror(saved_errno)));
4141 errno = saved_errno;
4142 exit_server_cleanly("send_file_readX sendfile failed");
4144 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4146 saved_errno = errno;
4147 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4148 "%s (%s) for client %s. Terminating\n",
4150 smbXsrv_connection_dbg(xconn),
4151 strerror(saved_errno)));
4152 errno = saved_errno;
4153 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4160 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4161 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4162 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4164 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4165 startpos, smb_maxcnt);
4166 saved_errno = errno;
4168 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4171 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4175 setup_readX_header((char *)req->outbuf, nread);
4177 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4178 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4182 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4183 TALLOC_FREE(req->outbuf);
4187 /****************************************************************************
4188 Work out how much space we have for a read return.
4189 ****************************************************************************/
4191 static size_t calc_max_read_pdu(const struct smb_request *req)
4193 struct smbXsrv_connection *xconn = req->xconn;
4195 if (xconn->protocol < PROTOCOL_NT1) {
4196 return xconn->smb1.sessions.max_send;
4199 if (!lp_large_readwrite()) {
4200 return xconn->smb1.sessions.max_send;
4203 if (req_is_in_chain(req)) {
4204 return xconn->smb1.sessions.max_send;
4207 if (req->encrypted) {
4209 * Don't take encrypted traffic up to the
4210 * limit. There are padding considerations
4211 * that make that tricky.
4213 return xconn->smb1.sessions.max_send;
4216 if (srv_is_signing_active(xconn)) {
4220 if (!lp_unix_extensions()) {
4225 * We can do ultra-large POSIX reads.
4230 /****************************************************************************
4231 Calculate how big a read can be. Copes with all clients. It's always
4232 safe to return a short read - Windows does this.
4233 ****************************************************************************/
4235 static size_t calc_read_size(const struct smb_request *req,
4239 struct smbXsrv_connection *xconn = req->xconn;
4240 size_t max_pdu = calc_max_read_pdu(req);
4241 size_t total_size = 0;
4242 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4243 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4246 * Windows explicitly ignores upper size of 0xFFFF.
4247 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4248 * We must do the same as these will never fit even in
4249 * an extended size NetBIOS packet.
4251 if (upper_size == 0xFFFF) {
4255 if (xconn->protocol < PROTOCOL_NT1) {
4259 total_size = ((upper_size<<16) | lower_size);
4262 * LARGE_READX test shows it's always safe to return
4263 * a short read. Windows does so.
4265 return MIN(total_size, max_len);
4268 /****************************************************************************
4269 Reply to a read and X.
4270 ****************************************************************************/
4272 void reply_read_and_X(struct smb_request *req)
4274 connection_struct *conn = req->conn;
4279 bool big_readX = False;
4281 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4284 START_PROFILE(SMBreadX);
4286 if ((req->wct != 10) && (req->wct != 12)) {
4287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4291 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4292 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4293 smb_maxcnt = SVAL(req->vwv+5, 0);
4295 /* If it's an IPC, pass off the pipe handler. */
4297 reply_pipe_read_and_X(req);
4298 END_PROFILE(SMBreadX);
4302 if (!check_fsp(conn, req, fsp)) {
4303 END_PROFILE(SMBreadX);
4307 if (!CHECK_READ(fsp,req)) {
4308 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4309 END_PROFILE(SMBreadX);
4313 upper_size = SVAL(req->vwv+7, 0);
4314 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4315 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4317 * This is a heuristic to avoid keeping large
4318 * outgoing buffers around over long-lived aio
4324 if (req->wct == 12) {
4326 * This is a large offset (64 bit) read.
4328 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4333 NTSTATUS status = schedule_aio_read_and_X(conn,
4338 if (NT_STATUS_IS_OK(status)) {
4339 /* Read scheduled - we're done. */
4342 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4343 /* Real error - report to client. */
4344 END_PROFILE(SMBreadX);
4345 reply_nterror(req, status);
4348 /* NT_STATUS_RETRY - fall back to sync read. */
4351 smbd_lock_socket(req->xconn);
4352 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4353 smbd_unlock_socket(req->xconn);
4356 END_PROFILE(SMBreadX);
4360 /****************************************************************************
4361 Error replies to writebraw must have smb_wct == 1. Fix this up.
4362 ****************************************************************************/
4364 void error_to_writebrawerr(struct smb_request *req)
4366 uint8_t *old_outbuf = req->outbuf;
4368 reply_outbuf(req, 1, 0);
4370 memcpy(req->outbuf, old_outbuf, smb_size);
4371 TALLOC_FREE(old_outbuf);
4374 /****************************************************************************
4375 Read 4 bytes of a smb packet and return the smb length of the packet.
4376 Store the result in the buffer. This version of the function will
4377 never return a session keepalive (length of zero).
4378 Timeout is in milliseconds.
4379 ****************************************************************************/
4381 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4384 uint8_t msgtype = NBSSkeepalive;
4386 while (msgtype == NBSSkeepalive) {
4389 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4391 if (!NT_STATUS_IS_OK(status)) {
4392 char addr[INET6_ADDRSTRLEN];
4393 /* Try and give an error message
4394 * saying what client failed. */
4395 DEBUG(0, ("read_fd_with_timeout failed for "
4396 "client %s read error = %s.\n",
4397 get_peer_addr(fd,addr,sizeof(addr)),
4398 nt_errstr(status)));
4402 msgtype = CVAL(inbuf, 0);
4405 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4406 (unsigned long)len));
4408 return NT_STATUS_OK;
4411 /****************************************************************************
4412 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4413 ****************************************************************************/
4415 void reply_writebraw(struct smb_request *req)
4417 connection_struct *conn = req->conn;
4418 struct smbXsrv_connection *xconn = req->xconn;
4421 ssize_t total_written=0;
4422 size_t numtowrite=0;
4425 const char *data=NULL;
4428 struct lock_struct lock;
4431 START_PROFILE(SMBwritebraw);
4434 * If we ever reply with an error, it must have the SMB command
4435 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4438 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4440 if (srv_is_signing_active(xconn)) {
4441 END_PROFILE(SMBwritebraw);
4442 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4443 "raw reads/writes are disallowed.");
4446 if (req->wct < 12) {
4447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4448 error_to_writebrawerr(req);
4449 END_PROFILE(SMBwritebraw);
4453 if (xconn->smb1.echo_handler.trusted_fde) {
4454 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4455 "'async smb echo handler = yes'\n"));
4456 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4457 error_to_writebrawerr(req);
4458 END_PROFILE(SMBwritebraw);
4462 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4463 if (!check_fsp(conn, req, fsp)) {
4464 error_to_writebrawerr(req);
4465 END_PROFILE(SMBwritebraw);
4469 if (!CHECK_WRITE(fsp)) {
4470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4471 error_to_writebrawerr(req);
4472 END_PROFILE(SMBwritebraw);
4476 tcount = IVAL(req->vwv+1, 0);
4477 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4478 write_through = BITSETW(req->vwv+7,0);
4480 /* We have to deal with slightly different formats depending
4481 on whether we are using the core+ or lanman1.0 protocol */
4483 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4484 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4485 data = smb_buf_const(req->inbuf);
4487 numtowrite = SVAL(req->vwv+10, 0);
4488 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4491 /* Ensure we don't write bytes past the end of this packet. */
4492 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4494 error_to_writebrawerr(req);
4495 END_PROFILE(SMBwritebraw);
4499 if (!fsp->print_file) {
4500 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4501 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4504 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4505 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4506 error_to_writebrawerr(req);
4507 END_PROFILE(SMBwritebraw);
4513 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4516 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4517 "wrote=%d sync=%d\n",
4518 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4519 (int)nwritten, (int)write_through));
4521 if (nwritten < (ssize_t)numtowrite) {
4522 reply_nterror(req, NT_STATUS_DISK_FULL);
4523 error_to_writebrawerr(req);
4527 total_written = nwritten;
4529 /* Allocate a buffer of 64k + length. */
4530 buf = talloc_array(NULL, char, 65540);
4532 reply_nterror(req, NT_STATUS_NO_MEMORY);
4533 error_to_writebrawerr(req);
4537 /* Return a SMBwritebraw message to the redirector to tell
4538 * it to send more bytes */
4540 memcpy(buf, req->inbuf, smb_size);
4541 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4542 SCVAL(buf,smb_com,SMBwritebraw);
4543 SSVALS(buf,smb_vwv0,0xFFFF);
4545 if (!srv_send_smb(req->xconn,
4547 false, 0, /* no signing */
4548 IS_CONN_ENCRYPTED(conn),
4550 exit_server_cleanly("reply_writebraw: srv_send_smb "
4554 /* Now read the raw data into the buffer and write it */
4555 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4557 if (!NT_STATUS_IS_OK(status)) {
4558 exit_server_cleanly("secondary writebraw failed");
4561 /* Set up outbuf to return the correct size */
4562 reply_outbuf(req, 1, 0);
4564 if (numtowrite != 0) {
4566 if (numtowrite > 0xFFFF) {
4567 DEBUG(0,("reply_writebraw: Oversize secondary write "
4568 "raw requested (%u). Terminating\n",
4569 (unsigned int)numtowrite ));
4570 exit_server_cleanly("secondary writebraw failed");
4573 if (tcount > nwritten+numtowrite) {
4574 DEBUG(3,("reply_writebraw: Client overestimated the "
4576 (int)tcount,(int)nwritten,(int)numtowrite));
4579 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4582 if (!NT_STATUS_IS_OK(status)) {
4583 /* Try and give an error message
4584 * saying what client failed. */
4585 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4586 "raw read failed (%s) for client %s. "
4587 "Terminating\n", nt_errstr(status),
4588 smbXsrv_connection_dbg(xconn)));
4589 exit_server_cleanly("secondary writebraw failed");
4592 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4593 if (nwritten == -1) {
4595 reply_nterror(req, map_nt_error_from_unix(errno));
4596 error_to_writebrawerr(req);
4600 if (nwritten < (ssize_t)numtowrite) {
4601 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4602 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4606 total_written += nwritten;
4611 SSVAL(req->outbuf,smb_vwv0,total_written);
4613 status = sync_file(conn, fsp, write_through);
4614 if (!NT_STATUS_IS_OK(status)) {
4615 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4616 fsp_str_dbg(fsp), nt_errstr(status)));
4617 reply_nterror(req, status);
4618 error_to_writebrawerr(req);
4622 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4624 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4625 (int)total_written));
4627 if (!fsp->print_file) {
4628 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4631 /* We won't return a status if write through is not selected - this
4632 * follows what WfWg does */
4633 END_PROFILE(SMBwritebraw);
4635 if (!write_through && total_written==tcount) {
4637 #if RABBIT_PELLET_FIX
4639 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4640 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4643 if (!send_keepalive(xconn->transport.sock)) {
4644 exit_server_cleanly("reply_writebraw: send of "
4645 "keepalive failed");
4648 TALLOC_FREE(req->outbuf);
4653 if (!fsp->print_file) {
4654 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4657 END_PROFILE(SMBwritebraw);
4662 #define DBGC_CLASS DBGC_LOCKING
4664 /****************************************************************************
4665 Reply to a writeunlock (core+).
4666 ****************************************************************************/
4668 void reply_writeunlock(struct smb_request *req)
4670 connection_struct *conn = req->conn;
4671 ssize_t nwritten = -1;
4675 NTSTATUS status = NT_STATUS_OK;
4677 struct lock_struct lock;
4678 int saved_errno = 0;
4680 START_PROFILE(SMBwriteunlock);
4683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4684 END_PROFILE(SMBwriteunlock);
4688 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4690 if (!check_fsp(conn, req, fsp)) {
4691 END_PROFILE(SMBwriteunlock);
4695 if (!CHECK_WRITE(fsp)) {
4696 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4697 END_PROFILE(SMBwriteunlock);
4701 numtowrite = SVAL(req->vwv+1, 0);
4702 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4703 data = (const char *)req->buf + 3;
4705 if (!fsp->print_file && numtowrite > 0) {
4706 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4707 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4710 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4711 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4712 END_PROFILE(SMBwriteunlock);
4717 /* The special X/Open SMB protocol handling of
4718 zero length writes is *NOT* done for
4720 if(numtowrite == 0) {
4723 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4724 saved_errno = errno;
4727 status = sync_file(conn, fsp, False /* write through */);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4730 fsp_str_dbg(fsp), nt_errstr(status)));
4731 reply_nterror(req, status);
4736 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4740 if((nwritten < numtowrite) && (numtowrite != 0)) {
4741 reply_nterror(req, NT_STATUS_DISK_FULL);
4745 if (numtowrite && !fsp->print_file) {
4746 status = do_unlock(req->sconn->msg_ctx,
4748 (uint64_t)req->smbpid,
4749 (uint64_t)numtowrite,
4753 if (NT_STATUS_V(status)) {
4754 reply_nterror(req, status);
4759 reply_outbuf(req, 1, 0);
4761 SSVAL(req->outbuf,smb_vwv0,nwritten);
4763 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4764 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4767 if (numtowrite && !fsp->print_file) {
4768 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4771 END_PROFILE(SMBwriteunlock);
4776 #define DBGC_CLASS DBGC_ALL
4778 /****************************************************************************
4780 ****************************************************************************/
4782 void reply_write(struct smb_request *req)
4784 connection_struct *conn = req->conn;
4786 ssize_t nwritten = -1;
4790 struct lock_struct lock;
4792 int saved_errno = 0;
4794 START_PROFILE(SMBwrite);
4797 END_PROFILE(SMBwrite);
4798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4802 /* If it's an IPC, pass off the pipe handler. */
4804 reply_pipe_write(req);
4805 END_PROFILE(SMBwrite);
4809 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4811 if (!check_fsp(conn, req, fsp)) {
4812 END_PROFILE(SMBwrite);
4816 if (!CHECK_WRITE(fsp)) {
4817 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4818 END_PROFILE(SMBwrite);
4822 numtowrite = SVAL(req->vwv+1, 0);
4823 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4824 data = (const char *)req->buf + 3;
4826 if (!fsp->print_file) {
4827 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4828 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4831 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4832 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4833 END_PROFILE(SMBwrite);
4839 * X/Open SMB protocol says that if smb_vwv1 is
4840 * zero then the file size should be extended or
4841 * truncated to the size given in smb_vwv[2-3].
4844 if(numtowrite == 0) {
4846 * This is actually an allocate call, and set EOF. JRA.
4848 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4850 reply_nterror(req, NT_STATUS_DISK_FULL);
4853 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4855 reply_nterror(req, NT_STATUS_DISK_FULL);
4858 trigger_write_time_update_immediate(fsp);
4860 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4863 status = sync_file(conn, fsp, False);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4866 fsp_str_dbg(fsp), nt_errstr(status)));
4867 reply_nterror(req, status);
4872 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4876 if((nwritten == 0) && (numtowrite != 0)) {
4877 reply_nterror(req, NT_STATUS_DISK_FULL);
4881 reply_outbuf(req, 1, 0);
4883 SSVAL(req->outbuf,smb_vwv0,nwritten);
4885 if (nwritten < (ssize_t)numtowrite) {
4886 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4887 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4890 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4893 if (!fsp->print_file) {
4894 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4897 END_PROFILE(SMBwrite);
4901 /****************************************************************************
4902 Ensure a buffer is a valid writeX for recvfile purposes.
4903 ****************************************************************************/
4905 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4906 (2*14) + /* word count (including bcc) */ \
4909 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4910 const uint8_t *inbuf)
4913 unsigned int doff = 0;
4914 size_t len = smb_len_large(inbuf);
4916 struct smbXsrv_open *op = NULL;
4917 struct files_struct *fsp = NULL;
4920 if (is_encrypted_packet(inbuf)) {
4921 /* Can't do this on encrypted
4926 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4930 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4931 CVAL(inbuf,smb_wct) != 14) {
4932 DEBUG(10,("is_valid_writeX_buffer: chained or "
4933 "invalid word length.\n"));
4937 fnum = SVAL(inbuf, smb_vwv2);
4938 status = smb1srv_open_lookup(xconn,
4942 if (!NT_STATUS_IS_OK(status)) {
4943 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4948 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4951 if (fsp->conn == NULL) {
4952 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4956 if (IS_IPC(fsp->conn)) {
4957 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4960 if (IS_PRINT(fsp->conn)) {
4961 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4964 doff = SVAL(inbuf,smb_vwv11);
4966 numtowrite = SVAL(inbuf,smb_vwv10);
4968 if (len > doff && len - doff > 0xFFFF) {
4969 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4972 if (numtowrite == 0) {
4973 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4977 /* Ensure the sizes match up. */
4978 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4979 /* no pad byte...old smbclient :-( */
4980 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4982 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4986 if (len - doff != numtowrite) {
4987 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4988 "len = %u, doff = %u, numtowrite = %u\n",
4991 (unsigned int)numtowrite ));
4995 DEBUG(10,("is_valid_writeX_buffer: true "
4996 "len = %u, doff = %u, numtowrite = %u\n",
4999 (unsigned int)numtowrite ));
5004 /****************************************************************************
5005 Reply to a write and X.
5006 ****************************************************************************/
5008 void reply_write_and_X(struct smb_request *req)
5010 connection_struct *conn = req->conn;
5011 struct smbXsrv_connection *xconn = req->xconn;
5013 struct lock_struct lock;
5018 unsigned int smb_doff;
5019 unsigned int smblen;
5022 int saved_errno = 0;
5024 START_PROFILE(SMBwriteX);
5026 if ((req->wct != 12) && (req->wct != 14)) {
5027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5031 numtowrite = SVAL(req->vwv+10, 0);
5032 smb_doff = SVAL(req->vwv+11, 0);
5033 smblen = smb_len(req->inbuf);
5035 if (req->unread_bytes > 0xFFFF ||
5036 (smblen > smb_doff &&
5037 smblen - smb_doff > 0xFFFF)) {
5038 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5041 if (req->unread_bytes) {
5042 /* Can't do a recvfile write on IPC$ */
5044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5047 if (numtowrite != req->unread_bytes) {
5048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5052 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5053 smb_doff + numtowrite > smblen) {
5054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5059 /* If it's an IPC, pass off the pipe handler. */
5061 if (req->unread_bytes) {
5062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5065 reply_pipe_write_and_X(req);
5069 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5070 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5071 write_through = BITSETW(req->vwv+7,0);
5073 if (!check_fsp(conn, req, fsp)) {
5077 if (!CHECK_WRITE(fsp)) {
5078 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5082 data = smb_base(req->inbuf) + smb_doff;
5084 if(req->wct == 14) {
5086 * This is a large offset (64 bit) write.
5088 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5092 /* X/Open SMB protocol says that, unlike SMBwrite
5093 if the length is zero then NO truncation is
5094 done, just a write of zero. To truncate a file,
5097 if(numtowrite == 0) {
5100 if (req->unread_bytes == 0) {
5101 status = schedule_aio_write_and_X(conn,
5108 if (NT_STATUS_IS_OK(status)) {
5109 /* write scheduled - we're done. */
5112 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5113 /* Real error - report to client. */
5114 reply_nterror(req, status);
5117 /* NT_STATUS_RETRY - fall through to sync write. */
5120 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5121 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5124 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5125 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5129 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5130 saved_errno = errno;
5132 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5136 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5140 if((nwritten == 0) && (numtowrite != 0)) {
5141 reply_nterror(req, NT_STATUS_DISK_FULL);
5145 reply_outbuf(req, 6, 0);
5146 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5147 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5148 SSVAL(req->outbuf,smb_vwv2,nwritten);
5149 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5151 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5152 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5154 status = sync_file(conn, fsp, write_through);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5157 fsp_str_dbg(fsp), nt_errstr(status)));
5158 reply_nterror(req, status);
5162 END_PROFILE(SMBwriteX);
5166 if (req->unread_bytes) {
5167 /* writeX failed. drain socket. */
5168 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5169 req->unread_bytes) {
5170 smb_panic("failed to drain pending bytes");
5172 req->unread_bytes = 0;
5175 END_PROFILE(SMBwriteX);
5179 /****************************************************************************
5181 ****************************************************************************/
5183 void reply_lseek(struct smb_request *req)
5185 connection_struct *conn = req->conn;
5191 START_PROFILE(SMBlseek);
5194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5195 END_PROFILE(SMBlseek);
5199 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5201 if (!check_fsp(conn, req, fsp)) {
5205 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5207 mode = SVAL(req->vwv+1, 0) & 3;
5208 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5209 startpos = (off_t)IVALS(req->vwv+2, 0);
5218 res = fsp->fh->pos + startpos;
5229 if (umode == SEEK_END) {
5230 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5231 if(errno == EINVAL) {
5232 off_t current_pos = startpos;
5234 if(fsp_stat(fsp) == -1) {
5236 map_nt_error_from_unix(errno));
5237 END_PROFILE(SMBlseek);
5241 current_pos += fsp->fsp_name->st.st_ex_size;
5243 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5248 reply_nterror(req, map_nt_error_from_unix(errno));
5249 END_PROFILE(SMBlseek);
5256 reply_outbuf(req, 2, 0);
5257 SIVAL(req->outbuf,smb_vwv0,res);
5259 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5260 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5262 END_PROFILE(SMBlseek);
5266 /****************************************************************************
5268 ****************************************************************************/
5270 void reply_flush(struct smb_request *req)
5272 connection_struct *conn = req->conn;
5276 START_PROFILE(SMBflush);
5279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5283 fnum = SVAL(req->vwv+0, 0);
5284 fsp = file_fsp(req, fnum);
5286 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5291 file_sync_all(conn);
5293 NTSTATUS status = sync_file(conn, fsp, True);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5296 fsp_str_dbg(fsp), nt_errstr(status)));
5297 reply_nterror(req, status);
5298 END_PROFILE(SMBflush);
5303 reply_outbuf(req, 0, 0);
5305 DEBUG(3,("flush\n"));
5306 END_PROFILE(SMBflush);
5310 /****************************************************************************
5312 conn POINTER CAN BE NULL HERE !
5313 ****************************************************************************/
5315 void reply_exit(struct smb_request *req)
5317 START_PROFILE(SMBexit);
5319 file_close_pid(req->sconn, req->smbpid, req->vuid);
5321 reply_outbuf(req, 0, 0);
5323 DEBUG(3,("exit\n"));
5325 END_PROFILE(SMBexit);
5329 struct reply_close_state {
5331 struct smb_request *smbreq;
5334 static void do_smb1_close(struct tevent_req *req);
5336 void reply_close(struct smb_request *req)
5338 connection_struct *conn = req->conn;
5339 NTSTATUS status = NT_STATUS_OK;
5340 files_struct *fsp = NULL;
5341 START_PROFILE(SMBclose);
5344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5345 END_PROFILE(SMBclose);
5349 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5352 * We can only use check_fsp if we know it's not a directory.
5355 if (!check_fsp_open(conn, req, fsp)) {
5356 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5357 END_PROFILE(SMBclose);
5361 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5362 fsp->is_directory ? "directory" : "file",
5363 fsp->fh->fd, fsp_fnum_dbg(fsp),
5364 conn->num_files_open));
5366 if (!fsp->is_directory) {
5370 * Take care of any time sent in the close.
5373 t = srv_make_unix_date3(req->vwv+1);
5374 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5377 if (fsp->num_aio_requests != 0) {
5379 struct reply_close_state *state;
5381 DEBUG(10, ("closing with aio %u requests pending\n",
5382 fsp->num_aio_requests));
5385 * We depend on the aio_extra destructor to take care of this
5386 * close request once fsp->num_aio_request drops to 0.
5389 fsp->deferred_close = tevent_wait_send(
5390 fsp, fsp->conn->sconn->ev_ctx);
5391 if (fsp->deferred_close == NULL) {
5392 status = NT_STATUS_NO_MEMORY;
5396 state = talloc(fsp, struct reply_close_state);
5397 if (state == NULL) {
5398 TALLOC_FREE(fsp->deferred_close);
5399 status = NT_STATUS_NO_MEMORY;
5403 state->smbreq = talloc_move(fsp, &req);
5404 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5406 END_PROFILE(SMBclose);
5411 * close_file() returns the unix errno if an error was detected on
5412 * close - normally this is due to a disk full error. If not then it
5413 * was probably an I/O error.
5416 status = close_file(req, fsp, NORMAL_CLOSE);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 reply_nterror(req, status);
5420 END_PROFILE(SMBclose);
5424 reply_outbuf(req, 0, 0);
5425 END_PROFILE(SMBclose);
5429 static void do_smb1_close(struct tevent_req *req)
5431 struct reply_close_state *state = tevent_req_callback_data(
5432 req, struct reply_close_state);
5433 struct smb_request *smbreq;
5437 ret = tevent_wait_recv(req);
5440 DEBUG(10, ("tevent_wait_recv returned %s\n",
5443 * Continue anyway, this should never happen
5448 * fsp->smb2_close_request right now is a talloc grandchild of
5449 * fsp. When we close_file(fsp), it would go with it. No chance to
5452 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5454 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5455 if (NT_STATUS_IS_OK(status)) {
5456 reply_outbuf(smbreq, 0, 0);
5458 reply_nterror(smbreq, status);
5460 if (!srv_send_smb(smbreq->xconn,
5461 (char *)smbreq->outbuf,
5464 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5466 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5469 TALLOC_FREE(smbreq);
5472 /****************************************************************************
5473 Reply to a writeclose (Core+ protocol).
5474 ****************************************************************************/
5476 void reply_writeclose(struct smb_request *req)
5478 connection_struct *conn = req->conn;
5480 ssize_t nwritten = -1;
5481 NTSTATUS close_status = NT_STATUS_OK;
5484 struct timespec mtime;
5486 struct lock_struct lock;
5488 START_PROFILE(SMBwriteclose);
5491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5492 END_PROFILE(SMBwriteclose);
5496 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5498 if (!check_fsp(conn, req, fsp)) {
5499 END_PROFILE(SMBwriteclose);
5502 if (!CHECK_WRITE(fsp)) {
5503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5504 END_PROFILE(SMBwriteclose);
5508 numtowrite = SVAL(req->vwv+1, 0);
5509 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5510 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5511 data = (const char *)req->buf + 1;
5513 if (fsp->print_file == NULL) {
5514 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5515 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5518 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5519 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5520 END_PROFILE(SMBwriteclose);
5525 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5527 if (fsp->print_file == NULL) {
5528 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5531 set_close_write_time(fsp, mtime);
5534 * More insanity. W2K only closes the file if writelen > 0.
5538 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5539 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5540 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5543 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5544 "file %s\n", fsp_str_dbg(fsp)));
5545 close_status = close_file(req, fsp, NORMAL_CLOSE);
5549 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5550 reply_nterror(req, NT_STATUS_DISK_FULL);
5554 if(!NT_STATUS_IS_OK(close_status)) {
5555 reply_nterror(req, close_status);
5559 reply_outbuf(req, 1, 0);
5561 SSVAL(req->outbuf,smb_vwv0,nwritten);
5565 END_PROFILE(SMBwriteclose);
5570 #define DBGC_CLASS DBGC_LOCKING
5572 /****************************************************************************
5574 ****************************************************************************/
5576 void reply_lock(struct smb_request *req)
5578 connection_struct *conn = req->conn;
5579 uint64_t count,offset;
5582 struct byte_range_lock *br_lck = NULL;
5584 START_PROFILE(SMBlock);
5587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5588 END_PROFILE(SMBlock);
5592 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5594 if (!check_fsp(conn, req, fsp)) {
5595 END_PROFILE(SMBlock);
5599 count = (uint64_t)IVAL(req->vwv+1, 0);
5600 offset = (uint64_t)IVAL(req->vwv+3, 0);
5602 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5603 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5605 br_lck = do_lock(req->sconn->msg_ctx,
5607 (uint64_t)req->smbpid,
5612 False, /* Non-blocking lock. */
5616 TALLOC_FREE(br_lck);
5618 if (NT_STATUS_V(status)) {
5619 reply_nterror(req, status);
5620 END_PROFILE(SMBlock);
5624 reply_outbuf(req, 0, 0);
5626 END_PROFILE(SMBlock);
5630 /****************************************************************************
5632 ****************************************************************************/
5634 void reply_unlock(struct smb_request *req)
5636 connection_struct *conn = req->conn;
5637 uint64_t count,offset;
5641 START_PROFILE(SMBunlock);
5644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5645 END_PROFILE(SMBunlock);
5649 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5651 if (!check_fsp(conn, req, fsp)) {
5652 END_PROFILE(SMBunlock);
5656 count = (uint64_t)IVAL(req->vwv+1, 0);
5657 offset = (uint64_t)IVAL(req->vwv+3, 0);
5659 status = do_unlock(req->sconn->msg_ctx,
5661 (uint64_t)req->smbpid,
5666 if (NT_STATUS_V(status)) {
5667 reply_nterror(req, status);
5668 END_PROFILE(SMBunlock);
5672 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5673 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5675 reply_outbuf(req, 0, 0);
5677 END_PROFILE(SMBunlock);
5682 #define DBGC_CLASS DBGC_ALL
5684 /****************************************************************************
5686 conn POINTER CAN BE NULL HERE !
5687 ****************************************************************************/
5689 void reply_tdis(struct smb_request *req)
5692 connection_struct *conn = req->conn;
5693 struct smbXsrv_tcon *tcon;
5695 START_PROFILE(SMBtdis);
5698 DEBUG(4,("Invalid connection in tdis\n"));
5699 reply_force_doserror(req, ERRSRV, ERRinvnid);
5700 END_PROFILE(SMBtdis);
5708 * TODO: cancel all outstanding requests on the tcon
5710 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5711 if (!NT_STATUS_IS_OK(status)) {
5712 DEBUG(0, ("reply_tdis: "
5713 "smbXsrv_tcon_disconnect() failed: %s\n",
5714 nt_errstr(status)));
5716 * If we hit this case, there is something completely
5717 * wrong, so we better disconnect the transport connection.
5719 END_PROFILE(SMBtdis);
5720 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5726 reply_outbuf(req, 0, 0);
5727 END_PROFILE(SMBtdis);
5731 /****************************************************************************
5733 conn POINTER CAN BE NULL HERE !
5734 ****************************************************************************/
5736 void reply_echo(struct smb_request *req)
5738 connection_struct *conn = req->conn;
5739 struct smb_perfcount_data local_pcd;
5740 struct smb_perfcount_data *cur_pcd;
5744 START_PROFILE(SMBecho);
5746 smb_init_perfcount_data(&local_pcd);
5749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5750 END_PROFILE(SMBecho);
5754 smb_reverb = SVAL(req->vwv+0, 0);
5756 reply_outbuf(req, 1, req->buflen);
5758 /* copy any incoming data back out */
5759 if (req->buflen > 0) {
5760 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5763 if (smb_reverb > 100) {
5764 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5768 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5770 /* this makes sure we catch the request pcd */
5771 if (seq_num == smb_reverb) {
5772 cur_pcd = &req->pcd;
5774 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5775 cur_pcd = &local_pcd;
5778 SSVAL(req->outbuf,smb_vwv0,seq_num);
5780 show_msg((char *)req->outbuf);
5781 if (!srv_send_smb(req->xconn,
5782 (char *)req->outbuf,
5783 true, req->seqnum+1,
5784 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5786 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5789 DEBUG(3,("echo %d times\n", smb_reverb));
5791 TALLOC_FREE(req->outbuf);
5793 END_PROFILE(SMBecho);
5797 /****************************************************************************
5798 Reply to a printopen.
5799 ****************************************************************************/
5801 void reply_printopen(struct smb_request *req)
5803 connection_struct *conn = req->conn;
5807 START_PROFILE(SMBsplopen);
5810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5811 END_PROFILE(SMBsplopen);
5815 if (!CAN_PRINT(conn)) {
5816 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5817 END_PROFILE(SMBsplopen);
5821 status = file_new(req, conn, &fsp);
5822 if(!NT_STATUS_IS_OK(status)) {
5823 reply_nterror(req, status);
5824 END_PROFILE(SMBsplopen);
5828 /* Open for exclusive use, write only. */
5829 status = print_spool_open(fsp, NULL, req->vuid);
5831 if (!NT_STATUS_IS_OK(status)) {
5832 file_free(req, fsp);
5833 reply_nterror(req, status);
5834 END_PROFILE(SMBsplopen);
5838 reply_outbuf(req, 1, 0);
5839 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5841 DEBUG(3,("openprint fd=%d %s\n",
5842 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5844 END_PROFILE(SMBsplopen);
5848 /****************************************************************************
5849 Reply to a printclose.
5850 ****************************************************************************/
5852 void reply_printclose(struct smb_request *req)
5854 connection_struct *conn = req->conn;
5858 START_PROFILE(SMBsplclose);
5861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5862 END_PROFILE(SMBsplclose);
5866 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5868 if (!check_fsp(conn, req, fsp)) {
5869 END_PROFILE(SMBsplclose);
5873 if (!CAN_PRINT(conn)) {
5874 reply_force_doserror(req, ERRSRV, ERRerror);
5875 END_PROFILE(SMBsplclose);
5879 DEBUG(3,("printclose fd=%d %s\n",
5880 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5882 status = close_file(req, fsp, NORMAL_CLOSE);
5884 if(!NT_STATUS_IS_OK(status)) {
5885 reply_nterror(req, status);
5886 END_PROFILE(SMBsplclose);
5890 reply_outbuf(req, 0, 0);
5892 END_PROFILE(SMBsplclose);
5896 /****************************************************************************
5897 Reply to a printqueue.
5898 ****************************************************************************/
5900 void reply_printqueue(struct smb_request *req)
5902 connection_struct *conn = req->conn;
5906 START_PROFILE(SMBsplretq);
5909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5910 END_PROFILE(SMBsplretq);
5914 max_count = SVAL(req->vwv+0, 0);
5915 start_index = SVAL(req->vwv+1, 0);
5917 /* we used to allow the client to get the cnum wrong, but that
5918 is really quite gross and only worked when there was only
5919 one printer - I think we should now only accept it if they
5920 get it right (tridge) */
5921 if (!CAN_PRINT(conn)) {
5922 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5923 END_PROFILE(SMBsplretq);
5927 reply_outbuf(req, 2, 3);
5928 SSVAL(req->outbuf,smb_vwv0,0);
5929 SSVAL(req->outbuf,smb_vwv1,0);
5930 SCVAL(smb_buf(req->outbuf),0,1);
5931 SSVAL(smb_buf(req->outbuf),1,0);
5933 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5934 start_index, max_count));
5937 TALLOC_CTX *mem_ctx = talloc_tos();
5940 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5941 struct rpc_pipe_client *cli = NULL;
5942 struct dcerpc_binding_handle *b = NULL;
5943 struct policy_handle handle;
5944 struct spoolss_DevmodeContainer devmode_ctr;
5945 union spoolss_JobInfo *info;
5947 uint32_t num_to_get;
5951 ZERO_STRUCT(handle);
5953 status = rpc_pipe_open_interface(conn,
5956 conn->sconn->remote_address,
5957 conn->sconn->msg_ctx,
5959 if (!NT_STATUS_IS_OK(status)) {
5960 DEBUG(0, ("reply_printqueue: "
5961 "could not connect to spoolss: %s\n",
5962 nt_errstr(status)));
5963 reply_nterror(req, status);
5966 b = cli->binding_handle;
5968 ZERO_STRUCT(devmode_ctr);
5970 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5973 SEC_FLAG_MAXIMUM_ALLOWED,
5976 if (!NT_STATUS_IS_OK(status)) {
5977 reply_nterror(req, status);
5980 if (!W_ERROR_IS_OK(werr)) {
5981 reply_nterror(req, werror_to_ntstatus(werr));
5985 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5993 if (!W_ERROR_IS_OK(werr)) {
5994 reply_nterror(req, werror_to_ntstatus(werr));
5998 if (max_count > 0) {
5999 first = start_index;
6001 first = start_index + max_count + 1;
6004 if (first >= count) {
6007 num_to_get = first + MIN(ABS(max_count), count - first);
6010 for (i = first; i < num_to_get; i++) {
6013 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6016 uint16_t qrapjobid = pjobid_to_rap(sharename,
6017 info[i].info2.job_id);
6019 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6025 srv_put_dos_date2(p, 0, qtime);
6026 SCVAL(p, 4, qstatus);
6027 SSVAL(p, 5, qrapjobid);
6028 SIVAL(p, 7, info[i].info2.size);
6030 status = srvstr_push(blob, req->flags2, p+12,
6031 info[i].info2.notify_name, 16, STR_ASCII, &len);
6032 if (!NT_STATUS_IS_OK(status)) {
6033 reply_nterror(req, status);
6036 if (message_push_blob(
6039 blob, sizeof(blob))) == -1) {
6040 reply_nterror(req, NT_STATUS_NO_MEMORY);
6046 SSVAL(req->outbuf,smb_vwv0,count);
6047 SSVAL(req->outbuf,smb_vwv1,
6048 (max_count>0?first+count:first-1));
6049 SCVAL(smb_buf(req->outbuf),0,1);
6050 SSVAL(smb_buf(req->outbuf),1,28*count);
6054 DEBUG(3, ("%u entries returned in queue\n",
6058 if (b && is_valid_policy_hnd(&handle)) {
6059 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6064 END_PROFILE(SMBsplretq);
6068 /****************************************************************************
6069 Reply to a printwrite.
6070 ****************************************************************************/
6072 void reply_printwrite(struct smb_request *req)
6074 connection_struct *conn = req->conn;
6079 START_PROFILE(SMBsplwr);
6082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6083 END_PROFILE(SMBsplwr);
6087 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6089 if (!check_fsp(conn, req, fsp)) {
6090 END_PROFILE(SMBsplwr);
6094 if (!fsp->print_file) {
6095 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6096 END_PROFILE(SMBsplwr);
6100 if (!CHECK_WRITE(fsp)) {
6101 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6102 END_PROFILE(SMBsplwr);
6106 numtowrite = SVAL(req->buf, 1);
6108 if (req->buflen < numtowrite + 3) {
6109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6110 END_PROFILE(SMBsplwr);
6114 data = (const char *)req->buf + 3;
6116 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6117 reply_nterror(req, map_nt_error_from_unix(errno));
6118 END_PROFILE(SMBsplwr);
6122 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6124 END_PROFILE(SMBsplwr);
6128 /****************************************************************************
6130 ****************************************************************************/
6132 void reply_mkdir(struct smb_request *req)
6134 connection_struct *conn = req->conn;
6135 struct smb_filename *smb_dname = NULL;
6136 char *directory = NULL;
6139 TALLOC_CTX *ctx = talloc_tos();
6141 START_PROFILE(SMBmkdir);
6143 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6144 STR_TERMINATE, &status);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 reply_nterror(req, status);
6150 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6151 status = filename_convert(ctx, conn,
6152 req->flags2 & FLAGS2_DFS_PATHNAMES,
6157 if (!NT_STATUS_IS_OK(status)) {
6158 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6159 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6160 ERRSRV, ERRbadpath);
6163 reply_nterror(req, status);
6167 status = create_directory(conn, req, smb_dname);
6169 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6171 if (!NT_STATUS_IS_OK(status)) {
6173 if (!use_nt_status()
6174 && NT_STATUS_EQUAL(status,
6175 NT_STATUS_OBJECT_NAME_COLLISION)) {
6177 * Yes, in the DOS error code case we get a
6178 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6179 * samba4 torture test.
6181 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6184 reply_nterror(req, status);
6188 reply_outbuf(req, 0, 0);
6190 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6192 TALLOC_FREE(smb_dname);
6193 END_PROFILE(SMBmkdir);
6197 /****************************************************************************
6199 ****************************************************************************/
6201 void reply_rmdir(struct smb_request *req)
6203 connection_struct *conn = req->conn;
6204 struct smb_filename *smb_dname = NULL;
6205 char *directory = NULL;
6207 TALLOC_CTX *ctx = talloc_tos();
6208 files_struct *fsp = NULL;
6210 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6211 struct smbd_server_connection *sconn = req->sconn;
6213 START_PROFILE(SMBrmdir);
6215 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6216 STR_TERMINATE, &status);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 reply_nterror(req, status);
6222 status = filename_convert(ctx, conn,
6223 req->flags2 & FLAGS2_DFS_PATHNAMES,
6228 if (!NT_STATUS_IS_OK(status)) {
6229 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6230 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6231 ERRSRV, ERRbadpath);
6234 reply_nterror(req, status);
6238 if (is_ntfs_stream_smb_fname(smb_dname)) {
6239 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6243 status = SMB_VFS_CREATE_FILE(
6246 0, /* root_dir_fid */
6247 smb_dname, /* fname */
6248 DELETE_ACCESS, /* access_mask */
6249 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6251 FILE_OPEN, /* create_disposition*/
6252 FILE_DIRECTORY_FILE, /* create_options */
6253 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6254 0, /* oplock_request */
6256 0, /* allocation_size */
6257 0, /* private_flags */
6262 NULL, NULL); /* create context */
6264 if (!NT_STATUS_IS_OK(status)) {
6265 if (open_was_deferred(req->xconn, req->mid)) {
6266 /* We have re-scheduled this call. */
6269 reply_nterror(req, status);
6273 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 close_file(req, fsp, ERROR_CLOSE);
6276 reply_nterror(req, status);
6280 if (!set_delete_on_close(fsp, true,
6281 conn->session_info->security_token,
6282 conn->session_info->unix_token)) {
6283 close_file(req, fsp, ERROR_CLOSE);
6284 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6288 status = close_file(req, fsp, NORMAL_CLOSE);
6289 if (!NT_STATUS_IS_OK(status)) {
6290 reply_nterror(req, status);
6292 reply_outbuf(req, 0, 0);
6295 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6297 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6299 TALLOC_FREE(smb_dname);
6300 END_PROFILE(SMBrmdir);
6304 /*******************************************************************
6305 Resolve wildcards in a filename rename.
6306 ********************************************************************/
6308 static bool resolve_wildcards(TALLOC_CTX *ctx,
6313 char *name2_copy = NULL;
6318 char *p,*p2, *pname1, *pname2;
6320 name2_copy = talloc_strdup(ctx, name2);
6325 pname1 = strrchr_m(name1,'/');
6326 pname2 = strrchr_m(name2_copy,'/');
6328 if (!pname1 || !pname2) {
6332 /* Truncate the copy of name2 at the last '/' */
6335 /* Now go past the '/' */
6339 root1 = talloc_strdup(ctx, pname1);
6340 root2 = talloc_strdup(ctx, pname2);
6342 if (!root1 || !root2) {
6346 p = strrchr_m(root1,'.');
6349 ext1 = talloc_strdup(ctx, p+1);
6351 ext1 = talloc_strdup(ctx, "");
6353 p = strrchr_m(root2,'.');
6356 ext2 = talloc_strdup(ctx, p+1);
6358 ext2 = talloc_strdup(ctx, "");
6361 if (!ext1 || !ext2) {
6369 /* Hmmm. Should this be mb-aware ? */
6372 } else if (*p2 == '*') {
6374 root2 = talloc_asprintf(ctx, "%s%s",
6393 /* Hmmm. Should this be mb-aware ? */
6396 } else if (*p2 == '*') {
6398 ext2 = talloc_asprintf(ctx, "%s%s",
6414 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6419 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6431 /****************************************************************************
6432 Ensure open files have their names updated. Updated to notify other smbd's
6434 ****************************************************************************/
6436 static void rename_open_files(connection_struct *conn,
6437 struct share_mode_lock *lck,
6439 uint32_t orig_name_hash,
6440 const struct smb_filename *smb_fname_dst)
6443 bool did_rename = False;
6445 uint32_t new_name_hash = 0;
6447 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6448 fsp = file_find_di_next(fsp)) {
6449 /* fsp_name is a relative path under the fsp. To change this for other
6450 sharepaths we need to manipulate relative paths. */
6451 /* TODO - create the absolute path and manipulate the newname
6452 relative to the sharepath. */
6453 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6456 if (fsp->name_hash != orig_name_hash) {
6459 DEBUG(10, ("rename_open_files: renaming file %s "
6460 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6461 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6462 smb_fname_str_dbg(smb_fname_dst)));
6464 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6465 if (NT_STATUS_IS_OK(status)) {
6467 new_name_hash = fsp->name_hash;
6472 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6473 "for %s\n", file_id_string_tos(&id),
6474 smb_fname_str_dbg(smb_fname_dst)));
6477 /* Send messages to all smbd's (not ourself) that the name has changed. */
6478 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6479 orig_name_hash, new_name_hash,
6484 /****************************************************************************
6485 We need to check if the source path is a parent directory of the destination
6486 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6487 refuse the rename with a sharing violation. Under UNIX the above call can
6488 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6489 probably need to check that the client is a Windows one before disallowing
6490 this as a UNIX client (one with UNIX extensions) can know the source is a
6491 symlink and make this decision intelligently. Found by an excellent bug
6492 report from <AndyLiebman@aol.com>.
6493 ****************************************************************************/
6495 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6496 const struct smb_filename *smb_fname_dst)
6498 const char *psrc = smb_fname_src->base_name;
6499 const char *pdst = smb_fname_dst->base_name;
6502 if (psrc[0] == '.' && psrc[1] == '/') {
6505 if (pdst[0] == '.' && pdst[1] == '/') {
6508 if ((slen = strlen(psrc)) > strlen(pdst)) {
6511 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6515 * Do the notify calls from a rename
6518 static void notify_rename(connection_struct *conn, bool is_dir,
6519 const struct smb_filename *smb_fname_src,
6520 const struct smb_filename *smb_fname_dst)
6522 char *parent_dir_src = NULL;
6523 char *parent_dir_dst = NULL;
6526 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6527 : FILE_NOTIFY_CHANGE_FILE_NAME;
6529 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6530 &parent_dir_src, NULL) ||
6531 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6532 &parent_dir_dst, NULL)) {
6536 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6537 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6538 smb_fname_src->base_name);
6539 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6540 smb_fname_dst->base_name);
6543 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6544 smb_fname_src->base_name);
6545 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6546 smb_fname_dst->base_name);
6549 /* this is a strange one. w2k3 gives an additional event for
6550 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6551 files, but not directories */
6553 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6554 FILE_NOTIFY_CHANGE_ATTRIBUTES
6555 |FILE_NOTIFY_CHANGE_CREATION,
6556 smb_fname_dst->base_name);
6559 TALLOC_FREE(parent_dir_src);
6560 TALLOC_FREE(parent_dir_dst);
6563 /****************************************************************************
6564 Returns an error if the parent directory for a filename is open in an
6566 ****************************************************************************/
6568 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6569 const struct smb_filename *smb_fname_dst_in)
6571 char *parent_dir = NULL;
6572 struct smb_filename smb_fname_parent;
6574 files_struct *fsp = NULL;
6577 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6578 &parent_dir, NULL)) {
6579 return NT_STATUS_NO_MEMORY;
6581 ZERO_STRUCT(smb_fname_parent);
6582 smb_fname_parent.base_name = parent_dir;
6584 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6586 return map_nt_error_from_unix(errno);
6590 * We're only checking on this smbd here, mostly good
6591 * enough.. and will pass tests.
6594 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6595 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6596 fsp = file_find_di_next(fsp)) {
6597 if (fsp->access_mask & DELETE_ACCESS) {
6598 return NT_STATUS_SHARING_VIOLATION;
6601 return NT_STATUS_OK;
6604 /****************************************************************************
6605 Rename an open file - given an fsp.
6606 ****************************************************************************/
6608 NTSTATUS rename_internals_fsp(connection_struct *conn,
6610 const struct smb_filename *smb_fname_dst_in,
6612 bool replace_if_exists)
6614 TALLOC_CTX *ctx = talloc_tos();
6615 struct smb_filename *smb_fname_dst = NULL;
6616 NTSTATUS status = NT_STATUS_OK;
6617 struct share_mode_lock *lck = NULL;
6618 uint32_t access_mask = SEC_DIR_ADD_FILE;
6619 bool dst_exists, old_is_stream, new_is_stream;
6621 status = check_name(conn, smb_fname_dst_in->base_name);
6622 if (!NT_STATUS_IS_OK(status)) {
6626 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6627 if (!NT_STATUS_IS_OK(status)) {
6631 /* Make a copy of the dst smb_fname structs */
6633 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6634 if (smb_fname_dst == NULL) {
6635 status = NT_STATUS_NO_MEMORY;
6640 * Check for special case with case preserving and not
6641 * case sensitive. If the new last component differs from the original
6642 * last component only by case, then we should allow
6643 * the rename (user is trying to change the case of the
6646 if (!conn->case_sensitive && conn->case_preserve &&
6647 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6648 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6649 char *fname_dst_parent = NULL;
6650 const char *fname_dst_lcomp = NULL;
6651 char *orig_lcomp_path = NULL;
6652 char *orig_lcomp_stream = NULL;
6656 * Split off the last component of the processed
6657 * destination name. We will compare this to
6658 * the split components of smb_fname_dst->original_lcomp.
6660 if (!parent_dirname(ctx,
6661 smb_fname_dst->base_name,
6663 &fname_dst_lcomp)) {
6664 status = NT_STATUS_NO_MEMORY;
6669 * The original_lcomp component contains
6670 * the last_component of the path + stream
6671 * name (if a stream exists).
6673 * Split off the stream name so we
6674 * can check them separately.
6677 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6678 /* POSIX - no stream component. */
6679 orig_lcomp_path = talloc_strdup(ctx,
6680 smb_fname_dst->original_lcomp);
6681 if (orig_lcomp_path == NULL) {
6685 ok = split_stream_filename(ctx,
6686 smb_fname_dst->original_lcomp,
6688 &orig_lcomp_stream);
6692 TALLOC_FREE(fname_dst_parent);
6693 status = NT_STATUS_NO_MEMORY;
6697 /* If the base names only differ by case, use original. */
6698 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6701 * Replace the modified last component with the
6704 if (!ISDOT(fname_dst_parent)) {
6705 tmp = talloc_asprintf(smb_fname_dst,
6710 tmp = talloc_strdup(smb_fname_dst,
6714 status = NT_STATUS_NO_MEMORY;
6715 TALLOC_FREE(fname_dst_parent);
6716 TALLOC_FREE(orig_lcomp_path);
6717 TALLOC_FREE(orig_lcomp_stream);
6720 TALLOC_FREE(smb_fname_dst->base_name);
6721 smb_fname_dst->base_name = tmp;
6724 /* If the stream_names only differ by case, use original. */
6725 if(!strcsequal(smb_fname_dst->stream_name,
6726 orig_lcomp_stream)) {
6727 /* Use the original stream. */
6728 char *tmp = talloc_strdup(smb_fname_dst,
6731 status = NT_STATUS_NO_MEMORY;
6732 TALLOC_FREE(fname_dst_parent);
6733 TALLOC_FREE(orig_lcomp_path);
6734 TALLOC_FREE(orig_lcomp_stream);
6737 TALLOC_FREE(smb_fname_dst->stream_name);
6738 smb_fname_dst->stream_name = tmp;
6740 TALLOC_FREE(fname_dst_parent);
6741 TALLOC_FREE(orig_lcomp_path);
6742 TALLOC_FREE(orig_lcomp_stream);
6746 * If the src and dest names are identical - including case,
6747 * don't do the rename, just return success.
6750 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6751 strcsequal(fsp->fsp_name->stream_name,
6752 smb_fname_dst->stream_name)) {
6753 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6754 "- returning success\n",
6755 smb_fname_str_dbg(smb_fname_dst)));
6756 status = NT_STATUS_OK;
6760 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6761 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6763 /* Return the correct error code if both names aren't streams. */
6764 if (!old_is_stream && new_is_stream) {
6765 status = NT_STATUS_OBJECT_NAME_INVALID;
6769 if (old_is_stream && !new_is_stream) {
6770 status = NT_STATUS_INVALID_PARAMETER;
6774 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6776 if(!replace_if_exists && dst_exists) {
6777 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6778 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6779 smb_fname_str_dbg(smb_fname_dst)));
6780 status = NT_STATUS_OBJECT_NAME_COLLISION;
6785 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6786 &smb_fname_dst->st);
6787 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6789 /* The file can be open when renaming a stream */
6790 if (dst_fsp && !new_is_stream) {
6791 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6792 status = NT_STATUS_ACCESS_DENIED;
6797 /* Ensure we have a valid stat struct for the source. */
6798 status = vfs_stat_fsp(fsp);
6799 if (!NT_STATUS_IS_OK(status)) {
6803 status = can_rename(conn, fsp, attrs);
6805 if (!NT_STATUS_IS_OK(status)) {
6806 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6807 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6808 smb_fname_str_dbg(smb_fname_dst)));
6809 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6810 status = NT_STATUS_ACCESS_DENIED;
6814 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6815 status = NT_STATUS_ACCESS_DENIED;
6819 /* Do we have rights to move into the destination ? */
6820 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6821 /* We're moving a directory. */
6822 access_mask = SEC_DIR_ADD_SUBDIR;
6824 status = check_parent_access(conn,
6827 if (!NT_STATUS_IS_OK(status)) {
6828 DBG_INFO("check_parent_access on "
6829 "dst %s returned %s\n",
6830 smb_fname_str_dbg(smb_fname_dst),
6835 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6838 * We have the file open ourselves, so not being able to get the
6839 * corresponding share mode lock is a fatal error.
6842 SMB_ASSERT(lck != NULL);
6844 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6845 uint32_t create_options = fsp->fh->private_options;
6847 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6848 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6849 smb_fname_str_dbg(smb_fname_dst)));
6851 if (!fsp->is_directory &&
6852 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6853 (lp_map_archive(SNUM(conn)) ||
6854 lp_store_dos_attributes(SNUM(conn)))) {
6855 /* We must set the archive bit on the newly
6857 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6858 uint32_t old_dosmode = dos_mode(conn,
6860 file_set_dosmode(conn,
6862 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6868 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6871 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6875 * A rename acts as a new file create w.r.t. allowing an initial delete
6876 * on close, probably because in Windows there is a new handle to the
6877 * new file. If initial delete on close was requested but not
6878 * originally set, we need to set it here. This is probably not 100% correct,
6879 * but will work for the CIFSFS client which in non-posix mode
6880 * depends on these semantics. JRA.
6883 if (create_options & FILE_DELETE_ON_CLOSE) {
6884 status = can_set_delete_on_close(fsp, 0);
6886 if (NT_STATUS_IS_OK(status)) {
6887 /* Note that here we set the *inital* delete on close flag,
6888 * not the regular one. The magic gets handled in close. */
6889 fsp->initial_delete_on_close = True;
6893 status = NT_STATUS_OK;
6899 if (errno == ENOTDIR || errno == EISDIR) {
6900 status = NT_STATUS_OBJECT_NAME_COLLISION;
6902 status = map_nt_error_from_unix(errno);
6905 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6906 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6907 smb_fname_str_dbg(smb_fname_dst)));
6910 TALLOC_FREE(smb_fname_dst);
6915 /****************************************************************************
6916 The guts of the rename command, split out so it may be called by the NT SMB
6918 ****************************************************************************/
6920 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6921 connection_struct *conn,
6922 struct smb_request *req,
6923 struct smb_filename *smb_fname_src,
6924 struct smb_filename *smb_fname_dst,
6926 bool replace_if_exists,
6929 uint32_t access_mask)
6931 char *fname_src_dir = NULL;
6932 struct smb_filename *smb_fname_src_dir = NULL;
6933 char *fname_src_mask = NULL;
6935 NTSTATUS status = NT_STATUS_OK;
6936 struct smb_Dir *dir_hnd = NULL;
6937 const char *dname = NULL;
6938 char *talloced = NULL;
6940 int create_options = 0;
6941 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6945 * Split the old name into directory and last component
6946 * strings. Note that unix_convert may have stripped off a
6947 * leading ./ from both name and newname if the rename is
6948 * at the root of the share. We need to make sure either both
6949 * name and newname contain a / character or neither of them do
6950 * as this is checked in resolve_wildcards().
6953 /* Split up the directory from the filename/mask. */
6954 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6955 &fname_src_dir, &fname_src_mask);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 status = NT_STATUS_NO_MEMORY;
6962 * We should only check the mangled cache
6963 * here if unix_convert failed. This means
6964 * that the path in 'mask' doesn't exist
6965 * on the file system and so we need to look
6966 * for a possible mangle. This patch from
6967 * Tine Smukavec <valentin.smukavec@hermes.si>.
6970 if (!VALID_STAT(smb_fname_src->st) &&
6971 mangle_is_mangled(fname_src_mask, conn->params)) {
6972 char *new_mask = NULL;
6973 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6976 TALLOC_FREE(fname_src_mask);
6977 fname_src_mask = new_mask;
6981 if (!src_has_wild) {
6985 * Only one file needs to be renamed. Append the mask back
6986 * onto the directory.
6988 TALLOC_FREE(smb_fname_src->base_name);
6989 if (ISDOT(fname_src_dir)) {
6990 /* Ensure we use canonical names on open. */
6991 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6995 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7000 if (!smb_fname_src->base_name) {
7001 status = NT_STATUS_NO_MEMORY;
7005 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7006 "case_preserve = %d, short case preserve = %d, "
7007 "directory = %s, newname = %s, "
7008 "last_component_dest = %s\n",
7009 conn->case_sensitive, conn->case_preserve,
7010 conn->short_case_preserve,
7011 smb_fname_str_dbg(smb_fname_src),
7012 smb_fname_str_dbg(smb_fname_dst),
7013 smb_fname_dst->original_lcomp));
7015 /* The dest name still may have wildcards. */
7016 if (dest_has_wild) {
7017 char *fname_dst_mod = NULL;
7018 if (!resolve_wildcards(smb_fname_dst,
7019 smb_fname_src->base_name,
7020 smb_fname_dst->base_name,
7022 DEBUG(6, ("rename_internals: resolve_wildcards "
7024 smb_fname_src->base_name,
7025 smb_fname_dst->base_name));
7026 status = NT_STATUS_NO_MEMORY;
7029 TALLOC_FREE(smb_fname_dst->base_name);
7030 smb_fname_dst->base_name = fname_dst_mod;
7033 ZERO_STRUCT(smb_fname_src->st);
7034 if (posix_pathnames) {
7035 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7037 rc = SMB_VFS_STAT(conn, smb_fname_src);
7040 status = map_nt_error_from_unix_common(errno);
7044 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7045 create_options |= FILE_DIRECTORY_FILE;
7048 status = SMB_VFS_CREATE_FILE(
7051 0, /* root_dir_fid */
7052 smb_fname_src, /* fname */
7053 access_mask, /* access_mask */
7054 (FILE_SHARE_READ | /* share_access */
7056 FILE_OPEN, /* create_disposition*/
7057 create_options, /* create_options */
7058 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7059 0, /* oplock_request */
7061 0, /* allocation_size */
7062 0, /* private_flags */
7067 NULL, NULL); /* create context */
7069 if (!NT_STATUS_IS_OK(status)) {
7070 DEBUG(3, ("Could not open rename source %s: %s\n",
7071 smb_fname_str_dbg(smb_fname_src),
7072 nt_errstr(status)));
7076 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7077 attrs, replace_if_exists);
7079 close_file(req, fsp, NORMAL_CLOSE);
7081 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7082 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7083 smb_fname_str_dbg(smb_fname_dst)));
7089 * Wildcards - process each file that matches.
7091 if (strequal(fname_src_mask, "????????.???")) {
7092 TALLOC_FREE(fname_src_mask);
7093 fname_src_mask = talloc_strdup(ctx, "*");
7094 if (!fname_src_mask) {
7095 status = NT_STATUS_NO_MEMORY;
7100 status = check_name(conn, fname_src_dir);
7101 if (!NT_STATUS_IS_OK(status)) {
7105 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7109 smb_fname_src->flags);
7110 if (smb_fname_src_dir == NULL) {
7111 status = NT_STATUS_NO_MEMORY;
7115 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7117 if (dir_hnd == NULL) {
7118 status = map_nt_error_from_unix(errno);
7122 status = NT_STATUS_NO_SUCH_FILE;
7124 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7125 * - gentest fix. JRA
7128 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7130 files_struct *fsp = NULL;
7131 char *destname = NULL;
7132 bool sysdir_entry = False;
7134 /* Quick check for "." and ".." */
7135 if (ISDOT(dname) || ISDOTDOT(dname)) {
7136 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7137 sysdir_entry = True;
7139 TALLOC_FREE(talloced);
7144 if (!is_visible_file(conn, fname_src_dir, dname,
7145 &smb_fname_src->st, false)) {
7146 TALLOC_FREE(talloced);
7150 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7151 TALLOC_FREE(talloced);
7156 status = NT_STATUS_OBJECT_NAME_INVALID;
7160 TALLOC_FREE(smb_fname_src->base_name);
7161 if (ISDOT(fname_src_dir)) {
7162 /* Ensure we use canonical names on open. */
7163 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7167 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7172 if (!smb_fname_src->base_name) {
7173 status = NT_STATUS_NO_MEMORY;
7177 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7178 smb_fname_dst->base_name,
7180 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7181 smb_fname_src->base_name, destname));
7182 TALLOC_FREE(talloced);
7186 status = NT_STATUS_NO_MEMORY;
7190 TALLOC_FREE(smb_fname_dst->base_name);
7191 smb_fname_dst->base_name = destname;
7193 ZERO_STRUCT(smb_fname_src->st);
7194 if (posix_pathnames) {
7195 SMB_VFS_LSTAT(conn, smb_fname_src);
7197 SMB_VFS_STAT(conn, smb_fname_src);
7202 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7203 create_options |= FILE_DIRECTORY_FILE;
7206 status = SMB_VFS_CREATE_FILE(
7209 0, /* root_dir_fid */
7210 smb_fname_src, /* fname */
7211 access_mask, /* access_mask */
7212 (FILE_SHARE_READ | /* share_access */
7214 FILE_OPEN, /* create_disposition*/
7215 create_options, /* create_options */
7216 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7217 0, /* oplock_request */
7219 0, /* allocation_size */
7220 0, /* private_flags */
7225 NULL, NULL); /* create context */
7227 if (!NT_STATUS_IS_OK(status)) {
7228 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7229 "returned %s rename %s -> %s\n",
7231 smb_fname_str_dbg(smb_fname_src),
7232 smb_fname_str_dbg(smb_fname_dst)));
7236 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7238 if (!smb_fname_dst->original_lcomp) {
7239 status = NT_STATUS_NO_MEMORY;
7243 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7244 attrs, replace_if_exists);
7246 close_file(req, fsp, NORMAL_CLOSE);
7248 if (!NT_STATUS_IS_OK(status)) {
7249 DEBUG(3, ("rename_internals_fsp returned %s for "
7250 "rename %s -> %s\n", nt_errstr(status),
7251 smb_fname_str_dbg(smb_fname_src),
7252 smb_fname_str_dbg(smb_fname_dst)));
7258 DEBUG(3,("rename_internals: doing rename on %s -> "
7259 "%s\n", smb_fname_str_dbg(smb_fname_src),
7260 smb_fname_str_dbg(smb_fname_src)));
7261 TALLOC_FREE(talloced);
7263 TALLOC_FREE(dir_hnd);
7265 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7266 status = map_nt_error_from_unix(errno);
7270 TALLOC_FREE(talloced);
7271 TALLOC_FREE(smb_fname_src_dir);
7272 TALLOC_FREE(fname_src_dir);
7273 TALLOC_FREE(fname_src_mask);
7277 /****************************************************************************
7279 ****************************************************************************/
7281 void reply_mv(struct smb_request *req)
7283 connection_struct *conn = req->conn;
7285 char *newname = NULL;
7289 bool src_has_wcard = False;
7290 bool dest_has_wcard = False;
7291 TALLOC_CTX *ctx = talloc_tos();
7292 struct smb_filename *smb_fname_src = NULL;
7293 struct smb_filename *smb_fname_dst = NULL;
7294 uint32_t src_ucf_flags = (req->posix_pathnames ?
7295 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7296 UCF_COND_ALLOW_WCARD_LCOMP);
7297 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7298 (req->posix_pathnames ? UCF_POSIX_PATHNAMES :
7299 UCF_COND_ALLOW_WCARD_LCOMP);
7300 bool stream_rename = false;
7302 START_PROFILE(SMBmv);
7305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7309 attrs = SVAL(req->vwv+0, 0);
7311 p = (const char *)req->buf + 1;
7312 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7313 &status, &src_has_wcard);
7314 if (!NT_STATUS_IS_OK(status)) {
7315 reply_nterror(req, status);
7319 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7320 &status, &dest_has_wcard);
7321 if (!NT_STATUS_IS_OK(status)) {
7322 reply_nterror(req, status);
7326 if (!req->posix_pathnames) {
7327 /* The newname must begin with a ':' if the
7328 name contains a ':'. */
7329 if (strchr_m(name, ':')) {
7330 if (newname[0] != ':') {
7331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7334 stream_rename = true;
7338 status = filename_convert(ctx,
7340 req->flags2 & FLAGS2_DFS_PATHNAMES,
7346 if (!NT_STATUS_IS_OK(status)) {
7347 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7348 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7349 ERRSRV, ERRbadpath);
7352 reply_nterror(req, status);
7356 status = filename_convert(ctx,
7358 req->flags2 & FLAGS2_DFS_PATHNAMES,
7364 if (!NT_STATUS_IS_OK(status)) {
7365 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7366 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7367 ERRSRV, ERRbadpath);
7370 reply_nterror(req, status);
7374 if (stream_rename) {
7375 /* smb_fname_dst->base_name must be the same as
7376 smb_fname_src->base_name. */
7377 TALLOC_FREE(smb_fname_dst->base_name);
7378 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7379 smb_fname_src->base_name);
7380 if (!smb_fname_dst->base_name) {
7381 reply_nterror(req, NT_STATUS_NO_MEMORY);
7386 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7387 smb_fname_str_dbg(smb_fname_dst)));
7389 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7390 attrs, False, src_has_wcard, dest_has_wcard,
7392 if (!NT_STATUS_IS_OK(status)) {
7393 if (open_was_deferred(req->xconn, req->mid)) {
7394 /* We have re-scheduled this call. */
7397 reply_nterror(req, status);
7401 reply_outbuf(req, 0, 0);
7403 TALLOC_FREE(smb_fname_src);
7404 TALLOC_FREE(smb_fname_dst);
7409 /*******************************************************************
7410 Copy a file as part of a reply_copy.
7411 ******************************************************************/
7414 * TODO: check error codes on all callers
7417 NTSTATUS copy_file(TALLOC_CTX *ctx,
7418 connection_struct *conn,
7419 struct smb_filename *smb_fname_src,
7420 struct smb_filename *smb_fname_dst,
7423 bool target_is_directory)
7425 struct smb_filename *smb_fname_dst_tmp = NULL;
7427 files_struct *fsp1,*fsp2;
7429 uint32_t new_create_disposition;
7433 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7434 if (smb_fname_dst_tmp == NULL) {
7435 return NT_STATUS_NO_MEMORY;
7439 * If the target is a directory, extract the last component from the
7440 * src filename and append it to the dst filename
7442 if (target_is_directory) {
7445 /* dest/target can't be a stream if it's a directory. */
7446 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7448 p = strrchr_m(smb_fname_src->base_name,'/');
7452 p = smb_fname_src->base_name;
7454 smb_fname_dst_tmp->base_name =
7455 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7457 if (!smb_fname_dst_tmp->base_name) {
7458 status = NT_STATUS_NO_MEMORY;
7463 status = vfs_file_exist(conn, smb_fname_src);
7464 if (!NT_STATUS_IS_OK(status)) {
7468 if (!target_is_directory && count) {
7469 new_create_disposition = FILE_OPEN;
7471 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7474 &new_create_disposition,
7477 status = NT_STATUS_INVALID_PARAMETER;
7482 /* Open the src file for reading. */
7483 status = SMB_VFS_CREATE_FILE(
7486 0, /* root_dir_fid */
7487 smb_fname_src, /* fname */
7488 FILE_GENERIC_READ, /* access_mask */
7489 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7490 FILE_OPEN, /* create_disposition*/
7491 0, /* create_options */
7492 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7493 INTERNAL_OPEN_ONLY, /* oplock_request */
7495 0, /* allocation_size */
7496 0, /* private_flags */
7501 NULL, NULL); /* create context */
7503 if (!NT_STATUS_IS_OK(status)) {
7507 dosattrs = dos_mode(conn, smb_fname_src);
7509 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7510 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7513 /* Open the dst file for writing. */
7514 status = SMB_VFS_CREATE_FILE(
7517 0, /* root_dir_fid */
7518 smb_fname_dst, /* fname */
7519 FILE_GENERIC_WRITE, /* access_mask */
7520 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7521 new_create_disposition, /* create_disposition*/
7522 0, /* create_options */
7523 dosattrs, /* file_attributes */
7524 INTERNAL_OPEN_ONLY, /* oplock_request */
7526 0, /* allocation_size */
7527 0, /* private_flags */
7532 NULL, NULL); /* create context */
7534 if (!NT_STATUS_IS_OK(status)) {
7535 close_file(NULL, fsp1, ERROR_CLOSE);
7539 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7540 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7542 DEBUG(0, ("error - vfs lseek returned error %s\n",
7544 status = map_nt_error_from_unix(errno);
7545 close_file(NULL, fsp1, ERROR_CLOSE);
7546 close_file(NULL, fsp2, ERROR_CLOSE);
7551 /* Do the actual copy. */
7552 if (smb_fname_src->st.st_ex_size) {
7553 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7558 close_file(NULL, fsp1, NORMAL_CLOSE);
7560 /* Ensure the modtime is set correctly on the destination file. */
7561 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7564 * As we are opening fsp1 read-only we only expect
7565 * an error on close on fsp2 if we are out of space.
7566 * Thus we don't look at the error return from the
7569 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7571 if (!NT_STATUS_IS_OK(status)) {
7575 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7576 status = NT_STATUS_DISK_FULL;
7580 status = NT_STATUS_OK;
7583 TALLOC_FREE(smb_fname_dst_tmp);
7587 /****************************************************************************
7588 Reply to a file copy.
7589 ****************************************************************************/
7591 void reply_copy(struct smb_request *req)
7593 connection_struct *conn = req->conn;
7594 struct smb_filename *smb_fname_src = NULL;
7595 struct smb_filename *smb_fname_src_dir = NULL;
7596 struct smb_filename *smb_fname_dst = NULL;
7597 char *fname_src = NULL;
7598 char *fname_dst = NULL;
7599 char *fname_src_mask = NULL;
7600 char *fname_src_dir = NULL;
7603 int error = ERRnoaccess;
7607 bool target_is_directory=False;
7608 bool source_has_wild = False;
7609 bool dest_has_wild = False;
7611 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7612 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7613 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7614 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7615 TALLOC_CTX *ctx = talloc_tos();
7617 START_PROFILE(SMBcopy);
7620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7624 tid2 = SVAL(req->vwv+0, 0);
7625 ofun = SVAL(req->vwv+1, 0);
7626 flags = SVAL(req->vwv+2, 0);
7628 p = (const char *)req->buf;
7629 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7630 &status, &source_has_wild);
7631 if (!NT_STATUS_IS_OK(status)) {
7632 reply_nterror(req, status);
7635 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7636 &status, &dest_has_wild);
7637 if (!NT_STATUS_IS_OK(status)) {
7638 reply_nterror(req, status);
7642 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7644 if (tid2 != conn->cnum) {
7645 /* can't currently handle inter share copies XXXX */
7646 DEBUG(3,("Rejecting inter-share copy\n"));
7647 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7651 status = filename_convert(ctx, conn,
7652 req->flags2 & FLAGS2_DFS_PATHNAMES,
7657 if (!NT_STATUS_IS_OK(status)) {
7658 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7659 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7660 ERRSRV, ERRbadpath);
7663 reply_nterror(req, status);
7667 status = filename_convert(ctx, conn,
7668 req->flags2 & FLAGS2_DFS_PATHNAMES,
7673 if (!NT_STATUS_IS_OK(status)) {
7674 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7675 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7676 ERRSRV, ERRbadpath);
7679 reply_nterror(req, status);
7683 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7685 if ((flags&1) && target_is_directory) {
7686 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7690 if ((flags&2) && !target_is_directory) {
7691 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7695 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7696 /* wants a tree copy! XXXX */
7697 DEBUG(3,("Rejecting tree copy\n"));
7698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7702 /* Split up the directory from the filename/mask. */
7703 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7704 &fname_src_dir, &fname_src_mask);
7705 if (!NT_STATUS_IS_OK(status)) {
7706 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 * We should only check the mangled cache
7712 * here if unix_convert failed. This means
7713 * that the path in 'mask' doesn't exist
7714 * on the file system and so we need to look
7715 * for a possible mangle. This patch from
7716 * Tine Smukavec <valentin.smukavec@hermes.si>.
7718 if (!VALID_STAT(smb_fname_src->st) &&
7719 mangle_is_mangled(fname_src_mask, conn->params)) {
7720 char *new_mask = NULL;
7721 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7722 &new_mask, conn->params);
7724 /* Use demangled name if one was successfully found. */
7726 TALLOC_FREE(fname_src_mask);
7727 fname_src_mask = new_mask;
7731 if (!source_has_wild) {
7734 * Only one file needs to be copied. Append the mask back onto
7737 TALLOC_FREE(smb_fname_src->base_name);
7738 if (ISDOT(fname_src_dir)) {
7739 /* Ensure we use canonical names on open. */
7740 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7744 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7749 if (!smb_fname_src->base_name) {
7750 reply_nterror(req, NT_STATUS_NO_MEMORY);
7754 if (dest_has_wild) {
7755 char *fname_dst_mod = NULL;
7756 if (!resolve_wildcards(smb_fname_dst,
7757 smb_fname_src->base_name,
7758 smb_fname_dst->base_name,
7760 reply_nterror(req, NT_STATUS_NO_MEMORY);
7763 TALLOC_FREE(smb_fname_dst->base_name);
7764 smb_fname_dst->base_name = fname_dst_mod;
7767 status = check_name(conn, smb_fname_src->base_name);
7768 if (!NT_STATUS_IS_OK(status)) {
7769 reply_nterror(req, status);
7773 status = check_name(conn, smb_fname_dst->base_name);
7774 if (!NT_STATUS_IS_OK(status)) {
7775 reply_nterror(req, status);
7779 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7780 ofun, count, target_is_directory);
7782 if(!NT_STATUS_IS_OK(status)) {
7783 reply_nterror(req, status);
7789 struct smb_Dir *dir_hnd = NULL;
7790 const char *dname = NULL;
7791 char *talloced = NULL;
7795 * There is a wildcard that requires us to actually read the
7796 * src dir and copy each file matching the mask to the dst.
7797 * Right now streams won't be copied, but this could
7798 * presumably be added with a nested loop for reach dir entry.
7800 SMB_ASSERT(!smb_fname_src->stream_name);
7801 SMB_ASSERT(!smb_fname_dst->stream_name);
7803 smb_fname_src->stream_name = NULL;
7804 smb_fname_dst->stream_name = NULL;
7806 if (strequal(fname_src_mask,"????????.???")) {
7807 TALLOC_FREE(fname_src_mask);
7808 fname_src_mask = talloc_strdup(ctx, "*");
7809 if (!fname_src_mask) {
7810 reply_nterror(req, NT_STATUS_NO_MEMORY);
7815 status = check_name(conn, fname_src_dir);
7816 if (!NT_STATUS_IS_OK(status)) {
7817 reply_nterror(req, status);
7821 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7825 smb_fname_src->flags);
7826 if (smb_fname_src_dir == NULL) {
7827 reply_nterror(req, NT_STATUS_NO_MEMORY);
7831 dir_hnd = OpenDir(ctx,
7836 if (dir_hnd == NULL) {
7837 status = map_nt_error_from_unix(errno);
7838 reply_nterror(req, status);
7844 /* Iterate over the src dir copying each entry to the dst. */
7845 while ((dname = ReadDirName(dir_hnd, &offset,
7846 &smb_fname_src->st, &talloced))) {
7847 char *destname = NULL;
7849 if (ISDOT(dname) || ISDOTDOT(dname)) {
7850 TALLOC_FREE(talloced);
7854 if (!is_visible_file(conn, fname_src_dir, dname,
7855 &smb_fname_src->st, false)) {
7856 TALLOC_FREE(talloced);
7860 if(!mask_match(dname, fname_src_mask,
7861 conn->case_sensitive)) {
7862 TALLOC_FREE(talloced);
7866 error = ERRnoaccess;
7868 /* Get the src smb_fname struct setup. */
7869 TALLOC_FREE(smb_fname_src->base_name);
7870 if (ISDOT(fname_src_dir)) {
7871 /* Ensure we use canonical names on open. */
7872 smb_fname_src->base_name =
7873 talloc_asprintf(smb_fname_src, "%s",
7876 smb_fname_src->base_name =
7877 talloc_asprintf(smb_fname_src, "%s/%s",
7878 fname_src_dir, dname);
7881 if (!smb_fname_src->base_name) {
7882 TALLOC_FREE(dir_hnd);
7883 TALLOC_FREE(talloced);
7884 reply_nterror(req, NT_STATUS_NO_MEMORY);
7888 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7889 smb_fname_dst->base_name,
7891 TALLOC_FREE(talloced);
7895 TALLOC_FREE(dir_hnd);
7896 TALLOC_FREE(talloced);
7897 reply_nterror(req, NT_STATUS_NO_MEMORY);
7901 TALLOC_FREE(smb_fname_dst->base_name);
7902 smb_fname_dst->base_name = destname;
7904 status = check_name(conn, smb_fname_src->base_name);
7905 if (!NT_STATUS_IS_OK(status)) {
7906 TALLOC_FREE(dir_hnd);
7907 TALLOC_FREE(talloced);
7908 reply_nterror(req, status);
7912 status = check_name(conn, smb_fname_dst->base_name);
7913 if (!NT_STATUS_IS_OK(status)) {
7914 TALLOC_FREE(dir_hnd);
7915 TALLOC_FREE(talloced);
7916 reply_nterror(req, status);
7920 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7921 smb_fname_src->base_name,
7922 smb_fname_dst->base_name));
7924 status = copy_file(ctx, conn, smb_fname_src,
7925 smb_fname_dst, ofun, count,
7926 target_is_directory);
7927 if (NT_STATUS_IS_OK(status)) {
7931 TALLOC_FREE(talloced);
7933 TALLOC_FREE(dir_hnd);
7937 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7941 reply_outbuf(req, 1, 0);
7942 SSVAL(req->outbuf,smb_vwv0,count);
7944 TALLOC_FREE(smb_fname_src);
7945 TALLOC_FREE(smb_fname_src_dir);
7946 TALLOC_FREE(smb_fname_dst);
7947 TALLOC_FREE(fname_src);
7948 TALLOC_FREE(fname_dst);
7949 TALLOC_FREE(fname_src_mask);
7950 TALLOC_FREE(fname_src_dir);
7952 END_PROFILE(SMBcopy);
7957 #define DBGC_CLASS DBGC_LOCKING
7959 /****************************************************************************
7960 Get a lock pid, dealing with large count requests.
7961 ****************************************************************************/
7963 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7964 bool large_file_format)
7966 if(!large_file_format)
7967 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7969 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7972 /****************************************************************************
7973 Get a lock count, dealing with large count requests.
7974 ****************************************************************************/
7976 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7977 bool large_file_format)
7981 if(!large_file_format) {
7982 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7985 * No BVAL, this is reversed!
7987 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7988 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7994 /****************************************************************************
7995 Get a lock offset, dealing with large offset requests.
7996 ****************************************************************************/
7998 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7999 bool large_file_format)
8001 uint64_t offset = 0;
8003 if(!large_file_format) {
8004 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8007 * No BVAL, this is reversed!
8009 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8010 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8016 NTSTATUS smbd_do_locking(struct smb_request *req,
8021 struct smbd_lock_element *locks,
8024 connection_struct *conn = req->conn;
8026 NTSTATUS status = NT_STATUS_OK;
8030 /* Setup the timeout in seconds. */
8032 if (!lp_blocking_locks(SNUM(conn))) {
8036 for(i = 0; i < (int)num_locks; i++) {
8037 struct smbd_lock_element *e = &locks[i];
8039 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8040 "%llu, file %s timeout = %d\n",
8043 (unsigned long long)e->smblctx,
8047 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8048 struct blocking_lock_record *blr = NULL;
8050 if (num_locks > 1) {
8052 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8053 * if the lock vector contains one entry. When given multiple cancel
8054 * requests in a single PDU we expect the server to return an
8055 * error. Windows servers seem to accept the request but only
8056 * cancel the first lock.
8057 * JRA - Do what Windows does (tm) :-).
8061 /* MS-CIFS (2.2.4.32.1) behavior. */
8062 return NT_STATUS_DOS(ERRDOS,
8063 ERRcancelviolation);
8065 /* Windows behavior. */
8067 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8068 "cancel request\n"));
8074 if (lp_blocking_locks(SNUM(conn))) {
8076 /* Schedule a message to ourselves to
8077 remove the blocking lock record and
8078 return the right error. */
8080 blr = blocking_lock_cancel_smb1(fsp,
8086 NT_STATUS_FILE_LOCK_CONFLICT);
8088 return NT_STATUS_DOS(
8090 ERRcancelviolation);
8093 /* Remove a matching pending lock. */
8094 status = do_lock_cancel(fsp,
8100 bool blocking_lock = timeout ? true : false;
8101 bool defer_lock = false;
8102 struct byte_range_lock *br_lck;
8103 uint64_t block_smblctx;
8105 br_lck = do_lock(req->sconn->msg_ctx,
8116 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8117 /* Windows internal resolution for blocking locks seems
8118 to be about 200ms... Don't wait for less than that. JRA. */
8119 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8120 timeout = lp_lock_spin_time();
8125 /* If a lock sent with timeout of zero would fail, and
8126 * this lock has been requested multiple times,
8127 * according to brl_lock_failed() we convert this
8128 * request to a blocking lock with a timeout of between
8129 * 150 - 300 milliseconds.
8131 * If lp_lock_spin_time() has been set to 0, we skip
8132 * this blocking retry and fail immediately.
8134 * Replacement for do_lock_spin(). JRA. */
8136 if (!req->sconn->using_smb2 &&
8137 br_lck && lp_blocking_locks(SNUM(conn)) &&
8138 lp_lock_spin_time() && !blocking_lock &&
8139 NT_STATUS_EQUAL((status),
8140 NT_STATUS_FILE_LOCK_CONFLICT))
8143 timeout = lp_lock_spin_time();
8146 if (br_lck && defer_lock) {
8148 * A blocking lock was requested. Package up
8149 * this smb into a queued request and push it
8150 * onto the blocking lock queue.
8152 if(push_blocking_lock_request(br_lck,
8163 TALLOC_FREE(br_lck);
8165 return NT_STATUS_OK;
8169 TALLOC_FREE(br_lck);
8172 if (!NT_STATUS_IS_OK(status)) {
8177 /* If any of the above locks failed, then we must unlock
8178 all of the previous locks (X/Open spec). */
8180 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8182 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8183 i = -1; /* we want to skip the for loop */
8187 * Ensure we don't do a remove on the lock that just failed,
8188 * as under POSIX rules, if we have a lock already there, we
8189 * will delete it (and we shouldn't) .....
8191 for(i--; i >= 0; i--) {
8192 struct smbd_lock_element *e = &locks[i];
8194 do_unlock(req->sconn->msg_ctx,
8204 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8205 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8207 return NT_STATUS_OK;
8210 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8212 uint16_t num_ulocks,
8213 struct smbd_lock_element *ulocks)
8217 for(i = 0; i < (int)num_ulocks; i++) {
8218 struct smbd_lock_element *e = &ulocks[i];
8221 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8222 "pid %u, file %s\n", __func__,
8225 (unsigned int)e->smblctx,
8228 if (e->brltype != UNLOCK_LOCK) {
8229 /* this can only happen with SMB2 */
8230 return NT_STATUS_INVALID_PARAMETER;
8233 status = do_unlock(req->sconn->msg_ctx,
8240 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8241 nt_errstr(status)));
8243 if (!NT_STATUS_IS_OK(status)) {
8248 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8251 return NT_STATUS_OK;
8254 /****************************************************************************
8255 Reply to a lockingX request.
8256 ****************************************************************************/
8258 void reply_lockingX(struct smb_request *req)
8260 connection_struct *conn = req->conn;
8262 unsigned char locktype;
8263 unsigned char oplocklevel;
8264 uint16_t num_ulocks;
8266 int32_t lock_timeout;
8268 const uint8_t *data;
8269 bool large_file_format;
8270 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8271 struct smbd_lock_element *ulocks;
8272 struct smbd_lock_element *locks;
8275 START_PROFILE(SMBlockingX);
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8279 END_PROFILE(SMBlockingX);
8283 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8284 locktype = CVAL(req->vwv+3, 0);
8285 oplocklevel = CVAL(req->vwv+3, 1);
8286 num_ulocks = SVAL(req->vwv+6, 0);
8287 num_locks = SVAL(req->vwv+7, 0);
8288 lock_timeout = IVAL(req->vwv+4, 0);
8289 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8291 if (!check_fsp(conn, req, fsp)) {
8292 END_PROFILE(SMBlockingX);
8298 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8299 /* we don't support these - and CANCEL_LOCK makes w2k
8300 and XP reboot so I don't really want to be
8301 compatible! (tridge) */
8302 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8303 END_PROFILE(SMBlockingX);
8307 /* Check if this is an oplock break on a file
8308 we have granted an oplock on.
8310 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8311 /* Client can insist on breaking to none. */
8312 bool break_to_none = (oplocklevel == 0);
8315 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8316 "for %s\n", (unsigned int)oplocklevel,
8317 fsp_fnum_dbg(fsp)));
8320 * Make sure we have granted an exclusive or batch oplock on
8324 if (fsp->oplock_type == 0) {
8326 /* The Samba4 nbench simulator doesn't understand
8327 the difference between break to level2 and break
8328 to none from level2 - it sends oplock break
8329 replies in both cases. Don't keep logging an error
8330 message here - just ignore it. JRA. */
8332 DEBUG(5,("reply_lockingX: Error : oplock break from "
8333 "client for %s (oplock=%d) and no "
8334 "oplock granted on this file (%s).\n",
8335 fsp_fnum_dbg(fsp), fsp->oplock_type,
8338 /* if this is a pure oplock break request then don't
8340 if (num_locks == 0 && num_ulocks == 0) {
8341 END_PROFILE(SMBlockingX);
8344 END_PROFILE(SMBlockingX);
8345 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8350 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8352 result = remove_oplock(fsp);
8354 result = downgrade_oplock(fsp);
8358 DEBUG(0, ("reply_lockingX: error in removing "
8359 "oplock on file %s\n", fsp_str_dbg(fsp)));
8360 /* Hmmm. Is this panic justified? */
8361 smb_panic("internal tdb error");
8364 /* if this is a pure oplock break request then don't send a
8366 if (num_locks == 0 && num_ulocks == 0) {
8367 /* Sanity check - ensure a pure oplock break is not a
8369 if (CVAL(req->vwv+0, 0) != 0xff) {
8370 DEBUG(0,("reply_lockingX: Error : pure oplock "
8371 "break is a chained %d request !\n",
8372 (unsigned int)CVAL(req->vwv+0, 0)));
8374 END_PROFILE(SMBlockingX);
8380 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8382 END_PROFILE(SMBlockingX);
8386 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8387 if (ulocks == NULL) {
8388 reply_nterror(req, NT_STATUS_NO_MEMORY);
8389 END_PROFILE(SMBlockingX);
8393 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8394 if (locks == NULL) {
8395 reply_nterror(req, NT_STATUS_NO_MEMORY);
8396 END_PROFILE(SMBlockingX);
8400 /* Data now points at the beginning of the list
8401 of smb_unlkrng structs */
8402 for(i = 0; i < (int)num_ulocks; i++) {
8403 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8404 ulocks[i].count = get_lock_count(data, i, large_file_format);
8405 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8406 ulocks[i].brltype = UNLOCK_LOCK;
8409 /* Now do any requested locks */
8410 data += ((large_file_format ? 20 : 10)*num_ulocks);
8412 /* Data now points at the beginning of the list
8413 of smb_lkrng structs */
8415 for(i = 0; i < (int)num_locks; i++) {
8416 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8417 locks[i].count = get_lock_count(data, i, large_file_format);
8418 locks[i].offset = get_lock_offset(data, i, large_file_format);
8420 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8421 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8422 locks[i].brltype = PENDING_READ_LOCK;
8424 locks[i].brltype = READ_LOCK;
8427 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8428 locks[i].brltype = PENDING_WRITE_LOCK;
8430 locks[i].brltype = WRITE_LOCK;
8435 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8436 if (!NT_STATUS_IS_OK(status)) {
8437 END_PROFILE(SMBlockingX);
8438 reply_nterror(req, status);
8442 status = smbd_do_locking(req, fsp,
8443 locktype, lock_timeout,
8446 if (!NT_STATUS_IS_OK(status)) {
8447 END_PROFILE(SMBlockingX);
8448 reply_nterror(req, status);
8452 END_PROFILE(SMBlockingX);
8456 reply_outbuf(req, 2, 0);
8457 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8458 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8460 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8461 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8463 END_PROFILE(SMBlockingX);
8467 #define DBGC_CLASS DBGC_ALL
8469 /****************************************************************************
8470 Reply to a SMBreadbmpx (read block multiplex) request.
8471 Always reply with an error, if someone has a platform really needs this,
8472 please contact vl@samba.org
8473 ****************************************************************************/
8475 void reply_readbmpx(struct smb_request *req)
8477 START_PROFILE(SMBreadBmpx);
8478 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8479 END_PROFILE(SMBreadBmpx);
8483 /****************************************************************************
8484 Reply to a SMBreadbs (read block multiplex secondary) request.
8485 Always reply with an error, if someone has a platform really needs this,
8486 please contact vl@samba.org
8487 ****************************************************************************/
8489 void reply_readbs(struct smb_request *req)
8491 START_PROFILE(SMBreadBs);
8492 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8493 END_PROFILE(SMBreadBs);
8497 /****************************************************************************
8498 Reply to a SMBsetattrE.
8499 ****************************************************************************/
8501 void reply_setattrE(struct smb_request *req)
8503 connection_struct *conn = req->conn;
8504 struct smb_file_time ft;
8508 START_PROFILE(SMBsetattrE);
8512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8516 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8518 if(!fsp || (fsp->conn != conn)) {
8519 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8524 * Convert the DOS times into unix times.
8527 ft.atime = convert_time_t_to_timespec(
8528 srv_make_unix_date2(req->vwv+3));
8529 ft.mtime = convert_time_t_to_timespec(
8530 srv_make_unix_date2(req->vwv+5));
8531 ft.create_time = convert_time_t_to_timespec(
8532 srv_make_unix_date2(req->vwv+1));
8534 reply_outbuf(req, 0, 0);
8537 * Patch from Ray Frush <frush@engr.colostate.edu>
8538 * Sometimes times are sent as zero - ignore them.
8541 /* Ensure we have a valid stat struct for the source. */
8542 status = vfs_stat_fsp(fsp);
8543 if (!NT_STATUS_IS_OK(status)) {
8544 reply_nterror(req, status);
8548 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8549 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8553 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8554 if (!NT_STATUS_IS_OK(status)) {
8555 reply_nterror(req, status);
8559 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8562 (unsigned int)ft.atime.tv_sec,
8563 (unsigned int)ft.mtime.tv_sec,
8564 (unsigned int)ft.create_time.tv_sec
8567 END_PROFILE(SMBsetattrE);
8572 /* Back from the dead for OS/2..... JRA. */
8574 /****************************************************************************
8575 Reply to a SMBwritebmpx (write block multiplex primary) request.
8576 Always reply with an error, if someone has a platform really needs this,
8577 please contact vl@samba.org
8578 ****************************************************************************/
8580 void reply_writebmpx(struct smb_request *req)
8582 START_PROFILE(SMBwriteBmpx);
8583 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8584 END_PROFILE(SMBwriteBmpx);
8588 /****************************************************************************
8589 Reply to a SMBwritebs (write block multiplex secondary) request.
8590 Always reply with an error, if someone has a platform really needs this,
8591 please contact vl@samba.org
8592 ****************************************************************************/
8594 void reply_writebs(struct smb_request *req)
8596 START_PROFILE(SMBwriteBs);
8597 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8598 END_PROFILE(SMBwriteBs);
8602 /****************************************************************************
8603 Reply to a SMBgetattrE.
8604 ****************************************************************************/
8606 void reply_getattrE(struct smb_request *req)
8608 connection_struct *conn = req->conn;
8611 struct timespec create_ts;
8613 START_PROFILE(SMBgetattrE);
8616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8617 END_PROFILE(SMBgetattrE);
8621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8623 if(!fsp || (fsp->conn != conn)) {
8624 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8625 END_PROFILE(SMBgetattrE);
8629 /* Do an fstat on this file */
8631 reply_nterror(req, map_nt_error_from_unix(errno));
8632 END_PROFILE(SMBgetattrE);
8636 mode = dos_mode(conn, fsp->fsp_name);
8639 * Convert the times into dos times. Set create
8640 * date to be last modify date as UNIX doesn't save
8644 reply_outbuf(req, 11, 0);
8646 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8647 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8648 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8649 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8650 /* Should we check pending modtime here ? JRA */
8651 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8652 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8654 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8655 SIVAL(req->outbuf, smb_vwv6, 0);
8656 SIVAL(req->outbuf, smb_vwv8, 0);
8658 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8659 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8660 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8662 SSVAL(req->outbuf,smb_vwv10, mode);
8664 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8666 END_PROFILE(SMBgetattrE);