2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
266 bool posix_pathnames,
268 bool *contains_wcard)
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 *err = NT_STATUS_INVALID_PARAMETER;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
369 return srvstr_get_path_wcard_internal(ctx,
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
396 return srvstr_get_path_wcard_internal(ctx,
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
416 *err = NT_STATUS_INVALID_PARAMETER;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
497 if (!check_fsp_open(conn, req, fsp)) {
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
508 fsp->num_smb_operations++;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
520 if (!check_fsp_open(conn, req, fsp)) {
524 if (fsp->is_directory) {
528 if (fsp->fake_file_handle == NULL) {
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 if (fsp->fake_file_handle->private_data == NULL) {
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
547 char *trim_name_type;
548 const char *retarget_parm;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
570 if (trim_name_type == NULL) {
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
580 if (retarget_parm == NULL) {
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
600 if (sscanf(p, "%x", &retarget_type) != 1) {
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
607 DEBUG(10, ("could not resolve %s\n", retarget));
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
631 TALLOC_FREE(trim_name);
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
667 int name_type1, name_type2;
668 int name_len1, name_len2;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
751 reply_called_name_not_present(outbuf);
755 reload_services(sconn, conn_snum_used, true);
758 xconn->transport.nbt.got_session = true;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
774 case NBSSkeepalive: /* session keepalive */
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
784 if (CVAL(outbuf, 0) != 0x82) {
785 exit_server_cleanly("invalid netbios session");
790 /****************************************************************************
792 conn POINTER CAN BE NULL HERE !
793 ****************************************************************************/
795 void reply_tcon(struct smb_request *req)
797 connection_struct *conn = req->conn;
799 char *service_buf = NULL;
800 char *password = NULL;
806 TALLOC_CTX *ctx = talloc_tos();
807 struct smbXsrv_connection *xconn = req->xconn;
808 NTTIME now = timeval_to_nttime(&req->request_time);
810 START_PROFILE(SMBtcon);
812 if (req->buflen < 4) {
813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
814 END_PROFILE(SMBtcon);
819 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
821 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
823 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
826 if (service_buf == NULL || password == NULL || dev == NULL) {
827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
828 END_PROFILE(SMBtcon);
831 p2 = strrchr_m(service_buf,'\\');
835 service = service_buf;
838 conn = make_connection(req, now, service, dev,
839 req->vuid,&nt_status);
843 reply_nterror(req, nt_status);
844 END_PROFILE(SMBtcon);
848 reply_outbuf(req, 2, 0);
849 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
850 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
853 DEBUG(3,("tcon service=%s cnum=%d\n",
854 service, conn->cnum));
856 END_PROFILE(SMBtcon);
860 /****************************************************************************
861 Reply to a tcon and X.
862 conn POINTER CAN BE NULL HERE !
863 ****************************************************************************/
865 void reply_tcon_and_X(struct smb_request *req)
867 connection_struct *conn = req->conn;
868 const char *service = NULL;
869 TALLOC_CTX *ctx = talloc_tos();
870 /* what the cleint thinks the device is */
871 char *client_devicetype = NULL;
872 /* what the server tells the client the share represents */
873 const char *server_devicetype;
880 struct smbXsrv_session *session = NULL;
881 NTTIME now = timeval_to_nttime(&req->request_time);
882 bool session_key_updated = false;
883 uint16_t optional_support = 0;
884 struct smbXsrv_connection *xconn = req->xconn;
886 START_PROFILE(SMBtconX);
889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
890 END_PROFILE(SMBtconX);
894 passlen = SVAL(req->vwv+3, 0);
895 tcon_flags = SVAL(req->vwv+2, 0);
897 /* we might have to close an old one */
898 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
899 struct smbXsrv_tcon *tcon;
907 * TODO: cancel all outstanding requests on the tcon
909 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(0, ("reply_tcon_and_X: "
912 "smbXsrv_tcon_disconnect() failed: %s\n",
915 * If we hit this case, there is something completely
916 * wrong, so we better disconnect the transport connection.
918 END_PROFILE(SMBtconX);
919 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
926 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
927 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
928 END_PROFILE(SMBtconX);
932 if (xconn->smb1.negprot.encrypted_passwords) {
933 p = req->buf + passlen;
935 p = req->buf + passlen + 1;
938 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
942 END_PROFILE(SMBtconX);
947 * the service name can be either: \\server\share
948 * or share directly like on the DELL PowerVault 705
951 q = strchr_m(path+2,'\\');
953 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
954 END_PROFILE(SMBtconX);
962 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
963 &client_devicetype, p,
964 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
966 if (client_devicetype == NULL) {
967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
968 END_PROFILE(SMBtconX);
972 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
974 nt_status = smb1srv_session_lookup(xconn,
975 req->vuid, now, &session);
976 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
977 reply_force_doserror(req, ERRSRV, ERRbaduid);
978 END_PROFILE(SMBtconX);
981 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
982 reply_nterror(req, nt_status);
983 END_PROFILE(SMBtconX);
986 if (!NT_STATUS_IS_OK(nt_status)) {
987 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
988 END_PROFILE(SMBtconX);
992 if (session->global->auth_session_info == NULL) {
993 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
994 END_PROFILE(SMBtconX);
999 * If there is no application key defined yet
1002 * This means we setup the application key on the
1003 * first tcon that happens via the given session.
1005 * Once the application key is defined, it does not
1008 if (session->global->application_key.length == 0 &&
1009 session->global->signing_key.length > 0)
1011 struct smbXsrv_session *x = session;
1012 struct auth_session_info *session_info =
1013 session->global->auth_session_info;
1014 uint8_t session_key[16];
1016 ZERO_STRUCT(session_key);
1017 memcpy(session_key, x->global->signing_key.data,
1018 MIN(x->global->signing_key.length, sizeof(session_key)));
1021 * The application key is truncated/padded to 16 bytes
1023 x->global->application_key = data_blob_talloc(x->global,
1025 sizeof(session_key));
1026 ZERO_STRUCT(session_key);
1027 if (x->global->application_key.data == NULL) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 END_PROFILE(SMBtconX);
1033 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1034 smb_key_derivation(x->global->application_key.data,
1035 x->global->application_key.length,
1036 x->global->application_key.data);
1037 optional_support |= SMB_EXTENDED_SIGNATURES;
1041 * Place the application key into the session_info
1043 data_blob_clear_free(&session_info->session_key);
1044 session_info->session_key = data_blob_dup_talloc(session_info,
1045 x->global->application_key);
1046 if (session_info->session_key.data == NULL) {
1047 data_blob_clear_free(&x->global->application_key);
1048 reply_nterror(req, NT_STATUS_NO_MEMORY);
1049 END_PROFILE(SMBtconX);
1052 session_key_updated = true;
1055 conn = make_connection(req, now, service, client_devicetype,
1056 req->vuid, &nt_status);
1060 if (session_key_updated) {
1061 struct smbXsrv_session *x = session;
1062 struct auth_session_info *session_info =
1063 session->global->auth_session_info;
1064 data_blob_clear_free(&x->global->application_key);
1065 data_blob_clear_free(&session_info->session_key);
1067 reply_nterror(req, nt_status);
1068 END_PROFILE(SMBtconX);
1073 server_devicetype = "IPC";
1074 else if ( IS_PRINT(conn) )
1075 server_devicetype = "LPT1:";
1077 server_devicetype = "A:";
1079 if (get_Protocol() < PROTOCOL_NT1) {
1080 reply_outbuf(req, 2, 0);
1081 if (message_push_string(&req->outbuf, server_devicetype,
1082 STR_TERMINATE|STR_ASCII) == -1) {
1083 reply_nterror(req, NT_STATUS_NO_MEMORY);
1084 END_PROFILE(SMBtconX);
1088 /* NT sets the fstype of IPC$ to the null string */
1089 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1091 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1092 /* Return permissions. */
1096 reply_outbuf(req, 7, 0);
1099 perm1 = FILE_ALL_ACCESS;
1100 perm2 = FILE_ALL_ACCESS;
1102 perm1 = conn->share_access;
1105 SIVAL(req->outbuf, smb_vwv3, perm1);
1106 SIVAL(req->outbuf, smb_vwv5, perm2);
1108 reply_outbuf(req, 3, 0);
1111 if ((message_push_string(&req->outbuf, server_devicetype,
1112 STR_TERMINATE|STR_ASCII) == -1)
1113 || (message_push_string(&req->outbuf, fstype,
1114 STR_TERMINATE) == -1)) {
1115 reply_nterror(req, NT_STATUS_NO_MEMORY);
1116 END_PROFILE(SMBtconX);
1120 /* what does setting this bit do? It is set by NT4 and
1121 may affect the ability to autorun mounted cdroms */
1122 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1124 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1126 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1127 DEBUG(2,("Serving %s as a Dfs root\n",
1128 lp_servicename(ctx, SNUM(conn)) ));
1129 optional_support |= SMB_SHARE_IN_DFS;
1132 SSVAL(req->outbuf, smb_vwv2, optional_support);
1135 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1136 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1138 DEBUG(3,("tconX service=%s \n",
1141 /* set the incoming and outgoing tid to the just created one */
1142 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1143 SSVAL(req->outbuf,smb_tid,conn->cnum);
1145 END_PROFILE(SMBtconX);
1147 req->tid = conn->cnum;
1150 /****************************************************************************
1151 Reply to an unknown type.
1152 ****************************************************************************/
1154 void reply_unknown_new(struct smb_request *req, uint8_t type)
1156 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1157 smb_fn_name(type), type, type));
1158 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1162 /****************************************************************************
1164 conn POINTER CAN BE NULL HERE !
1165 ****************************************************************************/
1167 void reply_ioctl(struct smb_request *req)
1169 connection_struct *conn = req->conn;
1172 uint32_t ioctl_code;
1176 START_PROFILE(SMBioctl);
1179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1180 END_PROFILE(SMBioctl);
1184 device = SVAL(req->vwv+1, 0);
1185 function = SVAL(req->vwv+2, 0);
1186 ioctl_code = (device << 16) + function;
1188 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1190 switch (ioctl_code) {
1191 case IOCTL_QUERY_JOB_INFO:
1195 reply_force_doserror(req, ERRSRV, ERRnosupport);
1196 END_PROFILE(SMBioctl);
1200 reply_outbuf(req, 8, replysize+1);
1201 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1202 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1203 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1204 p = smb_buf(req->outbuf);
1205 memset(p, '\0', replysize+1); /* valgrind-safe. */
1206 p += 1; /* Allow for alignment */
1208 switch (ioctl_code) {
1209 case IOCTL_QUERY_JOB_INFO:
1213 files_struct *fsp = file_fsp(
1214 req, SVAL(req->vwv+0, 0));
1216 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1217 END_PROFILE(SMBioctl);
1221 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1223 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1224 lp_netbios_name(), 15,
1225 STR_TERMINATE|STR_ASCII, &len);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 reply_nterror(req, status);
1228 END_PROFILE(SMBioctl);
1232 status = srvstr_push((char *)req->outbuf, req->flags2,
1234 lp_servicename(talloc_tos(),
1236 13, STR_TERMINATE|STR_ASCII, &len);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_nterror(req, status);
1239 END_PROFILE(SMBioctl);
1243 memset(p+18, 0, 13);
1249 END_PROFILE(SMBioctl);
1253 /****************************************************************************
1254 Strange checkpath NTSTATUS mapping.
1255 ****************************************************************************/
1257 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1259 /* Strange DOS error code semantics only for checkpath... */
1260 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1261 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1262 /* We need to map to ERRbadpath */
1263 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1269 /****************************************************************************
1270 Reply to a checkpath.
1271 ****************************************************************************/
1273 void reply_checkpath(struct smb_request *req)
1275 connection_struct *conn = req->conn;
1276 struct smb_filename *smb_fname = NULL;
1279 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1280 TALLOC_CTX *ctx = talloc_tos();
1282 START_PROFILE(SMBcheckpath);
1284 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1285 STR_TERMINATE, &status);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 status = map_checkpath_error(req->flags2, status);
1289 reply_nterror(req, status);
1290 END_PROFILE(SMBcheckpath);
1294 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1296 status = filename_convert(ctx,
1298 req->flags2 & FLAGS2_DFS_PATHNAMES,
1304 if (!NT_STATUS_IS_OK(status)) {
1305 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1306 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1307 ERRSRV, ERRbadpath);
1308 END_PROFILE(SMBcheckpath);
1314 if (!VALID_STAT(smb_fname->st) &&
1315 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1316 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1317 smb_fname_str_dbg(smb_fname), strerror(errno)));
1318 status = map_nt_error_from_unix(errno);
1322 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1323 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1324 ERRDOS, ERRbadpath);
1328 reply_outbuf(req, 0, 0);
1331 /* We special case this - as when a Windows machine
1332 is parsing a path is steps through the components
1333 one at a time - if a component fails it expects
1334 ERRbadpath, not ERRbadfile.
1336 status = map_checkpath_error(req->flags2, status);
1337 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1339 * Windows returns different error codes if
1340 * the parent directory is valid but not the
1341 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1342 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1343 * if the path is invalid.
1345 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1346 ERRDOS, ERRbadpath);
1350 reply_nterror(req, status);
1353 TALLOC_FREE(smb_fname);
1354 END_PROFILE(SMBcheckpath);
1358 /****************************************************************************
1360 ****************************************************************************/
1362 void reply_getatr(struct smb_request *req)
1364 connection_struct *conn = req->conn;
1365 struct smb_filename *smb_fname = NULL;
1372 TALLOC_CTX *ctx = talloc_tos();
1373 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1375 START_PROFILE(SMBgetatr);
1377 p = (const char *)req->buf + 1;
1378 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 reply_nterror(req, status);
1384 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1385 under WfWg - weird! */
1386 if (*fname == '\0') {
1387 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1388 if (!CAN_WRITE(conn)) {
1389 mode |= FILE_ATTRIBUTE_READONLY;
1394 uint32_t ucf_flags = (req->posix_pathnames ?
1395 UCF_POSIX_PATHNAMES : 0);
1396 status = filename_convert(ctx,
1398 req->flags2 & FLAGS2_DFS_PATHNAMES,
1403 if (!NT_STATUS_IS_OK(status)) {
1404 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1405 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1406 ERRSRV, ERRbadpath);
1409 reply_nterror(req, status);
1412 if (!VALID_STAT(smb_fname->st) &&
1413 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1414 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1415 smb_fname_str_dbg(smb_fname),
1417 reply_nterror(req, map_nt_error_from_unix(errno));
1421 mode = dos_mode(conn, smb_fname);
1422 size = smb_fname->st.st_ex_size;
1424 if (ask_sharemode) {
1425 struct timespec write_time_ts;
1426 struct file_id fileid;
1428 ZERO_STRUCT(write_time_ts);
1429 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1430 get_file_infos(fileid, 0, NULL, &write_time_ts);
1431 if (!null_timespec(write_time_ts)) {
1432 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1436 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1437 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1442 reply_outbuf(req, 10, 0);
1444 SSVAL(req->outbuf,smb_vwv0,mode);
1445 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1446 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1448 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1450 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1452 if (get_Protocol() >= PROTOCOL_NT1) {
1453 SSVAL(req->outbuf, smb_flg2,
1454 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1457 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1458 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1461 TALLOC_FREE(smb_fname);
1463 END_PROFILE(SMBgetatr);
1467 /****************************************************************************
1469 ****************************************************************************/
1471 void reply_setatr(struct smb_request *req)
1473 struct smb_file_time ft;
1474 connection_struct *conn = req->conn;
1475 struct smb_filename *smb_fname = NULL;
1481 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1482 TALLOC_CTX *ctx = talloc_tos();
1484 START_PROFILE(SMBsetatr);
1489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1493 p = (const char *)req->buf + 1;
1494 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 reply_nterror(req, status);
1500 status = filename_convert(ctx,
1502 req->flags2 & FLAGS2_DFS_PATHNAMES,
1507 if (!NT_STATUS_IS_OK(status)) {
1508 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1509 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1510 ERRSRV, ERRbadpath);
1513 reply_nterror(req, status);
1517 if (smb_fname->base_name[0] == '.' &&
1518 smb_fname->base_name[1] == '\0') {
1520 * Not sure here is the right place to catch this
1521 * condition. Might be moved to somewhere else later -- vl
1523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1527 mode = SVAL(req->vwv+0, 0);
1528 mtime = srv_make_unix_date3(req->vwv+1);
1530 if (mode != FILE_ATTRIBUTE_NORMAL) {
1531 if (VALID_STAT_OF_DIR(smb_fname->st))
1532 mode |= FILE_ATTRIBUTE_DIRECTORY;
1534 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1536 status = check_access(conn, NULL, smb_fname,
1537 FILE_WRITE_ATTRIBUTES);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 reply_nterror(req, status);
1543 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1545 reply_nterror(req, map_nt_error_from_unix(errno));
1550 ft.mtime = convert_time_t_to_timespec(mtime);
1551 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 reply_nterror(req, status);
1557 reply_outbuf(req, 0, 0);
1559 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1562 TALLOC_FREE(smb_fname);
1563 END_PROFILE(SMBsetatr);
1567 /****************************************************************************
1569 ****************************************************************************/
1571 void reply_dskattr(struct smb_request *req)
1573 connection_struct *conn = req->conn;
1575 uint64_t dfree,dsize,bsize;
1576 START_PROFILE(SMBdskattr);
1578 ret = get_dfree_info(conn, ".", &bsize, &dfree, &dsize);
1579 if (ret == (uint64_t)-1) {
1580 reply_nterror(req, map_nt_error_from_unix(errno));
1581 END_PROFILE(SMBdskattr);
1586 * Force max to fit in 16 bit fields.
1588 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1592 if (bsize > (WORDMAX*512)) {
1593 bsize = (WORDMAX*512);
1594 if (dsize > WORDMAX)
1596 if (dfree > WORDMAX)
1602 reply_outbuf(req, 5, 0);
1604 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1605 double total_space, free_space;
1606 /* we need to scale this to a number that DOS6 can handle. We
1607 use floating point so we can handle large drives on systems
1608 that don't have 64 bit integers
1610 we end up displaying a maximum of 2G to DOS systems
1612 total_space = dsize * (double)bsize;
1613 free_space = dfree * (double)bsize;
1615 dsize = (uint64_t)((total_space+63*512) / (64*512));
1616 dfree = (uint64_t)((free_space+63*512) / (64*512));
1618 if (dsize > 0xFFFF) dsize = 0xFFFF;
1619 if (dfree > 0xFFFF) dfree = 0xFFFF;
1621 SSVAL(req->outbuf,smb_vwv0,dsize);
1622 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1623 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1624 SSVAL(req->outbuf,smb_vwv3,dfree);
1626 SSVAL(req->outbuf,smb_vwv0,dsize);
1627 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1628 SSVAL(req->outbuf,smb_vwv2,512);
1629 SSVAL(req->outbuf,smb_vwv3,dfree);
1632 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1634 END_PROFILE(SMBdskattr);
1639 * Utility function to split the filename from the directory.
1641 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1642 char **fname_dir_out,
1643 char **fname_mask_out)
1645 const char *p = NULL;
1646 char *fname_dir = NULL;
1647 char *fname_mask = NULL;
1649 p = strrchr_m(fname_in, '/');
1651 fname_dir = talloc_strdup(ctx, ".");
1652 fname_mask = talloc_strdup(ctx, fname_in);
1654 fname_dir = talloc_strndup(ctx, fname_in,
1655 PTR_DIFF(p, fname_in));
1656 fname_mask = talloc_strdup(ctx, p+1);
1659 if (!fname_dir || !fname_mask) {
1660 TALLOC_FREE(fname_dir);
1661 TALLOC_FREE(fname_mask);
1662 return NT_STATUS_NO_MEMORY;
1665 *fname_dir_out = fname_dir;
1666 *fname_mask_out = fname_mask;
1667 return NT_STATUS_OK;
1670 /****************************************************************************
1672 ****************************************************************************/
1674 static bool make_dir_struct(TALLOC_CTX *ctx,
1684 char *mask2 = talloc_strdup(ctx, mask);
1690 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1694 memset(buf+1,' ',11);
1695 if ((p = strchr_m(mask2,'.')) != NULL) {
1697 push_ascii(buf+1,mask2,8, 0);
1698 push_ascii(buf+9,p+1,3, 0);
1701 push_ascii(buf+1,mask2,11, 0);
1704 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1706 srv_put_dos_date(buf,22,date);
1707 SSVAL(buf,26,size & 0xFFFF);
1708 SSVAL(buf,28,(size >> 16)&0xFFFF);
1709 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1710 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1711 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1712 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1716 /****************************************************************************
1718 Can be called from SMBsearch, SMBffirst or SMBfunique.
1719 ****************************************************************************/
1721 void reply_search(struct smb_request *req)
1723 connection_struct *conn = req->conn;
1726 char *directory = NULL;
1727 struct smb_filename *smb_fname = NULL;
1731 struct timespec date;
1733 unsigned int numentries = 0;
1734 unsigned int maxentries = 0;
1735 bool finished = False;
1740 bool check_descend = False;
1741 bool expect_close = False;
1743 bool mask_contains_wcard = False;
1744 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1745 TALLOC_CTX *ctx = talloc_tos();
1746 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1747 struct dptr_struct *dirptr = NULL;
1748 struct smbXsrv_connection *xconn = req->xconn;
1749 struct smbd_server_connection *sconn = req->sconn;
1751 START_PROFILE(SMBsearch);
1754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1758 if (req->posix_pathnames) {
1759 reply_unknown_new(req, req->cmd);
1763 /* If we were called as SMBffirst then we must expect close. */
1764 if(req->cmd == SMBffirst) {
1765 expect_close = True;
1768 reply_outbuf(req, 1, 3);
1769 maxentries = SVAL(req->vwv+0, 0);
1770 dirtype = SVAL(req->vwv+1, 0);
1771 p = (const char *)req->buf + 1;
1772 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1773 &nt_status, &mask_contains_wcard);
1774 if (!NT_STATUS_IS_OK(nt_status)) {
1775 reply_nterror(req, nt_status);
1780 status_len = SVAL(p, 0);
1783 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1785 if (status_len == 0) {
1786 struct smb_filename *smb_dname = NULL;
1787 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1788 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1789 nt_status = filename_convert(ctx, conn,
1790 req->flags2 & FLAGS2_DFS_PATHNAMES,
1793 &mask_contains_wcard,
1795 if (!NT_STATUS_IS_OK(nt_status)) {
1796 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1797 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1798 ERRSRV, ERRbadpath);
1801 reply_nterror(req, nt_status);
1805 directory = smb_fname->base_name;
1807 p = strrchr_m(directory,'/');
1808 if ((p != NULL) && (*directory != '/')) {
1809 mask = talloc_strdup(ctx, p + 1);
1810 directory = talloc_strndup(ctx, directory,
1811 PTR_DIFF(p, directory));
1813 mask = talloc_strdup(ctx, directory);
1814 directory = talloc_strdup(ctx,".");
1818 reply_nterror(req, NT_STATUS_NO_MEMORY);
1822 memset((char *)status,'\0',21);
1823 SCVAL(status,0,(dirtype & 0x1F));
1825 smb_dname = synthetic_smb_fname(talloc_tos(),
1829 if (smb_dname == NULL) {
1830 reply_nterror(req, NT_STATUS_NO_MEMORY);
1834 nt_status = dptr_create(conn,
1842 mask_contains_wcard,
1846 TALLOC_FREE(smb_dname);
1848 if (!NT_STATUS_IS_OK(nt_status)) {
1849 reply_nterror(req, nt_status);
1852 dptr_num = dptr_dnum(dirptr);
1855 const char *dirpath;
1857 memcpy(status,p,21);
1858 status_dirtype = CVAL(status,0) & 0x1F;
1859 if (status_dirtype != (dirtype & 0x1F)) {
1860 dirtype = status_dirtype;
1863 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1867 dirpath = dptr_path(sconn, dptr_num);
1868 directory = talloc_strdup(ctx, dirpath);
1870 reply_nterror(req, NT_STATUS_NO_MEMORY);
1874 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1879 * For a 'continue' search we have no string. So
1880 * check from the initial saved string.
1882 if (!req->posix_pathnames) {
1883 mask_contains_wcard = ms_has_wild(mask);
1885 dirtype = dptr_attr(sconn, dptr_num);
1888 DEBUG(4,("dptr_num is %d\n",dptr_num));
1890 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1891 dptr_init_search_op(dirptr);
1893 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1894 char buf[DIR_STRUCT_SIZE];
1895 memcpy(buf,status,21);
1896 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1897 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1898 reply_nterror(req, NT_STATUS_NO_MEMORY);
1901 dptr_fill(sconn, buf+12,dptr_num);
1902 if (dptr_zero(buf+12) && (status_len==0)) {
1907 if (message_push_blob(&req->outbuf,
1908 data_blob_const(buf, sizeof(buf)))
1910 reply_nterror(req, NT_STATUS_NO_MEMORY);
1915 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1916 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1918 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1920 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1921 directory,lp_dont_descend(ctx, SNUM(conn))));
1922 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1923 check_descend = True;
1926 for (i=numentries;(i<maxentries) && !finished;i++) {
1927 finished = !get_dir_entry(ctx,
1938 char buf[DIR_STRUCT_SIZE];
1939 memcpy(buf,status,21);
1940 if (!make_dir_struct(ctx,
1946 convert_timespec_to_time_t(date),
1947 !allow_long_path_components)) {
1948 reply_nterror(req, NT_STATUS_NO_MEMORY);
1951 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1954 if (message_push_blob(&req->outbuf,
1955 data_blob_const(buf, sizeof(buf)))
1957 reply_nterror(req, NT_STATUS_NO_MEMORY);
1967 /* If we were called as SMBffirst with smb_search_id == NULL
1968 and no entries were found then return error and close dirptr
1971 if (numentries == 0) {
1972 dptr_close(sconn, &dptr_num);
1973 } else if(expect_close && status_len == 0) {
1974 /* Close the dptr - we know it's gone */
1975 dptr_close(sconn, &dptr_num);
1978 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1979 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1980 dptr_close(sconn, &dptr_num);
1983 if ((numentries == 0) && !mask_contains_wcard) {
1984 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1988 SSVAL(req->outbuf,smb_vwv0,numentries);
1989 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1990 SCVAL(smb_buf(req->outbuf),0,5);
1991 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1993 /* The replies here are never long name. */
1994 SSVAL(req->outbuf, smb_flg2,
1995 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1996 if (!allow_long_path_components) {
1997 SSVAL(req->outbuf, smb_flg2,
1998 SVAL(req->outbuf, smb_flg2)
1999 & (~FLAGS2_LONG_PATH_COMPONENTS));
2002 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2003 SSVAL(req->outbuf, smb_flg2,
2004 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2006 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2007 smb_fn_name(req->cmd),
2014 TALLOC_FREE(directory);
2016 TALLOC_FREE(smb_fname);
2017 END_PROFILE(SMBsearch);
2021 /****************************************************************************
2022 Reply to a fclose (stop directory search).
2023 ****************************************************************************/
2025 void reply_fclose(struct smb_request *req)
2033 bool path_contains_wcard = False;
2034 TALLOC_CTX *ctx = talloc_tos();
2035 struct smbd_server_connection *sconn = req->sconn;
2037 START_PROFILE(SMBfclose);
2039 if (req->posix_pathnames) {
2040 reply_unknown_new(req, req->cmd);
2041 END_PROFILE(SMBfclose);
2045 p = (const char *)req->buf + 1;
2046 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2047 &err, &path_contains_wcard);
2048 if (!NT_STATUS_IS_OK(err)) {
2049 reply_nterror(req, err);
2050 END_PROFILE(SMBfclose);
2054 status_len = SVAL(p,0);
2057 if (status_len == 0) {
2058 reply_force_doserror(req, ERRSRV, ERRsrverror);
2059 END_PROFILE(SMBfclose);
2063 memcpy(status,p,21);
2065 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2066 /* Close the dptr - we know it's gone */
2067 dptr_close(sconn, &dptr_num);
2070 reply_outbuf(req, 1, 0);
2071 SSVAL(req->outbuf,smb_vwv0,0);
2073 DEBUG(3,("search close\n"));
2075 END_PROFILE(SMBfclose);
2079 /****************************************************************************
2081 ****************************************************************************/
2083 void reply_open(struct smb_request *req)
2085 connection_struct *conn = req->conn;
2086 struct smb_filename *smb_fname = NULL;
2096 uint32_t access_mask;
2097 uint32_t share_mode;
2098 uint32_t create_disposition;
2099 uint32_t create_options = 0;
2100 uint32_t private_flags = 0;
2102 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2103 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2104 TALLOC_CTX *ctx = talloc_tos();
2106 START_PROFILE(SMBopen);
2109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2113 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2114 deny_mode = SVAL(req->vwv+0, 0);
2115 dos_attr = SVAL(req->vwv+1, 0);
2117 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2118 STR_TERMINATE, &status);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 reply_nterror(req, status);
2124 if (!map_open_params_to_ntcreate(fname, deny_mode,
2125 OPENX_FILE_EXISTS_OPEN, &access_mask,
2126 &share_mode, &create_disposition,
2127 &create_options, &private_flags)) {
2128 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2132 status = filename_convert(ctx,
2134 req->flags2 & FLAGS2_DFS_PATHNAMES,
2139 if (!NT_STATUS_IS_OK(status)) {
2140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2141 reply_botherror(req,
2142 NT_STATUS_PATH_NOT_COVERED,
2143 ERRSRV, ERRbadpath);
2146 reply_nterror(req, status);
2150 status = SMB_VFS_CREATE_FILE(
2153 0, /* root_dir_fid */
2154 smb_fname, /* fname */
2155 access_mask, /* access_mask */
2156 share_mode, /* share_access */
2157 create_disposition, /* create_disposition*/
2158 create_options, /* create_options */
2159 dos_attr, /* file_attributes */
2160 oplock_request, /* oplock_request */
2162 0, /* allocation_size */
2168 NULL, NULL); /* create context */
2170 if (!NT_STATUS_IS_OK(status)) {
2171 if (open_was_deferred(req->xconn, req->mid)) {
2172 /* We have re-scheduled this call. */
2175 reply_openerror(req, status);
2179 /* Ensure we're pointing at the correct stat struct. */
2180 TALLOC_FREE(smb_fname);
2181 smb_fname = fsp->fsp_name;
2183 size = smb_fname->st.st_ex_size;
2184 fattr = dos_mode(conn, smb_fname);
2186 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2188 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2189 DEBUG(3,("attempt to open a directory %s\n",
2191 close_file(req, fsp, ERROR_CLOSE);
2192 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2193 ERRDOS, ERRnoaccess);
2197 reply_outbuf(req, 7, 0);
2198 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2199 SSVAL(req->outbuf,smb_vwv1,fattr);
2200 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2201 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2203 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2205 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2206 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2208 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2209 SCVAL(req->outbuf,smb_flg,
2210 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2213 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2214 SCVAL(req->outbuf,smb_flg,
2215 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2218 END_PROFILE(SMBopen);
2222 /****************************************************************************
2223 Reply to an open and X.
2224 ****************************************************************************/
2226 void reply_open_and_X(struct smb_request *req)
2228 connection_struct *conn = req->conn;
2229 struct smb_filename *smb_fname = NULL;
2231 uint16_t open_flags;
2234 /* Breakout the oplock request bits so we can set the
2235 reply bits separately. */
2236 int ex_oplock_request;
2237 int core_oplock_request;
2240 int smb_sattr = SVAL(req->vwv+4, 0);
2241 uint32_t smb_time = make_unix_date3(req->vwv+6);
2249 uint64_t allocation_size;
2250 ssize_t retval = -1;
2251 uint32_t access_mask;
2252 uint32_t share_mode;
2253 uint32_t create_disposition;
2254 uint32_t create_options = 0;
2255 uint32_t private_flags = 0;
2256 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2257 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2258 TALLOC_CTX *ctx = talloc_tos();
2260 START_PROFILE(SMBopenX);
2262 if (req->wct < 15) {
2263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2267 open_flags = SVAL(req->vwv+2, 0);
2268 deny_mode = SVAL(req->vwv+3, 0);
2269 smb_attr = SVAL(req->vwv+5, 0);
2270 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2271 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2272 oplock_request = ex_oplock_request | core_oplock_request;
2273 smb_ofun = SVAL(req->vwv+8, 0);
2274 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2276 /* If it's an IPC, pass off the pipe handler. */
2278 if (lp_nt_pipe_support()) {
2279 reply_open_pipe_and_X(conn, req);
2281 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2286 /* XXXX we need to handle passed times, sattr and flags */
2287 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2288 STR_TERMINATE, &status);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 reply_nterror(req, status);
2294 if (!map_open_params_to_ntcreate(fname, deny_mode,
2296 &access_mask, &share_mode,
2297 &create_disposition,
2300 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2304 status = filename_convert(ctx,
2306 req->flags2 & FLAGS2_DFS_PATHNAMES,
2311 if (!NT_STATUS_IS_OK(status)) {
2312 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2313 reply_botherror(req,
2314 NT_STATUS_PATH_NOT_COVERED,
2315 ERRSRV, ERRbadpath);
2318 reply_nterror(req, status);
2322 status = SMB_VFS_CREATE_FILE(
2325 0, /* root_dir_fid */
2326 smb_fname, /* fname */
2327 access_mask, /* access_mask */
2328 share_mode, /* share_access */
2329 create_disposition, /* create_disposition*/
2330 create_options, /* create_options */
2331 smb_attr, /* file_attributes */
2332 oplock_request, /* oplock_request */
2334 0, /* allocation_size */
2339 &smb_action, /* pinfo */
2340 NULL, NULL); /* create context */
2342 if (!NT_STATUS_IS_OK(status)) {
2343 if (open_was_deferred(req->xconn, req->mid)) {
2344 /* We have re-scheduled this call. */
2347 reply_openerror(req, status);
2351 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2352 if the file is truncated or created. */
2353 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2354 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2355 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2356 close_file(req, fsp, ERROR_CLOSE);
2357 reply_nterror(req, NT_STATUS_DISK_FULL);
2360 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2362 close_file(req, fsp, ERROR_CLOSE);
2363 reply_nterror(req, NT_STATUS_DISK_FULL);
2366 status = vfs_stat_fsp(fsp);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 close_file(req, fsp, ERROR_CLOSE);
2369 reply_nterror(req, status);
2374 fattr = dos_mode(conn, fsp->fsp_name);
2375 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2376 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2377 close_file(req, fsp, ERROR_CLOSE);
2378 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2382 /* If the caller set the extended oplock request bit
2383 and we granted one (by whatever means) - set the
2384 correct bit for extended oplock reply.
2387 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2388 smb_action |= EXTENDED_OPLOCK_GRANTED;
2391 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2392 smb_action |= EXTENDED_OPLOCK_GRANTED;
2395 /* If the caller set the core oplock request bit
2396 and we granted one (by whatever means) - set the
2397 correct bit for core oplock reply.
2400 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2401 reply_outbuf(req, 19, 0);
2403 reply_outbuf(req, 15, 0);
2406 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2407 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2409 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2410 SCVAL(req->outbuf, smb_flg,
2411 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2414 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2415 SCVAL(req->outbuf, smb_flg,
2416 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2419 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2420 SSVAL(req->outbuf,smb_vwv3,fattr);
2421 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2422 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2424 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2426 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2427 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2428 SSVAL(req->outbuf,smb_vwv11,smb_action);
2430 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2431 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2435 TALLOC_FREE(smb_fname);
2436 END_PROFILE(SMBopenX);
2440 /****************************************************************************
2441 Reply to a SMBulogoffX.
2442 ****************************************************************************/
2444 void reply_ulogoffX(struct smb_request *req)
2446 struct smbd_server_connection *sconn = req->sconn;
2447 struct user_struct *vuser;
2448 struct smbXsrv_session *session = NULL;
2451 START_PROFILE(SMBulogoffX);
2453 vuser = get_valid_user_struct(sconn, req->vuid);
2456 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2457 (unsigned long long)req->vuid));
2459 req->vuid = UID_FIELD_INVALID;
2460 reply_force_doserror(req, ERRSRV, ERRbaduid);
2461 END_PROFILE(SMBulogoffX);
2465 session = vuser->session;
2469 * TODO: cancel all outstanding requests on the session
2471 status = smbXsrv_session_logoff(session);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 DEBUG(0, ("reply_ulogoff: "
2474 "smbXsrv_session_logoff() failed: %s\n",
2475 nt_errstr(status)));
2477 * If we hit this case, there is something completely
2478 * wrong, so we better disconnect the transport connection.
2480 END_PROFILE(SMBulogoffX);
2481 exit_server(__location__ ": smbXsrv_session_logoff failed");
2485 TALLOC_FREE(session);
2487 reply_outbuf(req, 2, 0);
2488 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2489 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2491 DEBUG(3, ("ulogoffX vuid=%llu\n",
2492 (unsigned long long)req->vuid));
2494 END_PROFILE(SMBulogoffX);
2495 req->vuid = UID_FIELD_INVALID;
2498 /****************************************************************************
2499 Reply to a mknew or a create.
2500 ****************************************************************************/
2502 void reply_mknew(struct smb_request *req)
2504 connection_struct *conn = req->conn;
2505 struct smb_filename *smb_fname = NULL;
2508 struct smb_file_time ft;
2510 int oplock_request = 0;
2512 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2513 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2514 uint32_t create_disposition;
2515 uint32_t create_options = 0;
2516 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2517 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2518 TALLOC_CTX *ctx = talloc_tos();
2520 START_PROFILE(SMBcreate);
2524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2528 fattr = SVAL(req->vwv+0, 0);
2529 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2532 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2534 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2535 STR_TERMINATE, &status);
2536 if (!NT_STATUS_IS_OK(status)) {
2537 reply_nterror(req, status);
2541 status = filename_convert(ctx,
2543 req->flags2 & FLAGS2_DFS_PATHNAMES,
2548 if (!NT_STATUS_IS_OK(status)) {
2549 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2550 reply_botherror(req,
2551 NT_STATUS_PATH_NOT_COVERED,
2552 ERRSRV, ERRbadpath);
2555 reply_nterror(req, status);
2559 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2560 DEBUG(0,("Attempt to create file (%s) with volid set - "
2561 "please report this\n",
2562 smb_fname_str_dbg(smb_fname)));
2565 if(req->cmd == SMBmknew) {
2566 /* We should fail if file exists. */
2567 create_disposition = FILE_CREATE;
2569 /* Create if file doesn't exist, truncate if it does. */
2570 create_disposition = FILE_OVERWRITE_IF;
2573 status = SMB_VFS_CREATE_FILE(
2576 0, /* root_dir_fid */
2577 smb_fname, /* fname */
2578 access_mask, /* access_mask */
2579 share_mode, /* share_access */
2580 create_disposition, /* create_disposition*/
2581 create_options, /* create_options */
2582 fattr, /* file_attributes */
2583 oplock_request, /* oplock_request */
2585 0, /* allocation_size */
2586 0, /* private_flags */
2591 NULL, NULL); /* create context */
2593 if (!NT_STATUS_IS_OK(status)) {
2594 if (open_was_deferred(req->xconn, req->mid)) {
2595 /* We have re-scheduled this call. */
2598 reply_openerror(req, status);
2602 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2603 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 END_PROFILE(SMBcreate);
2609 reply_outbuf(req, 1, 0);
2610 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2612 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2613 SCVAL(req->outbuf,smb_flg,
2614 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2617 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2618 SCVAL(req->outbuf,smb_flg,
2619 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2622 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2623 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2624 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2625 (unsigned int)fattr));
2628 TALLOC_FREE(smb_fname);
2629 END_PROFILE(SMBcreate);
2633 /****************************************************************************
2634 Reply to a create temporary file.
2635 ****************************************************************************/
2637 void reply_ctemp(struct smb_request *req)
2639 connection_struct *conn = req->conn;
2640 struct smb_filename *smb_fname = NULL;
2641 char *wire_name = NULL;
2649 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2650 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2651 TALLOC_CTX *ctx = talloc_tos();
2653 START_PROFILE(SMBctemp);
2656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 fattr = SVAL(req->vwv+0, 0);
2661 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2663 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2664 STR_TERMINATE, &status);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 reply_nterror(req, status);
2670 for (i = 0; i < 10; i++) {
2672 fname = talloc_asprintf(ctx,
2675 generate_random_str_list(ctx, 5, "0123456789"));
2677 fname = talloc_asprintf(ctx,
2679 generate_random_str_list(ctx, 5, "0123456789"));
2683 reply_nterror(req, NT_STATUS_NO_MEMORY);
2687 status = filename_convert(ctx, conn,
2688 req->flags2 & FLAGS2_DFS_PATHNAMES,
2693 if (!NT_STATUS_IS_OK(status)) {
2694 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2695 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2696 ERRSRV, ERRbadpath);
2699 reply_nterror(req, status);
2703 /* Create the file. */
2704 status = SMB_VFS_CREATE_FILE(
2707 0, /* root_dir_fid */
2708 smb_fname, /* fname */
2709 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2710 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2711 FILE_CREATE, /* create_disposition*/
2712 0, /* create_options */
2713 fattr, /* file_attributes */
2714 oplock_request, /* oplock_request */
2716 0, /* allocation_size */
2717 0, /* private_flags */
2722 NULL, NULL); /* create context */
2724 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2726 TALLOC_FREE(smb_fname);
2730 if (!NT_STATUS_IS_OK(status)) {
2731 if (open_was_deferred(req->xconn, req->mid)) {
2732 /* We have re-scheduled this call. */
2735 reply_openerror(req, status);
2743 /* Collision after 10 times... */
2744 reply_nterror(req, status);
2748 reply_outbuf(req, 1, 0);
2749 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2751 /* the returned filename is relative to the directory */
2752 s = strrchr_m(fsp->fsp_name->base_name, '/');
2754 s = fsp->fsp_name->base_name;
2760 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2761 thing in the byte section. JRA */
2762 SSVALS(p, 0, -1); /* what is this? not in spec */
2764 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2766 reply_nterror(req, NT_STATUS_NO_MEMORY);
2770 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2771 SCVAL(req->outbuf, smb_flg,
2772 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2775 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2776 SCVAL(req->outbuf, smb_flg,
2777 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2780 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2781 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2782 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2784 TALLOC_FREE(smb_fname);
2785 TALLOC_FREE(wire_name);
2786 END_PROFILE(SMBctemp);
2790 /*******************************************************************
2791 Check if a user is allowed to rename a file.
2792 ********************************************************************/
2794 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2797 if (!CAN_WRITE(conn)) {
2798 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2801 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2802 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2803 /* Only bother to read the DOS attribute if we might deny the
2804 rename on the grounds of attribute mismatch. */
2805 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2806 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2807 return NT_STATUS_NO_SUCH_FILE;
2811 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2812 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2813 return NT_STATUS_OK;
2816 /* If no pathnames are open below this
2817 directory, allow the rename. */
2819 if (lp_strict_rename(SNUM(conn))) {
2821 * Strict rename, check open file db.
2823 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2824 return NT_STATUS_ACCESS_DENIED;
2826 } else if (file_find_subpath(fsp)) {
2828 * No strict rename, just look in local process.
2830 return NT_STATUS_ACCESS_DENIED;
2832 return NT_STATUS_OK;
2835 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2836 return NT_STATUS_OK;
2839 return NT_STATUS_ACCESS_DENIED;
2842 /*******************************************************************
2843 * unlink a file with all relevant access checks
2844 *******************************************************************/
2846 static NTSTATUS do_unlink(connection_struct *conn,
2847 struct smb_request *req,
2848 struct smb_filename *smb_fname,
2853 uint32_t dirtype_orig = dirtype;
2856 bool posix_paths = (req != NULL && req->posix_pathnames);
2858 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2859 smb_fname_str_dbg(smb_fname),
2862 if (!CAN_WRITE(conn)) {
2863 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2867 ret = SMB_VFS_LSTAT(conn, smb_fname);
2869 ret = SMB_VFS_STAT(conn, smb_fname);
2872 return map_nt_error_from_unix(errno);
2875 fattr = dos_mode(conn, smb_fname);
2877 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2878 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2881 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2883 return NT_STATUS_NO_SUCH_FILE;
2886 if (!dir_check_ftype(fattr, dirtype)) {
2887 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2888 return NT_STATUS_FILE_IS_A_DIRECTORY;
2890 return NT_STATUS_NO_SUCH_FILE;
2893 if (dirtype_orig & 0x8000) {
2894 /* These will never be set for POSIX. */
2895 return NT_STATUS_NO_SUCH_FILE;
2899 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2900 return NT_STATUS_FILE_IS_A_DIRECTORY;
2903 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2904 return NT_STATUS_NO_SUCH_FILE;
2907 if (dirtype & 0xFF00) {
2908 /* These will never be set for POSIX. */
2909 return NT_STATUS_NO_SUCH_FILE;
2914 return NT_STATUS_NO_SUCH_FILE;
2917 /* Can't delete a directory. */
2918 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2919 return NT_STATUS_FILE_IS_A_DIRECTORY;
2924 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2925 return NT_STATUS_OBJECT_NAME_INVALID;
2926 #endif /* JRATEST */
2928 /* On open checks the open itself will check the share mode, so
2929 don't do it here as we'll get it wrong. */
2931 status = SMB_VFS_CREATE_FILE
2934 0, /* root_dir_fid */
2935 smb_fname, /* fname */
2936 DELETE_ACCESS, /* access_mask */
2937 FILE_SHARE_NONE, /* share_access */
2938 FILE_OPEN, /* create_disposition*/
2939 FILE_NON_DIRECTORY_FILE, /* create_options */
2940 /* file_attributes */
2941 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2942 FILE_ATTRIBUTE_NORMAL,
2943 0, /* oplock_request */
2945 0, /* allocation_size */
2946 0, /* private_flags */
2951 NULL, NULL); /* create context */
2953 if (!NT_STATUS_IS_OK(status)) {
2954 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2955 nt_errstr(status)));
2959 status = can_set_delete_on_close(fsp, fattr);
2960 if (!NT_STATUS_IS_OK(status)) {
2961 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2963 smb_fname_str_dbg(smb_fname),
2964 nt_errstr(status)));
2965 close_file(req, fsp, NORMAL_CLOSE);
2969 /* The set is across all open files on this dev/inode pair. */
2970 if (!set_delete_on_close(fsp, True,
2971 conn->session_info->security_token,
2972 conn->session_info->unix_token)) {
2973 close_file(req, fsp, NORMAL_CLOSE);
2974 return NT_STATUS_ACCESS_DENIED;
2977 return close_file(req, fsp, NORMAL_CLOSE);
2980 /****************************************************************************
2981 The guts of the unlink command, split out so it may be called by the NT SMB
2983 ****************************************************************************/
2985 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2986 uint32_t dirtype, struct smb_filename *smb_fname,
2989 char *fname_dir = NULL;
2990 char *fname_mask = NULL;
2992 NTSTATUS status = NT_STATUS_OK;
2993 struct smb_filename *smb_fname_dir = NULL;
2994 TALLOC_CTX *ctx = talloc_tos();
2996 /* Split up the directory from the filename/mask. */
2997 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2998 &fname_dir, &fname_mask);
2999 if (!NT_STATUS_IS_OK(status)) {
3004 * We should only check the mangled cache
3005 * here if unix_convert failed. This means
3006 * that the path in 'mask' doesn't exist
3007 * on the file system and so we need to look
3008 * for a possible mangle. This patch from
3009 * Tine Smukavec <valentin.smukavec@hermes.si>.
3012 if (!VALID_STAT(smb_fname->st) &&
3013 mangle_is_mangled(fname_mask, conn->params)) {
3014 char *new_mask = NULL;
3015 mangle_lookup_name_from_8_3(ctx, fname_mask,
3016 &new_mask, conn->params);
3018 TALLOC_FREE(fname_mask);
3019 fname_mask = new_mask;
3026 * Only one file needs to be unlinked. Append the mask back
3027 * onto the directory.
3029 TALLOC_FREE(smb_fname->base_name);
3030 if (ISDOT(fname_dir)) {
3031 /* Ensure we use canonical names on open. */
3032 smb_fname->base_name = talloc_asprintf(smb_fname,
3036 smb_fname->base_name = talloc_asprintf(smb_fname,
3041 if (!smb_fname->base_name) {
3042 status = NT_STATUS_NO_MEMORY;
3046 dirtype = FILE_ATTRIBUTE_NORMAL;
3049 status = check_name(conn, smb_fname->base_name);
3050 if (!NT_STATUS_IS_OK(status)) {
3054 status = do_unlink(conn, req, smb_fname, dirtype);
3055 if (!NT_STATUS_IS_OK(status)) {
3061 struct smb_Dir *dir_hnd = NULL;
3063 const char *dname = NULL;
3064 char *talloced = NULL;
3066 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3067 status = NT_STATUS_OBJECT_NAME_INVALID;
3071 dirtype = FILE_ATTRIBUTE_NORMAL;
3074 if (strequal(fname_mask,"????????.???")) {
3075 TALLOC_FREE(fname_mask);
3076 fname_mask = talloc_strdup(ctx, "*");
3078 status = NT_STATUS_NO_MEMORY;
3083 status = check_name(conn, fname_dir);
3084 if (!NT_STATUS_IS_OK(status)) {
3088 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3092 if (smb_fname_dir == NULL) {
3093 status = NT_STATUS_NO_MEMORY;
3097 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3099 if (dir_hnd == NULL) {
3100 status = map_nt_error_from_unix(errno);
3104 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3105 the pattern matches against the long name, otherwise the short name
3106 We don't implement this yet XXXX
3109 status = NT_STATUS_NO_SUCH_FILE;
3111 while ((dname = ReadDirName(dir_hnd, &offset,
3112 &smb_fname->st, &talloced))) {
3113 TALLOC_CTX *frame = talloc_stackframe();
3115 if (!is_visible_file(conn, fname_dir, dname,
3116 &smb_fname->st, true)) {
3118 TALLOC_FREE(talloced);
3122 /* Quick check for "." and ".." */
3123 if (ISDOT(dname) || ISDOTDOT(dname)) {
3125 TALLOC_FREE(talloced);
3129 if(!mask_match(dname, fname_mask,
3130 conn->case_sensitive)) {
3132 TALLOC_FREE(talloced);
3136 TALLOC_FREE(smb_fname->base_name);
3137 if (ISDOT(fname_dir)) {
3138 /* Ensure we use canonical names on open. */
3139 smb_fname->base_name =
3140 talloc_asprintf(smb_fname, "%s",
3143 smb_fname->base_name =
3144 talloc_asprintf(smb_fname, "%s/%s",
3148 if (!smb_fname->base_name) {
3149 TALLOC_FREE(dir_hnd);
3150 status = NT_STATUS_NO_MEMORY;
3152 TALLOC_FREE(talloced);
3156 status = check_name(conn, smb_fname->base_name);
3157 if (!NT_STATUS_IS_OK(status)) {
3158 TALLOC_FREE(dir_hnd);
3160 TALLOC_FREE(talloced);
3164 status = do_unlink(conn, req, smb_fname, dirtype);
3165 if (!NT_STATUS_IS_OK(status)) {
3166 TALLOC_FREE(dir_hnd);
3168 TALLOC_FREE(talloced);
3173 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3174 smb_fname->base_name));
3177 TALLOC_FREE(talloced);
3179 TALLOC_FREE(dir_hnd);
3182 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3183 status = map_nt_error_from_unix(errno);
3187 TALLOC_FREE(smb_fname_dir);
3188 TALLOC_FREE(fname_dir);
3189 TALLOC_FREE(fname_mask);
3193 /****************************************************************************
3195 ****************************************************************************/
3197 void reply_unlink(struct smb_request *req)
3199 connection_struct *conn = req->conn;
3201 struct smb_filename *smb_fname = NULL;
3204 bool path_contains_wcard = False;
3205 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3206 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
3207 TALLOC_CTX *ctx = talloc_tos();
3209 START_PROFILE(SMBunlink);
3212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3216 dirtype = SVAL(req->vwv+0, 0);
3218 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3219 STR_TERMINATE, &status,
3220 &path_contains_wcard);
3221 if (!NT_STATUS_IS_OK(status)) {
3222 reply_nterror(req, status);
3226 status = filename_convert(ctx, conn,
3227 req->flags2 & FLAGS2_DFS_PATHNAMES,
3230 &path_contains_wcard,
3232 if (!NT_STATUS_IS_OK(status)) {
3233 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3234 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3235 ERRSRV, ERRbadpath);
3238 reply_nterror(req, status);
3242 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3244 status = unlink_internals(conn, req, dirtype, smb_fname,
3245 path_contains_wcard);
3246 if (!NT_STATUS_IS_OK(status)) {
3247 if (open_was_deferred(req->xconn, req->mid)) {
3248 /* We have re-scheduled this call. */
3251 reply_nterror(req, status);
3255 reply_outbuf(req, 0, 0);
3257 TALLOC_FREE(smb_fname);
3258 END_PROFILE(SMBunlink);
3262 /****************************************************************************
3264 ****************************************************************************/
3266 static void fail_readraw(void)
3268 const char *errstr = talloc_asprintf(talloc_tos(),
3269 "FAIL ! reply_readbraw: socket write fail (%s)",
3274 exit_server_cleanly(errstr);
3277 /****************************************************************************
3278 Fake (read/write) sendfile. Returns -1 on read or write fail.
3279 ****************************************************************************/
3281 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3282 off_t startpos, size_t nread)
3285 size_t tosend = nread;
3292 bufsize = MIN(nread, 65536);
3294 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3298 while (tosend > 0) {
3302 cur_read = MIN(tosend, bufsize);
3303 ret = read_file(fsp,buf,startpos,cur_read);
3309 /* If we had a short read, fill with zeros. */
3310 if (ret < cur_read) {
3311 memset(buf + ret, '\0', cur_read - ret);
3314 ret = write_data(xconn->transport.sock, buf, cur_read);
3315 if (ret != cur_read) {
3316 int saved_errno = errno;
3318 * Try and give an error message saying what
3321 DEBUG(0, ("write_data failed for client %s. "
3323 smbXsrv_connection_dbg(xconn),
3324 strerror(saved_errno)));
3326 errno = saved_errno;
3330 startpos += cur_read;
3334 return (ssize_t)nread;
3337 /****************************************************************************
3338 Deal with the case of sendfile reading less bytes from the file than
3339 requested. Fill with zeros (all we can do). Returns 0 on success
3340 ****************************************************************************/
3342 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3348 #define SHORT_SEND_BUFSIZE 1024
3349 if (nread < headersize) {
3350 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3351 "header for file %s (%s). Terminating\n",
3352 fsp_str_dbg(fsp), strerror(errno)));
3356 nread -= headersize;
3358 if (nread < smb_maxcnt) {
3359 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3361 DEBUG(0,("sendfile_short_send: malloc failed "
3362 "for file %s (%s). Terminating\n",
3363 fsp_str_dbg(fsp), strerror(errno)));
3367 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3368 "with zeros !\n", fsp_str_dbg(fsp)));
3370 while (nread < smb_maxcnt) {
3372 * We asked for the real file size and told sendfile
3373 * to not go beyond the end of the file. But it can
3374 * happen that in between our fstat call and the
3375 * sendfile call the file was truncated. This is very
3376 * bad because we have already announced the larger
3377 * number of bytes to the client.
3379 * The best we can do now is to send 0-bytes, just as
3380 * a read from a hole in a sparse file would do.
3382 * This should happen rarely enough that I don't care
3383 * about efficiency here :-)
3388 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3389 ret = write_data(xconn->transport.sock, buf, to_write);
3390 if (ret != to_write) {
3391 int saved_errno = errno;
3393 * Try and give an error message saying what
3396 DEBUG(0, ("write_data failed for client %s. "
3398 smbXsrv_connection_dbg(xconn),
3399 strerror(saved_errno)));
3400 errno = saved_errno;
3411 /****************************************************************************
3412 Return a readbraw error (4 bytes of zero).
3413 ****************************************************************************/
3415 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3421 smbd_lock_socket(xconn);
3422 if (write_data(xconn->transport.sock,header,4) != 4) {
3423 int saved_errno = errno;
3425 * Try and give an error message saying what
3428 DEBUG(0, ("write_data failed for client %s. "
3430 smbXsrv_connection_dbg(xconn),
3431 strerror(saved_errno)));
3432 errno = saved_errno;
3436 smbd_unlock_socket(xconn);
3439 /****************************************************************************
3440 Use sendfile in readbraw.
3441 ****************************************************************************/
3443 static void send_file_readbraw(connection_struct *conn,
3444 struct smb_request *req,
3450 struct smbXsrv_connection *xconn = req->xconn;
3451 char *outbuf = NULL;
3455 * We can only use sendfile on a non-chained packet
3456 * but we can use on a non-oplocked file. tridge proved this
3457 * on a train in Germany :-). JRA.
3458 * reply_readbraw has already checked the length.
3461 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3462 (fsp->wcp == NULL) &&
3463 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3464 ssize_t sendfile_read = -1;
3466 DATA_BLOB header_blob;
3468 _smb_setlen(header,nread);
3469 header_blob = data_blob_const(header, 4);
3471 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3472 &header_blob, startpos,
3474 if (sendfile_read == -1) {
3475 /* Returning ENOSYS means no data at all was sent.
3476 * Do this as a normal read. */
3477 if (errno == ENOSYS) {
3478 goto normal_readbraw;
3482 * Special hack for broken Linux with no working sendfile. If we
3483 * return EINTR we sent the header but not the rest of the data.
3484 * Fake this up by doing read/write calls.
3486 if (errno == EINTR) {
3487 /* Ensure we don't do this again. */
3488 set_use_sendfile(SNUM(conn), False);
3489 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3491 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3492 DEBUG(0,("send_file_readbraw: "
3493 "fake_sendfile failed for "
3497 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3502 DEBUG(0,("send_file_readbraw: sendfile failed for "
3503 "file %s (%s). Terminating\n",
3504 fsp_str_dbg(fsp), strerror(errno)));
3505 exit_server_cleanly("send_file_readbraw sendfile failed");
3506 } else if (sendfile_read == 0) {
3508 * Some sendfile implementations return 0 to indicate
3509 * that there was a short read, but nothing was
3510 * actually written to the socket. In this case,
3511 * fallback to the normal read path so the header gets
3512 * the correct byte count.
3514 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3515 "bytes falling back to the normal read: "
3516 "%s\n", fsp_str_dbg(fsp)));
3517 goto normal_readbraw;
3520 /* Deal with possible short send. */
3521 if (sendfile_read != 4+nread) {
3522 ret = sendfile_short_send(xconn, fsp,
3523 sendfile_read, 4, nread);
3533 outbuf = talloc_array(NULL, char, nread+4);
3535 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3536 (unsigned)(nread+4)));
3537 reply_readbraw_error(xconn);
3542 ret = read_file(fsp,outbuf+4,startpos,nread);
3543 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3552 _smb_setlen(outbuf,ret);
3553 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3554 int saved_errno = errno;
3556 * Try and give an error message saying what
3559 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3560 smbXsrv_connection_dbg(xconn),
3561 strerror(saved_errno)));
3562 errno = saved_errno;
3567 TALLOC_FREE(outbuf);
3570 /****************************************************************************
3571 Reply to a readbraw (core+ protocol).
3572 ****************************************************************************/
3574 void reply_readbraw(struct smb_request *req)
3576 connection_struct *conn = req->conn;
3577 struct smbXsrv_connection *xconn = req->xconn;
3578 ssize_t maxcount,mincount;
3582 struct lock_struct lock;
3585 START_PROFILE(SMBreadbraw);
3587 if (srv_is_signing_active(xconn) || req->encrypted) {
3588 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3589 "raw reads/writes are disallowed.");
3593 reply_readbraw_error(xconn);
3594 END_PROFILE(SMBreadbraw);
3598 if (xconn->smb1.echo_handler.trusted_fde) {
3599 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3600 "'async smb echo handler = yes'\n"));
3601 reply_readbraw_error(xconn);
3602 END_PROFILE(SMBreadbraw);
3607 * Special check if an oplock break has been issued
3608 * and the readraw request croses on the wire, we must
3609 * return a zero length response here.
3612 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3615 * We have to do a check_fsp by hand here, as
3616 * we must always return 4 zero bytes on error,
3620 if (!fsp || !conn || conn != fsp->conn ||
3621 req->vuid != fsp->vuid ||
3622 fsp->is_directory || fsp->fh->fd == -1) {
3624 * fsp could be NULL here so use the value from the packet. JRA.
3626 DEBUG(3,("reply_readbraw: fnum %d not valid "
3628 (int)SVAL(req->vwv+0, 0)));
3629 reply_readbraw_error(xconn);
3630 END_PROFILE(SMBreadbraw);
3634 /* Do a "by hand" version of CHECK_READ. */
3635 if (!(fsp->can_read ||
3636 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3637 (fsp->access_mask & FILE_EXECUTE)))) {
3638 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3639 (int)SVAL(req->vwv+0, 0)));
3640 reply_readbraw_error(xconn);
3641 END_PROFILE(SMBreadbraw);
3645 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3647 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3648 if(req->wct == 10) {
3650 * This is a large offset (64 bit) read.
3653 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3656 DEBUG(0,("reply_readbraw: negative 64 bit "
3657 "readraw offset (%.0f) !\n",
3658 (double)startpos ));
3659 reply_readbraw_error(xconn);
3660 END_PROFILE(SMBreadbraw);
3665 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3666 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3668 /* ensure we don't overrun the packet size */
3669 maxcount = MIN(65535,maxcount);
3671 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3672 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3675 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3676 reply_readbraw_error(xconn);
3677 END_PROFILE(SMBreadbraw);
3681 if (fsp_stat(fsp) == 0) {
3682 size = fsp->fsp_name->st.st_ex_size;
3685 if (startpos >= size) {
3688 nread = MIN(maxcount,(size - startpos));
3691 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3692 if (nread < mincount)
3696 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3697 "min=%lu nread=%lu\n",
3698 fsp_fnum_dbg(fsp), (double)startpos,
3699 (unsigned long)maxcount,
3700 (unsigned long)mincount,
3701 (unsigned long)nread ) );
3703 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3705 DEBUG(5,("reply_readbraw finished\n"));
3707 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3709 END_PROFILE(SMBreadbraw);
3714 #define DBGC_CLASS DBGC_LOCKING
3716 /****************************************************************************
3717 Reply to a lockread (core+ protocol).
3718 ****************************************************************************/
3720 void reply_lockread(struct smb_request *req)
3722 connection_struct *conn = req->conn;
3730 struct byte_range_lock *br_lck = NULL;
3732 struct smbXsrv_connection *xconn = req->xconn;
3734 START_PROFILE(SMBlockread);
3737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3738 END_PROFILE(SMBlockread);
3742 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3744 if (!check_fsp(conn, req, fsp)) {
3745 END_PROFILE(SMBlockread);
3749 if (!CHECK_READ(fsp,req)) {
3750 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3751 END_PROFILE(SMBlockread);
3755 numtoread = SVAL(req->vwv+1, 0);
3756 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3759 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3760 * protocol request that predates the read/write lock concept.
3761 * Thus instead of asking for a read lock here we need to ask
3762 * for a write lock. JRA.
3763 * Note that the requested lock size is unaffected by max_send.
3766 br_lck = do_lock(req->sconn->msg_ctx,
3768 (uint64_t)req->smbpid,
3769 (uint64_t)numtoread,
3773 False, /* Non-blocking lock. */
3776 TALLOC_FREE(br_lck);
3778 if (NT_STATUS_V(status)) {
3779 reply_nterror(req, status);
3780 END_PROFILE(SMBlockread);
3785 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3787 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3789 if (numtoread > maxtoread) {
3790 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3791 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3792 (unsigned int)numtoread, (unsigned int)maxtoread,
3793 (unsigned int)xconn->smb1.sessions.max_send));
3794 numtoread = maxtoread;
3797 reply_outbuf(req, 5, numtoread + 3);
3799 data = smb_buf(req->outbuf) + 3;
3801 nread = read_file(fsp,data,startpos,numtoread);
3804 reply_nterror(req, map_nt_error_from_unix(errno));
3805 END_PROFILE(SMBlockread);
3809 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3811 SSVAL(req->outbuf,smb_vwv0,nread);
3812 SSVAL(req->outbuf,smb_vwv5,nread+3);
3813 p = smb_buf(req->outbuf);
3814 SCVAL(p,0,0); /* pad byte. */
3817 DEBUG(3,("lockread %s num=%d nread=%d\n",
3818 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3820 END_PROFILE(SMBlockread);
3825 #define DBGC_CLASS DBGC_ALL
3827 /****************************************************************************
3829 ****************************************************************************/
3831 void reply_read(struct smb_request *req)
3833 connection_struct *conn = req->conn;
3840 struct lock_struct lock;
3841 struct smbXsrv_connection *xconn = req->xconn;
3843 START_PROFILE(SMBread);
3846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3847 END_PROFILE(SMBread);
3851 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3853 if (!check_fsp(conn, req, fsp)) {
3854 END_PROFILE(SMBread);
3858 if (!CHECK_READ(fsp,req)) {
3859 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3860 END_PROFILE(SMBread);
3864 numtoread = SVAL(req->vwv+1, 0);
3865 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3868 * The requested read size cannot be greater than max_send. JRA.
3870 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3872 if (numtoread > maxtoread) {
3873 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3874 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3875 (unsigned int)numtoread, (unsigned int)maxtoread,
3876 (unsigned int)xconn->smb1.sessions.max_send));
3877 numtoread = maxtoread;
3880 reply_outbuf(req, 5, numtoread+3);
3882 data = smb_buf(req->outbuf) + 3;
3884 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3885 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3888 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3889 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3890 END_PROFILE(SMBread);
3895 nread = read_file(fsp,data,startpos,numtoread);
3898 reply_nterror(req, map_nt_error_from_unix(errno));
3902 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3904 SSVAL(req->outbuf,smb_vwv0,nread);
3905 SSVAL(req->outbuf,smb_vwv5,nread+3);
3906 SCVAL(smb_buf(req->outbuf),0,1);
3907 SSVAL(smb_buf(req->outbuf),1,nread);
3909 DEBUG(3, ("read %s num=%d nread=%d\n",
3910 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3913 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3915 END_PROFILE(SMBread);
3919 /****************************************************************************
3921 ****************************************************************************/
3923 static int setup_readX_header(struct smb_request *req, char *outbuf,
3928 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3931 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3933 SCVAL(outbuf,smb_vwv0,0xFF);
3934 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3935 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3936 SSVAL(outbuf,smb_vwv6,
3937 (smb_wct - 4) /* offset from smb header to wct */
3938 + 1 /* the wct field */
3939 + 12 * sizeof(uint16_t) /* vwv */
3940 + 2 /* the buflen field */
3941 + 1); /* padding byte */
3942 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3943 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3944 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3945 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3946 _smb_setlen_large(outbuf,
3947 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3951 /****************************************************************************
3952 Reply to a read and X - possibly using sendfile.
3953 ****************************************************************************/
3955 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3956 files_struct *fsp, off_t startpos,
3959 struct smbXsrv_connection *xconn = req->xconn;
3961 struct lock_struct lock;
3962 int saved_errno = 0;
3964 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3965 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3968 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3969 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3974 * We can only use sendfile on a non-chained packet
3975 * but we can use on a non-oplocked file. tridge proved this
3976 * on a train in Germany :-). JRA.
3979 if (!req_is_in_chain(req) &&
3981 (fsp->base_fsp == NULL) &&
3982 (fsp->wcp == NULL) &&
3983 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3984 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3987 if(fsp_stat(fsp) == -1) {
3988 reply_nterror(req, map_nt_error_from_unix(errno));
3992 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3993 (startpos > fsp->fsp_name->st.st_ex_size) ||
3994 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3996 * We already know that we would do a short read, so don't
3997 * try the sendfile() path.
3999 goto nosendfile_read;
4003 * Set up the packet header before send. We
4004 * assume here the sendfile will work (get the
4005 * correct amount of data).
4008 header = data_blob_const(headerbuf, sizeof(headerbuf));
4010 construct_reply_common_req(req, (char *)headerbuf);
4011 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
4013 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4014 startpos, smb_maxcnt);
4016 saved_errno = errno;
4018 /* Returning ENOSYS means no data at all was sent.
4019 Do this as a normal read. */
4020 if (errno == ENOSYS) {
4025 * Special hack for broken Linux with no working sendfile. If we
4026 * return EINTR we sent the header but not the rest of the data.
4027 * Fake this up by doing read/write calls.
4030 if (errno == EINTR) {
4031 /* Ensure we don't do this again. */
4032 set_use_sendfile(SNUM(conn), False);
4033 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4034 nread = fake_sendfile(xconn, fsp, startpos,
4037 saved_errno = errno;
4038 DEBUG(0,("send_file_readX: "
4039 "fake_sendfile failed for "
4040 "file %s (%s) for client %s. "
4043 smbXsrv_connection_dbg(xconn),
4044 strerror(saved_errno)));
4045 errno = saved_errno;
4046 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4048 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4049 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4050 /* No outbuf here means successful sendfile. */
4054 DEBUG(0,("send_file_readX: sendfile failed for file "
4055 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4057 exit_server_cleanly("send_file_readX sendfile failed");
4058 } else if (nread == 0) {
4060 * Some sendfile implementations return 0 to indicate
4061 * that there was a short read, but nothing was
4062 * actually written to the socket. In this case,
4063 * fallback to the normal read path so the header gets
4064 * the correct byte count.
4066 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4067 "falling back to the normal read: %s\n",
4072 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4073 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4075 /* Deal with possible short send. */
4076 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4079 ret = sendfile_short_send(xconn, fsp, nread,
4080 sizeof(headerbuf), smb_maxcnt);
4083 r = "send_file_readX: sendfile_short_send failed";
4084 DEBUG(0,("%s for file %s (%s).\n",
4085 r, fsp_str_dbg(fsp), strerror(errno)));
4086 exit_server_cleanly(r);
4089 /* No outbuf here means successful sendfile. */
4090 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4091 SMB_PERFCOUNT_END(&req->pcd);
4097 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4098 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4101 construct_reply_common_req(req, (char *)headerbuf);
4102 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
4104 /* Send out the header. */
4105 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4107 if (ret != sizeof(headerbuf)) {
4108 saved_errno = errno;
4110 * Try and give an error message saying what
4113 DEBUG(0,("send_file_readX: write_data failed for file "
4114 "%s (%s) for client %s. Terminating\n",
4116 smbXsrv_connection_dbg(xconn),
4117 strerror(saved_errno)));
4118 errno = saved_errno;
4119 exit_server_cleanly("send_file_readX sendfile failed");
4121 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4123 saved_errno = errno;
4124 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4125 "%s (%s) for client %s. Terminating\n",
4127 smbXsrv_connection_dbg(xconn),
4128 strerror(saved_errno)));
4129 errno = saved_errno;
4130 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4137 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4138 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4139 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4141 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4142 startpos, smb_maxcnt);
4143 saved_errno = errno;
4145 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4148 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4152 setup_readX_header(req, (char *)req->outbuf, nread);
4154 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4155 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4159 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4160 TALLOC_FREE(req->outbuf);
4164 /****************************************************************************
4165 Work out how much space we have for a read return.
4166 ****************************************************************************/
4168 static size_t calc_max_read_pdu(const struct smb_request *req)
4170 struct smbXsrv_connection *xconn = req->xconn;
4172 if (xconn->protocol < PROTOCOL_NT1) {
4173 return xconn->smb1.sessions.max_send;
4176 if (!lp_large_readwrite()) {
4177 return xconn->smb1.sessions.max_send;
4180 if (req_is_in_chain(req)) {
4181 return xconn->smb1.sessions.max_send;
4184 if (req->encrypted) {
4186 * Don't take encrypted traffic up to the
4187 * limit. There are padding considerations
4188 * that make that tricky.
4190 return xconn->smb1.sessions.max_send;
4193 if (srv_is_signing_active(xconn)) {
4197 if (!lp_unix_extensions()) {
4202 * We can do ultra-large POSIX reads.
4207 /****************************************************************************
4208 Calculate how big a read can be. Copes with all clients. It's always
4209 safe to return a short read - Windows does this.
4210 ****************************************************************************/
4212 static size_t calc_read_size(const struct smb_request *req,
4216 struct smbXsrv_connection *xconn = req->xconn;
4217 size_t max_pdu = calc_max_read_pdu(req);
4218 size_t total_size = 0;
4219 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4220 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4223 * Windows explicitly ignores upper size of 0xFFFF.
4224 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4225 * We must do the same as these will never fit even in
4226 * an extended size NetBIOS packet.
4228 if (upper_size == 0xFFFF) {
4232 if (xconn->protocol < PROTOCOL_NT1) {
4236 total_size = ((upper_size<<16) | lower_size);
4239 * LARGE_READX test shows it's always safe to return
4240 * a short read. Windows does so.
4242 return MIN(total_size, max_len);
4245 /****************************************************************************
4246 Reply to a read and X.
4247 ****************************************************************************/
4249 void reply_read_and_X(struct smb_request *req)
4251 connection_struct *conn = req->conn;
4256 bool big_readX = False;
4258 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4261 START_PROFILE(SMBreadX);
4263 if ((req->wct != 10) && (req->wct != 12)) {
4264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4268 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4269 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4270 smb_maxcnt = SVAL(req->vwv+5, 0);
4272 /* If it's an IPC, pass off the pipe handler. */
4274 reply_pipe_read_and_X(req);
4275 END_PROFILE(SMBreadX);
4279 if (!check_fsp(conn, req, fsp)) {
4280 END_PROFILE(SMBreadX);
4284 if (!CHECK_READ(fsp,req)) {
4285 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4286 END_PROFILE(SMBreadX);
4290 upper_size = SVAL(req->vwv+7, 0);
4291 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4292 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4294 * This is a heuristic to avoid keeping large
4295 * outgoing buffers around over long-lived aio
4301 if (req->wct == 12) {
4303 * This is a large offset (64 bit) read.
4305 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4310 NTSTATUS status = schedule_aio_read_and_X(conn,
4315 if (NT_STATUS_IS_OK(status)) {
4316 /* Read scheduled - we're done. */
4319 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4320 /* Real error - report to client. */
4321 END_PROFILE(SMBreadX);
4322 reply_nterror(req, status);
4325 /* NT_STATUS_RETRY - fall back to sync read. */
4328 smbd_lock_socket(req->xconn);
4329 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4330 smbd_unlock_socket(req->xconn);
4333 END_PROFILE(SMBreadX);
4337 /****************************************************************************
4338 Error replies to writebraw must have smb_wct == 1. Fix this up.
4339 ****************************************************************************/
4341 void error_to_writebrawerr(struct smb_request *req)
4343 uint8_t *old_outbuf = req->outbuf;
4345 reply_outbuf(req, 1, 0);
4347 memcpy(req->outbuf, old_outbuf, smb_size);
4348 TALLOC_FREE(old_outbuf);
4351 /****************************************************************************
4352 Read 4 bytes of a smb packet and return the smb length of the packet.
4353 Store the result in the buffer. This version of the function will
4354 never return a session keepalive (length of zero).
4355 Timeout is in milliseconds.
4356 ****************************************************************************/
4358 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4361 uint8_t msgtype = NBSSkeepalive;
4363 while (msgtype == NBSSkeepalive) {
4366 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4368 if (!NT_STATUS_IS_OK(status)) {
4369 char addr[INET6_ADDRSTRLEN];
4370 /* Try and give an error message
4371 * saying what client failed. */
4372 DEBUG(0, ("read_fd_with_timeout failed for "
4373 "client %s read error = %s.\n",
4374 get_peer_addr(fd,addr,sizeof(addr)),
4375 nt_errstr(status)));
4379 msgtype = CVAL(inbuf, 0);
4382 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4383 (unsigned long)len));
4385 return NT_STATUS_OK;
4388 /****************************************************************************
4389 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4390 ****************************************************************************/
4392 void reply_writebraw(struct smb_request *req)
4394 connection_struct *conn = req->conn;
4395 struct smbXsrv_connection *xconn = req->xconn;
4398 ssize_t total_written=0;
4399 size_t numtowrite=0;
4402 const char *data=NULL;
4405 struct lock_struct lock;
4408 START_PROFILE(SMBwritebraw);
4411 * If we ever reply with an error, it must have the SMB command
4412 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4415 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4417 if (srv_is_signing_active(xconn)) {
4418 END_PROFILE(SMBwritebraw);
4419 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4420 "raw reads/writes are disallowed.");
4423 if (req->wct < 12) {
4424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4425 error_to_writebrawerr(req);
4426 END_PROFILE(SMBwritebraw);
4430 if (xconn->smb1.echo_handler.trusted_fde) {
4431 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4432 "'async smb echo handler = yes'\n"));
4433 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4434 error_to_writebrawerr(req);
4435 END_PROFILE(SMBwritebraw);
4439 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4440 if (!check_fsp(conn, req, fsp)) {
4441 error_to_writebrawerr(req);
4442 END_PROFILE(SMBwritebraw);
4446 if (!CHECK_WRITE(fsp)) {
4447 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4448 error_to_writebrawerr(req);
4449 END_PROFILE(SMBwritebraw);
4453 tcount = IVAL(req->vwv+1, 0);
4454 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4455 write_through = BITSETW(req->vwv+7,0);
4457 /* We have to deal with slightly different formats depending
4458 on whether we are using the core+ or lanman1.0 protocol */
4460 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4461 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4462 data = smb_buf_const(req->inbuf);
4464 numtowrite = SVAL(req->vwv+10, 0);
4465 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4468 /* Ensure we don't write bytes past the end of this packet. */
4469 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4471 error_to_writebrawerr(req);
4472 END_PROFILE(SMBwritebraw);
4476 if (!fsp->print_file) {
4477 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4478 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4481 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4482 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4483 error_to_writebrawerr(req);
4484 END_PROFILE(SMBwritebraw);
4490 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4493 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4494 "wrote=%d sync=%d\n",
4495 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4496 (int)nwritten, (int)write_through));
4498 if (nwritten < (ssize_t)numtowrite) {
4499 reply_nterror(req, NT_STATUS_DISK_FULL);
4500 error_to_writebrawerr(req);
4504 total_written = nwritten;
4506 /* Allocate a buffer of 64k + length. */
4507 buf = talloc_array(NULL, char, 65540);
4509 reply_nterror(req, NT_STATUS_NO_MEMORY);
4510 error_to_writebrawerr(req);
4514 /* Return a SMBwritebraw message to the redirector to tell
4515 * it to send more bytes */
4517 memcpy(buf, req->inbuf, smb_size);
4518 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4519 SCVAL(buf,smb_com,SMBwritebraw);
4520 SSVALS(buf,smb_vwv0,0xFFFF);
4522 if (!srv_send_smb(req->xconn,
4524 false, 0, /* no signing */
4525 IS_CONN_ENCRYPTED(conn),
4527 exit_server_cleanly("reply_writebraw: srv_send_smb "
4531 /* Now read the raw data into the buffer and write it */
4532 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4534 if (!NT_STATUS_IS_OK(status)) {
4535 exit_server_cleanly("secondary writebraw failed");
4538 /* Set up outbuf to return the correct size */
4539 reply_outbuf(req, 1, 0);
4541 if (numtowrite != 0) {
4543 if (numtowrite > 0xFFFF) {
4544 DEBUG(0,("reply_writebraw: Oversize secondary write "
4545 "raw requested (%u). Terminating\n",
4546 (unsigned int)numtowrite ));
4547 exit_server_cleanly("secondary writebraw failed");
4550 if (tcount > nwritten+numtowrite) {
4551 DEBUG(3,("reply_writebraw: Client overestimated the "
4553 (int)tcount,(int)nwritten,(int)numtowrite));
4556 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4559 if (!NT_STATUS_IS_OK(status)) {
4560 /* Try and give an error message
4561 * saying what client failed. */
4562 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4563 "raw read failed (%s) for client %s. "
4564 "Terminating\n", nt_errstr(status),
4565 smbXsrv_connection_dbg(xconn)));
4566 exit_server_cleanly("secondary writebraw failed");
4569 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4570 if (nwritten == -1) {
4572 reply_nterror(req, map_nt_error_from_unix(errno));
4573 error_to_writebrawerr(req);
4577 if (nwritten < (ssize_t)numtowrite) {
4578 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4579 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4583 total_written += nwritten;
4588 SSVAL(req->outbuf,smb_vwv0,total_written);
4590 status = sync_file(conn, fsp, write_through);
4591 if (!NT_STATUS_IS_OK(status)) {
4592 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4593 fsp_str_dbg(fsp), nt_errstr(status)));
4594 reply_nterror(req, status);
4595 error_to_writebrawerr(req);
4599 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4601 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4602 (int)total_written));
4604 if (!fsp->print_file) {
4605 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4608 /* We won't return a status if write through is not selected - this
4609 * follows what WfWg does */
4610 END_PROFILE(SMBwritebraw);
4612 if (!write_through && total_written==tcount) {
4614 #if RABBIT_PELLET_FIX
4616 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4617 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4620 if (!send_keepalive(xconn->transport.sock)) {
4621 exit_server_cleanly("reply_writebraw: send of "
4622 "keepalive failed");
4625 TALLOC_FREE(req->outbuf);
4630 if (!fsp->print_file) {
4631 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4634 END_PROFILE(SMBwritebraw);
4639 #define DBGC_CLASS DBGC_LOCKING
4641 /****************************************************************************
4642 Reply to a writeunlock (core+).
4643 ****************************************************************************/
4645 void reply_writeunlock(struct smb_request *req)
4647 connection_struct *conn = req->conn;
4648 ssize_t nwritten = -1;
4652 NTSTATUS status = NT_STATUS_OK;
4654 struct lock_struct lock;
4655 int saved_errno = 0;
4657 START_PROFILE(SMBwriteunlock);
4660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4661 END_PROFILE(SMBwriteunlock);
4665 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4667 if (!check_fsp(conn, req, fsp)) {
4668 END_PROFILE(SMBwriteunlock);
4672 if (!CHECK_WRITE(fsp)) {
4673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4674 END_PROFILE(SMBwriteunlock);
4678 numtowrite = SVAL(req->vwv+1, 0);
4679 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4680 data = (const char *)req->buf + 3;
4682 if (!fsp->print_file && numtowrite > 0) {
4683 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4684 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4687 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4688 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4689 END_PROFILE(SMBwriteunlock);
4694 /* The special X/Open SMB protocol handling of
4695 zero length writes is *NOT* done for
4697 if(numtowrite == 0) {
4700 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4701 saved_errno = errno;
4704 status = sync_file(conn, fsp, False /* write through */);
4705 if (!NT_STATUS_IS_OK(status)) {
4706 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4707 fsp_str_dbg(fsp), nt_errstr(status)));
4708 reply_nterror(req, status);
4713 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4717 if((nwritten < numtowrite) && (numtowrite != 0)) {
4718 reply_nterror(req, NT_STATUS_DISK_FULL);
4722 if (numtowrite && !fsp->print_file) {
4723 status = do_unlock(req->sconn->msg_ctx,
4725 (uint64_t)req->smbpid,
4726 (uint64_t)numtowrite,
4730 if (NT_STATUS_V(status)) {
4731 reply_nterror(req, status);
4736 reply_outbuf(req, 1, 0);
4738 SSVAL(req->outbuf,smb_vwv0,nwritten);
4740 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4741 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4744 if (numtowrite && !fsp->print_file) {
4745 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4748 END_PROFILE(SMBwriteunlock);
4753 #define DBGC_CLASS DBGC_ALL
4755 /****************************************************************************
4757 ****************************************************************************/
4759 void reply_write(struct smb_request *req)
4761 connection_struct *conn = req->conn;
4763 ssize_t nwritten = -1;
4767 struct lock_struct lock;
4769 int saved_errno = 0;
4771 START_PROFILE(SMBwrite);
4774 END_PROFILE(SMBwrite);
4775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4779 /* If it's an IPC, pass off the pipe handler. */
4781 reply_pipe_write(req);
4782 END_PROFILE(SMBwrite);
4786 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4788 if (!check_fsp(conn, req, fsp)) {
4789 END_PROFILE(SMBwrite);
4793 if (!CHECK_WRITE(fsp)) {
4794 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4795 END_PROFILE(SMBwrite);
4799 numtowrite = SVAL(req->vwv+1, 0);
4800 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4801 data = (const char *)req->buf + 3;
4803 if (!fsp->print_file) {
4804 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4805 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4808 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4809 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4810 END_PROFILE(SMBwrite);
4816 * X/Open SMB protocol says that if smb_vwv1 is
4817 * zero then the file size should be extended or
4818 * truncated to the size given in smb_vwv[2-3].
4821 if(numtowrite == 0) {
4823 * This is actually an allocate call, and set EOF. JRA.
4825 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4827 reply_nterror(req, NT_STATUS_DISK_FULL);
4830 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4832 reply_nterror(req, NT_STATUS_DISK_FULL);
4835 trigger_write_time_update_immediate(fsp);
4837 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4840 status = sync_file(conn, fsp, False);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4843 fsp_str_dbg(fsp), nt_errstr(status)));
4844 reply_nterror(req, status);
4849 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4853 if((nwritten == 0) && (numtowrite != 0)) {
4854 reply_nterror(req, NT_STATUS_DISK_FULL);
4858 reply_outbuf(req, 1, 0);
4860 SSVAL(req->outbuf,smb_vwv0,nwritten);
4862 if (nwritten < (ssize_t)numtowrite) {
4863 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4864 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4867 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4870 if (!fsp->print_file) {
4871 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4874 END_PROFILE(SMBwrite);
4878 /****************************************************************************
4879 Ensure a buffer is a valid writeX for recvfile purposes.
4880 ****************************************************************************/
4882 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4883 (2*14) + /* word count (including bcc) */ \
4886 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4887 const uint8_t *inbuf)
4890 unsigned int doff = 0;
4891 size_t len = smb_len_large(inbuf);
4893 struct smbXsrv_open *op = NULL;
4894 struct files_struct *fsp = NULL;
4897 if (is_encrypted_packet(inbuf)) {
4898 /* Can't do this on encrypted
4903 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4907 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4908 CVAL(inbuf,smb_wct) != 14) {
4909 DEBUG(10,("is_valid_writeX_buffer: chained or "
4910 "invalid word length.\n"));
4914 fnum = SVAL(inbuf, smb_vwv2);
4915 status = smb1srv_open_lookup(xconn,
4919 if (!NT_STATUS_IS_OK(status)) {
4920 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4925 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4928 if (fsp->conn == NULL) {
4929 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4933 if (IS_IPC(fsp->conn)) {
4934 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4937 if (IS_PRINT(fsp->conn)) {
4938 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4941 doff = SVAL(inbuf,smb_vwv11);
4943 numtowrite = SVAL(inbuf,smb_vwv10);
4945 if (len > doff && len - doff > 0xFFFF) {
4946 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4949 if (numtowrite == 0) {
4950 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4954 /* Ensure the sizes match up. */
4955 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4956 /* no pad byte...old smbclient :-( */
4957 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4959 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4963 if (len - doff != numtowrite) {
4964 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4965 "len = %u, doff = %u, numtowrite = %u\n",
4968 (unsigned int)numtowrite ));
4972 DEBUG(10,("is_valid_writeX_buffer: true "
4973 "len = %u, doff = %u, numtowrite = %u\n",
4976 (unsigned int)numtowrite ));
4981 /****************************************************************************
4982 Reply to a write and X.
4983 ****************************************************************************/
4985 void reply_write_and_X(struct smb_request *req)
4987 connection_struct *conn = req->conn;
4988 struct smbXsrv_connection *xconn = req->xconn;
4990 struct lock_struct lock;
4995 unsigned int smb_doff;
4996 unsigned int smblen;
4999 int saved_errno = 0;
5001 START_PROFILE(SMBwriteX);
5003 if ((req->wct != 12) && (req->wct != 14)) {
5004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5008 numtowrite = SVAL(req->vwv+10, 0);
5009 smb_doff = SVAL(req->vwv+11, 0);
5010 smblen = smb_len(req->inbuf);
5012 if (req->unread_bytes > 0xFFFF ||
5013 (smblen > smb_doff &&
5014 smblen - smb_doff > 0xFFFF)) {
5015 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5018 if (req->unread_bytes) {
5019 /* Can't do a recvfile write on IPC$ */
5021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5024 if (numtowrite != req->unread_bytes) {
5025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5029 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5030 smb_doff + numtowrite > smblen) {
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5036 /* If it's an IPC, pass off the pipe handler. */
5038 if (req->unread_bytes) {
5039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5042 reply_pipe_write_and_X(req);
5046 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5047 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5048 write_through = BITSETW(req->vwv+7,0);
5050 if (!check_fsp(conn, req, fsp)) {
5054 if (!CHECK_WRITE(fsp)) {
5055 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5059 data = smb_base(req->inbuf) + smb_doff;
5061 if(req->wct == 14) {
5063 * This is a large offset (64 bit) write.
5065 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5069 /* X/Open SMB protocol says that, unlike SMBwrite
5070 if the length is zero then NO truncation is
5071 done, just a write of zero. To truncate a file,
5074 if(numtowrite == 0) {
5077 if (req->unread_bytes == 0) {
5078 status = schedule_aio_write_and_X(conn,
5085 if (NT_STATUS_IS_OK(status)) {
5086 /* write scheduled - we're done. */
5089 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5090 /* Real error - report to client. */
5091 reply_nterror(req, status);
5094 /* NT_STATUS_RETRY - fall through to sync write. */
5097 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5098 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5101 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5102 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5106 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5107 saved_errno = errno;
5109 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5113 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5117 if((nwritten == 0) && (numtowrite != 0)) {
5118 reply_nterror(req, NT_STATUS_DISK_FULL);
5122 reply_outbuf(req, 6, 0);
5123 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5124 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5125 SSVAL(req->outbuf,smb_vwv2,nwritten);
5126 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5128 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5129 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5131 status = sync_file(conn, fsp, write_through);
5132 if (!NT_STATUS_IS_OK(status)) {
5133 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5134 fsp_str_dbg(fsp), nt_errstr(status)));
5135 reply_nterror(req, status);
5139 END_PROFILE(SMBwriteX);
5143 if (req->unread_bytes) {
5144 /* writeX failed. drain socket. */
5145 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5146 req->unread_bytes) {
5147 smb_panic("failed to drain pending bytes");
5149 req->unread_bytes = 0;
5152 END_PROFILE(SMBwriteX);
5156 /****************************************************************************
5158 ****************************************************************************/
5160 void reply_lseek(struct smb_request *req)
5162 connection_struct *conn = req->conn;
5168 START_PROFILE(SMBlseek);
5171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5172 END_PROFILE(SMBlseek);
5176 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5178 if (!check_fsp(conn, req, fsp)) {
5182 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5184 mode = SVAL(req->vwv+1, 0) & 3;
5185 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5186 startpos = (off_t)IVALS(req->vwv+2, 0);
5195 res = fsp->fh->pos + startpos;
5206 if (umode == SEEK_END) {
5207 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5208 if(errno == EINVAL) {
5209 off_t current_pos = startpos;
5211 if(fsp_stat(fsp) == -1) {
5213 map_nt_error_from_unix(errno));
5214 END_PROFILE(SMBlseek);
5218 current_pos += fsp->fsp_name->st.st_ex_size;
5220 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5225 reply_nterror(req, map_nt_error_from_unix(errno));
5226 END_PROFILE(SMBlseek);
5233 reply_outbuf(req, 2, 0);
5234 SIVAL(req->outbuf,smb_vwv0,res);
5236 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5237 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5239 END_PROFILE(SMBlseek);
5243 /****************************************************************************
5245 ****************************************************************************/
5247 void reply_flush(struct smb_request *req)
5249 connection_struct *conn = req->conn;
5253 START_PROFILE(SMBflush);
5256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5260 fnum = SVAL(req->vwv+0, 0);
5261 fsp = file_fsp(req, fnum);
5263 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5268 file_sync_all(conn);
5270 NTSTATUS status = sync_file(conn, fsp, True);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5273 fsp_str_dbg(fsp), nt_errstr(status)));
5274 reply_nterror(req, status);
5275 END_PROFILE(SMBflush);
5280 reply_outbuf(req, 0, 0);
5282 DEBUG(3,("flush\n"));
5283 END_PROFILE(SMBflush);
5287 /****************************************************************************
5289 conn POINTER CAN BE NULL HERE !
5290 ****************************************************************************/
5292 void reply_exit(struct smb_request *req)
5294 START_PROFILE(SMBexit);
5296 file_close_pid(req->sconn, req->smbpid, req->vuid);
5298 reply_outbuf(req, 0, 0);
5300 DEBUG(3,("exit\n"));
5302 END_PROFILE(SMBexit);
5306 struct reply_close_state {
5308 struct smb_request *smbreq;
5311 static void do_smb1_close(struct tevent_req *req);
5313 void reply_close(struct smb_request *req)
5315 connection_struct *conn = req->conn;
5316 NTSTATUS status = NT_STATUS_OK;
5317 files_struct *fsp = NULL;
5318 START_PROFILE(SMBclose);
5321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5322 END_PROFILE(SMBclose);
5326 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5329 * We can only use check_fsp if we know it's not a directory.
5332 if (!check_fsp_open(conn, req, fsp)) {
5333 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5334 END_PROFILE(SMBclose);
5338 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5339 fsp->is_directory ? "directory" : "file",
5340 fsp->fh->fd, fsp_fnum_dbg(fsp),
5341 conn->num_files_open));
5343 if (!fsp->is_directory) {
5347 * Take care of any time sent in the close.
5350 t = srv_make_unix_date3(req->vwv+1);
5351 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5354 if (fsp->num_aio_requests != 0) {
5356 struct reply_close_state *state;
5358 DEBUG(10, ("closing with aio %u requests pending\n",
5359 fsp->num_aio_requests));
5362 * We depend on the aio_extra destructor to take care of this
5363 * close request once fsp->num_aio_request drops to 0.
5366 fsp->deferred_close = tevent_wait_send(
5367 fsp, fsp->conn->sconn->ev_ctx);
5368 if (fsp->deferred_close == NULL) {
5369 status = NT_STATUS_NO_MEMORY;
5373 state = talloc(fsp, struct reply_close_state);
5374 if (state == NULL) {
5375 TALLOC_FREE(fsp->deferred_close);
5376 status = NT_STATUS_NO_MEMORY;
5380 state->smbreq = talloc_move(fsp, &req);
5381 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5383 END_PROFILE(SMBclose);
5388 * close_file() returns the unix errno if an error was detected on
5389 * close - normally this is due to a disk full error. If not then it
5390 * was probably an I/O error.
5393 status = close_file(req, fsp, NORMAL_CLOSE);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 reply_nterror(req, status);
5397 END_PROFILE(SMBclose);
5401 reply_outbuf(req, 0, 0);
5402 END_PROFILE(SMBclose);
5406 static void do_smb1_close(struct tevent_req *req)
5408 struct reply_close_state *state = tevent_req_callback_data(
5409 req, struct reply_close_state);
5410 struct smb_request *smbreq;
5414 ret = tevent_wait_recv(req);
5417 DEBUG(10, ("tevent_wait_recv returned %s\n",
5420 * Continue anyway, this should never happen
5425 * fsp->smb2_close_request right now is a talloc grandchild of
5426 * fsp. When we close_file(fsp), it would go with it. No chance to
5429 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5431 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5432 if (NT_STATUS_IS_OK(status)) {
5433 reply_outbuf(smbreq, 0, 0);
5435 reply_nterror(smbreq, status);
5437 if (!srv_send_smb(smbreq->xconn,
5438 (char *)smbreq->outbuf,
5441 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5443 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5446 TALLOC_FREE(smbreq);
5449 /****************************************************************************
5450 Reply to a writeclose (Core+ protocol).
5451 ****************************************************************************/
5453 void reply_writeclose(struct smb_request *req)
5455 connection_struct *conn = req->conn;
5457 ssize_t nwritten = -1;
5458 NTSTATUS close_status = NT_STATUS_OK;
5461 struct timespec mtime;
5463 struct lock_struct lock;
5465 START_PROFILE(SMBwriteclose);
5468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 END_PROFILE(SMBwriteclose);
5473 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5475 if (!check_fsp(conn, req, fsp)) {
5476 END_PROFILE(SMBwriteclose);
5479 if (!CHECK_WRITE(fsp)) {
5480 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5481 END_PROFILE(SMBwriteclose);
5485 numtowrite = SVAL(req->vwv+1, 0);
5486 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5487 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5488 data = (const char *)req->buf + 1;
5490 if (fsp->print_file == NULL) {
5491 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5492 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5495 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5496 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5497 END_PROFILE(SMBwriteclose);
5502 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5504 if (fsp->print_file == NULL) {
5505 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5508 set_close_write_time(fsp, mtime);
5511 * More insanity. W2K only closes the file if writelen > 0.
5515 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5516 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5517 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5520 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5521 "file %s\n", fsp_str_dbg(fsp)));
5522 close_status = close_file(req, fsp, NORMAL_CLOSE);
5526 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5527 reply_nterror(req, NT_STATUS_DISK_FULL);
5531 if(!NT_STATUS_IS_OK(close_status)) {
5532 reply_nterror(req, close_status);
5536 reply_outbuf(req, 1, 0);
5538 SSVAL(req->outbuf,smb_vwv0,nwritten);
5542 END_PROFILE(SMBwriteclose);
5547 #define DBGC_CLASS DBGC_LOCKING
5549 /****************************************************************************
5551 ****************************************************************************/
5553 void reply_lock(struct smb_request *req)
5555 connection_struct *conn = req->conn;
5556 uint64_t count,offset;
5559 struct byte_range_lock *br_lck = NULL;
5561 START_PROFILE(SMBlock);
5564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5565 END_PROFILE(SMBlock);
5569 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5571 if (!check_fsp(conn, req, fsp)) {
5572 END_PROFILE(SMBlock);
5576 count = (uint64_t)IVAL(req->vwv+1, 0);
5577 offset = (uint64_t)IVAL(req->vwv+3, 0);
5579 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5580 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5582 br_lck = do_lock(req->sconn->msg_ctx,
5584 (uint64_t)req->smbpid,
5589 False, /* Non-blocking lock. */
5593 TALLOC_FREE(br_lck);
5595 if (NT_STATUS_V(status)) {
5596 reply_nterror(req, status);
5597 END_PROFILE(SMBlock);
5601 reply_outbuf(req, 0, 0);
5603 END_PROFILE(SMBlock);
5607 /****************************************************************************
5609 ****************************************************************************/
5611 void reply_unlock(struct smb_request *req)
5613 connection_struct *conn = req->conn;
5614 uint64_t count,offset;
5618 START_PROFILE(SMBunlock);
5621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5622 END_PROFILE(SMBunlock);
5626 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5628 if (!check_fsp(conn, req, fsp)) {
5629 END_PROFILE(SMBunlock);
5633 count = (uint64_t)IVAL(req->vwv+1, 0);
5634 offset = (uint64_t)IVAL(req->vwv+3, 0);
5636 status = do_unlock(req->sconn->msg_ctx,
5638 (uint64_t)req->smbpid,
5643 if (NT_STATUS_V(status)) {
5644 reply_nterror(req, status);
5645 END_PROFILE(SMBunlock);
5649 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5650 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5652 reply_outbuf(req, 0, 0);
5654 END_PROFILE(SMBunlock);
5659 #define DBGC_CLASS DBGC_ALL
5661 /****************************************************************************
5663 conn POINTER CAN BE NULL HERE !
5664 ****************************************************************************/
5666 void reply_tdis(struct smb_request *req)
5669 connection_struct *conn = req->conn;
5670 struct smbXsrv_tcon *tcon;
5672 START_PROFILE(SMBtdis);
5675 DEBUG(4,("Invalid connection in tdis\n"));
5676 reply_force_doserror(req, ERRSRV, ERRinvnid);
5677 END_PROFILE(SMBtdis);
5685 * TODO: cancel all outstanding requests on the tcon
5687 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5688 if (!NT_STATUS_IS_OK(status)) {
5689 DEBUG(0, ("reply_tdis: "
5690 "smbXsrv_tcon_disconnect() failed: %s\n",
5691 nt_errstr(status)));
5693 * If we hit this case, there is something completely
5694 * wrong, so we better disconnect the transport connection.
5696 END_PROFILE(SMBtdis);
5697 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5703 reply_outbuf(req, 0, 0);
5704 END_PROFILE(SMBtdis);
5708 /****************************************************************************
5710 conn POINTER CAN BE NULL HERE !
5711 ****************************************************************************/
5713 void reply_echo(struct smb_request *req)
5715 connection_struct *conn = req->conn;
5716 struct smb_perfcount_data local_pcd;
5717 struct smb_perfcount_data *cur_pcd;
5721 START_PROFILE(SMBecho);
5723 smb_init_perfcount_data(&local_pcd);
5726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5727 END_PROFILE(SMBecho);
5731 smb_reverb = SVAL(req->vwv+0, 0);
5733 reply_outbuf(req, 1, req->buflen);
5735 /* copy any incoming data back out */
5736 if (req->buflen > 0) {
5737 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5740 if (smb_reverb > 100) {
5741 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5745 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5747 /* this makes sure we catch the request pcd */
5748 if (seq_num == smb_reverb) {
5749 cur_pcd = &req->pcd;
5751 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5752 cur_pcd = &local_pcd;
5755 SSVAL(req->outbuf,smb_vwv0,seq_num);
5757 show_msg((char *)req->outbuf);
5758 if (!srv_send_smb(req->xconn,
5759 (char *)req->outbuf,
5760 true, req->seqnum+1,
5761 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5763 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5766 DEBUG(3,("echo %d times\n", smb_reverb));
5768 TALLOC_FREE(req->outbuf);
5770 END_PROFILE(SMBecho);
5774 /****************************************************************************
5775 Reply to a printopen.
5776 ****************************************************************************/
5778 void reply_printopen(struct smb_request *req)
5780 connection_struct *conn = req->conn;
5784 START_PROFILE(SMBsplopen);
5787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5788 END_PROFILE(SMBsplopen);
5792 if (!CAN_PRINT(conn)) {
5793 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5794 END_PROFILE(SMBsplopen);
5798 status = file_new(req, conn, &fsp);
5799 if(!NT_STATUS_IS_OK(status)) {
5800 reply_nterror(req, status);
5801 END_PROFILE(SMBsplopen);
5805 /* Open for exclusive use, write only. */
5806 status = print_spool_open(fsp, NULL, req->vuid);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 file_free(req, fsp);
5810 reply_nterror(req, status);
5811 END_PROFILE(SMBsplopen);
5815 reply_outbuf(req, 1, 0);
5816 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5818 DEBUG(3,("openprint fd=%d %s\n",
5819 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5821 END_PROFILE(SMBsplopen);
5825 /****************************************************************************
5826 Reply to a printclose.
5827 ****************************************************************************/
5829 void reply_printclose(struct smb_request *req)
5831 connection_struct *conn = req->conn;
5835 START_PROFILE(SMBsplclose);
5838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5839 END_PROFILE(SMBsplclose);
5843 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5845 if (!check_fsp(conn, req, fsp)) {
5846 END_PROFILE(SMBsplclose);
5850 if (!CAN_PRINT(conn)) {
5851 reply_force_doserror(req, ERRSRV, ERRerror);
5852 END_PROFILE(SMBsplclose);
5856 DEBUG(3,("printclose fd=%d %s\n",
5857 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5859 status = close_file(req, fsp, NORMAL_CLOSE);
5861 if(!NT_STATUS_IS_OK(status)) {
5862 reply_nterror(req, status);
5863 END_PROFILE(SMBsplclose);
5867 reply_outbuf(req, 0, 0);
5869 END_PROFILE(SMBsplclose);
5873 /****************************************************************************
5874 Reply to a printqueue.
5875 ****************************************************************************/
5877 void reply_printqueue(struct smb_request *req)
5879 connection_struct *conn = req->conn;
5883 START_PROFILE(SMBsplretq);
5886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5887 END_PROFILE(SMBsplretq);
5891 max_count = SVAL(req->vwv+0, 0);
5892 start_index = SVAL(req->vwv+1, 0);
5894 /* we used to allow the client to get the cnum wrong, but that
5895 is really quite gross and only worked when there was only
5896 one printer - I think we should now only accept it if they
5897 get it right (tridge) */
5898 if (!CAN_PRINT(conn)) {
5899 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5900 END_PROFILE(SMBsplretq);
5904 reply_outbuf(req, 2, 3);
5905 SSVAL(req->outbuf,smb_vwv0,0);
5906 SSVAL(req->outbuf,smb_vwv1,0);
5907 SCVAL(smb_buf(req->outbuf),0,1);
5908 SSVAL(smb_buf(req->outbuf),1,0);
5910 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5911 start_index, max_count));
5914 TALLOC_CTX *mem_ctx = talloc_tos();
5917 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5918 struct rpc_pipe_client *cli = NULL;
5919 struct dcerpc_binding_handle *b = NULL;
5920 struct policy_handle handle;
5921 struct spoolss_DevmodeContainer devmode_ctr;
5922 union spoolss_JobInfo *info;
5924 uint32_t num_to_get;
5928 ZERO_STRUCT(handle);
5930 status = rpc_pipe_open_interface(conn,
5933 conn->sconn->remote_address,
5934 conn->sconn->msg_ctx,
5936 if (!NT_STATUS_IS_OK(status)) {
5937 DEBUG(0, ("reply_printqueue: "
5938 "could not connect to spoolss: %s\n",
5939 nt_errstr(status)));
5940 reply_nterror(req, status);
5943 b = cli->binding_handle;
5945 ZERO_STRUCT(devmode_ctr);
5947 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5950 SEC_FLAG_MAXIMUM_ALLOWED,
5953 if (!NT_STATUS_IS_OK(status)) {
5954 reply_nterror(req, status);
5957 if (!W_ERROR_IS_OK(werr)) {
5958 reply_nterror(req, werror_to_ntstatus(werr));
5962 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5970 if (!W_ERROR_IS_OK(werr)) {
5971 reply_nterror(req, werror_to_ntstatus(werr));
5975 if (max_count > 0) {
5976 first = start_index;
5978 first = start_index + max_count + 1;
5981 if (first >= count) {
5984 num_to_get = first + MIN(ABS(max_count), count - first);
5987 for (i = first; i < num_to_get; i++) {
5990 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5993 uint16_t qrapjobid = pjobid_to_rap(sharename,
5994 info[i].info2.job_id);
5996 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6002 srv_put_dos_date2(p, 0, qtime);
6003 SCVAL(p, 4, qstatus);
6004 SSVAL(p, 5, qrapjobid);
6005 SIVAL(p, 7, info[i].info2.size);
6007 status = srvstr_push(blob, req->flags2, p+12,
6008 info[i].info2.notify_name, 16, STR_ASCII, &len);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 reply_nterror(req, status);
6013 if (message_push_blob(
6016 blob, sizeof(blob))) == -1) {
6017 reply_nterror(req, NT_STATUS_NO_MEMORY);
6023 SSVAL(req->outbuf,smb_vwv0,count);
6024 SSVAL(req->outbuf,smb_vwv1,
6025 (max_count>0?first+count:first-1));
6026 SCVAL(smb_buf(req->outbuf),0,1);
6027 SSVAL(smb_buf(req->outbuf),1,28*count);
6031 DEBUG(3, ("%u entries returned in queue\n",
6035 if (b && is_valid_policy_hnd(&handle)) {
6036 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6041 END_PROFILE(SMBsplretq);
6045 /****************************************************************************
6046 Reply to a printwrite.
6047 ****************************************************************************/
6049 void reply_printwrite(struct smb_request *req)
6051 connection_struct *conn = req->conn;
6056 START_PROFILE(SMBsplwr);
6059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6060 END_PROFILE(SMBsplwr);
6064 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6066 if (!check_fsp(conn, req, fsp)) {
6067 END_PROFILE(SMBsplwr);
6071 if (!fsp->print_file) {
6072 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6073 END_PROFILE(SMBsplwr);
6077 if (!CHECK_WRITE(fsp)) {
6078 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6079 END_PROFILE(SMBsplwr);
6083 numtowrite = SVAL(req->buf, 1);
6085 if (req->buflen < numtowrite + 3) {
6086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6087 END_PROFILE(SMBsplwr);
6091 data = (const char *)req->buf + 3;
6093 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6094 reply_nterror(req, map_nt_error_from_unix(errno));
6095 END_PROFILE(SMBsplwr);
6099 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6101 END_PROFILE(SMBsplwr);
6105 /****************************************************************************
6107 ****************************************************************************/
6109 void reply_mkdir(struct smb_request *req)
6111 connection_struct *conn = req->conn;
6112 struct smb_filename *smb_dname = NULL;
6113 char *directory = NULL;
6115 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
6116 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6117 TALLOC_CTX *ctx = talloc_tos();
6119 START_PROFILE(SMBmkdir);
6121 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6122 STR_TERMINATE, &status);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 reply_nterror(req, status);
6128 status = filename_convert(ctx, conn,
6129 req->flags2 & FLAGS2_DFS_PATHNAMES,
6134 if (!NT_STATUS_IS_OK(status)) {
6135 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6136 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6137 ERRSRV, ERRbadpath);
6140 reply_nterror(req, status);
6144 status = create_directory(conn, req, smb_dname);
6146 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6148 if (!NT_STATUS_IS_OK(status)) {
6150 if (!use_nt_status()
6151 && NT_STATUS_EQUAL(status,
6152 NT_STATUS_OBJECT_NAME_COLLISION)) {
6154 * Yes, in the DOS error code case we get a
6155 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6156 * samba4 torture test.
6158 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6161 reply_nterror(req, status);
6165 reply_outbuf(req, 0, 0);
6167 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6169 TALLOC_FREE(smb_dname);
6170 END_PROFILE(SMBmkdir);
6174 /****************************************************************************
6176 ****************************************************************************/
6178 void reply_rmdir(struct smb_request *req)
6180 connection_struct *conn = req->conn;
6181 struct smb_filename *smb_dname = NULL;
6182 char *directory = NULL;
6184 TALLOC_CTX *ctx = talloc_tos();
6185 files_struct *fsp = NULL;
6187 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6188 struct smbd_server_connection *sconn = req->sconn;
6190 START_PROFILE(SMBrmdir);
6192 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6193 STR_TERMINATE, &status);
6194 if (!NT_STATUS_IS_OK(status)) {
6195 reply_nterror(req, status);
6199 status = filename_convert(ctx, conn,
6200 req->flags2 & FLAGS2_DFS_PATHNAMES,
6205 if (!NT_STATUS_IS_OK(status)) {
6206 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6207 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6208 ERRSRV, ERRbadpath);
6211 reply_nterror(req, status);
6215 if (is_ntfs_stream_smb_fname(smb_dname)) {
6216 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6220 status = SMB_VFS_CREATE_FILE(
6223 0, /* root_dir_fid */
6224 smb_dname, /* fname */
6225 DELETE_ACCESS, /* access_mask */
6226 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6228 FILE_OPEN, /* create_disposition*/
6229 FILE_DIRECTORY_FILE, /* create_options */
6230 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6231 0, /* oplock_request */
6233 0, /* allocation_size */
6234 0, /* private_flags */
6239 NULL, NULL); /* create context */
6241 if (!NT_STATUS_IS_OK(status)) {
6242 if (open_was_deferred(req->xconn, req->mid)) {
6243 /* We have re-scheduled this call. */
6246 reply_nterror(req, status);
6250 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 close_file(req, fsp, ERROR_CLOSE);
6253 reply_nterror(req, status);
6257 if (!set_delete_on_close(fsp, true,
6258 conn->session_info->security_token,
6259 conn->session_info->unix_token)) {
6260 close_file(req, fsp, ERROR_CLOSE);
6261 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6265 status = close_file(req, fsp, NORMAL_CLOSE);
6266 if (!NT_STATUS_IS_OK(status)) {
6267 reply_nterror(req, status);
6269 reply_outbuf(req, 0, 0);
6272 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6274 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6276 TALLOC_FREE(smb_dname);
6277 END_PROFILE(SMBrmdir);
6281 /*******************************************************************
6282 Resolve wildcards in a filename rename.
6283 ********************************************************************/
6285 static bool resolve_wildcards(TALLOC_CTX *ctx,
6290 char *name2_copy = NULL;
6295 char *p,*p2, *pname1, *pname2;
6297 name2_copy = talloc_strdup(ctx, name2);
6302 pname1 = strrchr_m(name1,'/');
6303 pname2 = strrchr_m(name2_copy,'/');
6305 if (!pname1 || !pname2) {
6309 /* Truncate the copy of name2 at the last '/' */
6312 /* Now go past the '/' */
6316 root1 = talloc_strdup(ctx, pname1);
6317 root2 = talloc_strdup(ctx, pname2);
6319 if (!root1 || !root2) {
6323 p = strrchr_m(root1,'.');
6326 ext1 = talloc_strdup(ctx, p+1);
6328 ext1 = talloc_strdup(ctx, "");
6330 p = strrchr_m(root2,'.');
6333 ext2 = talloc_strdup(ctx, p+1);
6335 ext2 = talloc_strdup(ctx, "");
6338 if (!ext1 || !ext2) {
6346 /* Hmmm. Should this be mb-aware ? */
6349 } else if (*p2 == '*') {
6351 root2 = talloc_asprintf(ctx, "%s%s",
6370 /* Hmmm. Should this be mb-aware ? */
6373 } else if (*p2 == '*') {
6375 ext2 = talloc_asprintf(ctx, "%s%s",
6391 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6396 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6408 /****************************************************************************
6409 Ensure open files have their names updated. Updated to notify other smbd's
6411 ****************************************************************************/
6413 static void rename_open_files(connection_struct *conn,
6414 struct share_mode_lock *lck,
6416 uint32_t orig_name_hash,
6417 const struct smb_filename *smb_fname_dst)
6420 bool did_rename = False;
6422 uint32_t new_name_hash = 0;
6424 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6425 fsp = file_find_di_next(fsp)) {
6426 /* fsp_name is a relative path under the fsp. To change this for other
6427 sharepaths we need to manipulate relative paths. */
6428 /* TODO - create the absolute path and manipulate the newname
6429 relative to the sharepath. */
6430 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6433 if (fsp->name_hash != orig_name_hash) {
6436 DEBUG(10, ("rename_open_files: renaming file %s "
6437 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6438 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6439 smb_fname_str_dbg(smb_fname_dst)));
6441 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6442 if (NT_STATUS_IS_OK(status)) {
6444 new_name_hash = fsp->name_hash;
6449 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6450 "for %s\n", file_id_string_tos(&id),
6451 smb_fname_str_dbg(smb_fname_dst)));
6454 /* Send messages to all smbd's (not ourself) that the name has changed. */
6455 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6456 orig_name_hash, new_name_hash,
6461 /****************************************************************************
6462 We need to check if the source path is a parent directory of the destination
6463 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6464 refuse the rename with a sharing violation. Under UNIX the above call can
6465 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6466 probably need to check that the client is a Windows one before disallowing
6467 this as a UNIX client (one with UNIX extensions) can know the source is a
6468 symlink and make this decision intelligently. Found by an excellent bug
6469 report from <AndyLiebman@aol.com>.
6470 ****************************************************************************/
6472 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6473 const struct smb_filename *smb_fname_dst)
6475 const char *psrc = smb_fname_src->base_name;
6476 const char *pdst = smb_fname_dst->base_name;
6479 if (psrc[0] == '.' && psrc[1] == '/') {
6482 if (pdst[0] == '.' && pdst[1] == '/') {
6485 if ((slen = strlen(psrc)) > strlen(pdst)) {
6488 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6492 * Do the notify calls from a rename
6495 static void notify_rename(connection_struct *conn, bool is_dir,
6496 const struct smb_filename *smb_fname_src,
6497 const struct smb_filename *smb_fname_dst)
6499 char *parent_dir_src = NULL;
6500 char *parent_dir_dst = NULL;
6503 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6504 : FILE_NOTIFY_CHANGE_FILE_NAME;
6506 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6507 &parent_dir_src, NULL) ||
6508 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6509 &parent_dir_dst, NULL)) {
6513 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6514 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6515 smb_fname_src->base_name);
6516 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6517 smb_fname_dst->base_name);
6520 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6521 smb_fname_src->base_name);
6522 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6523 smb_fname_dst->base_name);
6526 /* this is a strange one. w2k3 gives an additional event for
6527 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6528 files, but not directories */
6530 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6531 FILE_NOTIFY_CHANGE_ATTRIBUTES
6532 |FILE_NOTIFY_CHANGE_CREATION,
6533 smb_fname_dst->base_name);
6536 TALLOC_FREE(parent_dir_src);
6537 TALLOC_FREE(parent_dir_dst);
6540 /****************************************************************************
6541 Returns an error if the parent directory for a filename is open in an
6543 ****************************************************************************/
6545 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6546 const struct smb_filename *smb_fname_dst_in)
6548 char *parent_dir = NULL;
6549 struct smb_filename smb_fname_parent;
6551 files_struct *fsp = NULL;
6554 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6555 &parent_dir, NULL)) {
6556 return NT_STATUS_NO_MEMORY;
6558 ZERO_STRUCT(smb_fname_parent);
6559 smb_fname_parent.base_name = parent_dir;
6561 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6563 return map_nt_error_from_unix(errno);
6567 * We're only checking on this smbd here, mostly good
6568 * enough.. and will pass tests.
6571 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6572 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6573 fsp = file_find_di_next(fsp)) {
6574 if (fsp->access_mask & DELETE_ACCESS) {
6575 return NT_STATUS_SHARING_VIOLATION;
6578 return NT_STATUS_OK;
6581 /****************************************************************************
6582 Rename an open file - given an fsp.
6583 ****************************************************************************/
6585 NTSTATUS rename_internals_fsp(connection_struct *conn,
6587 const struct smb_filename *smb_fname_dst_in,
6589 bool replace_if_exists)
6591 TALLOC_CTX *ctx = talloc_tos();
6592 struct smb_filename *smb_fname_dst = NULL;
6593 NTSTATUS status = NT_STATUS_OK;
6594 struct share_mode_lock *lck = NULL;
6595 bool dst_exists, old_is_stream, new_is_stream;
6597 status = check_name(conn, smb_fname_dst_in->base_name);
6598 if (!NT_STATUS_IS_OK(status)) {
6602 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6603 if (!NT_STATUS_IS_OK(status)) {
6607 /* Make a copy of the dst smb_fname structs */
6609 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6610 if (smb_fname_dst == NULL) {
6611 status = NT_STATUS_NO_MEMORY;
6616 * Check for special case with case preserving and not
6617 * case sensitive. If the new last component differs from the original
6618 * last component only by case, then we should allow
6619 * the rename (user is trying to change the case of the
6622 if (!conn->case_sensitive && conn->case_preserve &&
6623 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6624 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6625 char *fname_dst_parent = NULL;
6626 const char *fname_dst_lcomp = NULL;
6627 char *orig_lcomp_path = NULL;
6628 char *orig_lcomp_stream = NULL;
6632 * Split off the last component of the processed
6633 * destination name. We will compare this to
6634 * the split components of smb_fname_dst->original_lcomp.
6636 if (!parent_dirname(ctx,
6637 smb_fname_dst->base_name,
6639 &fname_dst_lcomp)) {
6640 status = NT_STATUS_NO_MEMORY;
6645 * The original_lcomp component contains
6646 * the last_component of the path + stream
6647 * name (if a stream exists).
6649 * Split off the stream name so we
6650 * can check them separately.
6653 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6654 /* POSIX - no stream component. */
6655 orig_lcomp_path = talloc_strdup(ctx,
6656 smb_fname_dst->original_lcomp);
6657 if (orig_lcomp_path == NULL) {
6661 ok = split_stream_filename(ctx,
6662 smb_fname_dst->original_lcomp,
6664 &orig_lcomp_stream);
6668 TALLOC_FREE(fname_dst_parent);
6669 status = NT_STATUS_NO_MEMORY;
6673 /* If the base names only differ by case, use original. */
6674 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6677 * Replace the modified last component with the
6680 if (!ISDOT(fname_dst_parent)) {
6681 tmp = talloc_asprintf(smb_fname_dst,
6686 tmp = talloc_strdup(smb_fname_dst,
6690 status = NT_STATUS_NO_MEMORY;
6691 TALLOC_FREE(fname_dst_parent);
6692 TALLOC_FREE(orig_lcomp_path);
6693 TALLOC_FREE(orig_lcomp_stream);
6696 TALLOC_FREE(smb_fname_dst->base_name);
6697 smb_fname_dst->base_name = tmp;
6700 /* If the stream_names only differ by case, use original. */
6701 if(!strcsequal(smb_fname_dst->stream_name,
6702 orig_lcomp_stream)) {
6703 /* Use the original stream. */
6704 char *tmp = talloc_strdup(smb_fname_dst,
6707 status = NT_STATUS_NO_MEMORY;
6708 TALLOC_FREE(fname_dst_parent);
6709 TALLOC_FREE(orig_lcomp_path);
6710 TALLOC_FREE(orig_lcomp_stream);
6713 TALLOC_FREE(smb_fname_dst->stream_name);
6714 smb_fname_dst->stream_name = tmp;
6716 TALLOC_FREE(fname_dst_parent);
6717 TALLOC_FREE(orig_lcomp_path);
6718 TALLOC_FREE(orig_lcomp_stream);
6722 * If the src and dest names are identical - including case,
6723 * don't do the rename, just return success.
6726 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6727 strcsequal(fsp->fsp_name->stream_name,
6728 smb_fname_dst->stream_name)) {
6729 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6730 "- returning success\n",
6731 smb_fname_str_dbg(smb_fname_dst)));
6732 status = NT_STATUS_OK;
6736 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6737 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6739 /* Return the correct error code if both names aren't streams. */
6740 if (!old_is_stream && new_is_stream) {
6741 status = NT_STATUS_OBJECT_NAME_INVALID;
6745 if (old_is_stream && !new_is_stream) {
6746 status = NT_STATUS_INVALID_PARAMETER;
6750 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6752 if(!replace_if_exists && dst_exists) {
6753 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6754 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6755 smb_fname_str_dbg(smb_fname_dst)));
6756 status = NT_STATUS_OBJECT_NAME_COLLISION;
6761 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6762 &smb_fname_dst->st);
6763 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6765 /* The file can be open when renaming a stream */
6766 if (dst_fsp && !new_is_stream) {
6767 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6768 status = NT_STATUS_ACCESS_DENIED;
6773 /* Ensure we have a valid stat struct for the source. */
6774 status = vfs_stat_fsp(fsp);
6775 if (!NT_STATUS_IS_OK(status)) {
6779 status = can_rename(conn, fsp, attrs);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6783 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6784 smb_fname_str_dbg(smb_fname_dst)));
6785 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6786 status = NT_STATUS_ACCESS_DENIED;
6790 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6791 status = NT_STATUS_ACCESS_DENIED;
6794 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6797 * We have the file open ourselves, so not being able to get the
6798 * corresponding share mode lock is a fatal error.
6801 SMB_ASSERT(lck != NULL);
6803 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6804 uint32_t create_options = fsp->fh->private_options;
6806 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6807 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6808 smb_fname_str_dbg(smb_fname_dst)));
6810 if (!fsp->is_directory &&
6811 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6812 (lp_map_archive(SNUM(conn)) ||
6813 lp_store_dos_attributes(SNUM(conn)))) {
6814 /* We must set the archive bit on the newly
6816 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6817 uint32_t old_dosmode = dos_mode(conn,
6819 file_set_dosmode(conn,
6821 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6827 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6830 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6834 * A rename acts as a new file create w.r.t. allowing an initial delete
6835 * on close, probably because in Windows there is a new handle to the
6836 * new file. If initial delete on close was requested but not
6837 * originally set, we need to set it here. This is probably not 100% correct,
6838 * but will work for the CIFSFS client which in non-posix mode
6839 * depends on these semantics. JRA.
6842 if (create_options & FILE_DELETE_ON_CLOSE) {
6843 status = can_set_delete_on_close(fsp, 0);
6845 if (NT_STATUS_IS_OK(status)) {
6846 /* Note that here we set the *inital* delete on close flag,
6847 * not the regular one. The magic gets handled in close. */
6848 fsp->initial_delete_on_close = True;
6852 status = NT_STATUS_OK;
6858 if (errno == ENOTDIR || errno == EISDIR) {
6859 status = NT_STATUS_OBJECT_NAME_COLLISION;
6861 status = map_nt_error_from_unix(errno);
6864 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6865 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6866 smb_fname_str_dbg(smb_fname_dst)));
6869 TALLOC_FREE(smb_fname_dst);
6874 /****************************************************************************
6875 The guts of the rename command, split out so it may be called by the NT SMB
6877 ****************************************************************************/
6879 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6880 connection_struct *conn,
6881 struct smb_request *req,
6882 struct smb_filename *smb_fname_src,
6883 struct smb_filename *smb_fname_dst,
6885 bool replace_if_exists,
6888 uint32_t access_mask)
6890 char *fname_src_dir = NULL;
6891 struct smb_filename *smb_fname_src_dir = NULL;
6892 char *fname_src_mask = NULL;
6894 NTSTATUS status = NT_STATUS_OK;
6895 struct smb_Dir *dir_hnd = NULL;
6896 const char *dname = NULL;
6897 char *talloced = NULL;
6899 int create_options = 0;
6900 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6904 * Split the old name into directory and last component
6905 * strings. Note that unix_convert may have stripped off a
6906 * leading ./ from both name and newname if the rename is
6907 * at the root of the share. We need to make sure either both
6908 * name and newname contain a / character or neither of them do
6909 * as this is checked in resolve_wildcards().
6912 /* Split up the directory from the filename/mask. */
6913 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6914 &fname_src_dir, &fname_src_mask);
6915 if (!NT_STATUS_IS_OK(status)) {
6916 status = NT_STATUS_NO_MEMORY;
6921 * We should only check the mangled cache
6922 * here if unix_convert failed. This means
6923 * that the path in 'mask' doesn't exist
6924 * on the file system and so we need to look
6925 * for a possible mangle. This patch from
6926 * Tine Smukavec <valentin.smukavec@hermes.si>.
6929 if (!VALID_STAT(smb_fname_src->st) &&
6930 mangle_is_mangled(fname_src_mask, conn->params)) {
6931 char *new_mask = NULL;
6932 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6935 TALLOC_FREE(fname_src_mask);
6936 fname_src_mask = new_mask;
6940 if (!src_has_wild) {
6944 * Only one file needs to be renamed. Append the mask back
6945 * onto the directory.
6947 TALLOC_FREE(smb_fname_src->base_name);
6948 if (ISDOT(fname_src_dir)) {
6949 /* Ensure we use canonical names on open. */
6950 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6954 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6959 if (!smb_fname_src->base_name) {
6960 status = NT_STATUS_NO_MEMORY;
6964 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6965 "case_preserve = %d, short case preserve = %d, "
6966 "directory = %s, newname = %s, "
6967 "last_component_dest = %s\n",
6968 conn->case_sensitive, conn->case_preserve,
6969 conn->short_case_preserve,
6970 smb_fname_str_dbg(smb_fname_src),
6971 smb_fname_str_dbg(smb_fname_dst),
6972 smb_fname_dst->original_lcomp));
6974 /* The dest name still may have wildcards. */
6975 if (dest_has_wild) {
6976 char *fname_dst_mod = NULL;
6977 if (!resolve_wildcards(smb_fname_dst,
6978 smb_fname_src->base_name,
6979 smb_fname_dst->base_name,
6981 DEBUG(6, ("rename_internals: resolve_wildcards "
6983 smb_fname_src->base_name,
6984 smb_fname_dst->base_name));
6985 status = NT_STATUS_NO_MEMORY;
6988 TALLOC_FREE(smb_fname_dst->base_name);
6989 smb_fname_dst->base_name = fname_dst_mod;
6992 ZERO_STRUCT(smb_fname_src->st);
6993 if (posix_pathnames) {
6994 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6996 rc = SMB_VFS_STAT(conn, smb_fname_src);
6999 status = map_nt_error_from_unix_common(errno);
7003 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7004 create_options |= FILE_DIRECTORY_FILE;
7007 status = SMB_VFS_CREATE_FILE(
7010 0, /* root_dir_fid */
7011 smb_fname_src, /* fname */
7012 access_mask, /* access_mask */
7013 (FILE_SHARE_READ | /* share_access */
7015 FILE_OPEN, /* create_disposition*/
7016 create_options, /* create_options */
7017 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7018 0, /* oplock_request */
7020 0, /* allocation_size */
7021 0, /* private_flags */
7026 NULL, NULL); /* create context */
7028 if (!NT_STATUS_IS_OK(status)) {
7029 DEBUG(3, ("Could not open rename source %s: %s\n",
7030 smb_fname_str_dbg(smb_fname_src),
7031 nt_errstr(status)));
7035 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7036 attrs, replace_if_exists);
7038 close_file(req, fsp, NORMAL_CLOSE);
7040 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7041 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7042 smb_fname_str_dbg(smb_fname_dst)));
7048 * Wildcards - process each file that matches.
7050 if (strequal(fname_src_mask, "????????.???")) {
7051 TALLOC_FREE(fname_src_mask);
7052 fname_src_mask = talloc_strdup(ctx, "*");
7053 if (!fname_src_mask) {
7054 status = NT_STATUS_NO_MEMORY;
7059 status = check_name(conn, fname_src_dir);
7060 if (!NT_STATUS_IS_OK(status)) {
7064 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7068 if (smb_fname_src_dir == NULL) {
7069 status = NT_STATUS_NO_MEMORY;
7073 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7075 if (dir_hnd == NULL) {
7076 status = map_nt_error_from_unix(errno);
7080 status = NT_STATUS_NO_SUCH_FILE;
7082 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7083 * - gentest fix. JRA
7086 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7088 files_struct *fsp = NULL;
7089 char *destname = NULL;
7090 bool sysdir_entry = False;
7092 /* Quick check for "." and ".." */
7093 if (ISDOT(dname) || ISDOTDOT(dname)) {
7094 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7095 sysdir_entry = True;
7097 TALLOC_FREE(talloced);
7102 if (!is_visible_file(conn, fname_src_dir, dname,
7103 &smb_fname_src->st, false)) {
7104 TALLOC_FREE(talloced);
7108 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7109 TALLOC_FREE(talloced);
7114 status = NT_STATUS_OBJECT_NAME_INVALID;
7118 TALLOC_FREE(smb_fname_src->base_name);
7119 if (ISDOT(fname_src_dir)) {
7120 /* Ensure we use canonical names on open. */
7121 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7125 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7130 if (!smb_fname_src->base_name) {
7131 status = NT_STATUS_NO_MEMORY;
7135 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7136 smb_fname_dst->base_name,
7138 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7139 smb_fname_src->base_name, destname));
7140 TALLOC_FREE(talloced);
7144 status = NT_STATUS_NO_MEMORY;
7148 TALLOC_FREE(smb_fname_dst->base_name);
7149 smb_fname_dst->base_name = destname;
7151 ZERO_STRUCT(smb_fname_src->st);
7152 if (posix_pathnames) {
7153 SMB_VFS_LSTAT(conn, smb_fname_src);
7155 SMB_VFS_STAT(conn, smb_fname_src);
7160 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7161 create_options |= FILE_DIRECTORY_FILE;
7164 status = SMB_VFS_CREATE_FILE(
7167 0, /* root_dir_fid */
7168 smb_fname_src, /* fname */
7169 access_mask, /* access_mask */
7170 (FILE_SHARE_READ | /* share_access */
7172 FILE_OPEN, /* create_disposition*/
7173 create_options, /* create_options */
7174 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7175 0, /* oplock_request */
7177 0, /* allocation_size */
7178 0, /* private_flags */
7183 NULL, NULL); /* create context */
7185 if (!NT_STATUS_IS_OK(status)) {
7186 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7187 "returned %s rename %s -> %s\n",
7189 smb_fname_str_dbg(smb_fname_src),
7190 smb_fname_str_dbg(smb_fname_dst)));
7194 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7196 if (!smb_fname_dst->original_lcomp) {
7197 status = NT_STATUS_NO_MEMORY;
7201 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7202 attrs, replace_if_exists);
7204 close_file(req, fsp, NORMAL_CLOSE);
7206 if (!NT_STATUS_IS_OK(status)) {
7207 DEBUG(3, ("rename_internals_fsp returned %s for "
7208 "rename %s -> %s\n", nt_errstr(status),
7209 smb_fname_str_dbg(smb_fname_src),
7210 smb_fname_str_dbg(smb_fname_dst)));
7216 DEBUG(3,("rename_internals: doing rename on %s -> "
7217 "%s\n", smb_fname_str_dbg(smb_fname_src),
7218 smb_fname_str_dbg(smb_fname_src)));
7219 TALLOC_FREE(talloced);
7221 TALLOC_FREE(dir_hnd);
7223 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7224 status = map_nt_error_from_unix(errno);
7228 TALLOC_FREE(talloced);
7229 TALLOC_FREE(smb_fname_src_dir);
7230 TALLOC_FREE(fname_src_dir);
7231 TALLOC_FREE(fname_src_mask);
7235 /****************************************************************************
7237 ****************************************************************************/
7239 void reply_mv(struct smb_request *req)
7241 connection_struct *conn = req->conn;
7243 char *newname = NULL;
7247 bool src_has_wcard = False;
7248 bool dest_has_wcard = False;
7249 TALLOC_CTX *ctx = talloc_tos();
7250 struct smb_filename *smb_fname_src = NULL;
7251 struct smb_filename *smb_fname_dst = NULL;
7252 uint32_t src_ucf_flags = (req->posix_pathnames ?
7253 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7254 UCF_COND_ALLOW_WCARD_LCOMP);
7255 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7256 (req->posix_pathnames ? UCF_POSIX_PATHNAMES :
7257 UCF_COND_ALLOW_WCARD_LCOMP);
7258 bool stream_rename = false;
7260 START_PROFILE(SMBmv);
7263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7267 attrs = SVAL(req->vwv+0, 0);
7269 p = (const char *)req->buf + 1;
7270 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7271 &status, &src_has_wcard);
7272 if (!NT_STATUS_IS_OK(status)) {
7273 reply_nterror(req, status);
7277 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7278 &status, &dest_has_wcard);
7279 if (!NT_STATUS_IS_OK(status)) {
7280 reply_nterror(req, status);
7284 if (!req->posix_pathnames) {
7285 /* The newname must begin with a ':' if the
7286 name contains a ':'. */
7287 if (strchr_m(name, ':')) {
7288 if (newname[0] != ':') {
7289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7292 stream_rename = true;
7296 status = filename_convert(ctx,
7298 req->flags2 & FLAGS2_DFS_PATHNAMES,
7304 if (!NT_STATUS_IS_OK(status)) {
7305 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7306 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7307 ERRSRV, ERRbadpath);
7310 reply_nterror(req, status);
7314 status = filename_convert(ctx,
7316 req->flags2 & FLAGS2_DFS_PATHNAMES,
7322 if (!NT_STATUS_IS_OK(status)) {
7323 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7324 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7325 ERRSRV, ERRbadpath);
7328 reply_nterror(req, status);
7332 if (stream_rename) {
7333 /* smb_fname_dst->base_name must be the same as
7334 smb_fname_src->base_name. */
7335 TALLOC_FREE(smb_fname_dst->base_name);
7336 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7337 smb_fname_src->base_name);
7338 if (!smb_fname_dst->base_name) {
7339 reply_nterror(req, NT_STATUS_NO_MEMORY);
7344 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7345 smb_fname_str_dbg(smb_fname_dst)));
7347 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7348 attrs, False, src_has_wcard, dest_has_wcard,
7350 if (!NT_STATUS_IS_OK(status)) {
7351 if (open_was_deferred(req->xconn, req->mid)) {
7352 /* We have re-scheduled this call. */
7355 reply_nterror(req, status);
7359 reply_outbuf(req, 0, 0);
7361 TALLOC_FREE(smb_fname_src);
7362 TALLOC_FREE(smb_fname_dst);
7367 /*******************************************************************
7368 Copy a file as part of a reply_copy.
7369 ******************************************************************/
7372 * TODO: check error codes on all callers
7375 NTSTATUS copy_file(TALLOC_CTX *ctx,
7376 connection_struct *conn,
7377 struct smb_filename *smb_fname_src,
7378 struct smb_filename *smb_fname_dst,
7381 bool target_is_directory)
7383 struct smb_filename *smb_fname_dst_tmp = NULL;
7385 files_struct *fsp1,*fsp2;
7387 uint32_t new_create_disposition;
7391 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7392 if (smb_fname_dst_tmp == NULL) {
7393 return NT_STATUS_NO_MEMORY;
7397 * If the target is a directory, extract the last component from the
7398 * src filename and append it to the dst filename
7400 if (target_is_directory) {
7403 /* dest/target can't be a stream if it's a directory. */
7404 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7406 p = strrchr_m(smb_fname_src->base_name,'/');
7410 p = smb_fname_src->base_name;
7412 smb_fname_dst_tmp->base_name =
7413 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7415 if (!smb_fname_dst_tmp->base_name) {
7416 status = NT_STATUS_NO_MEMORY;
7421 status = vfs_file_exist(conn, smb_fname_src);
7422 if (!NT_STATUS_IS_OK(status)) {
7426 if (!target_is_directory && count) {
7427 new_create_disposition = FILE_OPEN;
7429 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7432 &new_create_disposition,
7435 status = NT_STATUS_INVALID_PARAMETER;
7440 /* Open the src file for reading. */
7441 status = SMB_VFS_CREATE_FILE(
7444 0, /* root_dir_fid */
7445 smb_fname_src, /* fname */
7446 FILE_GENERIC_READ, /* access_mask */
7447 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7448 FILE_OPEN, /* create_disposition*/
7449 0, /* create_options */
7450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7451 INTERNAL_OPEN_ONLY, /* oplock_request */
7453 0, /* allocation_size */
7454 0, /* private_flags */
7459 NULL, NULL); /* create context */
7461 if (!NT_STATUS_IS_OK(status)) {
7465 dosattrs = dos_mode(conn, smb_fname_src);
7467 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7468 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7471 /* Open the dst file for writing. */
7472 status = SMB_VFS_CREATE_FILE(
7475 0, /* root_dir_fid */
7476 smb_fname_dst, /* fname */
7477 FILE_GENERIC_WRITE, /* access_mask */
7478 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7479 new_create_disposition, /* create_disposition*/
7480 0, /* create_options */
7481 dosattrs, /* file_attributes */
7482 INTERNAL_OPEN_ONLY, /* oplock_request */
7484 0, /* allocation_size */
7485 0, /* private_flags */
7490 NULL, NULL); /* create context */
7492 if (!NT_STATUS_IS_OK(status)) {
7493 close_file(NULL, fsp1, ERROR_CLOSE);
7497 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7498 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7500 DEBUG(0, ("error - vfs lseek returned error %s\n",
7502 status = map_nt_error_from_unix(errno);
7503 close_file(NULL, fsp1, ERROR_CLOSE);
7504 close_file(NULL, fsp2, ERROR_CLOSE);
7509 /* Do the actual copy. */
7510 if (smb_fname_src->st.st_ex_size) {
7511 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7516 close_file(NULL, fsp1, NORMAL_CLOSE);
7518 /* Ensure the modtime is set correctly on the destination file. */
7519 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7522 * As we are opening fsp1 read-only we only expect
7523 * an error on close on fsp2 if we are out of space.
7524 * Thus we don't look at the error return from the
7527 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7529 if (!NT_STATUS_IS_OK(status)) {
7533 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7534 status = NT_STATUS_DISK_FULL;
7538 status = NT_STATUS_OK;
7541 TALLOC_FREE(smb_fname_dst_tmp);
7545 /****************************************************************************
7546 Reply to a file copy.
7547 ****************************************************************************/
7549 void reply_copy(struct smb_request *req)
7551 connection_struct *conn = req->conn;
7552 struct smb_filename *smb_fname_src = NULL;
7553 struct smb_filename *smb_fname_src_dir = NULL;
7554 struct smb_filename *smb_fname_dst = NULL;
7555 char *fname_src = NULL;
7556 char *fname_dst = NULL;
7557 char *fname_src_mask = NULL;
7558 char *fname_src_dir = NULL;
7561 int error = ERRnoaccess;
7565 bool target_is_directory=False;
7566 bool source_has_wild = False;
7567 bool dest_has_wild = False;
7569 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7570 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7571 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7572 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7573 TALLOC_CTX *ctx = talloc_tos();
7575 START_PROFILE(SMBcopy);
7578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7582 tid2 = SVAL(req->vwv+0, 0);
7583 ofun = SVAL(req->vwv+1, 0);
7584 flags = SVAL(req->vwv+2, 0);
7586 p = (const char *)req->buf;
7587 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7588 &status, &source_has_wild);
7589 if (!NT_STATUS_IS_OK(status)) {
7590 reply_nterror(req, status);
7593 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7594 &status, &dest_has_wild);
7595 if (!NT_STATUS_IS_OK(status)) {
7596 reply_nterror(req, status);
7600 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7602 if (tid2 != conn->cnum) {
7603 /* can't currently handle inter share copies XXXX */
7604 DEBUG(3,("Rejecting inter-share copy\n"));
7605 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7609 status = filename_convert(ctx, conn,
7610 req->flags2 & FLAGS2_DFS_PATHNAMES,
7615 if (!NT_STATUS_IS_OK(status)) {
7616 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7617 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7618 ERRSRV, ERRbadpath);
7621 reply_nterror(req, status);
7625 status = filename_convert(ctx, conn,
7626 req->flags2 & FLAGS2_DFS_PATHNAMES,
7631 if (!NT_STATUS_IS_OK(status)) {
7632 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7633 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7634 ERRSRV, ERRbadpath);
7637 reply_nterror(req, status);
7641 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7643 if ((flags&1) && target_is_directory) {
7644 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7648 if ((flags&2) && !target_is_directory) {
7649 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7653 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7654 /* wants a tree copy! XXXX */
7655 DEBUG(3,("Rejecting tree copy\n"));
7656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7660 /* Split up the directory from the filename/mask. */
7661 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7662 &fname_src_dir, &fname_src_mask);
7663 if (!NT_STATUS_IS_OK(status)) {
7664 reply_nterror(req, NT_STATUS_NO_MEMORY);
7669 * We should only check the mangled cache
7670 * here if unix_convert failed. This means
7671 * that the path in 'mask' doesn't exist
7672 * on the file system and so we need to look
7673 * for a possible mangle. This patch from
7674 * Tine Smukavec <valentin.smukavec@hermes.si>.
7676 if (!VALID_STAT(smb_fname_src->st) &&
7677 mangle_is_mangled(fname_src_mask, conn->params)) {
7678 char *new_mask = NULL;
7679 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7680 &new_mask, conn->params);
7682 /* Use demangled name if one was successfully found. */
7684 TALLOC_FREE(fname_src_mask);
7685 fname_src_mask = new_mask;
7689 if (!source_has_wild) {
7692 * Only one file needs to be copied. Append the mask back onto
7695 TALLOC_FREE(smb_fname_src->base_name);
7696 if (ISDOT(fname_src_dir)) {
7697 /* Ensure we use canonical names on open. */
7698 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7702 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7707 if (!smb_fname_src->base_name) {
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7712 if (dest_has_wild) {
7713 char *fname_dst_mod = NULL;
7714 if (!resolve_wildcards(smb_fname_dst,
7715 smb_fname_src->base_name,
7716 smb_fname_dst->base_name,
7718 reply_nterror(req, NT_STATUS_NO_MEMORY);
7721 TALLOC_FREE(smb_fname_dst->base_name);
7722 smb_fname_dst->base_name = fname_dst_mod;
7725 status = check_name(conn, smb_fname_src->base_name);
7726 if (!NT_STATUS_IS_OK(status)) {
7727 reply_nterror(req, status);
7731 status = check_name(conn, smb_fname_dst->base_name);
7732 if (!NT_STATUS_IS_OK(status)) {
7733 reply_nterror(req, status);
7737 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7738 ofun, count, target_is_directory);
7740 if(!NT_STATUS_IS_OK(status)) {
7741 reply_nterror(req, status);
7747 struct smb_Dir *dir_hnd = NULL;
7748 const char *dname = NULL;
7749 char *talloced = NULL;
7753 * There is a wildcard that requires us to actually read the
7754 * src dir and copy each file matching the mask to the dst.
7755 * Right now streams won't be copied, but this could
7756 * presumably be added with a nested loop for reach dir entry.
7758 SMB_ASSERT(!smb_fname_src->stream_name);
7759 SMB_ASSERT(!smb_fname_dst->stream_name);
7761 smb_fname_src->stream_name = NULL;
7762 smb_fname_dst->stream_name = NULL;
7764 if (strequal(fname_src_mask,"????????.???")) {
7765 TALLOC_FREE(fname_src_mask);
7766 fname_src_mask = talloc_strdup(ctx, "*");
7767 if (!fname_src_mask) {
7768 reply_nterror(req, NT_STATUS_NO_MEMORY);
7773 status = check_name(conn, fname_src_dir);
7774 if (!NT_STATUS_IS_OK(status)) {
7775 reply_nterror(req, status);
7779 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7783 if (smb_fname_src_dir == NULL) {
7784 reply_nterror(req, NT_STATUS_NO_MEMORY);
7788 dir_hnd = OpenDir(ctx,
7793 if (dir_hnd == NULL) {
7794 status = map_nt_error_from_unix(errno);
7795 reply_nterror(req, status);
7801 /* Iterate over the src dir copying each entry to the dst. */
7802 while ((dname = ReadDirName(dir_hnd, &offset,
7803 &smb_fname_src->st, &talloced))) {
7804 char *destname = NULL;
7806 if (ISDOT(dname) || ISDOTDOT(dname)) {
7807 TALLOC_FREE(talloced);
7811 if (!is_visible_file(conn, fname_src_dir, dname,
7812 &smb_fname_src->st, false)) {
7813 TALLOC_FREE(talloced);
7817 if(!mask_match(dname, fname_src_mask,
7818 conn->case_sensitive)) {
7819 TALLOC_FREE(talloced);
7823 error = ERRnoaccess;
7825 /* Get the src smb_fname struct setup. */
7826 TALLOC_FREE(smb_fname_src->base_name);
7827 if (ISDOT(fname_src_dir)) {
7828 /* Ensure we use canonical names on open. */
7829 smb_fname_src->base_name =
7830 talloc_asprintf(smb_fname_src, "%s",
7833 smb_fname_src->base_name =
7834 talloc_asprintf(smb_fname_src, "%s/%s",
7835 fname_src_dir, dname);
7838 if (!smb_fname_src->base_name) {
7839 TALLOC_FREE(dir_hnd);
7840 TALLOC_FREE(talloced);
7841 reply_nterror(req, NT_STATUS_NO_MEMORY);
7845 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7846 smb_fname_dst->base_name,
7848 TALLOC_FREE(talloced);
7852 TALLOC_FREE(dir_hnd);
7853 TALLOC_FREE(talloced);
7854 reply_nterror(req, NT_STATUS_NO_MEMORY);
7858 TALLOC_FREE(smb_fname_dst->base_name);
7859 smb_fname_dst->base_name = destname;
7861 status = check_name(conn, smb_fname_src->base_name);
7862 if (!NT_STATUS_IS_OK(status)) {
7863 TALLOC_FREE(dir_hnd);
7864 TALLOC_FREE(talloced);
7865 reply_nterror(req, status);
7869 status = check_name(conn, smb_fname_dst->base_name);
7870 if (!NT_STATUS_IS_OK(status)) {
7871 TALLOC_FREE(dir_hnd);
7872 TALLOC_FREE(talloced);
7873 reply_nterror(req, status);
7877 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7878 smb_fname_src->base_name,
7879 smb_fname_dst->base_name));
7881 status = copy_file(ctx, conn, smb_fname_src,
7882 smb_fname_dst, ofun, count,
7883 target_is_directory);
7884 if (NT_STATUS_IS_OK(status)) {
7888 TALLOC_FREE(talloced);
7890 TALLOC_FREE(dir_hnd);
7894 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7898 reply_outbuf(req, 1, 0);
7899 SSVAL(req->outbuf,smb_vwv0,count);
7901 TALLOC_FREE(smb_fname_src);
7902 TALLOC_FREE(smb_fname_src_dir);
7903 TALLOC_FREE(smb_fname_dst);
7904 TALLOC_FREE(fname_src);
7905 TALLOC_FREE(fname_dst);
7906 TALLOC_FREE(fname_src_mask);
7907 TALLOC_FREE(fname_src_dir);
7909 END_PROFILE(SMBcopy);
7914 #define DBGC_CLASS DBGC_LOCKING
7916 /****************************************************************************
7917 Get a lock pid, dealing with large count requests.
7918 ****************************************************************************/
7920 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7921 bool large_file_format)
7923 if(!large_file_format)
7924 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7926 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7929 /****************************************************************************
7930 Get a lock count, dealing with large count requests.
7931 ****************************************************************************/
7933 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7934 bool large_file_format)
7938 if(!large_file_format) {
7939 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7942 * No BVAL, this is reversed!
7944 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7945 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7951 /****************************************************************************
7952 Get a lock offset, dealing with large offset requests.
7953 ****************************************************************************/
7955 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7956 bool large_file_format)
7958 uint64_t offset = 0;
7960 if(!large_file_format) {
7961 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7964 * No BVAL, this is reversed!
7966 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7967 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7973 NTSTATUS smbd_do_locking(struct smb_request *req,
7978 struct smbd_lock_element *locks,
7981 connection_struct *conn = req->conn;
7983 NTSTATUS status = NT_STATUS_OK;
7987 /* Setup the timeout in seconds. */
7989 if (!lp_blocking_locks(SNUM(conn))) {
7993 for(i = 0; i < (int)num_locks; i++) {
7994 struct smbd_lock_element *e = &locks[i];
7996 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7997 "%llu, file %s timeout = %d\n",
8000 (unsigned long long)e->smblctx,
8004 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8005 struct blocking_lock_record *blr = NULL;
8007 if (num_locks > 1) {
8009 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8010 * if the lock vector contains one entry. When given multiple cancel
8011 * requests in a single PDU we expect the server to return an
8012 * error. Windows servers seem to accept the request but only
8013 * cancel the first lock.
8014 * JRA - Do what Windows does (tm) :-).
8018 /* MS-CIFS (2.2.4.32.1) behavior. */
8019 return NT_STATUS_DOS(ERRDOS,
8020 ERRcancelviolation);
8022 /* Windows behavior. */
8024 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8025 "cancel request\n"));
8031 if (lp_blocking_locks(SNUM(conn))) {
8033 /* Schedule a message to ourselves to
8034 remove the blocking lock record and
8035 return the right error. */
8037 blr = blocking_lock_cancel_smb1(fsp,
8043 NT_STATUS_FILE_LOCK_CONFLICT);
8045 return NT_STATUS_DOS(
8047 ERRcancelviolation);
8050 /* Remove a matching pending lock. */
8051 status = do_lock_cancel(fsp,
8057 bool blocking_lock = timeout ? true : false;
8058 bool defer_lock = false;
8059 struct byte_range_lock *br_lck;
8060 uint64_t block_smblctx;
8062 br_lck = do_lock(req->sconn->msg_ctx,
8073 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8074 /* Windows internal resolution for blocking locks seems
8075 to be about 200ms... Don't wait for less than that. JRA. */
8076 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8077 timeout = lp_lock_spin_time();
8082 /* If a lock sent with timeout of zero would fail, and
8083 * this lock has been requested multiple times,
8084 * according to brl_lock_failed() we convert this
8085 * request to a blocking lock with a timeout of between
8086 * 150 - 300 milliseconds.
8088 * If lp_lock_spin_time() has been set to 0, we skip
8089 * this blocking retry and fail immediately.
8091 * Replacement for do_lock_spin(). JRA. */
8093 if (!req->sconn->using_smb2 &&
8094 br_lck && lp_blocking_locks(SNUM(conn)) &&
8095 lp_lock_spin_time() && !blocking_lock &&
8096 NT_STATUS_EQUAL((status),
8097 NT_STATUS_FILE_LOCK_CONFLICT))
8100 timeout = lp_lock_spin_time();
8103 if (br_lck && defer_lock) {
8105 * A blocking lock was requested. Package up
8106 * this smb into a queued request and push it
8107 * onto the blocking lock queue.
8109 if(push_blocking_lock_request(br_lck,
8120 TALLOC_FREE(br_lck);
8122 return NT_STATUS_OK;
8126 TALLOC_FREE(br_lck);
8129 if (!NT_STATUS_IS_OK(status)) {
8134 /* If any of the above locks failed, then we must unlock
8135 all of the previous locks (X/Open spec). */
8137 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8139 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8140 i = -1; /* we want to skip the for loop */
8144 * Ensure we don't do a remove on the lock that just failed,
8145 * as under POSIX rules, if we have a lock already there, we
8146 * will delete it (and we shouldn't) .....
8148 for(i--; i >= 0; i--) {
8149 struct smbd_lock_element *e = &locks[i];
8151 do_unlock(req->sconn->msg_ctx,
8161 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8162 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8164 return NT_STATUS_OK;
8167 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8169 uint16_t num_ulocks,
8170 struct smbd_lock_element *ulocks)
8174 for(i = 0; i < (int)num_ulocks; i++) {
8175 struct smbd_lock_element *e = &ulocks[i];
8178 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8179 "pid %u, file %s\n", __func__,
8182 (unsigned int)e->smblctx,
8185 if (e->brltype != UNLOCK_LOCK) {
8186 /* this can only happen with SMB2 */
8187 return NT_STATUS_INVALID_PARAMETER;
8190 status = do_unlock(req->sconn->msg_ctx,
8197 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8198 nt_errstr(status)));
8200 if (!NT_STATUS_IS_OK(status)) {
8205 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8208 return NT_STATUS_OK;
8211 /****************************************************************************
8212 Reply to a lockingX request.
8213 ****************************************************************************/
8215 void reply_lockingX(struct smb_request *req)
8217 connection_struct *conn = req->conn;
8219 unsigned char locktype;
8220 unsigned char oplocklevel;
8221 uint16_t num_ulocks;
8223 int32_t lock_timeout;
8225 const uint8_t *data;
8226 bool large_file_format;
8227 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8228 struct smbd_lock_element *ulocks;
8229 struct smbd_lock_element *locks;
8232 START_PROFILE(SMBlockingX);
8235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8236 END_PROFILE(SMBlockingX);
8240 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8241 locktype = CVAL(req->vwv+3, 0);
8242 oplocklevel = CVAL(req->vwv+3, 1);
8243 num_ulocks = SVAL(req->vwv+6, 0);
8244 num_locks = SVAL(req->vwv+7, 0);
8245 lock_timeout = IVAL(req->vwv+4, 0);
8246 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8248 if (!check_fsp(conn, req, fsp)) {
8249 END_PROFILE(SMBlockingX);
8255 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8256 /* we don't support these - and CANCEL_LOCK makes w2k
8257 and XP reboot so I don't really want to be
8258 compatible! (tridge) */
8259 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8260 END_PROFILE(SMBlockingX);
8264 /* Check if this is an oplock break on a file
8265 we have granted an oplock on.
8267 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8268 /* Client can insist on breaking to none. */
8269 bool break_to_none = (oplocklevel == 0);
8272 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8273 "for %s\n", (unsigned int)oplocklevel,
8274 fsp_fnum_dbg(fsp)));
8277 * Make sure we have granted an exclusive or batch oplock on
8281 if (fsp->oplock_type == 0) {
8283 /* The Samba4 nbench simulator doesn't understand
8284 the difference between break to level2 and break
8285 to none from level2 - it sends oplock break
8286 replies in both cases. Don't keep logging an error
8287 message here - just ignore it. JRA. */
8289 DEBUG(5,("reply_lockingX: Error : oplock break from "
8290 "client for %s (oplock=%d) and no "
8291 "oplock granted on this file (%s).\n",
8292 fsp_fnum_dbg(fsp), fsp->oplock_type,
8295 /* if this is a pure oplock break request then don't
8297 if (num_locks == 0 && num_ulocks == 0) {
8298 END_PROFILE(SMBlockingX);
8301 END_PROFILE(SMBlockingX);
8302 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8307 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8309 result = remove_oplock(fsp);
8311 result = downgrade_oplock(fsp);
8315 DEBUG(0, ("reply_lockingX: error in removing "
8316 "oplock on file %s\n", fsp_str_dbg(fsp)));
8317 /* Hmmm. Is this panic justified? */
8318 smb_panic("internal tdb error");
8321 /* if this is a pure oplock break request then don't send a
8323 if (num_locks == 0 && num_ulocks == 0) {
8324 /* Sanity check - ensure a pure oplock break is not a
8326 if (CVAL(req->vwv+0, 0) != 0xff) {
8327 DEBUG(0,("reply_lockingX: Error : pure oplock "
8328 "break is a chained %d request !\n",
8329 (unsigned int)CVAL(req->vwv+0, 0)));
8331 END_PROFILE(SMBlockingX);
8337 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8339 END_PROFILE(SMBlockingX);
8343 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8344 if (ulocks == NULL) {
8345 reply_nterror(req, NT_STATUS_NO_MEMORY);
8346 END_PROFILE(SMBlockingX);
8350 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8351 if (locks == NULL) {
8352 reply_nterror(req, NT_STATUS_NO_MEMORY);
8353 END_PROFILE(SMBlockingX);
8357 /* Data now points at the beginning of the list
8358 of smb_unlkrng structs */
8359 for(i = 0; i < (int)num_ulocks; i++) {
8360 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8361 ulocks[i].count = get_lock_count(data, i, large_file_format);
8362 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8363 ulocks[i].brltype = UNLOCK_LOCK;
8366 /* Now do any requested locks */
8367 data += ((large_file_format ? 20 : 10)*num_ulocks);
8369 /* Data now points at the beginning of the list
8370 of smb_lkrng structs */
8372 for(i = 0; i < (int)num_locks; i++) {
8373 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8374 locks[i].count = get_lock_count(data, i, large_file_format);
8375 locks[i].offset = get_lock_offset(data, i, large_file_format);
8377 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8378 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8379 locks[i].brltype = PENDING_READ_LOCK;
8381 locks[i].brltype = READ_LOCK;
8384 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8385 locks[i].brltype = PENDING_WRITE_LOCK;
8387 locks[i].brltype = WRITE_LOCK;
8392 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8393 if (!NT_STATUS_IS_OK(status)) {
8394 END_PROFILE(SMBlockingX);
8395 reply_nterror(req, status);
8399 status = smbd_do_locking(req, fsp,
8400 locktype, lock_timeout,
8403 if (!NT_STATUS_IS_OK(status)) {
8404 END_PROFILE(SMBlockingX);
8405 reply_nterror(req, status);
8409 END_PROFILE(SMBlockingX);
8413 reply_outbuf(req, 2, 0);
8414 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8415 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8417 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8418 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8420 END_PROFILE(SMBlockingX);
8424 #define DBGC_CLASS DBGC_ALL
8426 /****************************************************************************
8427 Reply to a SMBreadbmpx (read block multiplex) request.
8428 Always reply with an error, if someone has a platform really needs this,
8429 please contact vl@samba.org
8430 ****************************************************************************/
8432 void reply_readbmpx(struct smb_request *req)
8434 START_PROFILE(SMBreadBmpx);
8435 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8436 END_PROFILE(SMBreadBmpx);
8440 /****************************************************************************
8441 Reply to a SMBreadbs (read block multiplex secondary) request.
8442 Always reply with an error, if someone has a platform really needs this,
8443 please contact vl@samba.org
8444 ****************************************************************************/
8446 void reply_readbs(struct smb_request *req)
8448 START_PROFILE(SMBreadBs);
8449 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8450 END_PROFILE(SMBreadBs);
8454 /****************************************************************************
8455 Reply to a SMBsetattrE.
8456 ****************************************************************************/
8458 void reply_setattrE(struct smb_request *req)
8460 connection_struct *conn = req->conn;
8461 struct smb_file_time ft;
8465 START_PROFILE(SMBsetattrE);
8469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8473 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8475 if(!fsp || (fsp->conn != conn)) {
8476 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8481 * Convert the DOS times into unix times.
8484 ft.atime = convert_time_t_to_timespec(
8485 srv_make_unix_date2(req->vwv+3));
8486 ft.mtime = convert_time_t_to_timespec(
8487 srv_make_unix_date2(req->vwv+5));
8488 ft.create_time = convert_time_t_to_timespec(
8489 srv_make_unix_date2(req->vwv+1));
8491 reply_outbuf(req, 0, 0);
8494 * Patch from Ray Frush <frush@engr.colostate.edu>
8495 * Sometimes times are sent as zero - ignore them.
8498 /* Ensure we have a valid stat struct for the source. */
8499 status = vfs_stat_fsp(fsp);
8500 if (!NT_STATUS_IS_OK(status)) {
8501 reply_nterror(req, status);
8505 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8506 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8510 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8511 if (!NT_STATUS_IS_OK(status)) {
8512 reply_nterror(req, status);
8516 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8519 (unsigned int)ft.atime.tv_sec,
8520 (unsigned int)ft.mtime.tv_sec,
8521 (unsigned int)ft.create_time.tv_sec
8524 END_PROFILE(SMBsetattrE);
8529 /* Back from the dead for OS/2..... JRA. */
8531 /****************************************************************************
8532 Reply to a SMBwritebmpx (write block multiplex primary) request.
8533 Always reply with an error, if someone has a platform really needs this,
8534 please contact vl@samba.org
8535 ****************************************************************************/
8537 void reply_writebmpx(struct smb_request *req)
8539 START_PROFILE(SMBwriteBmpx);
8540 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8541 END_PROFILE(SMBwriteBmpx);
8545 /****************************************************************************
8546 Reply to a SMBwritebs (write block multiplex secondary) request.
8547 Always reply with an error, if someone has a platform really needs this,
8548 please contact vl@samba.org
8549 ****************************************************************************/
8551 void reply_writebs(struct smb_request *req)
8553 START_PROFILE(SMBwriteBs);
8554 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8555 END_PROFILE(SMBwriteBs);
8559 /****************************************************************************
8560 Reply to a SMBgetattrE.
8561 ****************************************************************************/
8563 void reply_getattrE(struct smb_request *req)
8565 connection_struct *conn = req->conn;
8568 struct timespec create_ts;
8570 START_PROFILE(SMBgetattrE);
8573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8574 END_PROFILE(SMBgetattrE);
8578 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8580 if(!fsp || (fsp->conn != conn)) {
8581 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8582 END_PROFILE(SMBgetattrE);
8586 /* Do an fstat on this file */
8588 reply_nterror(req, map_nt_error_from_unix(errno));
8589 END_PROFILE(SMBgetattrE);
8593 mode = dos_mode(conn, fsp->fsp_name);
8596 * Convert the times into dos times. Set create
8597 * date to be last modify date as UNIX doesn't save
8601 reply_outbuf(req, 11, 0);
8603 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8604 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8605 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8606 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8607 /* Should we check pending modtime here ? JRA */
8608 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8609 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8611 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8612 SIVAL(req->outbuf, smb_vwv6, 0);
8613 SIVAL(req->outbuf, smb_vwv8, 0);
8615 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8616 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8617 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8619 SSVAL(req->outbuf,smb_vwv10, mode);
8621 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8623 END_PROFILE(SMBgetattrE);