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(),
1830 if (smb_dname == NULL) {
1831 reply_nterror(req, NT_STATUS_NO_MEMORY);
1835 nt_status = dptr_create(conn,
1843 mask_contains_wcard,
1847 TALLOC_FREE(smb_dname);
1849 if (!NT_STATUS_IS_OK(nt_status)) {
1850 reply_nterror(req, nt_status);
1853 dptr_num = dptr_dnum(dirptr);
1856 const char *dirpath;
1858 memcpy(status,p,21);
1859 status_dirtype = CVAL(status,0) & 0x1F;
1860 if (status_dirtype != (dirtype & 0x1F)) {
1861 dirtype = status_dirtype;
1864 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1868 dirpath = dptr_path(sconn, dptr_num);
1869 directory = talloc_strdup(ctx, dirpath);
1871 reply_nterror(req, NT_STATUS_NO_MEMORY);
1875 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1880 * For a 'continue' search we have no string. So
1881 * check from the initial saved string.
1883 if (!req->posix_pathnames) {
1884 mask_contains_wcard = ms_has_wild(mask);
1886 dirtype = dptr_attr(sconn, dptr_num);
1889 DEBUG(4,("dptr_num is %d\n",dptr_num));
1891 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1892 dptr_init_search_op(dirptr);
1894 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1895 char buf[DIR_STRUCT_SIZE];
1896 memcpy(buf,status,21);
1897 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1898 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1899 reply_nterror(req, NT_STATUS_NO_MEMORY);
1902 dptr_fill(sconn, buf+12,dptr_num);
1903 if (dptr_zero(buf+12) && (status_len==0)) {
1908 if (message_push_blob(&req->outbuf,
1909 data_blob_const(buf, sizeof(buf)))
1911 reply_nterror(req, NT_STATUS_NO_MEMORY);
1916 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1917 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1919 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1921 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1922 directory,lp_dont_descend(ctx, SNUM(conn))));
1923 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1924 check_descend = True;
1927 for (i=numentries;(i<maxentries) && !finished;i++) {
1928 finished = !get_dir_entry(ctx,
1939 char buf[DIR_STRUCT_SIZE];
1940 memcpy(buf,status,21);
1941 if (!make_dir_struct(ctx,
1947 convert_timespec_to_time_t(date),
1948 !allow_long_path_components)) {
1949 reply_nterror(req, NT_STATUS_NO_MEMORY);
1952 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1955 if (message_push_blob(&req->outbuf,
1956 data_blob_const(buf, sizeof(buf)))
1958 reply_nterror(req, NT_STATUS_NO_MEMORY);
1968 /* If we were called as SMBffirst with smb_search_id == NULL
1969 and no entries were found then return error and close dirptr
1972 if (numentries == 0) {
1973 dptr_close(sconn, &dptr_num);
1974 } else if(expect_close && status_len == 0) {
1975 /* Close the dptr - we know it's gone */
1976 dptr_close(sconn, &dptr_num);
1979 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1980 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1981 dptr_close(sconn, &dptr_num);
1984 if ((numentries == 0) && !mask_contains_wcard) {
1985 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1989 SSVAL(req->outbuf,smb_vwv0,numentries);
1990 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1991 SCVAL(smb_buf(req->outbuf),0,5);
1992 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1994 /* The replies here are never long name. */
1995 SSVAL(req->outbuf, smb_flg2,
1996 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1997 if (!allow_long_path_components) {
1998 SSVAL(req->outbuf, smb_flg2,
1999 SVAL(req->outbuf, smb_flg2)
2000 & (~FLAGS2_LONG_PATH_COMPONENTS));
2003 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2004 SSVAL(req->outbuf, smb_flg2,
2005 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2007 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2008 smb_fn_name(req->cmd),
2015 TALLOC_FREE(directory);
2017 TALLOC_FREE(smb_fname);
2018 END_PROFILE(SMBsearch);
2022 /****************************************************************************
2023 Reply to a fclose (stop directory search).
2024 ****************************************************************************/
2026 void reply_fclose(struct smb_request *req)
2034 bool path_contains_wcard = False;
2035 TALLOC_CTX *ctx = talloc_tos();
2036 struct smbd_server_connection *sconn = req->sconn;
2038 START_PROFILE(SMBfclose);
2040 if (req->posix_pathnames) {
2041 reply_unknown_new(req, req->cmd);
2042 END_PROFILE(SMBfclose);
2046 p = (const char *)req->buf + 1;
2047 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2048 &err, &path_contains_wcard);
2049 if (!NT_STATUS_IS_OK(err)) {
2050 reply_nterror(req, err);
2051 END_PROFILE(SMBfclose);
2055 status_len = SVAL(p,0);
2058 if (status_len == 0) {
2059 reply_force_doserror(req, ERRSRV, ERRsrverror);
2060 END_PROFILE(SMBfclose);
2064 memcpy(status,p,21);
2066 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2067 /* Close the dptr - we know it's gone */
2068 dptr_close(sconn, &dptr_num);
2071 reply_outbuf(req, 1, 0);
2072 SSVAL(req->outbuf,smb_vwv0,0);
2074 DEBUG(3,("search close\n"));
2076 END_PROFILE(SMBfclose);
2080 /****************************************************************************
2082 ****************************************************************************/
2084 void reply_open(struct smb_request *req)
2086 connection_struct *conn = req->conn;
2087 struct smb_filename *smb_fname = NULL;
2097 uint32_t access_mask;
2098 uint32_t share_mode;
2099 uint32_t create_disposition;
2100 uint32_t create_options = 0;
2101 uint32_t private_flags = 0;
2103 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2104 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2105 TALLOC_CTX *ctx = talloc_tos();
2107 START_PROFILE(SMBopen);
2110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2114 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2115 deny_mode = SVAL(req->vwv+0, 0);
2116 dos_attr = SVAL(req->vwv+1, 0);
2118 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2119 STR_TERMINATE, &status);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 reply_nterror(req, status);
2125 if (!map_open_params_to_ntcreate(fname, deny_mode,
2126 OPENX_FILE_EXISTS_OPEN, &access_mask,
2127 &share_mode, &create_disposition,
2128 &create_options, &private_flags)) {
2129 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2133 status = filename_convert(ctx,
2135 req->flags2 & FLAGS2_DFS_PATHNAMES,
2140 if (!NT_STATUS_IS_OK(status)) {
2141 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2142 reply_botherror(req,
2143 NT_STATUS_PATH_NOT_COVERED,
2144 ERRSRV, ERRbadpath);
2147 reply_nterror(req, status);
2151 status = SMB_VFS_CREATE_FILE(
2154 0, /* root_dir_fid */
2155 smb_fname, /* fname */
2156 access_mask, /* access_mask */
2157 share_mode, /* share_access */
2158 create_disposition, /* create_disposition*/
2159 create_options, /* create_options */
2160 dos_attr, /* file_attributes */
2161 oplock_request, /* oplock_request */
2163 0, /* allocation_size */
2169 NULL, NULL); /* create context */
2171 if (!NT_STATUS_IS_OK(status)) {
2172 if (open_was_deferred(req->xconn, req->mid)) {
2173 /* We have re-scheduled this call. */
2176 reply_openerror(req, status);
2180 /* Ensure we're pointing at the correct stat struct. */
2181 TALLOC_FREE(smb_fname);
2182 smb_fname = fsp->fsp_name;
2184 size = smb_fname->st.st_ex_size;
2185 fattr = dos_mode(conn, smb_fname);
2187 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2189 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2190 DEBUG(3,("attempt to open a directory %s\n",
2192 close_file(req, fsp, ERROR_CLOSE);
2193 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2194 ERRDOS, ERRnoaccess);
2198 reply_outbuf(req, 7, 0);
2199 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2200 SSVAL(req->outbuf,smb_vwv1,fattr);
2201 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2202 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2204 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2206 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2207 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2209 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2210 SCVAL(req->outbuf,smb_flg,
2211 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2214 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2215 SCVAL(req->outbuf,smb_flg,
2216 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2219 END_PROFILE(SMBopen);
2223 /****************************************************************************
2224 Reply to an open and X.
2225 ****************************************************************************/
2227 void reply_open_and_X(struct smb_request *req)
2229 connection_struct *conn = req->conn;
2230 struct smb_filename *smb_fname = NULL;
2232 uint16_t open_flags;
2235 /* Breakout the oplock request bits so we can set the
2236 reply bits separately. */
2237 int ex_oplock_request;
2238 int core_oplock_request;
2241 int smb_sattr = SVAL(req->vwv+4, 0);
2242 uint32_t smb_time = make_unix_date3(req->vwv+6);
2250 uint64_t allocation_size;
2251 ssize_t retval = -1;
2252 uint32_t access_mask;
2253 uint32_t share_mode;
2254 uint32_t create_disposition;
2255 uint32_t create_options = 0;
2256 uint32_t private_flags = 0;
2257 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2258 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2259 TALLOC_CTX *ctx = talloc_tos();
2261 START_PROFILE(SMBopenX);
2263 if (req->wct < 15) {
2264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2268 open_flags = SVAL(req->vwv+2, 0);
2269 deny_mode = SVAL(req->vwv+3, 0);
2270 smb_attr = SVAL(req->vwv+5, 0);
2271 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2272 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2273 oplock_request = ex_oplock_request | core_oplock_request;
2274 smb_ofun = SVAL(req->vwv+8, 0);
2275 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2277 /* If it's an IPC, pass off the pipe handler. */
2279 if (lp_nt_pipe_support()) {
2280 reply_open_pipe_and_X(conn, req);
2282 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2287 /* XXXX we need to handle passed times, sattr and flags */
2288 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2289 STR_TERMINATE, &status);
2290 if (!NT_STATUS_IS_OK(status)) {
2291 reply_nterror(req, status);
2295 if (!map_open_params_to_ntcreate(fname, deny_mode,
2297 &access_mask, &share_mode,
2298 &create_disposition,
2301 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2305 status = filename_convert(ctx,
2307 req->flags2 & FLAGS2_DFS_PATHNAMES,
2312 if (!NT_STATUS_IS_OK(status)) {
2313 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2314 reply_botherror(req,
2315 NT_STATUS_PATH_NOT_COVERED,
2316 ERRSRV, ERRbadpath);
2319 reply_nterror(req, status);
2323 status = SMB_VFS_CREATE_FILE(
2326 0, /* root_dir_fid */
2327 smb_fname, /* fname */
2328 access_mask, /* access_mask */
2329 share_mode, /* share_access */
2330 create_disposition, /* create_disposition*/
2331 create_options, /* create_options */
2332 smb_attr, /* file_attributes */
2333 oplock_request, /* oplock_request */
2335 0, /* allocation_size */
2340 &smb_action, /* pinfo */
2341 NULL, NULL); /* create context */
2343 if (!NT_STATUS_IS_OK(status)) {
2344 if (open_was_deferred(req->xconn, req->mid)) {
2345 /* We have re-scheduled this call. */
2348 reply_openerror(req, status);
2352 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2353 if the file is truncated or created. */
2354 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2355 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2356 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2357 close_file(req, fsp, ERROR_CLOSE);
2358 reply_nterror(req, NT_STATUS_DISK_FULL);
2361 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2363 close_file(req, fsp, ERROR_CLOSE);
2364 reply_nterror(req, NT_STATUS_DISK_FULL);
2367 status = vfs_stat_fsp(fsp);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 close_file(req, fsp, ERROR_CLOSE);
2370 reply_nterror(req, status);
2375 fattr = dos_mode(conn, fsp->fsp_name);
2376 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2377 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2378 close_file(req, fsp, ERROR_CLOSE);
2379 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2383 /* If the caller set the extended oplock request bit
2384 and we granted one (by whatever means) - set the
2385 correct bit for extended oplock reply.
2388 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2389 smb_action |= EXTENDED_OPLOCK_GRANTED;
2392 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2393 smb_action |= EXTENDED_OPLOCK_GRANTED;
2396 /* If the caller set the core oplock request bit
2397 and we granted one (by whatever means) - set the
2398 correct bit for core oplock reply.
2401 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2402 reply_outbuf(req, 19, 0);
2404 reply_outbuf(req, 15, 0);
2407 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2408 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2410 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2411 SCVAL(req->outbuf, smb_flg,
2412 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2415 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2416 SCVAL(req->outbuf, smb_flg,
2417 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2420 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2421 SSVAL(req->outbuf,smb_vwv3,fattr);
2422 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2423 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2425 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2427 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2428 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2429 SSVAL(req->outbuf,smb_vwv11,smb_action);
2431 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2432 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2436 TALLOC_FREE(smb_fname);
2437 END_PROFILE(SMBopenX);
2441 /****************************************************************************
2442 Reply to a SMBulogoffX.
2443 ****************************************************************************/
2445 void reply_ulogoffX(struct smb_request *req)
2447 struct smbd_server_connection *sconn = req->sconn;
2448 struct user_struct *vuser;
2449 struct smbXsrv_session *session = NULL;
2452 START_PROFILE(SMBulogoffX);
2454 vuser = get_valid_user_struct(sconn, req->vuid);
2457 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2458 (unsigned long long)req->vuid));
2460 req->vuid = UID_FIELD_INVALID;
2461 reply_force_doserror(req, ERRSRV, ERRbaduid);
2462 END_PROFILE(SMBulogoffX);
2466 session = vuser->session;
2470 * TODO: cancel all outstanding requests on the session
2472 status = smbXsrv_session_logoff(session);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 DEBUG(0, ("reply_ulogoff: "
2475 "smbXsrv_session_logoff() failed: %s\n",
2476 nt_errstr(status)));
2478 * If we hit this case, there is something completely
2479 * wrong, so we better disconnect the transport connection.
2481 END_PROFILE(SMBulogoffX);
2482 exit_server(__location__ ": smbXsrv_session_logoff failed");
2486 TALLOC_FREE(session);
2488 reply_outbuf(req, 2, 0);
2489 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2490 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2492 DEBUG(3, ("ulogoffX vuid=%llu\n",
2493 (unsigned long long)req->vuid));
2495 END_PROFILE(SMBulogoffX);
2496 req->vuid = UID_FIELD_INVALID;
2499 /****************************************************************************
2500 Reply to a mknew or a create.
2501 ****************************************************************************/
2503 void reply_mknew(struct smb_request *req)
2505 connection_struct *conn = req->conn;
2506 struct smb_filename *smb_fname = NULL;
2509 struct smb_file_time ft;
2511 int oplock_request = 0;
2513 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2514 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2515 uint32_t create_disposition;
2516 uint32_t create_options = 0;
2517 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2518 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2519 TALLOC_CTX *ctx = talloc_tos();
2521 START_PROFILE(SMBcreate);
2525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2529 fattr = SVAL(req->vwv+0, 0);
2530 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2533 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2535 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2536 STR_TERMINATE, &status);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 reply_nterror(req, status);
2542 status = filename_convert(ctx,
2544 req->flags2 & FLAGS2_DFS_PATHNAMES,
2549 if (!NT_STATUS_IS_OK(status)) {
2550 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2551 reply_botherror(req,
2552 NT_STATUS_PATH_NOT_COVERED,
2553 ERRSRV, ERRbadpath);
2556 reply_nterror(req, status);
2560 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2561 DEBUG(0,("Attempt to create file (%s) with volid set - "
2562 "please report this\n",
2563 smb_fname_str_dbg(smb_fname)));
2566 if(req->cmd == SMBmknew) {
2567 /* We should fail if file exists. */
2568 create_disposition = FILE_CREATE;
2570 /* Create if file doesn't exist, truncate if it does. */
2571 create_disposition = FILE_OVERWRITE_IF;
2574 status = SMB_VFS_CREATE_FILE(
2577 0, /* root_dir_fid */
2578 smb_fname, /* fname */
2579 access_mask, /* access_mask */
2580 share_mode, /* share_access */
2581 create_disposition, /* create_disposition*/
2582 create_options, /* create_options */
2583 fattr, /* file_attributes */
2584 oplock_request, /* oplock_request */
2586 0, /* allocation_size */
2587 0, /* private_flags */
2592 NULL, NULL); /* create context */
2594 if (!NT_STATUS_IS_OK(status)) {
2595 if (open_was_deferred(req->xconn, req->mid)) {
2596 /* We have re-scheduled this call. */
2599 reply_openerror(req, status);
2603 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2604 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 END_PROFILE(SMBcreate);
2610 reply_outbuf(req, 1, 0);
2611 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2613 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2614 SCVAL(req->outbuf,smb_flg,
2615 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2618 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2619 SCVAL(req->outbuf,smb_flg,
2620 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2623 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2624 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2625 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2626 (unsigned int)fattr));
2629 TALLOC_FREE(smb_fname);
2630 END_PROFILE(SMBcreate);
2634 /****************************************************************************
2635 Reply to a create temporary file.
2636 ****************************************************************************/
2638 void reply_ctemp(struct smb_request *req)
2640 connection_struct *conn = req->conn;
2641 struct smb_filename *smb_fname = NULL;
2642 char *wire_name = NULL;
2650 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2651 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2652 TALLOC_CTX *ctx = talloc_tos();
2654 START_PROFILE(SMBctemp);
2657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2661 fattr = SVAL(req->vwv+0, 0);
2662 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2664 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2665 STR_TERMINATE, &status);
2666 if (!NT_STATUS_IS_OK(status)) {
2667 reply_nterror(req, status);
2671 for (i = 0; i < 10; i++) {
2673 fname = talloc_asprintf(ctx,
2676 generate_random_str_list(ctx, 5, "0123456789"));
2678 fname = talloc_asprintf(ctx,
2680 generate_random_str_list(ctx, 5, "0123456789"));
2684 reply_nterror(req, NT_STATUS_NO_MEMORY);
2688 status = filename_convert(ctx, conn,
2689 req->flags2 & FLAGS2_DFS_PATHNAMES,
2694 if (!NT_STATUS_IS_OK(status)) {
2695 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2696 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2697 ERRSRV, ERRbadpath);
2700 reply_nterror(req, status);
2704 /* Create the file. */
2705 status = SMB_VFS_CREATE_FILE(
2708 0, /* root_dir_fid */
2709 smb_fname, /* fname */
2710 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2711 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2712 FILE_CREATE, /* create_disposition*/
2713 0, /* create_options */
2714 fattr, /* file_attributes */
2715 oplock_request, /* oplock_request */
2717 0, /* allocation_size */
2718 0, /* private_flags */
2723 NULL, NULL); /* create context */
2725 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2727 TALLOC_FREE(smb_fname);
2731 if (!NT_STATUS_IS_OK(status)) {
2732 if (open_was_deferred(req->xconn, req->mid)) {
2733 /* We have re-scheduled this call. */
2736 reply_openerror(req, status);
2744 /* Collision after 10 times... */
2745 reply_nterror(req, status);
2749 reply_outbuf(req, 1, 0);
2750 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2752 /* the returned filename is relative to the directory */
2753 s = strrchr_m(fsp->fsp_name->base_name, '/');
2755 s = fsp->fsp_name->base_name;
2761 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2762 thing in the byte section. JRA */
2763 SSVALS(p, 0, -1); /* what is this? not in spec */
2765 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2767 reply_nterror(req, NT_STATUS_NO_MEMORY);
2771 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2772 SCVAL(req->outbuf, smb_flg,
2773 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2776 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2777 SCVAL(req->outbuf, smb_flg,
2778 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2781 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2782 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2783 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2785 TALLOC_FREE(smb_fname);
2786 TALLOC_FREE(wire_name);
2787 END_PROFILE(SMBctemp);
2791 /*******************************************************************
2792 Check if a user is allowed to rename a file.
2793 ********************************************************************/
2795 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2798 if (!CAN_WRITE(conn)) {
2799 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2802 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2803 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2804 /* Only bother to read the DOS attribute if we might deny the
2805 rename on the grounds of attribute mismatch. */
2806 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2807 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2808 return NT_STATUS_NO_SUCH_FILE;
2812 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2813 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2814 return NT_STATUS_OK;
2817 /* If no pathnames are open below this
2818 directory, allow the rename. */
2820 if (lp_strict_rename(SNUM(conn))) {
2822 * Strict rename, check open file db.
2824 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2825 return NT_STATUS_ACCESS_DENIED;
2827 } else if (file_find_subpath(fsp)) {
2829 * No strict rename, just look in local process.
2831 return NT_STATUS_ACCESS_DENIED;
2833 return NT_STATUS_OK;
2836 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2837 return NT_STATUS_OK;
2840 return NT_STATUS_ACCESS_DENIED;
2843 /*******************************************************************
2844 * unlink a file with all relevant access checks
2845 *******************************************************************/
2847 static NTSTATUS do_unlink(connection_struct *conn,
2848 struct smb_request *req,
2849 struct smb_filename *smb_fname,
2854 uint32_t dirtype_orig = dirtype;
2857 bool posix_paths = (req != NULL && req->posix_pathnames);
2859 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2860 smb_fname_str_dbg(smb_fname),
2863 if (!CAN_WRITE(conn)) {
2864 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2868 ret = SMB_VFS_LSTAT(conn, smb_fname);
2870 ret = SMB_VFS_STAT(conn, smb_fname);
2873 return map_nt_error_from_unix(errno);
2876 fattr = dos_mode(conn, smb_fname);
2878 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2879 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2882 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2884 return NT_STATUS_NO_SUCH_FILE;
2887 if (!dir_check_ftype(fattr, dirtype)) {
2888 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2889 return NT_STATUS_FILE_IS_A_DIRECTORY;
2891 return NT_STATUS_NO_SUCH_FILE;
2894 if (dirtype_orig & 0x8000) {
2895 /* These will never be set for POSIX. */
2896 return NT_STATUS_NO_SUCH_FILE;
2900 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2901 return NT_STATUS_FILE_IS_A_DIRECTORY;
2904 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2905 return NT_STATUS_NO_SUCH_FILE;
2908 if (dirtype & 0xFF00) {
2909 /* These will never be set for POSIX. */
2910 return NT_STATUS_NO_SUCH_FILE;
2915 return NT_STATUS_NO_SUCH_FILE;
2918 /* Can't delete a directory. */
2919 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2920 return NT_STATUS_FILE_IS_A_DIRECTORY;
2925 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2926 return NT_STATUS_OBJECT_NAME_INVALID;
2927 #endif /* JRATEST */
2929 /* On open checks the open itself will check the share mode, so
2930 don't do it here as we'll get it wrong. */
2932 status = SMB_VFS_CREATE_FILE
2935 0, /* root_dir_fid */
2936 smb_fname, /* fname */
2937 DELETE_ACCESS, /* access_mask */
2938 FILE_SHARE_NONE, /* share_access */
2939 FILE_OPEN, /* create_disposition*/
2940 FILE_NON_DIRECTORY_FILE, /* create_options */
2941 /* file_attributes */
2942 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2943 FILE_ATTRIBUTE_NORMAL,
2944 0, /* oplock_request */
2946 0, /* allocation_size */
2947 0, /* private_flags */
2952 NULL, NULL); /* create context */
2954 if (!NT_STATUS_IS_OK(status)) {
2955 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2956 nt_errstr(status)));
2960 status = can_set_delete_on_close(fsp, fattr);
2961 if (!NT_STATUS_IS_OK(status)) {
2962 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2964 smb_fname_str_dbg(smb_fname),
2965 nt_errstr(status)));
2966 close_file(req, fsp, NORMAL_CLOSE);
2970 /* The set is across all open files on this dev/inode pair. */
2971 if (!set_delete_on_close(fsp, True,
2972 conn->session_info->security_token,
2973 conn->session_info->unix_token)) {
2974 close_file(req, fsp, NORMAL_CLOSE);
2975 return NT_STATUS_ACCESS_DENIED;
2978 return close_file(req, fsp, NORMAL_CLOSE);
2981 /****************************************************************************
2982 The guts of the unlink command, split out so it may be called by the NT SMB
2984 ****************************************************************************/
2986 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2987 uint32_t dirtype, struct smb_filename *smb_fname,
2990 char *fname_dir = NULL;
2991 char *fname_mask = NULL;
2993 NTSTATUS status = NT_STATUS_OK;
2994 struct smb_filename *smb_fname_dir = NULL;
2995 TALLOC_CTX *ctx = talloc_tos();
2997 /* Split up the directory from the filename/mask. */
2998 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2999 &fname_dir, &fname_mask);
3000 if (!NT_STATUS_IS_OK(status)) {
3005 * We should only check the mangled cache
3006 * here if unix_convert failed. This means
3007 * that the path in 'mask' doesn't exist
3008 * on the file system and so we need to look
3009 * for a possible mangle. This patch from
3010 * Tine Smukavec <valentin.smukavec@hermes.si>.
3013 if (!VALID_STAT(smb_fname->st) &&
3014 mangle_is_mangled(fname_mask, conn->params)) {
3015 char *new_mask = NULL;
3016 mangle_lookup_name_from_8_3(ctx, fname_mask,
3017 &new_mask, conn->params);
3019 TALLOC_FREE(fname_mask);
3020 fname_mask = new_mask;
3027 * Only one file needs to be unlinked. Append the mask back
3028 * onto the directory.
3030 TALLOC_FREE(smb_fname->base_name);
3031 if (ISDOT(fname_dir)) {
3032 /* Ensure we use canonical names on open. */
3033 smb_fname->base_name = talloc_asprintf(smb_fname,
3037 smb_fname->base_name = talloc_asprintf(smb_fname,
3042 if (!smb_fname->base_name) {
3043 status = NT_STATUS_NO_MEMORY;
3047 dirtype = FILE_ATTRIBUTE_NORMAL;
3050 status = check_name(conn, smb_fname->base_name);
3051 if (!NT_STATUS_IS_OK(status)) {
3055 status = do_unlink(conn, req, smb_fname, dirtype);
3056 if (!NT_STATUS_IS_OK(status)) {
3062 struct smb_Dir *dir_hnd = NULL;
3064 const char *dname = NULL;
3065 char *talloced = NULL;
3067 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3068 status = NT_STATUS_OBJECT_NAME_INVALID;
3072 dirtype = FILE_ATTRIBUTE_NORMAL;
3075 if (strequal(fname_mask,"????????.???")) {
3076 TALLOC_FREE(fname_mask);
3077 fname_mask = talloc_strdup(ctx, "*");
3079 status = NT_STATUS_NO_MEMORY;
3084 status = check_name(conn, fname_dir);
3085 if (!NT_STATUS_IS_OK(status)) {
3089 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3094 if (smb_fname_dir == NULL) {
3095 status = NT_STATUS_NO_MEMORY;
3099 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3101 if (dir_hnd == NULL) {
3102 status = map_nt_error_from_unix(errno);
3106 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3107 the pattern matches against the long name, otherwise the short name
3108 We don't implement this yet XXXX
3111 status = NT_STATUS_NO_SUCH_FILE;
3113 while ((dname = ReadDirName(dir_hnd, &offset,
3114 &smb_fname->st, &talloced))) {
3115 TALLOC_CTX *frame = talloc_stackframe();
3117 if (!is_visible_file(conn, fname_dir, dname,
3118 &smb_fname->st, true)) {
3120 TALLOC_FREE(talloced);
3124 /* Quick check for "." and ".." */
3125 if (ISDOT(dname) || ISDOTDOT(dname)) {
3127 TALLOC_FREE(talloced);
3131 if(!mask_match(dname, fname_mask,
3132 conn->case_sensitive)) {
3134 TALLOC_FREE(talloced);
3138 TALLOC_FREE(smb_fname->base_name);
3139 if (ISDOT(fname_dir)) {
3140 /* Ensure we use canonical names on open. */
3141 smb_fname->base_name =
3142 talloc_asprintf(smb_fname, "%s",
3145 smb_fname->base_name =
3146 talloc_asprintf(smb_fname, "%s/%s",
3150 if (!smb_fname->base_name) {
3151 TALLOC_FREE(dir_hnd);
3152 status = NT_STATUS_NO_MEMORY;
3154 TALLOC_FREE(talloced);
3158 status = check_name(conn, smb_fname->base_name);
3159 if (!NT_STATUS_IS_OK(status)) {
3160 TALLOC_FREE(dir_hnd);
3162 TALLOC_FREE(talloced);
3166 status = do_unlink(conn, req, smb_fname, dirtype);
3167 if (!NT_STATUS_IS_OK(status)) {
3168 TALLOC_FREE(dir_hnd);
3170 TALLOC_FREE(talloced);
3175 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3176 smb_fname->base_name));
3179 TALLOC_FREE(talloced);
3181 TALLOC_FREE(dir_hnd);
3184 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3185 status = map_nt_error_from_unix(errno);
3189 TALLOC_FREE(smb_fname_dir);
3190 TALLOC_FREE(fname_dir);
3191 TALLOC_FREE(fname_mask);
3195 /****************************************************************************
3197 ****************************************************************************/
3199 void reply_unlink(struct smb_request *req)
3201 connection_struct *conn = req->conn;
3203 struct smb_filename *smb_fname = NULL;
3206 bool path_contains_wcard = False;
3207 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3208 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
3209 TALLOC_CTX *ctx = talloc_tos();
3211 START_PROFILE(SMBunlink);
3214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3218 dirtype = SVAL(req->vwv+0, 0);
3220 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3221 STR_TERMINATE, &status,
3222 &path_contains_wcard);
3223 if (!NT_STATUS_IS_OK(status)) {
3224 reply_nterror(req, status);
3228 status = filename_convert(ctx, conn,
3229 req->flags2 & FLAGS2_DFS_PATHNAMES,
3232 &path_contains_wcard,
3234 if (!NT_STATUS_IS_OK(status)) {
3235 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3236 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3237 ERRSRV, ERRbadpath);
3240 reply_nterror(req, status);
3244 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3246 status = unlink_internals(conn, req, dirtype, smb_fname,
3247 path_contains_wcard);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 if (open_was_deferred(req->xconn, req->mid)) {
3250 /* We have re-scheduled this call. */
3253 reply_nterror(req, status);
3257 reply_outbuf(req, 0, 0);
3259 TALLOC_FREE(smb_fname);
3260 END_PROFILE(SMBunlink);
3264 /****************************************************************************
3266 ****************************************************************************/
3268 static void fail_readraw(void)
3270 const char *errstr = talloc_asprintf(talloc_tos(),
3271 "FAIL ! reply_readbraw: socket write fail (%s)",
3276 exit_server_cleanly(errstr);
3279 /****************************************************************************
3280 Fake (read/write) sendfile. Returns -1 on read or write fail.
3281 ****************************************************************************/
3283 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3284 off_t startpos, size_t nread)
3287 size_t tosend = nread;
3294 bufsize = MIN(nread, 65536);
3296 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3300 while (tosend > 0) {
3304 cur_read = MIN(tosend, bufsize);
3305 ret = read_file(fsp,buf,startpos,cur_read);
3311 /* If we had a short read, fill with zeros. */
3312 if (ret < cur_read) {
3313 memset(buf + ret, '\0', cur_read - ret);
3316 ret = write_data(xconn->transport.sock, buf, cur_read);
3317 if (ret != cur_read) {
3318 int saved_errno = errno;
3320 * Try and give an error message saying what
3323 DEBUG(0, ("write_data failed for client %s. "
3325 smbXsrv_connection_dbg(xconn),
3326 strerror(saved_errno)));
3328 errno = saved_errno;
3332 startpos += cur_read;
3336 return (ssize_t)nread;
3339 /****************************************************************************
3340 Deal with the case of sendfile reading less bytes from the file than
3341 requested. Fill with zeros (all we can do). Returns 0 on success
3342 ****************************************************************************/
3344 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3350 #define SHORT_SEND_BUFSIZE 1024
3351 if (nread < headersize) {
3352 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3353 "header for file %s (%s). Terminating\n",
3354 fsp_str_dbg(fsp), strerror(errno)));
3358 nread -= headersize;
3360 if (nread < smb_maxcnt) {
3361 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3363 DEBUG(0,("sendfile_short_send: malloc failed "
3364 "for file %s (%s). Terminating\n",
3365 fsp_str_dbg(fsp), strerror(errno)));
3369 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3370 "with zeros !\n", fsp_str_dbg(fsp)));
3372 while (nread < smb_maxcnt) {
3374 * We asked for the real file size and told sendfile
3375 * to not go beyond the end of the file. But it can
3376 * happen that in between our fstat call and the
3377 * sendfile call the file was truncated. This is very
3378 * bad because we have already announced the larger
3379 * number of bytes to the client.
3381 * The best we can do now is to send 0-bytes, just as
3382 * a read from a hole in a sparse file would do.
3384 * This should happen rarely enough that I don't care
3385 * about efficiency here :-)
3390 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3391 ret = write_data(xconn->transport.sock, buf, to_write);
3392 if (ret != to_write) {
3393 int saved_errno = errno;
3395 * Try and give an error message saying what
3398 DEBUG(0, ("write_data failed for client %s. "
3400 smbXsrv_connection_dbg(xconn),
3401 strerror(saved_errno)));
3402 errno = saved_errno;
3413 /****************************************************************************
3414 Return a readbraw error (4 bytes of zero).
3415 ****************************************************************************/
3417 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3423 smbd_lock_socket(xconn);
3424 if (write_data(xconn->transport.sock,header,4) != 4) {
3425 int saved_errno = errno;
3427 * Try and give an error message saying what
3430 DEBUG(0, ("write_data failed for client %s. "
3432 smbXsrv_connection_dbg(xconn),
3433 strerror(saved_errno)));
3434 errno = saved_errno;
3438 smbd_unlock_socket(xconn);
3441 /****************************************************************************
3442 Use sendfile in readbraw.
3443 ****************************************************************************/
3445 static void send_file_readbraw(connection_struct *conn,
3446 struct smb_request *req,
3452 struct smbXsrv_connection *xconn = req->xconn;
3453 char *outbuf = NULL;
3457 * We can only use sendfile on a non-chained packet
3458 * but we can use on a non-oplocked file. tridge proved this
3459 * on a train in Germany :-). JRA.
3460 * reply_readbraw has already checked the length.
3463 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3464 (fsp->wcp == NULL) &&
3465 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3466 ssize_t sendfile_read = -1;
3468 DATA_BLOB header_blob;
3470 _smb_setlen(header,nread);
3471 header_blob = data_blob_const(header, 4);
3473 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3474 &header_blob, startpos,
3476 if (sendfile_read == -1) {
3477 /* Returning ENOSYS means no data at all was sent.
3478 * Do this as a normal read. */
3479 if (errno == ENOSYS) {
3480 goto normal_readbraw;
3484 * Special hack for broken Linux with no working sendfile. If we
3485 * return EINTR we sent the header but not the rest of the data.
3486 * Fake this up by doing read/write calls.
3488 if (errno == EINTR) {
3489 /* Ensure we don't do this again. */
3490 set_use_sendfile(SNUM(conn), False);
3491 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3493 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3494 DEBUG(0,("send_file_readbraw: "
3495 "fake_sendfile failed for "
3499 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3504 DEBUG(0,("send_file_readbraw: sendfile failed for "
3505 "file %s (%s). Terminating\n",
3506 fsp_str_dbg(fsp), strerror(errno)));
3507 exit_server_cleanly("send_file_readbraw sendfile failed");
3508 } else if (sendfile_read == 0) {
3510 * Some sendfile implementations return 0 to indicate
3511 * that there was a short read, but nothing was
3512 * actually written to the socket. In this case,
3513 * fallback to the normal read path so the header gets
3514 * the correct byte count.
3516 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3517 "bytes falling back to the normal read: "
3518 "%s\n", fsp_str_dbg(fsp)));
3519 goto normal_readbraw;
3522 /* Deal with possible short send. */
3523 if (sendfile_read != 4+nread) {
3524 ret = sendfile_short_send(xconn, fsp,
3525 sendfile_read, 4, nread);
3535 outbuf = talloc_array(NULL, char, nread+4);
3537 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3538 (unsigned)(nread+4)));
3539 reply_readbraw_error(xconn);
3544 ret = read_file(fsp,outbuf+4,startpos,nread);
3545 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3554 _smb_setlen(outbuf,ret);
3555 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3556 int saved_errno = errno;
3558 * Try and give an error message saying what
3561 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3562 smbXsrv_connection_dbg(xconn),
3563 strerror(saved_errno)));
3564 errno = saved_errno;
3569 TALLOC_FREE(outbuf);
3572 /****************************************************************************
3573 Reply to a readbraw (core+ protocol).
3574 ****************************************************************************/
3576 void reply_readbraw(struct smb_request *req)
3578 connection_struct *conn = req->conn;
3579 struct smbXsrv_connection *xconn = req->xconn;
3580 ssize_t maxcount,mincount;
3584 struct lock_struct lock;
3587 START_PROFILE(SMBreadbraw);
3589 if (srv_is_signing_active(xconn) || req->encrypted) {
3590 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3591 "raw reads/writes are disallowed.");
3595 reply_readbraw_error(xconn);
3596 END_PROFILE(SMBreadbraw);
3600 if (xconn->smb1.echo_handler.trusted_fde) {
3601 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3602 "'async smb echo handler = yes'\n"));
3603 reply_readbraw_error(xconn);
3604 END_PROFILE(SMBreadbraw);
3609 * Special check if an oplock break has been issued
3610 * and the readraw request croses on the wire, we must
3611 * return a zero length response here.
3614 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3617 * We have to do a check_fsp by hand here, as
3618 * we must always return 4 zero bytes on error,
3622 if (!fsp || !conn || conn != fsp->conn ||
3623 req->vuid != fsp->vuid ||
3624 fsp->is_directory || fsp->fh->fd == -1) {
3626 * fsp could be NULL here so use the value from the packet. JRA.
3628 DEBUG(3,("reply_readbraw: fnum %d not valid "
3630 (int)SVAL(req->vwv+0, 0)));
3631 reply_readbraw_error(xconn);
3632 END_PROFILE(SMBreadbraw);
3636 /* Do a "by hand" version of CHECK_READ. */
3637 if (!(fsp->can_read ||
3638 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3639 (fsp->access_mask & FILE_EXECUTE)))) {
3640 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3641 (int)SVAL(req->vwv+0, 0)));
3642 reply_readbraw_error(xconn);
3643 END_PROFILE(SMBreadbraw);
3647 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3649 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3650 if(req->wct == 10) {
3652 * This is a large offset (64 bit) read.
3655 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3658 DEBUG(0,("reply_readbraw: negative 64 bit "
3659 "readraw offset (%.0f) !\n",
3660 (double)startpos ));
3661 reply_readbraw_error(xconn);
3662 END_PROFILE(SMBreadbraw);
3667 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3668 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3670 /* ensure we don't overrun the packet size */
3671 maxcount = MIN(65535,maxcount);
3673 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3674 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3677 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3678 reply_readbraw_error(xconn);
3679 END_PROFILE(SMBreadbraw);
3683 if (fsp_stat(fsp) == 0) {
3684 size = fsp->fsp_name->st.st_ex_size;
3687 if (startpos >= size) {
3690 nread = MIN(maxcount,(size - startpos));
3693 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3694 if (nread < mincount)
3698 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3699 "min=%lu nread=%lu\n",
3700 fsp_fnum_dbg(fsp), (double)startpos,
3701 (unsigned long)maxcount,
3702 (unsigned long)mincount,
3703 (unsigned long)nread ) );
3705 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3707 DEBUG(5,("reply_readbraw finished\n"));
3709 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3711 END_PROFILE(SMBreadbraw);
3716 #define DBGC_CLASS DBGC_LOCKING
3718 /****************************************************************************
3719 Reply to a lockread (core+ protocol).
3720 ****************************************************************************/
3722 void reply_lockread(struct smb_request *req)
3724 connection_struct *conn = req->conn;
3732 struct byte_range_lock *br_lck = NULL;
3734 struct smbXsrv_connection *xconn = req->xconn;
3736 START_PROFILE(SMBlockread);
3739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3740 END_PROFILE(SMBlockread);
3744 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3746 if (!check_fsp(conn, req, fsp)) {
3747 END_PROFILE(SMBlockread);
3751 if (!CHECK_READ(fsp,req)) {
3752 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3753 END_PROFILE(SMBlockread);
3757 numtoread = SVAL(req->vwv+1, 0);
3758 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3761 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3762 * protocol request that predates the read/write lock concept.
3763 * Thus instead of asking for a read lock here we need to ask
3764 * for a write lock. JRA.
3765 * Note that the requested lock size is unaffected by max_send.
3768 br_lck = do_lock(req->sconn->msg_ctx,
3770 (uint64_t)req->smbpid,
3771 (uint64_t)numtoread,
3775 False, /* Non-blocking lock. */
3778 TALLOC_FREE(br_lck);
3780 if (NT_STATUS_V(status)) {
3781 reply_nterror(req, status);
3782 END_PROFILE(SMBlockread);
3787 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3789 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3791 if (numtoread > maxtoread) {
3792 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3793 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3794 (unsigned int)numtoread, (unsigned int)maxtoread,
3795 (unsigned int)xconn->smb1.sessions.max_send));
3796 numtoread = maxtoread;
3799 reply_outbuf(req, 5, numtoread + 3);
3801 data = smb_buf(req->outbuf) + 3;
3803 nread = read_file(fsp,data,startpos,numtoread);
3806 reply_nterror(req, map_nt_error_from_unix(errno));
3807 END_PROFILE(SMBlockread);
3811 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3813 SSVAL(req->outbuf,smb_vwv0,nread);
3814 SSVAL(req->outbuf,smb_vwv5,nread+3);
3815 p = smb_buf(req->outbuf);
3816 SCVAL(p,0,0); /* pad byte. */
3819 DEBUG(3,("lockread %s num=%d nread=%d\n",
3820 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3822 END_PROFILE(SMBlockread);
3827 #define DBGC_CLASS DBGC_ALL
3829 /****************************************************************************
3831 ****************************************************************************/
3833 void reply_read(struct smb_request *req)
3835 connection_struct *conn = req->conn;
3842 struct lock_struct lock;
3843 struct smbXsrv_connection *xconn = req->xconn;
3845 START_PROFILE(SMBread);
3848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3849 END_PROFILE(SMBread);
3853 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3855 if (!check_fsp(conn, req, fsp)) {
3856 END_PROFILE(SMBread);
3860 if (!CHECK_READ(fsp,req)) {
3861 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3862 END_PROFILE(SMBread);
3866 numtoread = SVAL(req->vwv+1, 0);
3867 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3870 * The requested read size cannot be greater than max_send. JRA.
3872 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3874 if (numtoread > maxtoread) {
3875 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3876 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3877 (unsigned int)numtoread, (unsigned int)maxtoread,
3878 (unsigned int)xconn->smb1.sessions.max_send));
3879 numtoread = maxtoread;
3882 reply_outbuf(req, 5, numtoread+3);
3884 data = smb_buf(req->outbuf) + 3;
3886 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3887 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3890 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3891 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3892 END_PROFILE(SMBread);
3897 nread = read_file(fsp,data,startpos,numtoread);
3900 reply_nterror(req, map_nt_error_from_unix(errno));
3904 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3906 SSVAL(req->outbuf,smb_vwv0,nread);
3907 SSVAL(req->outbuf,smb_vwv5,nread+3);
3908 SCVAL(smb_buf(req->outbuf),0,1);
3909 SSVAL(smb_buf(req->outbuf),1,nread);
3911 DEBUG(3, ("read %s num=%d nread=%d\n",
3912 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3915 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3917 END_PROFILE(SMBread);
3921 /****************************************************************************
3923 ****************************************************************************/
3925 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3929 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3932 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3934 SCVAL(outbuf,smb_vwv0,0xFF);
3935 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3936 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3937 SSVAL(outbuf,smb_vwv6,
3938 (smb_wct - 4) /* offset from smb header to wct */
3939 + 1 /* the wct field */
3940 + 12 * sizeof(uint16_t) /* vwv */
3941 + 2 /* the buflen field */
3942 + 1); /* padding byte */
3943 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3944 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3945 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3946 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3947 _smb_setlen_large(outbuf,
3948 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3952 /****************************************************************************
3953 Reply to a read and X - possibly using sendfile.
3954 ****************************************************************************/
3956 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3957 files_struct *fsp, off_t startpos,
3960 struct smbXsrv_connection *xconn = req->xconn;
3962 struct lock_struct lock;
3963 int saved_errno = 0;
3965 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3966 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3969 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3970 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3975 * We can only use sendfile on a non-chained packet
3976 * but we can use on a non-oplocked file. tridge proved this
3977 * on a train in Germany :-). JRA.
3980 if (!req_is_in_chain(req) &&
3982 (fsp->base_fsp == NULL) &&
3983 (fsp->wcp == NULL) &&
3984 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3985 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3988 if(fsp_stat(fsp) == -1) {
3989 reply_nterror(req, map_nt_error_from_unix(errno));
3993 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3994 (startpos > fsp->fsp_name->st.st_ex_size) ||
3995 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3997 * We already know that we would do a short read, so don't
3998 * try the sendfile() path.
4000 goto nosendfile_read;
4004 * Set up the packet header before send. We
4005 * assume here the sendfile will work (get the
4006 * correct amount of data).
4009 header = data_blob_const(headerbuf, sizeof(headerbuf));
4011 construct_reply_common_req(req, (char *)headerbuf);
4012 setup_readX_header((char *)headerbuf, smb_maxcnt);
4014 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4015 startpos, smb_maxcnt);
4017 saved_errno = errno;
4019 /* Returning ENOSYS means no data at all was sent.
4020 Do this as a normal read. */
4021 if (errno == ENOSYS) {
4026 * Special hack for broken Linux with no working sendfile. If we
4027 * return EINTR we sent the header but not the rest of the data.
4028 * Fake this up by doing read/write calls.
4031 if (errno == EINTR) {
4032 /* Ensure we don't do this again. */
4033 set_use_sendfile(SNUM(conn), False);
4034 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4035 nread = fake_sendfile(xconn, fsp, startpos,
4038 saved_errno = errno;
4039 DEBUG(0,("send_file_readX: "
4040 "fake_sendfile failed for "
4041 "file %s (%s) for client %s. "
4044 smbXsrv_connection_dbg(xconn),
4045 strerror(saved_errno)));
4046 errno = saved_errno;
4047 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4049 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4050 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4051 /* No outbuf here means successful sendfile. */
4055 DEBUG(0,("send_file_readX: sendfile failed for file "
4056 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4058 exit_server_cleanly("send_file_readX sendfile failed");
4059 } else if (nread == 0) {
4061 * Some sendfile implementations return 0 to indicate
4062 * that there was a short read, but nothing was
4063 * actually written to the socket. In this case,
4064 * fallback to the normal read path so the header gets
4065 * the correct byte count.
4067 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4068 "falling back to the normal read: %s\n",
4073 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4074 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4076 /* Deal with possible short send. */
4077 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4080 ret = sendfile_short_send(xconn, fsp, nread,
4081 sizeof(headerbuf), smb_maxcnt);
4084 r = "send_file_readX: sendfile_short_send failed";
4085 DEBUG(0,("%s for file %s (%s).\n",
4086 r, fsp_str_dbg(fsp), strerror(errno)));
4087 exit_server_cleanly(r);
4090 /* No outbuf here means successful sendfile. */
4091 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4092 SMB_PERFCOUNT_END(&req->pcd);
4098 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4099 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4102 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4103 (startpos > fsp->fsp_name->st.st_ex_size) ||
4104 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4106 * We already know that we would do a short
4107 * read, so don't try the sendfile() path.
4109 goto nosendfile_read;
4112 construct_reply_common_req(req, (char *)headerbuf);
4113 setup_readX_header((char *)headerbuf, smb_maxcnt);
4115 /* Send out the header. */
4116 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4118 if (ret != sizeof(headerbuf)) {
4119 saved_errno = errno;
4121 * Try and give an error message saying what
4124 DEBUG(0,("send_file_readX: write_data 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 sendfile failed");
4132 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4134 saved_errno = errno;
4135 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4136 "%s (%s) for client %s. Terminating\n",
4138 smbXsrv_connection_dbg(xconn),
4139 strerror(saved_errno)));
4140 errno = saved_errno;
4141 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4148 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4149 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4150 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4152 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4153 startpos, smb_maxcnt);
4154 saved_errno = errno;
4156 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4159 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4163 setup_readX_header((char *)req->outbuf, nread);
4165 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4166 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4170 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4171 TALLOC_FREE(req->outbuf);
4175 /****************************************************************************
4176 Work out how much space we have for a read return.
4177 ****************************************************************************/
4179 static size_t calc_max_read_pdu(const struct smb_request *req)
4181 struct smbXsrv_connection *xconn = req->xconn;
4183 if (xconn->protocol < PROTOCOL_NT1) {
4184 return xconn->smb1.sessions.max_send;
4187 if (!lp_large_readwrite()) {
4188 return xconn->smb1.sessions.max_send;
4191 if (req_is_in_chain(req)) {
4192 return xconn->smb1.sessions.max_send;
4195 if (req->encrypted) {
4197 * Don't take encrypted traffic up to the
4198 * limit. There are padding considerations
4199 * that make that tricky.
4201 return xconn->smb1.sessions.max_send;
4204 if (srv_is_signing_active(xconn)) {
4208 if (!lp_unix_extensions()) {
4213 * We can do ultra-large POSIX reads.
4218 /****************************************************************************
4219 Calculate how big a read can be. Copes with all clients. It's always
4220 safe to return a short read - Windows does this.
4221 ****************************************************************************/
4223 static size_t calc_read_size(const struct smb_request *req,
4227 struct smbXsrv_connection *xconn = req->xconn;
4228 size_t max_pdu = calc_max_read_pdu(req);
4229 size_t total_size = 0;
4230 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4231 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4234 * Windows explicitly ignores upper size of 0xFFFF.
4235 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4236 * We must do the same as these will never fit even in
4237 * an extended size NetBIOS packet.
4239 if (upper_size == 0xFFFF) {
4243 if (xconn->protocol < PROTOCOL_NT1) {
4247 total_size = ((upper_size<<16) | lower_size);
4250 * LARGE_READX test shows it's always safe to return
4251 * a short read. Windows does so.
4253 return MIN(total_size, max_len);
4256 /****************************************************************************
4257 Reply to a read and X.
4258 ****************************************************************************/
4260 void reply_read_and_X(struct smb_request *req)
4262 connection_struct *conn = req->conn;
4267 bool big_readX = False;
4269 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4272 START_PROFILE(SMBreadX);
4274 if ((req->wct != 10) && (req->wct != 12)) {
4275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4279 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4280 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4281 smb_maxcnt = SVAL(req->vwv+5, 0);
4283 /* If it's an IPC, pass off the pipe handler. */
4285 reply_pipe_read_and_X(req);
4286 END_PROFILE(SMBreadX);
4290 if (!check_fsp(conn, req, fsp)) {
4291 END_PROFILE(SMBreadX);
4295 if (!CHECK_READ(fsp,req)) {
4296 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4297 END_PROFILE(SMBreadX);
4301 upper_size = SVAL(req->vwv+7, 0);
4302 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4303 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4305 * This is a heuristic to avoid keeping large
4306 * outgoing buffers around over long-lived aio
4312 if (req->wct == 12) {
4314 * This is a large offset (64 bit) read.
4316 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4321 NTSTATUS status = schedule_aio_read_and_X(conn,
4326 if (NT_STATUS_IS_OK(status)) {
4327 /* Read scheduled - we're done. */
4330 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4331 /* Real error - report to client. */
4332 END_PROFILE(SMBreadX);
4333 reply_nterror(req, status);
4336 /* NT_STATUS_RETRY - fall back to sync read. */
4339 smbd_lock_socket(req->xconn);
4340 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4341 smbd_unlock_socket(req->xconn);
4344 END_PROFILE(SMBreadX);
4348 /****************************************************************************
4349 Error replies to writebraw must have smb_wct == 1. Fix this up.
4350 ****************************************************************************/
4352 void error_to_writebrawerr(struct smb_request *req)
4354 uint8_t *old_outbuf = req->outbuf;
4356 reply_outbuf(req, 1, 0);
4358 memcpy(req->outbuf, old_outbuf, smb_size);
4359 TALLOC_FREE(old_outbuf);
4362 /****************************************************************************
4363 Read 4 bytes of a smb packet and return the smb length of the packet.
4364 Store the result in the buffer. This version of the function will
4365 never return a session keepalive (length of zero).
4366 Timeout is in milliseconds.
4367 ****************************************************************************/
4369 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4372 uint8_t msgtype = NBSSkeepalive;
4374 while (msgtype == NBSSkeepalive) {
4377 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4379 if (!NT_STATUS_IS_OK(status)) {
4380 char addr[INET6_ADDRSTRLEN];
4381 /* Try and give an error message
4382 * saying what client failed. */
4383 DEBUG(0, ("read_fd_with_timeout failed for "
4384 "client %s read error = %s.\n",
4385 get_peer_addr(fd,addr,sizeof(addr)),
4386 nt_errstr(status)));
4390 msgtype = CVAL(inbuf, 0);
4393 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4394 (unsigned long)len));
4396 return NT_STATUS_OK;
4399 /****************************************************************************
4400 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4401 ****************************************************************************/
4403 void reply_writebraw(struct smb_request *req)
4405 connection_struct *conn = req->conn;
4406 struct smbXsrv_connection *xconn = req->xconn;
4409 ssize_t total_written=0;
4410 size_t numtowrite=0;
4413 const char *data=NULL;
4416 struct lock_struct lock;
4419 START_PROFILE(SMBwritebraw);
4422 * If we ever reply with an error, it must have the SMB command
4423 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4426 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4428 if (srv_is_signing_active(xconn)) {
4429 END_PROFILE(SMBwritebraw);
4430 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4431 "raw reads/writes are disallowed.");
4434 if (req->wct < 12) {
4435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4436 error_to_writebrawerr(req);
4437 END_PROFILE(SMBwritebraw);
4441 if (xconn->smb1.echo_handler.trusted_fde) {
4442 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4443 "'async smb echo handler = yes'\n"));
4444 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4445 error_to_writebrawerr(req);
4446 END_PROFILE(SMBwritebraw);
4450 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4451 if (!check_fsp(conn, req, fsp)) {
4452 error_to_writebrawerr(req);
4453 END_PROFILE(SMBwritebraw);
4457 if (!CHECK_WRITE(fsp)) {
4458 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4459 error_to_writebrawerr(req);
4460 END_PROFILE(SMBwritebraw);
4464 tcount = IVAL(req->vwv+1, 0);
4465 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4466 write_through = BITSETW(req->vwv+7,0);
4468 /* We have to deal with slightly different formats depending
4469 on whether we are using the core+ or lanman1.0 protocol */
4471 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4472 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4473 data = smb_buf_const(req->inbuf);
4475 numtowrite = SVAL(req->vwv+10, 0);
4476 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4479 /* Ensure we don't write bytes past the end of this packet. */
4480 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4482 error_to_writebrawerr(req);
4483 END_PROFILE(SMBwritebraw);
4487 if (!fsp->print_file) {
4488 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4489 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4492 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4493 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4494 error_to_writebrawerr(req);
4495 END_PROFILE(SMBwritebraw);
4501 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4504 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4505 "wrote=%d sync=%d\n",
4506 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4507 (int)nwritten, (int)write_through));
4509 if (nwritten < (ssize_t)numtowrite) {
4510 reply_nterror(req, NT_STATUS_DISK_FULL);
4511 error_to_writebrawerr(req);
4515 total_written = nwritten;
4517 /* Allocate a buffer of 64k + length. */
4518 buf = talloc_array(NULL, char, 65540);
4520 reply_nterror(req, NT_STATUS_NO_MEMORY);
4521 error_to_writebrawerr(req);
4525 /* Return a SMBwritebraw message to the redirector to tell
4526 * it to send more bytes */
4528 memcpy(buf, req->inbuf, smb_size);
4529 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4530 SCVAL(buf,smb_com,SMBwritebraw);
4531 SSVALS(buf,smb_vwv0,0xFFFF);
4533 if (!srv_send_smb(req->xconn,
4535 false, 0, /* no signing */
4536 IS_CONN_ENCRYPTED(conn),
4538 exit_server_cleanly("reply_writebraw: srv_send_smb "
4542 /* Now read the raw data into the buffer and write it */
4543 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4545 if (!NT_STATUS_IS_OK(status)) {
4546 exit_server_cleanly("secondary writebraw failed");
4549 /* Set up outbuf to return the correct size */
4550 reply_outbuf(req, 1, 0);
4552 if (numtowrite != 0) {
4554 if (numtowrite > 0xFFFF) {
4555 DEBUG(0,("reply_writebraw: Oversize secondary write "
4556 "raw requested (%u). Terminating\n",
4557 (unsigned int)numtowrite ));
4558 exit_server_cleanly("secondary writebraw failed");
4561 if (tcount > nwritten+numtowrite) {
4562 DEBUG(3,("reply_writebraw: Client overestimated the "
4564 (int)tcount,(int)nwritten,(int)numtowrite));
4567 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4570 if (!NT_STATUS_IS_OK(status)) {
4571 /* Try and give an error message
4572 * saying what client failed. */
4573 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4574 "raw read failed (%s) for client %s. "
4575 "Terminating\n", nt_errstr(status),
4576 smbXsrv_connection_dbg(xconn)));
4577 exit_server_cleanly("secondary writebraw failed");
4580 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4581 if (nwritten == -1) {
4583 reply_nterror(req, map_nt_error_from_unix(errno));
4584 error_to_writebrawerr(req);
4588 if (nwritten < (ssize_t)numtowrite) {
4589 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4590 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4594 total_written += nwritten;
4599 SSVAL(req->outbuf,smb_vwv0,total_written);
4601 status = sync_file(conn, fsp, write_through);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4604 fsp_str_dbg(fsp), nt_errstr(status)));
4605 reply_nterror(req, status);
4606 error_to_writebrawerr(req);
4610 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4612 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4613 (int)total_written));
4615 if (!fsp->print_file) {
4616 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4619 /* We won't return a status if write through is not selected - this
4620 * follows what WfWg does */
4621 END_PROFILE(SMBwritebraw);
4623 if (!write_through && total_written==tcount) {
4625 #if RABBIT_PELLET_FIX
4627 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4628 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4631 if (!send_keepalive(xconn->transport.sock)) {
4632 exit_server_cleanly("reply_writebraw: send of "
4633 "keepalive failed");
4636 TALLOC_FREE(req->outbuf);
4641 if (!fsp->print_file) {
4642 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4645 END_PROFILE(SMBwritebraw);
4650 #define DBGC_CLASS DBGC_LOCKING
4652 /****************************************************************************
4653 Reply to a writeunlock (core+).
4654 ****************************************************************************/
4656 void reply_writeunlock(struct smb_request *req)
4658 connection_struct *conn = req->conn;
4659 ssize_t nwritten = -1;
4663 NTSTATUS status = NT_STATUS_OK;
4665 struct lock_struct lock;
4666 int saved_errno = 0;
4668 START_PROFILE(SMBwriteunlock);
4671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4672 END_PROFILE(SMBwriteunlock);
4676 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4678 if (!check_fsp(conn, req, fsp)) {
4679 END_PROFILE(SMBwriteunlock);
4683 if (!CHECK_WRITE(fsp)) {
4684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4685 END_PROFILE(SMBwriteunlock);
4689 numtowrite = SVAL(req->vwv+1, 0);
4690 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4691 data = (const char *)req->buf + 3;
4693 if (!fsp->print_file && numtowrite > 0) {
4694 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4695 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4698 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4699 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4700 END_PROFILE(SMBwriteunlock);
4705 /* The special X/Open SMB protocol handling of
4706 zero length writes is *NOT* done for
4708 if(numtowrite == 0) {
4711 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4712 saved_errno = errno;
4715 status = sync_file(conn, fsp, False /* write through */);
4716 if (!NT_STATUS_IS_OK(status)) {
4717 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4718 fsp_str_dbg(fsp), nt_errstr(status)));
4719 reply_nterror(req, status);
4724 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4728 if((nwritten < numtowrite) && (numtowrite != 0)) {
4729 reply_nterror(req, NT_STATUS_DISK_FULL);
4733 if (numtowrite && !fsp->print_file) {
4734 status = do_unlock(req->sconn->msg_ctx,
4736 (uint64_t)req->smbpid,
4737 (uint64_t)numtowrite,
4741 if (NT_STATUS_V(status)) {
4742 reply_nterror(req, status);
4747 reply_outbuf(req, 1, 0);
4749 SSVAL(req->outbuf,smb_vwv0,nwritten);
4751 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4752 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4755 if (numtowrite && !fsp->print_file) {
4756 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4759 END_PROFILE(SMBwriteunlock);
4764 #define DBGC_CLASS DBGC_ALL
4766 /****************************************************************************
4768 ****************************************************************************/
4770 void reply_write(struct smb_request *req)
4772 connection_struct *conn = req->conn;
4774 ssize_t nwritten = -1;
4778 struct lock_struct lock;
4780 int saved_errno = 0;
4782 START_PROFILE(SMBwrite);
4785 END_PROFILE(SMBwrite);
4786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4790 /* If it's an IPC, pass off the pipe handler. */
4792 reply_pipe_write(req);
4793 END_PROFILE(SMBwrite);
4797 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4799 if (!check_fsp(conn, req, fsp)) {
4800 END_PROFILE(SMBwrite);
4804 if (!CHECK_WRITE(fsp)) {
4805 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4806 END_PROFILE(SMBwrite);
4810 numtowrite = SVAL(req->vwv+1, 0);
4811 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4812 data = (const char *)req->buf + 3;
4814 if (!fsp->print_file) {
4815 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4816 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4819 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4820 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4821 END_PROFILE(SMBwrite);
4827 * X/Open SMB protocol says that if smb_vwv1 is
4828 * zero then the file size should be extended or
4829 * truncated to the size given in smb_vwv[2-3].
4832 if(numtowrite == 0) {
4834 * This is actually an allocate call, and set EOF. JRA.
4836 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4838 reply_nterror(req, NT_STATUS_DISK_FULL);
4841 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4843 reply_nterror(req, NT_STATUS_DISK_FULL);
4846 trigger_write_time_update_immediate(fsp);
4848 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4851 status = sync_file(conn, fsp, False);
4852 if (!NT_STATUS_IS_OK(status)) {
4853 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4854 fsp_str_dbg(fsp), nt_errstr(status)));
4855 reply_nterror(req, status);
4860 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4864 if((nwritten == 0) && (numtowrite != 0)) {
4865 reply_nterror(req, NT_STATUS_DISK_FULL);
4869 reply_outbuf(req, 1, 0);
4871 SSVAL(req->outbuf,smb_vwv0,nwritten);
4873 if (nwritten < (ssize_t)numtowrite) {
4874 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4875 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4878 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4881 if (!fsp->print_file) {
4882 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4885 END_PROFILE(SMBwrite);
4889 /****************************************************************************
4890 Ensure a buffer is a valid writeX for recvfile purposes.
4891 ****************************************************************************/
4893 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4894 (2*14) + /* word count (including bcc) */ \
4897 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4898 const uint8_t *inbuf)
4901 unsigned int doff = 0;
4902 size_t len = smb_len_large(inbuf);
4904 struct smbXsrv_open *op = NULL;
4905 struct files_struct *fsp = NULL;
4908 if (is_encrypted_packet(inbuf)) {
4909 /* Can't do this on encrypted
4914 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4918 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4919 CVAL(inbuf,smb_wct) != 14) {
4920 DEBUG(10,("is_valid_writeX_buffer: chained or "
4921 "invalid word length.\n"));
4925 fnum = SVAL(inbuf, smb_vwv2);
4926 status = smb1srv_open_lookup(xconn,
4930 if (!NT_STATUS_IS_OK(status)) {
4931 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4936 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4939 if (fsp->conn == NULL) {
4940 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4944 if (IS_IPC(fsp->conn)) {
4945 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4948 if (IS_PRINT(fsp->conn)) {
4949 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4952 doff = SVAL(inbuf,smb_vwv11);
4954 numtowrite = SVAL(inbuf,smb_vwv10);
4956 if (len > doff && len - doff > 0xFFFF) {
4957 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4960 if (numtowrite == 0) {
4961 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4965 /* Ensure the sizes match up. */
4966 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4967 /* no pad byte...old smbclient :-( */
4968 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4970 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4974 if (len - doff != numtowrite) {
4975 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4976 "len = %u, doff = %u, numtowrite = %u\n",
4979 (unsigned int)numtowrite ));
4983 DEBUG(10,("is_valid_writeX_buffer: true "
4984 "len = %u, doff = %u, numtowrite = %u\n",
4987 (unsigned int)numtowrite ));
4992 /****************************************************************************
4993 Reply to a write and X.
4994 ****************************************************************************/
4996 void reply_write_and_X(struct smb_request *req)
4998 connection_struct *conn = req->conn;
4999 struct smbXsrv_connection *xconn = req->xconn;
5001 struct lock_struct lock;
5006 unsigned int smb_doff;
5007 unsigned int smblen;
5010 int saved_errno = 0;
5012 START_PROFILE(SMBwriteX);
5014 if ((req->wct != 12) && (req->wct != 14)) {
5015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5019 numtowrite = SVAL(req->vwv+10, 0);
5020 smb_doff = SVAL(req->vwv+11, 0);
5021 smblen = smb_len(req->inbuf);
5023 if (req->unread_bytes > 0xFFFF ||
5024 (smblen > smb_doff &&
5025 smblen - smb_doff > 0xFFFF)) {
5026 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5029 if (req->unread_bytes) {
5030 /* Can't do a recvfile write on IPC$ */
5032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 if (numtowrite != req->unread_bytes) {
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5040 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5041 smb_doff + numtowrite > smblen) {
5042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5047 /* If it's an IPC, pass off the pipe handler. */
5049 if (req->unread_bytes) {
5050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5053 reply_pipe_write_and_X(req);
5057 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5058 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5059 write_through = BITSETW(req->vwv+7,0);
5061 if (!check_fsp(conn, req, fsp)) {
5065 if (!CHECK_WRITE(fsp)) {
5066 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5070 data = smb_base(req->inbuf) + smb_doff;
5072 if(req->wct == 14) {
5074 * This is a large offset (64 bit) write.
5076 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5080 /* X/Open SMB protocol says that, unlike SMBwrite
5081 if the length is zero then NO truncation is
5082 done, just a write of zero. To truncate a file,
5085 if(numtowrite == 0) {
5088 if (req->unread_bytes == 0) {
5089 status = schedule_aio_write_and_X(conn,
5096 if (NT_STATUS_IS_OK(status)) {
5097 /* write scheduled - we're done. */
5100 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5101 /* Real error - report to client. */
5102 reply_nterror(req, status);
5105 /* NT_STATUS_RETRY - fall through to sync write. */
5108 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5109 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5112 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5113 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5117 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5118 saved_errno = errno;
5120 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5124 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5128 if((nwritten == 0) && (numtowrite != 0)) {
5129 reply_nterror(req, NT_STATUS_DISK_FULL);
5133 reply_outbuf(req, 6, 0);
5134 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5135 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5136 SSVAL(req->outbuf,smb_vwv2,nwritten);
5137 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5139 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5140 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5142 status = sync_file(conn, fsp, write_through);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5145 fsp_str_dbg(fsp), nt_errstr(status)));
5146 reply_nterror(req, status);
5150 END_PROFILE(SMBwriteX);
5154 if (req->unread_bytes) {
5155 /* writeX failed. drain socket. */
5156 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5157 req->unread_bytes) {
5158 smb_panic("failed to drain pending bytes");
5160 req->unread_bytes = 0;
5163 END_PROFILE(SMBwriteX);
5167 /****************************************************************************
5169 ****************************************************************************/
5171 void reply_lseek(struct smb_request *req)
5173 connection_struct *conn = req->conn;
5179 START_PROFILE(SMBlseek);
5182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5183 END_PROFILE(SMBlseek);
5187 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5189 if (!check_fsp(conn, req, fsp)) {
5193 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5195 mode = SVAL(req->vwv+1, 0) & 3;
5196 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5197 startpos = (off_t)IVALS(req->vwv+2, 0);
5206 res = fsp->fh->pos + startpos;
5217 if (umode == SEEK_END) {
5218 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5219 if(errno == EINVAL) {
5220 off_t current_pos = startpos;
5222 if(fsp_stat(fsp) == -1) {
5224 map_nt_error_from_unix(errno));
5225 END_PROFILE(SMBlseek);
5229 current_pos += fsp->fsp_name->st.st_ex_size;
5231 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5236 reply_nterror(req, map_nt_error_from_unix(errno));
5237 END_PROFILE(SMBlseek);
5244 reply_outbuf(req, 2, 0);
5245 SIVAL(req->outbuf,smb_vwv0,res);
5247 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5248 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5250 END_PROFILE(SMBlseek);
5254 /****************************************************************************
5256 ****************************************************************************/
5258 void reply_flush(struct smb_request *req)
5260 connection_struct *conn = req->conn;
5264 START_PROFILE(SMBflush);
5267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5271 fnum = SVAL(req->vwv+0, 0);
5272 fsp = file_fsp(req, fnum);
5274 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5279 file_sync_all(conn);
5281 NTSTATUS status = sync_file(conn, fsp, True);
5282 if (!NT_STATUS_IS_OK(status)) {
5283 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5284 fsp_str_dbg(fsp), nt_errstr(status)));
5285 reply_nterror(req, status);
5286 END_PROFILE(SMBflush);
5291 reply_outbuf(req, 0, 0);
5293 DEBUG(3,("flush\n"));
5294 END_PROFILE(SMBflush);
5298 /****************************************************************************
5300 conn POINTER CAN BE NULL HERE !
5301 ****************************************************************************/
5303 void reply_exit(struct smb_request *req)
5305 START_PROFILE(SMBexit);
5307 file_close_pid(req->sconn, req->smbpid, req->vuid);
5309 reply_outbuf(req, 0, 0);
5311 DEBUG(3,("exit\n"));
5313 END_PROFILE(SMBexit);
5317 struct reply_close_state {
5319 struct smb_request *smbreq;
5322 static void do_smb1_close(struct tevent_req *req);
5324 void reply_close(struct smb_request *req)
5326 connection_struct *conn = req->conn;
5327 NTSTATUS status = NT_STATUS_OK;
5328 files_struct *fsp = NULL;
5329 START_PROFILE(SMBclose);
5332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5333 END_PROFILE(SMBclose);
5337 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5340 * We can only use check_fsp if we know it's not a directory.
5343 if (!check_fsp_open(conn, req, fsp)) {
5344 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5345 END_PROFILE(SMBclose);
5349 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5350 fsp->is_directory ? "directory" : "file",
5351 fsp->fh->fd, fsp_fnum_dbg(fsp),
5352 conn->num_files_open));
5354 if (!fsp->is_directory) {
5358 * Take care of any time sent in the close.
5361 t = srv_make_unix_date3(req->vwv+1);
5362 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5365 if (fsp->num_aio_requests != 0) {
5367 struct reply_close_state *state;
5369 DEBUG(10, ("closing with aio %u requests pending\n",
5370 fsp->num_aio_requests));
5373 * We depend on the aio_extra destructor to take care of this
5374 * close request once fsp->num_aio_request drops to 0.
5377 fsp->deferred_close = tevent_wait_send(
5378 fsp, fsp->conn->sconn->ev_ctx);
5379 if (fsp->deferred_close == NULL) {
5380 status = NT_STATUS_NO_MEMORY;
5384 state = talloc(fsp, struct reply_close_state);
5385 if (state == NULL) {
5386 TALLOC_FREE(fsp->deferred_close);
5387 status = NT_STATUS_NO_MEMORY;
5391 state->smbreq = talloc_move(fsp, &req);
5392 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5394 END_PROFILE(SMBclose);
5399 * close_file() returns the unix errno if an error was detected on
5400 * close - normally this is due to a disk full error. If not then it
5401 * was probably an I/O error.
5404 status = close_file(req, fsp, NORMAL_CLOSE);
5406 if (!NT_STATUS_IS_OK(status)) {
5407 reply_nterror(req, status);
5408 END_PROFILE(SMBclose);
5412 reply_outbuf(req, 0, 0);
5413 END_PROFILE(SMBclose);
5417 static void do_smb1_close(struct tevent_req *req)
5419 struct reply_close_state *state = tevent_req_callback_data(
5420 req, struct reply_close_state);
5421 struct smb_request *smbreq;
5425 ret = tevent_wait_recv(req);
5428 DEBUG(10, ("tevent_wait_recv returned %s\n",
5431 * Continue anyway, this should never happen
5436 * fsp->smb2_close_request right now is a talloc grandchild of
5437 * fsp. When we close_file(fsp), it would go with it. No chance to
5440 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5442 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5443 if (NT_STATUS_IS_OK(status)) {
5444 reply_outbuf(smbreq, 0, 0);
5446 reply_nterror(smbreq, status);
5448 if (!srv_send_smb(smbreq->xconn,
5449 (char *)smbreq->outbuf,
5452 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5454 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5457 TALLOC_FREE(smbreq);
5460 /****************************************************************************
5461 Reply to a writeclose (Core+ protocol).
5462 ****************************************************************************/
5464 void reply_writeclose(struct smb_request *req)
5466 connection_struct *conn = req->conn;
5468 ssize_t nwritten = -1;
5469 NTSTATUS close_status = NT_STATUS_OK;
5472 struct timespec mtime;
5474 struct lock_struct lock;
5476 START_PROFILE(SMBwriteclose);
5479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5480 END_PROFILE(SMBwriteclose);
5484 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5486 if (!check_fsp(conn, req, fsp)) {
5487 END_PROFILE(SMBwriteclose);
5490 if (!CHECK_WRITE(fsp)) {
5491 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5492 END_PROFILE(SMBwriteclose);
5496 numtowrite = SVAL(req->vwv+1, 0);
5497 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5498 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5499 data = (const char *)req->buf + 1;
5501 if (fsp->print_file == NULL) {
5502 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5503 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5506 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5507 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5508 END_PROFILE(SMBwriteclose);
5513 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5515 if (fsp->print_file == NULL) {
5516 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5519 set_close_write_time(fsp, mtime);
5522 * More insanity. W2K only closes the file if writelen > 0.
5526 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5527 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5528 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5531 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5532 "file %s\n", fsp_str_dbg(fsp)));
5533 close_status = close_file(req, fsp, NORMAL_CLOSE);
5537 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5538 reply_nterror(req, NT_STATUS_DISK_FULL);
5542 if(!NT_STATUS_IS_OK(close_status)) {
5543 reply_nterror(req, close_status);
5547 reply_outbuf(req, 1, 0);
5549 SSVAL(req->outbuf,smb_vwv0,nwritten);
5553 END_PROFILE(SMBwriteclose);
5558 #define DBGC_CLASS DBGC_LOCKING
5560 /****************************************************************************
5562 ****************************************************************************/
5564 void reply_lock(struct smb_request *req)
5566 connection_struct *conn = req->conn;
5567 uint64_t count,offset;
5570 struct byte_range_lock *br_lck = NULL;
5572 START_PROFILE(SMBlock);
5575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5576 END_PROFILE(SMBlock);
5580 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5582 if (!check_fsp(conn, req, fsp)) {
5583 END_PROFILE(SMBlock);
5587 count = (uint64_t)IVAL(req->vwv+1, 0);
5588 offset = (uint64_t)IVAL(req->vwv+3, 0);
5590 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5591 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5593 br_lck = do_lock(req->sconn->msg_ctx,
5595 (uint64_t)req->smbpid,
5600 False, /* Non-blocking lock. */
5604 TALLOC_FREE(br_lck);
5606 if (NT_STATUS_V(status)) {
5607 reply_nterror(req, status);
5608 END_PROFILE(SMBlock);
5612 reply_outbuf(req, 0, 0);
5614 END_PROFILE(SMBlock);
5618 /****************************************************************************
5620 ****************************************************************************/
5622 void reply_unlock(struct smb_request *req)
5624 connection_struct *conn = req->conn;
5625 uint64_t count,offset;
5629 START_PROFILE(SMBunlock);
5632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5633 END_PROFILE(SMBunlock);
5637 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5639 if (!check_fsp(conn, req, fsp)) {
5640 END_PROFILE(SMBunlock);
5644 count = (uint64_t)IVAL(req->vwv+1, 0);
5645 offset = (uint64_t)IVAL(req->vwv+3, 0);
5647 status = do_unlock(req->sconn->msg_ctx,
5649 (uint64_t)req->smbpid,
5654 if (NT_STATUS_V(status)) {
5655 reply_nterror(req, status);
5656 END_PROFILE(SMBunlock);
5660 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5661 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5663 reply_outbuf(req, 0, 0);
5665 END_PROFILE(SMBunlock);
5670 #define DBGC_CLASS DBGC_ALL
5672 /****************************************************************************
5674 conn POINTER CAN BE NULL HERE !
5675 ****************************************************************************/
5677 void reply_tdis(struct smb_request *req)
5680 connection_struct *conn = req->conn;
5681 struct smbXsrv_tcon *tcon;
5683 START_PROFILE(SMBtdis);
5686 DEBUG(4,("Invalid connection in tdis\n"));
5687 reply_force_doserror(req, ERRSRV, ERRinvnid);
5688 END_PROFILE(SMBtdis);
5696 * TODO: cancel all outstanding requests on the tcon
5698 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5699 if (!NT_STATUS_IS_OK(status)) {
5700 DEBUG(0, ("reply_tdis: "
5701 "smbXsrv_tcon_disconnect() failed: %s\n",
5702 nt_errstr(status)));
5704 * If we hit this case, there is something completely
5705 * wrong, so we better disconnect the transport connection.
5707 END_PROFILE(SMBtdis);
5708 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5714 reply_outbuf(req, 0, 0);
5715 END_PROFILE(SMBtdis);
5719 /****************************************************************************
5721 conn POINTER CAN BE NULL HERE !
5722 ****************************************************************************/
5724 void reply_echo(struct smb_request *req)
5726 connection_struct *conn = req->conn;
5727 struct smb_perfcount_data local_pcd;
5728 struct smb_perfcount_data *cur_pcd;
5732 START_PROFILE(SMBecho);
5734 smb_init_perfcount_data(&local_pcd);
5737 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5738 END_PROFILE(SMBecho);
5742 smb_reverb = SVAL(req->vwv+0, 0);
5744 reply_outbuf(req, 1, req->buflen);
5746 /* copy any incoming data back out */
5747 if (req->buflen > 0) {
5748 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5751 if (smb_reverb > 100) {
5752 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5756 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5758 /* this makes sure we catch the request pcd */
5759 if (seq_num == smb_reverb) {
5760 cur_pcd = &req->pcd;
5762 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5763 cur_pcd = &local_pcd;
5766 SSVAL(req->outbuf,smb_vwv0,seq_num);
5768 show_msg((char *)req->outbuf);
5769 if (!srv_send_smb(req->xconn,
5770 (char *)req->outbuf,
5771 true, req->seqnum+1,
5772 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5774 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5777 DEBUG(3,("echo %d times\n", smb_reverb));
5779 TALLOC_FREE(req->outbuf);
5781 END_PROFILE(SMBecho);
5785 /****************************************************************************
5786 Reply to a printopen.
5787 ****************************************************************************/
5789 void reply_printopen(struct smb_request *req)
5791 connection_struct *conn = req->conn;
5795 START_PROFILE(SMBsplopen);
5798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5799 END_PROFILE(SMBsplopen);
5803 if (!CAN_PRINT(conn)) {
5804 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5805 END_PROFILE(SMBsplopen);
5809 status = file_new(req, conn, &fsp);
5810 if(!NT_STATUS_IS_OK(status)) {
5811 reply_nterror(req, status);
5812 END_PROFILE(SMBsplopen);
5816 /* Open for exclusive use, write only. */
5817 status = print_spool_open(fsp, NULL, req->vuid);
5819 if (!NT_STATUS_IS_OK(status)) {
5820 file_free(req, fsp);
5821 reply_nterror(req, status);
5822 END_PROFILE(SMBsplopen);
5826 reply_outbuf(req, 1, 0);
5827 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5829 DEBUG(3,("openprint fd=%d %s\n",
5830 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5832 END_PROFILE(SMBsplopen);
5836 /****************************************************************************
5837 Reply to a printclose.
5838 ****************************************************************************/
5840 void reply_printclose(struct smb_request *req)
5842 connection_struct *conn = req->conn;
5846 START_PROFILE(SMBsplclose);
5849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5850 END_PROFILE(SMBsplclose);
5854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5856 if (!check_fsp(conn, req, fsp)) {
5857 END_PROFILE(SMBsplclose);
5861 if (!CAN_PRINT(conn)) {
5862 reply_force_doserror(req, ERRSRV, ERRerror);
5863 END_PROFILE(SMBsplclose);
5867 DEBUG(3,("printclose fd=%d %s\n",
5868 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5870 status = close_file(req, fsp, NORMAL_CLOSE);
5872 if(!NT_STATUS_IS_OK(status)) {
5873 reply_nterror(req, status);
5874 END_PROFILE(SMBsplclose);
5878 reply_outbuf(req, 0, 0);
5880 END_PROFILE(SMBsplclose);
5884 /****************************************************************************
5885 Reply to a printqueue.
5886 ****************************************************************************/
5888 void reply_printqueue(struct smb_request *req)
5890 connection_struct *conn = req->conn;
5894 START_PROFILE(SMBsplretq);
5897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5898 END_PROFILE(SMBsplretq);
5902 max_count = SVAL(req->vwv+0, 0);
5903 start_index = SVAL(req->vwv+1, 0);
5905 /* we used to allow the client to get the cnum wrong, but that
5906 is really quite gross and only worked when there was only
5907 one printer - I think we should now only accept it if they
5908 get it right (tridge) */
5909 if (!CAN_PRINT(conn)) {
5910 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5911 END_PROFILE(SMBsplretq);
5915 reply_outbuf(req, 2, 3);
5916 SSVAL(req->outbuf,smb_vwv0,0);
5917 SSVAL(req->outbuf,smb_vwv1,0);
5918 SCVAL(smb_buf(req->outbuf),0,1);
5919 SSVAL(smb_buf(req->outbuf),1,0);
5921 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5922 start_index, max_count));
5925 TALLOC_CTX *mem_ctx = talloc_tos();
5928 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5929 struct rpc_pipe_client *cli = NULL;
5930 struct dcerpc_binding_handle *b = NULL;
5931 struct policy_handle handle;
5932 struct spoolss_DevmodeContainer devmode_ctr;
5933 union spoolss_JobInfo *info;
5935 uint32_t num_to_get;
5939 ZERO_STRUCT(handle);
5941 status = rpc_pipe_open_interface(conn,
5944 conn->sconn->remote_address,
5945 conn->sconn->msg_ctx,
5947 if (!NT_STATUS_IS_OK(status)) {
5948 DEBUG(0, ("reply_printqueue: "
5949 "could not connect to spoolss: %s\n",
5950 nt_errstr(status)));
5951 reply_nterror(req, status);
5954 b = cli->binding_handle;
5956 ZERO_STRUCT(devmode_ctr);
5958 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5961 SEC_FLAG_MAXIMUM_ALLOWED,
5964 if (!NT_STATUS_IS_OK(status)) {
5965 reply_nterror(req, status);
5968 if (!W_ERROR_IS_OK(werr)) {
5969 reply_nterror(req, werror_to_ntstatus(werr));
5973 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5981 if (!W_ERROR_IS_OK(werr)) {
5982 reply_nterror(req, werror_to_ntstatus(werr));
5986 if (max_count > 0) {
5987 first = start_index;
5989 first = start_index + max_count + 1;
5992 if (first >= count) {
5995 num_to_get = first + MIN(ABS(max_count), count - first);
5998 for (i = first; i < num_to_get; i++) {
6001 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6004 uint16_t qrapjobid = pjobid_to_rap(sharename,
6005 info[i].info2.job_id);
6007 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6013 srv_put_dos_date2(p, 0, qtime);
6014 SCVAL(p, 4, qstatus);
6015 SSVAL(p, 5, qrapjobid);
6016 SIVAL(p, 7, info[i].info2.size);
6018 status = srvstr_push(blob, req->flags2, p+12,
6019 info[i].info2.notify_name, 16, STR_ASCII, &len);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 reply_nterror(req, status);
6024 if (message_push_blob(
6027 blob, sizeof(blob))) == -1) {
6028 reply_nterror(req, NT_STATUS_NO_MEMORY);
6034 SSVAL(req->outbuf,smb_vwv0,count);
6035 SSVAL(req->outbuf,smb_vwv1,
6036 (max_count>0?first+count:first-1));
6037 SCVAL(smb_buf(req->outbuf),0,1);
6038 SSVAL(smb_buf(req->outbuf),1,28*count);
6042 DEBUG(3, ("%u entries returned in queue\n",
6046 if (b && is_valid_policy_hnd(&handle)) {
6047 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6052 END_PROFILE(SMBsplretq);
6056 /****************************************************************************
6057 Reply to a printwrite.
6058 ****************************************************************************/
6060 void reply_printwrite(struct smb_request *req)
6062 connection_struct *conn = req->conn;
6067 START_PROFILE(SMBsplwr);
6070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6071 END_PROFILE(SMBsplwr);
6075 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6077 if (!check_fsp(conn, req, fsp)) {
6078 END_PROFILE(SMBsplwr);
6082 if (!fsp->print_file) {
6083 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6084 END_PROFILE(SMBsplwr);
6088 if (!CHECK_WRITE(fsp)) {
6089 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6090 END_PROFILE(SMBsplwr);
6094 numtowrite = SVAL(req->buf, 1);
6096 if (req->buflen < numtowrite + 3) {
6097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6098 END_PROFILE(SMBsplwr);
6102 data = (const char *)req->buf + 3;
6104 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6105 reply_nterror(req, map_nt_error_from_unix(errno));
6106 END_PROFILE(SMBsplwr);
6110 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6112 END_PROFILE(SMBsplwr);
6116 /****************************************************************************
6118 ****************************************************************************/
6120 void reply_mkdir(struct smb_request *req)
6122 connection_struct *conn = req->conn;
6123 struct smb_filename *smb_dname = NULL;
6124 char *directory = NULL;
6126 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
6127 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6128 TALLOC_CTX *ctx = talloc_tos();
6130 START_PROFILE(SMBmkdir);
6132 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6133 STR_TERMINATE, &status);
6134 if (!NT_STATUS_IS_OK(status)) {
6135 reply_nterror(req, status);
6139 status = filename_convert(ctx, conn,
6140 req->flags2 & FLAGS2_DFS_PATHNAMES,
6145 if (!NT_STATUS_IS_OK(status)) {
6146 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6147 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6148 ERRSRV, ERRbadpath);
6151 reply_nterror(req, status);
6155 status = create_directory(conn, req, smb_dname);
6157 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6159 if (!NT_STATUS_IS_OK(status)) {
6161 if (!use_nt_status()
6162 && NT_STATUS_EQUAL(status,
6163 NT_STATUS_OBJECT_NAME_COLLISION)) {
6165 * Yes, in the DOS error code case we get a
6166 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6167 * samba4 torture test.
6169 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6172 reply_nterror(req, status);
6176 reply_outbuf(req, 0, 0);
6178 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6180 TALLOC_FREE(smb_dname);
6181 END_PROFILE(SMBmkdir);
6185 /****************************************************************************
6187 ****************************************************************************/
6189 void reply_rmdir(struct smb_request *req)
6191 connection_struct *conn = req->conn;
6192 struct smb_filename *smb_dname = NULL;
6193 char *directory = NULL;
6195 TALLOC_CTX *ctx = talloc_tos();
6196 files_struct *fsp = NULL;
6198 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6199 struct smbd_server_connection *sconn = req->sconn;
6201 START_PROFILE(SMBrmdir);
6203 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6204 STR_TERMINATE, &status);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 reply_nterror(req, status);
6210 status = filename_convert(ctx, conn,
6211 req->flags2 & FLAGS2_DFS_PATHNAMES,
6216 if (!NT_STATUS_IS_OK(status)) {
6217 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6218 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6219 ERRSRV, ERRbadpath);
6222 reply_nterror(req, status);
6226 if (is_ntfs_stream_smb_fname(smb_dname)) {
6227 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6231 status = SMB_VFS_CREATE_FILE(
6234 0, /* root_dir_fid */
6235 smb_dname, /* fname */
6236 DELETE_ACCESS, /* access_mask */
6237 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6239 FILE_OPEN, /* create_disposition*/
6240 FILE_DIRECTORY_FILE, /* create_options */
6241 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6242 0, /* oplock_request */
6244 0, /* allocation_size */
6245 0, /* private_flags */
6250 NULL, NULL); /* create context */
6252 if (!NT_STATUS_IS_OK(status)) {
6253 if (open_was_deferred(req->xconn, req->mid)) {
6254 /* We have re-scheduled this call. */
6257 reply_nterror(req, status);
6261 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 close_file(req, fsp, ERROR_CLOSE);
6264 reply_nterror(req, status);
6268 if (!set_delete_on_close(fsp, true,
6269 conn->session_info->security_token,
6270 conn->session_info->unix_token)) {
6271 close_file(req, fsp, ERROR_CLOSE);
6272 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6276 status = close_file(req, fsp, NORMAL_CLOSE);
6277 if (!NT_STATUS_IS_OK(status)) {
6278 reply_nterror(req, status);
6280 reply_outbuf(req, 0, 0);
6283 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6285 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6287 TALLOC_FREE(smb_dname);
6288 END_PROFILE(SMBrmdir);
6292 /*******************************************************************
6293 Resolve wildcards in a filename rename.
6294 ********************************************************************/
6296 static bool resolve_wildcards(TALLOC_CTX *ctx,
6301 char *name2_copy = NULL;
6306 char *p,*p2, *pname1, *pname2;
6308 name2_copy = talloc_strdup(ctx, name2);
6313 pname1 = strrchr_m(name1,'/');
6314 pname2 = strrchr_m(name2_copy,'/');
6316 if (!pname1 || !pname2) {
6320 /* Truncate the copy of name2 at the last '/' */
6323 /* Now go past the '/' */
6327 root1 = talloc_strdup(ctx, pname1);
6328 root2 = talloc_strdup(ctx, pname2);
6330 if (!root1 || !root2) {
6334 p = strrchr_m(root1,'.');
6337 ext1 = talloc_strdup(ctx, p+1);
6339 ext1 = talloc_strdup(ctx, "");
6341 p = strrchr_m(root2,'.');
6344 ext2 = talloc_strdup(ctx, p+1);
6346 ext2 = talloc_strdup(ctx, "");
6349 if (!ext1 || !ext2) {
6357 /* Hmmm. Should this be mb-aware ? */
6360 } else if (*p2 == '*') {
6362 root2 = talloc_asprintf(ctx, "%s%s",
6381 /* Hmmm. Should this be mb-aware ? */
6384 } else if (*p2 == '*') {
6386 ext2 = talloc_asprintf(ctx, "%s%s",
6402 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6407 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6419 /****************************************************************************
6420 Ensure open files have their names updated. Updated to notify other smbd's
6422 ****************************************************************************/
6424 static void rename_open_files(connection_struct *conn,
6425 struct share_mode_lock *lck,
6427 uint32_t orig_name_hash,
6428 const struct smb_filename *smb_fname_dst)
6431 bool did_rename = False;
6433 uint32_t new_name_hash = 0;
6435 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6436 fsp = file_find_di_next(fsp)) {
6437 /* fsp_name is a relative path under the fsp. To change this for other
6438 sharepaths we need to manipulate relative paths. */
6439 /* TODO - create the absolute path and manipulate the newname
6440 relative to the sharepath. */
6441 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6444 if (fsp->name_hash != orig_name_hash) {
6447 DEBUG(10, ("rename_open_files: renaming file %s "
6448 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6449 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6450 smb_fname_str_dbg(smb_fname_dst)));
6452 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6453 if (NT_STATUS_IS_OK(status)) {
6455 new_name_hash = fsp->name_hash;
6460 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6461 "for %s\n", file_id_string_tos(&id),
6462 smb_fname_str_dbg(smb_fname_dst)));
6465 /* Send messages to all smbd's (not ourself) that the name has changed. */
6466 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6467 orig_name_hash, new_name_hash,
6472 /****************************************************************************
6473 We need to check if the source path is a parent directory of the destination
6474 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6475 refuse the rename with a sharing violation. Under UNIX the above call can
6476 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6477 probably need to check that the client is a Windows one before disallowing
6478 this as a UNIX client (one with UNIX extensions) can know the source is a
6479 symlink and make this decision intelligently. Found by an excellent bug
6480 report from <AndyLiebman@aol.com>.
6481 ****************************************************************************/
6483 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6484 const struct smb_filename *smb_fname_dst)
6486 const char *psrc = smb_fname_src->base_name;
6487 const char *pdst = smb_fname_dst->base_name;
6490 if (psrc[0] == '.' && psrc[1] == '/') {
6493 if (pdst[0] == '.' && pdst[1] == '/') {
6496 if ((slen = strlen(psrc)) > strlen(pdst)) {
6499 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6503 * Do the notify calls from a rename
6506 static void notify_rename(connection_struct *conn, bool is_dir,
6507 const struct smb_filename *smb_fname_src,
6508 const struct smb_filename *smb_fname_dst)
6510 char *parent_dir_src = NULL;
6511 char *parent_dir_dst = NULL;
6514 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6515 : FILE_NOTIFY_CHANGE_FILE_NAME;
6517 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6518 &parent_dir_src, NULL) ||
6519 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6520 &parent_dir_dst, NULL)) {
6524 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6525 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6526 smb_fname_src->base_name);
6527 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6528 smb_fname_dst->base_name);
6531 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6532 smb_fname_src->base_name);
6533 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6534 smb_fname_dst->base_name);
6537 /* this is a strange one. w2k3 gives an additional event for
6538 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6539 files, but not directories */
6541 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6542 FILE_NOTIFY_CHANGE_ATTRIBUTES
6543 |FILE_NOTIFY_CHANGE_CREATION,
6544 smb_fname_dst->base_name);
6547 TALLOC_FREE(parent_dir_src);
6548 TALLOC_FREE(parent_dir_dst);
6551 /****************************************************************************
6552 Returns an error if the parent directory for a filename is open in an
6554 ****************************************************************************/
6556 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6557 const struct smb_filename *smb_fname_dst_in)
6559 char *parent_dir = NULL;
6560 struct smb_filename smb_fname_parent;
6562 files_struct *fsp = NULL;
6565 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6566 &parent_dir, NULL)) {
6567 return NT_STATUS_NO_MEMORY;
6569 ZERO_STRUCT(smb_fname_parent);
6570 smb_fname_parent.base_name = parent_dir;
6572 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6574 return map_nt_error_from_unix(errno);
6578 * We're only checking on this smbd here, mostly good
6579 * enough.. and will pass tests.
6582 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6583 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6584 fsp = file_find_di_next(fsp)) {
6585 if (fsp->access_mask & DELETE_ACCESS) {
6586 return NT_STATUS_SHARING_VIOLATION;
6589 return NT_STATUS_OK;
6592 /****************************************************************************
6593 Rename an open file - given an fsp.
6594 ****************************************************************************/
6596 NTSTATUS rename_internals_fsp(connection_struct *conn,
6598 const struct smb_filename *smb_fname_dst_in,
6600 bool replace_if_exists)
6602 TALLOC_CTX *ctx = talloc_tos();
6603 struct smb_filename *smb_fname_dst = NULL;
6604 NTSTATUS status = NT_STATUS_OK;
6605 struct share_mode_lock *lck = NULL;
6606 bool dst_exists, old_is_stream, new_is_stream;
6608 status = check_name(conn, smb_fname_dst_in->base_name);
6609 if (!NT_STATUS_IS_OK(status)) {
6613 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6614 if (!NT_STATUS_IS_OK(status)) {
6618 /* Make a copy of the dst smb_fname structs */
6620 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6621 if (smb_fname_dst == NULL) {
6622 status = NT_STATUS_NO_MEMORY;
6627 * Check for special case with case preserving and not
6628 * case sensitive. If the new last component differs from the original
6629 * last component only by case, then we should allow
6630 * the rename (user is trying to change the case of the
6633 if (!conn->case_sensitive && conn->case_preserve &&
6634 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6635 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6636 char *fname_dst_parent = NULL;
6637 const char *fname_dst_lcomp = NULL;
6638 char *orig_lcomp_path = NULL;
6639 char *orig_lcomp_stream = NULL;
6643 * Split off the last component of the processed
6644 * destination name. We will compare this to
6645 * the split components of smb_fname_dst->original_lcomp.
6647 if (!parent_dirname(ctx,
6648 smb_fname_dst->base_name,
6650 &fname_dst_lcomp)) {
6651 status = NT_STATUS_NO_MEMORY;
6656 * The original_lcomp component contains
6657 * the last_component of the path + stream
6658 * name (if a stream exists).
6660 * Split off the stream name so we
6661 * can check them separately.
6664 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6665 /* POSIX - no stream component. */
6666 orig_lcomp_path = talloc_strdup(ctx,
6667 smb_fname_dst->original_lcomp);
6668 if (orig_lcomp_path == NULL) {
6672 ok = split_stream_filename(ctx,
6673 smb_fname_dst->original_lcomp,
6675 &orig_lcomp_stream);
6679 TALLOC_FREE(fname_dst_parent);
6680 status = NT_STATUS_NO_MEMORY;
6684 /* If the base names only differ by case, use original. */
6685 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6688 * Replace the modified last component with the
6691 if (!ISDOT(fname_dst_parent)) {
6692 tmp = talloc_asprintf(smb_fname_dst,
6697 tmp = talloc_strdup(smb_fname_dst,
6701 status = NT_STATUS_NO_MEMORY;
6702 TALLOC_FREE(fname_dst_parent);
6703 TALLOC_FREE(orig_lcomp_path);
6704 TALLOC_FREE(orig_lcomp_stream);
6707 TALLOC_FREE(smb_fname_dst->base_name);
6708 smb_fname_dst->base_name = tmp;
6711 /* If the stream_names only differ by case, use original. */
6712 if(!strcsequal(smb_fname_dst->stream_name,
6713 orig_lcomp_stream)) {
6714 /* Use the original stream. */
6715 char *tmp = talloc_strdup(smb_fname_dst,
6718 status = NT_STATUS_NO_MEMORY;
6719 TALLOC_FREE(fname_dst_parent);
6720 TALLOC_FREE(orig_lcomp_path);
6721 TALLOC_FREE(orig_lcomp_stream);
6724 TALLOC_FREE(smb_fname_dst->stream_name);
6725 smb_fname_dst->stream_name = tmp;
6727 TALLOC_FREE(fname_dst_parent);
6728 TALLOC_FREE(orig_lcomp_path);
6729 TALLOC_FREE(orig_lcomp_stream);
6733 * If the src and dest names are identical - including case,
6734 * don't do the rename, just return success.
6737 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6738 strcsequal(fsp->fsp_name->stream_name,
6739 smb_fname_dst->stream_name)) {
6740 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6741 "- returning success\n",
6742 smb_fname_str_dbg(smb_fname_dst)));
6743 status = NT_STATUS_OK;
6747 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6748 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6750 /* Return the correct error code if both names aren't streams. */
6751 if (!old_is_stream && new_is_stream) {
6752 status = NT_STATUS_OBJECT_NAME_INVALID;
6756 if (old_is_stream && !new_is_stream) {
6757 status = NT_STATUS_INVALID_PARAMETER;
6761 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6763 if(!replace_if_exists && dst_exists) {
6764 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6765 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6766 smb_fname_str_dbg(smb_fname_dst)));
6767 status = NT_STATUS_OBJECT_NAME_COLLISION;
6772 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6773 &smb_fname_dst->st);
6774 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6776 /* The file can be open when renaming a stream */
6777 if (dst_fsp && !new_is_stream) {
6778 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6779 status = NT_STATUS_ACCESS_DENIED;
6784 /* Ensure we have a valid stat struct for the source. */
6785 status = vfs_stat_fsp(fsp);
6786 if (!NT_STATUS_IS_OK(status)) {
6790 status = can_rename(conn, fsp, attrs);
6792 if (!NT_STATUS_IS_OK(status)) {
6793 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6794 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6795 smb_fname_str_dbg(smb_fname_dst)));
6796 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6797 status = NT_STATUS_ACCESS_DENIED;
6801 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6802 status = NT_STATUS_ACCESS_DENIED;
6805 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6808 * We have the file open ourselves, so not being able to get the
6809 * corresponding share mode lock is a fatal error.
6812 SMB_ASSERT(lck != NULL);
6814 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6815 uint32_t create_options = fsp->fh->private_options;
6817 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6818 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6819 smb_fname_str_dbg(smb_fname_dst)));
6821 if (!fsp->is_directory &&
6822 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6823 (lp_map_archive(SNUM(conn)) ||
6824 lp_store_dos_attributes(SNUM(conn)))) {
6825 /* We must set the archive bit on the newly
6827 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6828 uint32_t old_dosmode = dos_mode(conn,
6830 file_set_dosmode(conn,
6832 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6838 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6841 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6845 * A rename acts as a new file create w.r.t. allowing an initial delete
6846 * on close, probably because in Windows there is a new handle to the
6847 * new file. If initial delete on close was requested but not
6848 * originally set, we need to set it here. This is probably not 100% correct,
6849 * but will work for the CIFSFS client which in non-posix mode
6850 * depends on these semantics. JRA.
6853 if (create_options & FILE_DELETE_ON_CLOSE) {
6854 status = can_set_delete_on_close(fsp, 0);
6856 if (NT_STATUS_IS_OK(status)) {
6857 /* Note that here we set the *inital* delete on close flag,
6858 * not the regular one. The magic gets handled in close. */
6859 fsp->initial_delete_on_close = True;
6863 status = NT_STATUS_OK;
6869 if (errno == ENOTDIR || errno == EISDIR) {
6870 status = NT_STATUS_OBJECT_NAME_COLLISION;
6872 status = map_nt_error_from_unix(errno);
6875 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6876 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6877 smb_fname_str_dbg(smb_fname_dst)));
6880 TALLOC_FREE(smb_fname_dst);
6885 /****************************************************************************
6886 The guts of the rename command, split out so it may be called by the NT SMB
6888 ****************************************************************************/
6890 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6891 connection_struct *conn,
6892 struct smb_request *req,
6893 struct smb_filename *smb_fname_src,
6894 struct smb_filename *smb_fname_dst,
6896 bool replace_if_exists,
6899 uint32_t access_mask)
6901 char *fname_src_dir = NULL;
6902 struct smb_filename *smb_fname_src_dir = NULL;
6903 char *fname_src_mask = NULL;
6905 NTSTATUS status = NT_STATUS_OK;
6906 struct smb_Dir *dir_hnd = NULL;
6907 const char *dname = NULL;
6908 char *talloced = NULL;
6910 int create_options = 0;
6911 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6915 * Split the old name into directory and last component
6916 * strings. Note that unix_convert may have stripped off a
6917 * leading ./ from both name and newname if the rename is
6918 * at the root of the share. We need to make sure either both
6919 * name and newname contain a / character or neither of them do
6920 * as this is checked in resolve_wildcards().
6923 /* Split up the directory from the filename/mask. */
6924 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6925 &fname_src_dir, &fname_src_mask);
6926 if (!NT_STATUS_IS_OK(status)) {
6927 status = NT_STATUS_NO_MEMORY;
6932 * We should only check the mangled cache
6933 * here if unix_convert failed. This means
6934 * that the path in 'mask' doesn't exist
6935 * on the file system and so we need to look
6936 * for a possible mangle. This patch from
6937 * Tine Smukavec <valentin.smukavec@hermes.si>.
6940 if (!VALID_STAT(smb_fname_src->st) &&
6941 mangle_is_mangled(fname_src_mask, conn->params)) {
6942 char *new_mask = NULL;
6943 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6946 TALLOC_FREE(fname_src_mask);
6947 fname_src_mask = new_mask;
6951 if (!src_has_wild) {
6955 * Only one file needs to be renamed. Append the mask back
6956 * onto the directory.
6958 TALLOC_FREE(smb_fname_src->base_name);
6959 if (ISDOT(fname_src_dir)) {
6960 /* Ensure we use canonical names on open. */
6961 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6965 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6970 if (!smb_fname_src->base_name) {
6971 status = NT_STATUS_NO_MEMORY;
6975 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6976 "case_preserve = %d, short case preserve = %d, "
6977 "directory = %s, newname = %s, "
6978 "last_component_dest = %s\n",
6979 conn->case_sensitive, conn->case_preserve,
6980 conn->short_case_preserve,
6981 smb_fname_str_dbg(smb_fname_src),
6982 smb_fname_str_dbg(smb_fname_dst),
6983 smb_fname_dst->original_lcomp));
6985 /* The dest name still may have wildcards. */
6986 if (dest_has_wild) {
6987 char *fname_dst_mod = NULL;
6988 if (!resolve_wildcards(smb_fname_dst,
6989 smb_fname_src->base_name,
6990 smb_fname_dst->base_name,
6992 DEBUG(6, ("rename_internals: resolve_wildcards "
6994 smb_fname_src->base_name,
6995 smb_fname_dst->base_name));
6996 status = NT_STATUS_NO_MEMORY;
6999 TALLOC_FREE(smb_fname_dst->base_name);
7000 smb_fname_dst->base_name = fname_dst_mod;
7003 ZERO_STRUCT(smb_fname_src->st);
7004 if (posix_pathnames) {
7005 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7007 rc = SMB_VFS_STAT(conn, smb_fname_src);
7010 status = map_nt_error_from_unix_common(errno);
7014 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7015 create_options |= FILE_DIRECTORY_FILE;
7018 status = SMB_VFS_CREATE_FILE(
7021 0, /* root_dir_fid */
7022 smb_fname_src, /* fname */
7023 access_mask, /* access_mask */
7024 (FILE_SHARE_READ | /* share_access */
7026 FILE_OPEN, /* create_disposition*/
7027 create_options, /* create_options */
7028 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7029 0, /* oplock_request */
7031 0, /* allocation_size */
7032 0, /* private_flags */
7037 NULL, NULL); /* create context */
7039 if (!NT_STATUS_IS_OK(status)) {
7040 DEBUG(3, ("Could not open rename source %s: %s\n",
7041 smb_fname_str_dbg(smb_fname_src),
7042 nt_errstr(status)));
7046 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7047 attrs, replace_if_exists);
7049 close_file(req, fsp, NORMAL_CLOSE);
7051 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7052 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7053 smb_fname_str_dbg(smb_fname_dst)));
7059 * Wildcards - process each file that matches.
7061 if (strequal(fname_src_mask, "????????.???")) {
7062 TALLOC_FREE(fname_src_mask);
7063 fname_src_mask = talloc_strdup(ctx, "*");
7064 if (!fname_src_mask) {
7065 status = NT_STATUS_NO_MEMORY;
7070 status = check_name(conn, fname_src_dir);
7071 if (!NT_STATUS_IS_OK(status)) {
7075 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7079 smb_fname_src->flags);
7080 if (smb_fname_src_dir == NULL) {
7081 status = NT_STATUS_NO_MEMORY;
7085 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7087 if (dir_hnd == NULL) {
7088 status = map_nt_error_from_unix(errno);
7092 status = NT_STATUS_NO_SUCH_FILE;
7094 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7095 * - gentest fix. JRA
7098 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7100 files_struct *fsp = NULL;
7101 char *destname = NULL;
7102 bool sysdir_entry = False;
7104 /* Quick check for "." and ".." */
7105 if (ISDOT(dname) || ISDOTDOT(dname)) {
7106 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7107 sysdir_entry = True;
7109 TALLOC_FREE(talloced);
7114 if (!is_visible_file(conn, fname_src_dir, dname,
7115 &smb_fname_src->st, false)) {
7116 TALLOC_FREE(talloced);
7120 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7121 TALLOC_FREE(talloced);
7126 status = NT_STATUS_OBJECT_NAME_INVALID;
7130 TALLOC_FREE(smb_fname_src->base_name);
7131 if (ISDOT(fname_src_dir)) {
7132 /* Ensure we use canonical names on open. */
7133 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7137 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7142 if (!smb_fname_src->base_name) {
7143 status = NT_STATUS_NO_MEMORY;
7147 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7148 smb_fname_dst->base_name,
7150 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7151 smb_fname_src->base_name, destname));
7152 TALLOC_FREE(talloced);
7156 status = NT_STATUS_NO_MEMORY;
7160 TALLOC_FREE(smb_fname_dst->base_name);
7161 smb_fname_dst->base_name = destname;
7163 ZERO_STRUCT(smb_fname_src->st);
7164 if (posix_pathnames) {
7165 SMB_VFS_LSTAT(conn, smb_fname_src);
7167 SMB_VFS_STAT(conn, smb_fname_src);
7172 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7173 create_options |= FILE_DIRECTORY_FILE;
7176 status = SMB_VFS_CREATE_FILE(
7179 0, /* root_dir_fid */
7180 smb_fname_src, /* fname */
7181 access_mask, /* access_mask */
7182 (FILE_SHARE_READ | /* share_access */
7184 FILE_OPEN, /* create_disposition*/
7185 create_options, /* create_options */
7186 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7187 0, /* oplock_request */
7189 0, /* allocation_size */
7190 0, /* private_flags */
7195 NULL, NULL); /* create context */
7197 if (!NT_STATUS_IS_OK(status)) {
7198 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7199 "returned %s rename %s -> %s\n",
7201 smb_fname_str_dbg(smb_fname_src),
7202 smb_fname_str_dbg(smb_fname_dst)));
7206 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7208 if (!smb_fname_dst->original_lcomp) {
7209 status = NT_STATUS_NO_MEMORY;
7213 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7214 attrs, replace_if_exists);
7216 close_file(req, fsp, NORMAL_CLOSE);
7218 if (!NT_STATUS_IS_OK(status)) {
7219 DEBUG(3, ("rename_internals_fsp returned %s for "
7220 "rename %s -> %s\n", nt_errstr(status),
7221 smb_fname_str_dbg(smb_fname_src),
7222 smb_fname_str_dbg(smb_fname_dst)));
7228 DEBUG(3,("rename_internals: doing rename on %s -> "
7229 "%s\n", smb_fname_str_dbg(smb_fname_src),
7230 smb_fname_str_dbg(smb_fname_src)));
7231 TALLOC_FREE(talloced);
7233 TALLOC_FREE(dir_hnd);
7235 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7236 status = map_nt_error_from_unix(errno);
7240 TALLOC_FREE(talloced);
7241 TALLOC_FREE(smb_fname_src_dir);
7242 TALLOC_FREE(fname_src_dir);
7243 TALLOC_FREE(fname_src_mask);
7247 /****************************************************************************
7249 ****************************************************************************/
7251 void reply_mv(struct smb_request *req)
7253 connection_struct *conn = req->conn;
7255 char *newname = NULL;
7259 bool src_has_wcard = False;
7260 bool dest_has_wcard = False;
7261 TALLOC_CTX *ctx = talloc_tos();
7262 struct smb_filename *smb_fname_src = NULL;
7263 struct smb_filename *smb_fname_dst = NULL;
7264 uint32_t src_ucf_flags = (req->posix_pathnames ?
7265 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7266 UCF_COND_ALLOW_WCARD_LCOMP);
7267 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7268 (req->posix_pathnames ? UCF_POSIX_PATHNAMES :
7269 UCF_COND_ALLOW_WCARD_LCOMP);
7270 bool stream_rename = false;
7272 START_PROFILE(SMBmv);
7275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7279 attrs = SVAL(req->vwv+0, 0);
7281 p = (const char *)req->buf + 1;
7282 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7283 &status, &src_has_wcard);
7284 if (!NT_STATUS_IS_OK(status)) {
7285 reply_nterror(req, status);
7289 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7290 &status, &dest_has_wcard);
7291 if (!NT_STATUS_IS_OK(status)) {
7292 reply_nterror(req, status);
7296 if (!req->posix_pathnames) {
7297 /* The newname must begin with a ':' if the
7298 name contains a ':'. */
7299 if (strchr_m(name, ':')) {
7300 if (newname[0] != ':') {
7301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7304 stream_rename = true;
7308 status = filename_convert(ctx,
7310 req->flags2 & FLAGS2_DFS_PATHNAMES,
7316 if (!NT_STATUS_IS_OK(status)) {
7317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7318 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7319 ERRSRV, ERRbadpath);
7322 reply_nterror(req, status);
7326 status = filename_convert(ctx,
7328 req->flags2 & FLAGS2_DFS_PATHNAMES,
7334 if (!NT_STATUS_IS_OK(status)) {
7335 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7336 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7337 ERRSRV, ERRbadpath);
7340 reply_nterror(req, status);
7344 if (stream_rename) {
7345 /* smb_fname_dst->base_name must be the same as
7346 smb_fname_src->base_name. */
7347 TALLOC_FREE(smb_fname_dst->base_name);
7348 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7349 smb_fname_src->base_name);
7350 if (!smb_fname_dst->base_name) {
7351 reply_nterror(req, NT_STATUS_NO_MEMORY);
7356 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7357 smb_fname_str_dbg(smb_fname_dst)));
7359 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7360 attrs, False, src_has_wcard, dest_has_wcard,
7362 if (!NT_STATUS_IS_OK(status)) {
7363 if (open_was_deferred(req->xconn, req->mid)) {
7364 /* We have re-scheduled this call. */
7367 reply_nterror(req, status);
7371 reply_outbuf(req, 0, 0);
7373 TALLOC_FREE(smb_fname_src);
7374 TALLOC_FREE(smb_fname_dst);
7379 /*******************************************************************
7380 Copy a file as part of a reply_copy.
7381 ******************************************************************/
7384 * TODO: check error codes on all callers
7387 NTSTATUS copy_file(TALLOC_CTX *ctx,
7388 connection_struct *conn,
7389 struct smb_filename *smb_fname_src,
7390 struct smb_filename *smb_fname_dst,
7393 bool target_is_directory)
7395 struct smb_filename *smb_fname_dst_tmp = NULL;
7397 files_struct *fsp1,*fsp2;
7399 uint32_t new_create_disposition;
7403 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7404 if (smb_fname_dst_tmp == NULL) {
7405 return NT_STATUS_NO_MEMORY;
7409 * If the target is a directory, extract the last component from the
7410 * src filename and append it to the dst filename
7412 if (target_is_directory) {
7415 /* dest/target can't be a stream if it's a directory. */
7416 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7418 p = strrchr_m(smb_fname_src->base_name,'/');
7422 p = smb_fname_src->base_name;
7424 smb_fname_dst_tmp->base_name =
7425 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7427 if (!smb_fname_dst_tmp->base_name) {
7428 status = NT_STATUS_NO_MEMORY;
7433 status = vfs_file_exist(conn, smb_fname_src);
7434 if (!NT_STATUS_IS_OK(status)) {
7438 if (!target_is_directory && count) {
7439 new_create_disposition = FILE_OPEN;
7441 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7444 &new_create_disposition,
7447 status = NT_STATUS_INVALID_PARAMETER;
7452 /* Open the src file for reading. */
7453 status = SMB_VFS_CREATE_FILE(
7456 0, /* root_dir_fid */
7457 smb_fname_src, /* fname */
7458 FILE_GENERIC_READ, /* access_mask */
7459 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7460 FILE_OPEN, /* create_disposition*/
7461 0, /* create_options */
7462 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7463 INTERNAL_OPEN_ONLY, /* oplock_request */
7465 0, /* allocation_size */
7466 0, /* private_flags */
7471 NULL, NULL); /* create context */
7473 if (!NT_STATUS_IS_OK(status)) {
7477 dosattrs = dos_mode(conn, smb_fname_src);
7479 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7480 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7483 /* Open the dst file for writing. */
7484 status = SMB_VFS_CREATE_FILE(
7487 0, /* root_dir_fid */
7488 smb_fname_dst, /* fname */
7489 FILE_GENERIC_WRITE, /* access_mask */
7490 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7491 new_create_disposition, /* create_disposition*/
7492 0, /* create_options */
7493 dosattrs, /* file_attributes */
7494 INTERNAL_OPEN_ONLY, /* oplock_request */
7496 0, /* allocation_size */
7497 0, /* private_flags */
7502 NULL, NULL); /* create context */
7504 if (!NT_STATUS_IS_OK(status)) {
7505 close_file(NULL, fsp1, ERROR_CLOSE);
7509 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7510 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7512 DEBUG(0, ("error - vfs lseek returned error %s\n",
7514 status = map_nt_error_from_unix(errno);
7515 close_file(NULL, fsp1, ERROR_CLOSE);
7516 close_file(NULL, fsp2, ERROR_CLOSE);
7521 /* Do the actual copy. */
7522 if (smb_fname_src->st.st_ex_size) {
7523 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7528 close_file(NULL, fsp1, NORMAL_CLOSE);
7530 /* Ensure the modtime is set correctly on the destination file. */
7531 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7534 * As we are opening fsp1 read-only we only expect
7535 * an error on close on fsp2 if we are out of space.
7536 * Thus we don't look at the error return from the
7539 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7541 if (!NT_STATUS_IS_OK(status)) {
7545 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7546 status = NT_STATUS_DISK_FULL;
7550 status = NT_STATUS_OK;
7553 TALLOC_FREE(smb_fname_dst_tmp);
7557 /****************************************************************************
7558 Reply to a file copy.
7559 ****************************************************************************/
7561 void reply_copy(struct smb_request *req)
7563 connection_struct *conn = req->conn;
7564 struct smb_filename *smb_fname_src = NULL;
7565 struct smb_filename *smb_fname_src_dir = NULL;
7566 struct smb_filename *smb_fname_dst = NULL;
7567 char *fname_src = NULL;
7568 char *fname_dst = NULL;
7569 char *fname_src_mask = NULL;
7570 char *fname_src_dir = NULL;
7573 int error = ERRnoaccess;
7577 bool target_is_directory=False;
7578 bool source_has_wild = False;
7579 bool dest_has_wild = False;
7581 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7582 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7583 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7584 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7585 TALLOC_CTX *ctx = talloc_tos();
7587 START_PROFILE(SMBcopy);
7590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7594 tid2 = SVAL(req->vwv+0, 0);
7595 ofun = SVAL(req->vwv+1, 0);
7596 flags = SVAL(req->vwv+2, 0);
7598 p = (const char *)req->buf;
7599 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7600 &status, &source_has_wild);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 reply_nterror(req, status);
7605 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7606 &status, &dest_has_wild);
7607 if (!NT_STATUS_IS_OK(status)) {
7608 reply_nterror(req, status);
7612 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7614 if (tid2 != conn->cnum) {
7615 /* can't currently handle inter share copies XXXX */
7616 DEBUG(3,("Rejecting inter-share copy\n"));
7617 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7621 status = filename_convert(ctx, conn,
7622 req->flags2 & FLAGS2_DFS_PATHNAMES,
7627 if (!NT_STATUS_IS_OK(status)) {
7628 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7629 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7630 ERRSRV, ERRbadpath);
7633 reply_nterror(req, status);
7637 status = filename_convert(ctx, conn,
7638 req->flags2 & FLAGS2_DFS_PATHNAMES,
7643 if (!NT_STATUS_IS_OK(status)) {
7644 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7645 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7646 ERRSRV, ERRbadpath);
7649 reply_nterror(req, status);
7653 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7655 if ((flags&1) && target_is_directory) {
7656 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7660 if ((flags&2) && !target_is_directory) {
7661 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7665 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7666 /* wants a tree copy! XXXX */
7667 DEBUG(3,("Rejecting tree copy\n"));
7668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7672 /* Split up the directory from the filename/mask. */
7673 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7674 &fname_src_dir, &fname_src_mask);
7675 if (!NT_STATUS_IS_OK(status)) {
7676 reply_nterror(req, NT_STATUS_NO_MEMORY);
7681 * We should only check the mangled cache
7682 * here if unix_convert failed. This means
7683 * that the path in 'mask' doesn't exist
7684 * on the file system and so we need to look
7685 * for a possible mangle. This patch from
7686 * Tine Smukavec <valentin.smukavec@hermes.si>.
7688 if (!VALID_STAT(smb_fname_src->st) &&
7689 mangle_is_mangled(fname_src_mask, conn->params)) {
7690 char *new_mask = NULL;
7691 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7692 &new_mask, conn->params);
7694 /* Use demangled name if one was successfully found. */
7696 TALLOC_FREE(fname_src_mask);
7697 fname_src_mask = new_mask;
7701 if (!source_has_wild) {
7704 * Only one file needs to be copied. Append the mask back onto
7707 TALLOC_FREE(smb_fname_src->base_name);
7708 if (ISDOT(fname_src_dir)) {
7709 /* Ensure we use canonical names on open. */
7710 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7714 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7719 if (!smb_fname_src->base_name) {
7720 reply_nterror(req, NT_STATUS_NO_MEMORY);
7724 if (dest_has_wild) {
7725 char *fname_dst_mod = NULL;
7726 if (!resolve_wildcards(smb_fname_dst,
7727 smb_fname_src->base_name,
7728 smb_fname_dst->base_name,
7730 reply_nterror(req, NT_STATUS_NO_MEMORY);
7733 TALLOC_FREE(smb_fname_dst->base_name);
7734 smb_fname_dst->base_name = fname_dst_mod;
7737 status = check_name(conn, smb_fname_src->base_name);
7738 if (!NT_STATUS_IS_OK(status)) {
7739 reply_nterror(req, status);
7743 status = check_name(conn, smb_fname_dst->base_name);
7744 if (!NT_STATUS_IS_OK(status)) {
7745 reply_nterror(req, status);
7749 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7750 ofun, count, target_is_directory);
7752 if(!NT_STATUS_IS_OK(status)) {
7753 reply_nterror(req, status);
7759 struct smb_Dir *dir_hnd = NULL;
7760 const char *dname = NULL;
7761 char *talloced = NULL;
7765 * There is a wildcard that requires us to actually read the
7766 * src dir and copy each file matching the mask to the dst.
7767 * Right now streams won't be copied, but this could
7768 * presumably be added with a nested loop for reach dir entry.
7770 SMB_ASSERT(!smb_fname_src->stream_name);
7771 SMB_ASSERT(!smb_fname_dst->stream_name);
7773 smb_fname_src->stream_name = NULL;
7774 smb_fname_dst->stream_name = NULL;
7776 if (strequal(fname_src_mask,"????????.???")) {
7777 TALLOC_FREE(fname_src_mask);
7778 fname_src_mask = talloc_strdup(ctx, "*");
7779 if (!fname_src_mask) {
7780 reply_nterror(req, NT_STATUS_NO_MEMORY);
7785 status = check_name(conn, fname_src_dir);
7786 if (!NT_STATUS_IS_OK(status)) {
7787 reply_nterror(req, status);
7791 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7795 smb_fname_src->flags);
7796 if (smb_fname_src_dir == NULL) {
7797 reply_nterror(req, NT_STATUS_NO_MEMORY);
7801 dir_hnd = OpenDir(ctx,
7806 if (dir_hnd == NULL) {
7807 status = map_nt_error_from_unix(errno);
7808 reply_nterror(req, status);
7814 /* Iterate over the src dir copying each entry to the dst. */
7815 while ((dname = ReadDirName(dir_hnd, &offset,
7816 &smb_fname_src->st, &talloced))) {
7817 char *destname = NULL;
7819 if (ISDOT(dname) || ISDOTDOT(dname)) {
7820 TALLOC_FREE(talloced);
7824 if (!is_visible_file(conn, fname_src_dir, dname,
7825 &smb_fname_src->st, false)) {
7826 TALLOC_FREE(talloced);
7830 if(!mask_match(dname, fname_src_mask,
7831 conn->case_sensitive)) {
7832 TALLOC_FREE(talloced);
7836 error = ERRnoaccess;
7838 /* Get the src smb_fname struct setup. */
7839 TALLOC_FREE(smb_fname_src->base_name);
7840 if (ISDOT(fname_src_dir)) {
7841 /* Ensure we use canonical names on open. */
7842 smb_fname_src->base_name =
7843 talloc_asprintf(smb_fname_src, "%s",
7846 smb_fname_src->base_name =
7847 talloc_asprintf(smb_fname_src, "%s/%s",
7848 fname_src_dir, dname);
7851 if (!smb_fname_src->base_name) {
7852 TALLOC_FREE(dir_hnd);
7853 TALLOC_FREE(talloced);
7854 reply_nterror(req, NT_STATUS_NO_MEMORY);
7858 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7859 smb_fname_dst->base_name,
7861 TALLOC_FREE(talloced);
7865 TALLOC_FREE(dir_hnd);
7866 TALLOC_FREE(talloced);
7867 reply_nterror(req, NT_STATUS_NO_MEMORY);
7871 TALLOC_FREE(smb_fname_dst->base_name);
7872 smb_fname_dst->base_name = destname;
7874 status = check_name(conn, smb_fname_src->base_name);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 TALLOC_FREE(dir_hnd);
7877 TALLOC_FREE(talloced);
7878 reply_nterror(req, status);
7882 status = check_name(conn, smb_fname_dst->base_name);
7883 if (!NT_STATUS_IS_OK(status)) {
7884 TALLOC_FREE(dir_hnd);
7885 TALLOC_FREE(talloced);
7886 reply_nterror(req, status);
7890 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7891 smb_fname_src->base_name,
7892 smb_fname_dst->base_name));
7894 status = copy_file(ctx, conn, smb_fname_src,
7895 smb_fname_dst, ofun, count,
7896 target_is_directory);
7897 if (NT_STATUS_IS_OK(status)) {
7901 TALLOC_FREE(talloced);
7903 TALLOC_FREE(dir_hnd);
7907 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7911 reply_outbuf(req, 1, 0);
7912 SSVAL(req->outbuf,smb_vwv0,count);
7914 TALLOC_FREE(smb_fname_src);
7915 TALLOC_FREE(smb_fname_src_dir);
7916 TALLOC_FREE(smb_fname_dst);
7917 TALLOC_FREE(fname_src);
7918 TALLOC_FREE(fname_dst);
7919 TALLOC_FREE(fname_src_mask);
7920 TALLOC_FREE(fname_src_dir);
7922 END_PROFILE(SMBcopy);
7927 #define DBGC_CLASS DBGC_LOCKING
7929 /****************************************************************************
7930 Get a lock pid, dealing with large count requests.
7931 ****************************************************************************/
7933 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7934 bool large_file_format)
7936 if(!large_file_format)
7937 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7939 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7942 /****************************************************************************
7943 Get a lock count, dealing with large count requests.
7944 ****************************************************************************/
7946 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7947 bool large_file_format)
7951 if(!large_file_format) {
7952 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7955 * No BVAL, this is reversed!
7957 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7958 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7964 /****************************************************************************
7965 Get a lock offset, dealing with large offset requests.
7966 ****************************************************************************/
7968 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7969 bool large_file_format)
7971 uint64_t offset = 0;
7973 if(!large_file_format) {
7974 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7977 * No BVAL, this is reversed!
7979 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7980 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7986 NTSTATUS smbd_do_locking(struct smb_request *req,
7991 struct smbd_lock_element *locks,
7994 connection_struct *conn = req->conn;
7996 NTSTATUS status = NT_STATUS_OK;
8000 /* Setup the timeout in seconds. */
8002 if (!lp_blocking_locks(SNUM(conn))) {
8006 for(i = 0; i < (int)num_locks; i++) {
8007 struct smbd_lock_element *e = &locks[i];
8009 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8010 "%llu, file %s timeout = %d\n",
8013 (unsigned long long)e->smblctx,
8017 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8018 struct blocking_lock_record *blr = NULL;
8020 if (num_locks > 1) {
8022 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8023 * if the lock vector contains one entry. When given multiple cancel
8024 * requests in a single PDU we expect the server to return an
8025 * error. Windows servers seem to accept the request but only
8026 * cancel the first lock.
8027 * JRA - Do what Windows does (tm) :-).
8031 /* MS-CIFS (2.2.4.32.1) behavior. */
8032 return NT_STATUS_DOS(ERRDOS,
8033 ERRcancelviolation);
8035 /* Windows behavior. */
8037 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8038 "cancel request\n"));
8044 if (lp_blocking_locks(SNUM(conn))) {
8046 /* Schedule a message to ourselves to
8047 remove the blocking lock record and
8048 return the right error. */
8050 blr = blocking_lock_cancel_smb1(fsp,
8056 NT_STATUS_FILE_LOCK_CONFLICT);
8058 return NT_STATUS_DOS(
8060 ERRcancelviolation);
8063 /* Remove a matching pending lock. */
8064 status = do_lock_cancel(fsp,
8070 bool blocking_lock = timeout ? true : false;
8071 bool defer_lock = false;
8072 struct byte_range_lock *br_lck;
8073 uint64_t block_smblctx;
8075 br_lck = do_lock(req->sconn->msg_ctx,
8086 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8087 /* Windows internal resolution for blocking locks seems
8088 to be about 200ms... Don't wait for less than that. JRA. */
8089 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8090 timeout = lp_lock_spin_time();
8095 /* If a lock sent with timeout of zero would fail, and
8096 * this lock has been requested multiple times,
8097 * according to brl_lock_failed() we convert this
8098 * request to a blocking lock with a timeout of between
8099 * 150 - 300 milliseconds.
8101 * If lp_lock_spin_time() has been set to 0, we skip
8102 * this blocking retry and fail immediately.
8104 * Replacement for do_lock_spin(). JRA. */
8106 if (!req->sconn->using_smb2 &&
8107 br_lck && lp_blocking_locks(SNUM(conn)) &&
8108 lp_lock_spin_time() && !blocking_lock &&
8109 NT_STATUS_EQUAL((status),
8110 NT_STATUS_FILE_LOCK_CONFLICT))
8113 timeout = lp_lock_spin_time();
8116 if (br_lck && defer_lock) {
8118 * A blocking lock was requested. Package up
8119 * this smb into a queued request and push it
8120 * onto the blocking lock queue.
8122 if(push_blocking_lock_request(br_lck,
8133 TALLOC_FREE(br_lck);
8135 return NT_STATUS_OK;
8139 TALLOC_FREE(br_lck);
8142 if (!NT_STATUS_IS_OK(status)) {
8147 /* If any of the above locks failed, then we must unlock
8148 all of the previous locks (X/Open spec). */
8150 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8152 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8153 i = -1; /* we want to skip the for loop */
8157 * Ensure we don't do a remove on the lock that just failed,
8158 * as under POSIX rules, if we have a lock already there, we
8159 * will delete it (and we shouldn't) .....
8161 for(i--; i >= 0; i--) {
8162 struct smbd_lock_element *e = &locks[i];
8164 do_unlock(req->sconn->msg_ctx,
8174 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8175 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8177 return NT_STATUS_OK;
8180 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8182 uint16_t num_ulocks,
8183 struct smbd_lock_element *ulocks)
8187 for(i = 0; i < (int)num_ulocks; i++) {
8188 struct smbd_lock_element *e = &ulocks[i];
8191 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8192 "pid %u, file %s\n", __func__,
8195 (unsigned int)e->smblctx,
8198 if (e->brltype != UNLOCK_LOCK) {
8199 /* this can only happen with SMB2 */
8200 return NT_STATUS_INVALID_PARAMETER;
8203 status = do_unlock(req->sconn->msg_ctx,
8210 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8211 nt_errstr(status)));
8213 if (!NT_STATUS_IS_OK(status)) {
8218 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8221 return NT_STATUS_OK;
8224 /****************************************************************************
8225 Reply to a lockingX request.
8226 ****************************************************************************/
8228 void reply_lockingX(struct smb_request *req)
8230 connection_struct *conn = req->conn;
8232 unsigned char locktype;
8233 unsigned char oplocklevel;
8234 uint16_t num_ulocks;
8236 int32_t lock_timeout;
8238 const uint8_t *data;
8239 bool large_file_format;
8240 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8241 struct smbd_lock_element *ulocks;
8242 struct smbd_lock_element *locks;
8245 START_PROFILE(SMBlockingX);
8248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8249 END_PROFILE(SMBlockingX);
8253 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8254 locktype = CVAL(req->vwv+3, 0);
8255 oplocklevel = CVAL(req->vwv+3, 1);
8256 num_ulocks = SVAL(req->vwv+6, 0);
8257 num_locks = SVAL(req->vwv+7, 0);
8258 lock_timeout = IVAL(req->vwv+4, 0);
8259 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8261 if (!check_fsp(conn, req, fsp)) {
8262 END_PROFILE(SMBlockingX);
8268 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8269 /* we don't support these - and CANCEL_LOCK makes w2k
8270 and XP reboot so I don't really want to be
8271 compatible! (tridge) */
8272 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8273 END_PROFILE(SMBlockingX);
8277 /* Check if this is an oplock break on a file
8278 we have granted an oplock on.
8280 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8281 /* Client can insist on breaking to none. */
8282 bool break_to_none = (oplocklevel == 0);
8285 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8286 "for %s\n", (unsigned int)oplocklevel,
8287 fsp_fnum_dbg(fsp)));
8290 * Make sure we have granted an exclusive or batch oplock on
8294 if (fsp->oplock_type == 0) {
8296 /* The Samba4 nbench simulator doesn't understand
8297 the difference between break to level2 and break
8298 to none from level2 - it sends oplock break
8299 replies in both cases. Don't keep logging an error
8300 message here - just ignore it. JRA. */
8302 DEBUG(5,("reply_lockingX: Error : oplock break from "
8303 "client for %s (oplock=%d) and no "
8304 "oplock granted on this file (%s).\n",
8305 fsp_fnum_dbg(fsp), fsp->oplock_type,
8308 /* if this is a pure oplock break request then don't
8310 if (num_locks == 0 && num_ulocks == 0) {
8311 END_PROFILE(SMBlockingX);
8314 END_PROFILE(SMBlockingX);
8315 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8320 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8322 result = remove_oplock(fsp);
8324 result = downgrade_oplock(fsp);
8328 DEBUG(0, ("reply_lockingX: error in removing "
8329 "oplock on file %s\n", fsp_str_dbg(fsp)));
8330 /* Hmmm. Is this panic justified? */
8331 smb_panic("internal tdb error");
8334 /* if this is a pure oplock break request then don't send a
8336 if (num_locks == 0 && num_ulocks == 0) {
8337 /* Sanity check - ensure a pure oplock break is not a
8339 if (CVAL(req->vwv+0, 0) != 0xff) {
8340 DEBUG(0,("reply_lockingX: Error : pure oplock "
8341 "break is a chained %d request !\n",
8342 (unsigned int)CVAL(req->vwv+0, 0)));
8344 END_PROFILE(SMBlockingX);
8350 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8352 END_PROFILE(SMBlockingX);
8356 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8357 if (ulocks == NULL) {
8358 reply_nterror(req, NT_STATUS_NO_MEMORY);
8359 END_PROFILE(SMBlockingX);
8363 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8364 if (locks == NULL) {
8365 reply_nterror(req, NT_STATUS_NO_MEMORY);
8366 END_PROFILE(SMBlockingX);
8370 /* Data now points at the beginning of the list
8371 of smb_unlkrng structs */
8372 for(i = 0; i < (int)num_ulocks; i++) {
8373 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8374 ulocks[i].count = get_lock_count(data, i, large_file_format);
8375 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8376 ulocks[i].brltype = UNLOCK_LOCK;
8379 /* Now do any requested locks */
8380 data += ((large_file_format ? 20 : 10)*num_ulocks);
8382 /* Data now points at the beginning of the list
8383 of smb_lkrng structs */
8385 for(i = 0; i < (int)num_locks; i++) {
8386 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8387 locks[i].count = get_lock_count(data, i, large_file_format);
8388 locks[i].offset = get_lock_offset(data, i, large_file_format);
8390 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8391 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8392 locks[i].brltype = PENDING_READ_LOCK;
8394 locks[i].brltype = READ_LOCK;
8397 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8398 locks[i].brltype = PENDING_WRITE_LOCK;
8400 locks[i].brltype = WRITE_LOCK;
8405 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8406 if (!NT_STATUS_IS_OK(status)) {
8407 END_PROFILE(SMBlockingX);
8408 reply_nterror(req, status);
8412 status = smbd_do_locking(req, fsp,
8413 locktype, lock_timeout,
8416 if (!NT_STATUS_IS_OK(status)) {
8417 END_PROFILE(SMBlockingX);
8418 reply_nterror(req, status);
8422 END_PROFILE(SMBlockingX);
8426 reply_outbuf(req, 2, 0);
8427 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8428 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8430 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8431 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8433 END_PROFILE(SMBlockingX);
8437 #define DBGC_CLASS DBGC_ALL
8439 /****************************************************************************
8440 Reply to a SMBreadbmpx (read block multiplex) request.
8441 Always reply with an error, if someone has a platform really needs this,
8442 please contact vl@samba.org
8443 ****************************************************************************/
8445 void reply_readbmpx(struct smb_request *req)
8447 START_PROFILE(SMBreadBmpx);
8448 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8449 END_PROFILE(SMBreadBmpx);
8453 /****************************************************************************
8454 Reply to a SMBreadbs (read block multiplex secondary) request.
8455 Always reply with an error, if someone has a platform really needs this,
8456 please contact vl@samba.org
8457 ****************************************************************************/
8459 void reply_readbs(struct smb_request *req)
8461 START_PROFILE(SMBreadBs);
8462 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8463 END_PROFILE(SMBreadBs);
8467 /****************************************************************************
8468 Reply to a SMBsetattrE.
8469 ****************************************************************************/
8471 void reply_setattrE(struct smb_request *req)
8473 connection_struct *conn = req->conn;
8474 struct smb_file_time ft;
8478 START_PROFILE(SMBsetattrE);
8482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8486 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8488 if(!fsp || (fsp->conn != conn)) {
8489 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8494 * Convert the DOS times into unix times.
8497 ft.atime = convert_time_t_to_timespec(
8498 srv_make_unix_date2(req->vwv+3));
8499 ft.mtime = convert_time_t_to_timespec(
8500 srv_make_unix_date2(req->vwv+5));
8501 ft.create_time = convert_time_t_to_timespec(
8502 srv_make_unix_date2(req->vwv+1));
8504 reply_outbuf(req, 0, 0);
8507 * Patch from Ray Frush <frush@engr.colostate.edu>
8508 * Sometimes times are sent as zero - ignore them.
8511 /* Ensure we have a valid stat struct for the source. */
8512 status = vfs_stat_fsp(fsp);
8513 if (!NT_STATUS_IS_OK(status)) {
8514 reply_nterror(req, status);
8518 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8519 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8523 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8524 if (!NT_STATUS_IS_OK(status)) {
8525 reply_nterror(req, status);
8529 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8532 (unsigned int)ft.atime.tv_sec,
8533 (unsigned int)ft.mtime.tv_sec,
8534 (unsigned int)ft.create_time.tv_sec
8537 END_PROFILE(SMBsetattrE);
8542 /* Back from the dead for OS/2..... JRA. */
8544 /****************************************************************************
8545 Reply to a SMBwritebmpx (write block multiplex primary) request.
8546 Always reply with an error, if someone has a platform really needs this,
8547 please contact vl@samba.org
8548 ****************************************************************************/
8550 void reply_writebmpx(struct smb_request *req)
8552 START_PROFILE(SMBwriteBmpx);
8553 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8554 END_PROFILE(SMBwriteBmpx);
8558 /****************************************************************************
8559 Reply to a SMBwritebs (write block multiplex secondary) request.
8560 Always reply with an error, if someone has a platform really needs this,
8561 please contact vl@samba.org
8562 ****************************************************************************/
8564 void reply_writebs(struct smb_request *req)
8566 START_PROFILE(SMBwriteBs);
8567 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8568 END_PROFILE(SMBwriteBs);
8572 /****************************************************************************
8573 Reply to a SMBgetattrE.
8574 ****************************************************************************/
8576 void reply_getattrE(struct smb_request *req)
8578 connection_struct *conn = req->conn;
8581 struct timespec create_ts;
8583 START_PROFILE(SMBgetattrE);
8586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8587 END_PROFILE(SMBgetattrE);
8591 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8593 if(!fsp || (fsp->conn != conn)) {
8594 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8595 END_PROFILE(SMBgetattrE);
8599 /* Do an fstat on this file */
8601 reply_nterror(req, map_nt_error_from_unix(errno));
8602 END_PROFILE(SMBgetattrE);
8606 mode = dos_mode(conn, fsp->fsp_name);
8609 * Convert the times into dos times. Set create
8610 * date to be last modify date as UNIX doesn't save
8614 reply_outbuf(req, 11, 0);
8616 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8617 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8618 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8619 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8620 /* Should we check pending modtime here ? JRA */
8621 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8622 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8624 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8625 SIVAL(req->outbuf, smb_vwv6, 0);
8626 SIVAL(req->outbuf, smb_vwv8, 0);
8628 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8629 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8630 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8632 SSVAL(req->outbuf,smb_vwv10, mode);
8634 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8636 END_PROFILE(SMBgetattrE);