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,
323 lp_posix_pathnames(),
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 if (lp_posix_pathnames()) {
370 return srvstr_get_path_wcard_internal(ctx,
381 return srvstr_get_path_wcard_internal(ctx,
394 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
395 char **pp_dest, const char *src, int flags,
396 NTSTATUS *err, bool *contains_wcard)
398 ssize_t bufrem = smbreq_bufrem(req, src);
401 *err = NT_STATUS_INVALID_PARAMETER;
405 if (lp_posix_pathnames()) {
406 return srvstr_get_path_wcard_internal(mem_ctx,
407 (const char *)req->inbuf,
417 return srvstr_get_path_wcard_internal(mem_ctx,
418 (const char *)req->inbuf,
430 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
431 char **pp_dest, const char *src, int flags,
435 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
436 flags, err, &ignore);
440 * pull a string from the smb_buf part of a packet. In this case the
441 * string can either be null terminated or it can be terminated by the
442 * end of the smbbuf area
444 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
445 char **dest, const uint8_t *src, int flags)
447 ssize_t bufrem = smbreq_bufrem(req, src);
453 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
457 /****************************************************************************
458 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
459 ****************************************************************************/
461 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
464 if ((fsp == NULL) || (conn == NULL)) {
465 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
468 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
469 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
475 /****************************************************************************
476 Check if we have a correct fsp pointing to a file.
477 ****************************************************************************/
479 bool check_fsp(connection_struct *conn, struct smb_request *req,
482 if (!check_fsp_open(conn, req, fsp)) {
485 if (fsp->is_directory) {
486 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
489 if (fsp->fh->fd == -1) {
490 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
493 fsp->num_smb_operations++;
497 /****************************************************************************
498 Check if we have a correct fsp pointing to a quota fake file. Replacement for
499 the CHECK_NTQUOTA_HANDLE_OK macro.
500 ****************************************************************************/
502 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
505 if (!check_fsp_open(conn, req, fsp)) {
509 if (fsp->is_directory) {
513 if (fsp->fake_file_handle == NULL) {
517 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
521 if (fsp->fake_file_handle->private_data == NULL) {
528 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
529 const char *name, int name_type)
532 char *trim_name_type;
533 const char *retarget_parm;
536 int retarget_type = 0x20;
537 int retarget_port = NBT_SMB_PORT;
538 struct sockaddr_storage retarget_addr;
539 struct sockaddr_in *in_addr;
543 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
547 trim_name = talloc_strdup(talloc_tos(), name);
548 if (trim_name == NULL) {
551 trim_char(trim_name, ' ', ' ');
553 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
555 if (trim_name_type == NULL) {
559 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
560 trim_name_type, NULL);
561 if (retarget_parm == NULL) {
562 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
565 if (retarget_parm == NULL) {
569 retarget = talloc_strdup(trim_name, retarget_parm);
570 if (retarget == NULL) {
574 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
576 p = strchr(retarget, ':');
579 retarget_port = atoi(p);
582 p = strchr_m(retarget, '#');
585 if (sscanf(p, "%x", &retarget_type) != 1) {
590 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
592 DEBUG(10, ("could not resolve %s\n", retarget));
596 if (retarget_addr.ss_family != AF_INET) {
597 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
601 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
603 _smb_setlen(outbuf, 6);
604 SCVAL(outbuf, 0, 0x84);
605 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
606 *(uint16_t *)(outbuf+8) = htons(retarget_port);
608 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
610 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
616 TALLOC_FREE(trim_name);
620 static void reply_called_name_not_present(char *outbuf)
622 smb_setlen(outbuf, 1);
623 SCVAL(outbuf, 0, 0x83);
624 SCVAL(outbuf, 4, 0x82);
627 /****************************************************************************
628 Reply to a (netbios-level) special message.
629 ****************************************************************************/
631 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
633 struct smbd_server_connection *sconn = xconn->client->sconn;
634 int msg_type = CVAL(inbuf,0);
635 int msg_flags = CVAL(inbuf,1);
637 * We only really use 4 bytes of the outbuf, but for the smb_setlen
638 * calculation & friends (srv_send_smb uses that) we need the full smb
641 char outbuf[smb_size];
643 memset(outbuf, '\0', sizeof(outbuf));
645 smb_setlen(outbuf,0);
648 case NBSSrequest: /* session request */
650 /* inbuf_size is guarenteed to be at least 4. */
652 int name_type1, name_type2;
653 int name_len1, name_len2;
657 if (xconn->transport.nbt.got_session) {
658 exit_server_cleanly("multiple session request not permitted");
661 SCVAL(outbuf,0,NBSSpositive);
664 /* inbuf_size is guaranteed to be at least 4. */
665 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
666 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
667 DEBUG(0,("Invalid name length in session request\n"));
668 reply_called_name_not_present(outbuf);
671 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
672 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
673 DEBUG(0,("Invalid name length in session request\n"));
674 reply_called_name_not_present(outbuf);
678 name_type1 = name_extract((unsigned char *)inbuf,
679 inbuf_size,(unsigned int)4,name1);
680 name_type2 = name_extract((unsigned char *)inbuf,
681 inbuf_size,(unsigned int)(4 + name_len1),name2);
683 if (name_type1 == -1 || name_type2 == -1) {
684 DEBUG(0,("Invalid name type in session request\n"));
685 reply_called_name_not_present(outbuf);
689 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
690 name1, name_type1, name2, name_type2));
692 if (netbios_session_retarget(xconn, name1, name_type1)) {
693 exit_server_cleanly("retargeted client");
697 * Windows NT/2k uses "*SMBSERVER" and XP uses
698 * "*SMBSERV" arrggg!!!
700 if (strequal(name1, "*SMBSERVER ")
701 || strequal(name1, "*SMBSERV ")) {
704 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
707 exit_server_cleanly("could not allocate raddr");
710 fstrcpy(name1, raddr);
713 set_local_machine_name(name1, True);
714 set_remote_machine_name(name2, True);
716 if (is_ipaddress(sconn->remote_hostname)) {
717 char *p = discard_const_p(char, sconn->remote_hostname);
721 sconn->remote_hostname = talloc_strdup(sconn,
722 get_remote_machine_name());
723 if (sconn->remote_hostname == NULL) {
724 exit_server_cleanly("could not copy remote name");
726 xconn->remote_hostname = sconn->remote_hostname;
729 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
730 get_local_machine_name(), get_remote_machine_name(),
733 if (name_type2 == 'R') {
734 /* We are being asked for a pathworks session ---
736 reply_called_name_not_present(outbuf);
740 reload_services(sconn, conn_snum_used, true);
743 xconn->transport.nbt.got_session = true;
747 case 0x89: /* session keepalive request
748 (some old clients produce this?) */
749 SCVAL(outbuf,0,NBSSkeepalive);
753 case NBSSpositive: /* positive session response */
754 case NBSSnegative: /* negative session response */
755 case NBSSretarget: /* retarget session response */
756 DEBUG(0,("Unexpected session response\n"));
759 case NBSSkeepalive: /* session keepalive */
764 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
765 msg_type, msg_flags));
767 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
769 if (CVAL(outbuf, 0) != 0x82) {
770 exit_server_cleanly("invalid netbios session");
775 /****************************************************************************
777 conn POINTER CAN BE NULL HERE !
778 ****************************************************************************/
780 void reply_tcon(struct smb_request *req)
782 connection_struct *conn = req->conn;
784 char *service_buf = NULL;
785 char *password = NULL;
791 TALLOC_CTX *ctx = talloc_tos();
792 struct smbXsrv_connection *xconn = req->xconn;
793 NTTIME now = timeval_to_nttime(&req->request_time);
795 START_PROFILE(SMBtcon);
797 if (req->buflen < 4) {
798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
799 END_PROFILE(SMBtcon);
804 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
806 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
808 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
811 if (service_buf == NULL || password == NULL || dev == NULL) {
812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
813 END_PROFILE(SMBtcon);
816 p2 = strrchr_m(service_buf,'\\');
820 service = service_buf;
823 conn = make_connection(req, now, service, dev,
824 req->vuid,&nt_status);
828 reply_nterror(req, nt_status);
829 END_PROFILE(SMBtcon);
833 reply_outbuf(req, 2, 0);
834 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
835 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
836 SSVAL(req->outbuf,smb_tid,conn->cnum);
838 DEBUG(3,("tcon service=%s cnum=%d\n",
839 service, conn->cnum));
841 END_PROFILE(SMBtcon);
845 /****************************************************************************
846 Reply to a tcon and X.
847 conn POINTER CAN BE NULL HERE !
848 ****************************************************************************/
850 void reply_tcon_and_X(struct smb_request *req)
852 connection_struct *conn = req->conn;
853 const char *service = NULL;
854 TALLOC_CTX *ctx = talloc_tos();
855 /* what the cleint thinks the device is */
856 char *client_devicetype = NULL;
857 /* what the server tells the client the share represents */
858 const char *server_devicetype;
865 struct smbXsrv_session *session = NULL;
866 NTTIME now = timeval_to_nttime(&req->request_time);
867 bool session_key_updated = false;
868 uint16_t optional_support = 0;
869 struct smbXsrv_connection *xconn = req->xconn;
871 START_PROFILE(SMBtconX);
874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
875 END_PROFILE(SMBtconX);
879 passlen = SVAL(req->vwv+3, 0);
880 tcon_flags = SVAL(req->vwv+2, 0);
882 /* we might have to close an old one */
883 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
884 struct smbXsrv_tcon *tcon;
892 * TODO: cancel all outstanding requests on the tcon
894 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
895 if (!NT_STATUS_IS_OK(status)) {
896 DEBUG(0, ("reply_tcon_and_X: "
897 "smbXsrv_tcon_disconnect() failed: %s\n",
900 * If we hit this case, there is something completely
901 * wrong, so we better disconnect the transport connection.
903 END_PROFILE(SMBtconX);
904 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
911 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
912 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
913 END_PROFILE(SMBtconX);
917 if (xconn->smb1.negprot.encrypted_passwords) {
918 p = req->buf + passlen;
920 p = req->buf + passlen + 1;
923 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
927 END_PROFILE(SMBtconX);
932 * the service name can be either: \\server\share
933 * or share directly like on the DELL PowerVault 705
936 q = strchr_m(path+2,'\\');
938 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
939 END_PROFILE(SMBtconX);
947 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
948 &client_devicetype, p,
949 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
951 if (client_devicetype == NULL) {
952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
953 END_PROFILE(SMBtconX);
957 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
959 nt_status = smb1srv_session_lookup(xconn,
960 req->vuid, now, &session);
961 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
962 reply_force_doserror(req, ERRSRV, ERRbaduid);
963 END_PROFILE(SMBtconX);
966 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
967 reply_nterror(req, nt_status);
968 END_PROFILE(SMBtconX);
971 if (!NT_STATUS_IS_OK(nt_status)) {
972 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
973 END_PROFILE(SMBtconX);
977 if (session->global->auth_session_info == NULL) {
978 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
979 END_PROFILE(SMBtconX);
984 * If there is no application key defined yet
987 * This means we setup the application key on the
988 * first tcon that happens via the given session.
990 * Once the application key is defined, it does not
993 if (session->global->application_key.length == 0 &&
994 session->global->signing_key.length > 0)
996 struct smbXsrv_session *x = session;
997 struct auth_session_info *session_info =
998 session->global->auth_session_info;
999 uint8_t session_key[16];
1001 ZERO_STRUCT(session_key);
1002 memcpy(session_key, x->global->signing_key.data,
1003 MIN(x->global->signing_key.length, sizeof(session_key)));
1006 * The application key is truncated/padded to 16 bytes
1008 x->global->application_key = data_blob_talloc(x->global,
1010 sizeof(session_key));
1011 ZERO_STRUCT(session_key);
1012 if (x->global->application_key.data == NULL) {
1013 reply_nterror(req, NT_STATUS_NO_MEMORY);
1014 END_PROFILE(SMBtconX);
1018 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1019 smb_key_derivation(x->global->application_key.data,
1020 x->global->application_key.length,
1021 x->global->application_key.data);
1022 optional_support |= SMB_EXTENDED_SIGNATURES;
1026 * Place the application key into the session_info
1028 data_blob_clear_free(&session_info->session_key);
1029 session_info->session_key = data_blob_dup_talloc(session_info,
1030 x->global->application_key);
1031 if (session_info->session_key.data == NULL) {
1032 data_blob_clear_free(&x->global->application_key);
1033 reply_nterror(req, NT_STATUS_NO_MEMORY);
1034 END_PROFILE(SMBtconX);
1037 session_key_updated = true;
1040 conn = make_connection(req, now, service, client_devicetype,
1041 req->vuid, &nt_status);
1045 if (session_key_updated) {
1046 struct smbXsrv_session *x = session;
1047 struct auth_session_info *session_info =
1048 session->global->auth_session_info;
1049 data_blob_clear_free(&x->global->application_key);
1050 data_blob_clear_free(&session_info->session_key);
1052 reply_nterror(req, nt_status);
1053 END_PROFILE(SMBtconX);
1058 server_devicetype = "IPC";
1059 else if ( IS_PRINT(conn) )
1060 server_devicetype = "LPT1:";
1062 server_devicetype = "A:";
1064 if (get_Protocol() < PROTOCOL_NT1) {
1065 reply_outbuf(req, 2, 0);
1066 if (message_push_string(&req->outbuf, server_devicetype,
1067 STR_TERMINATE|STR_ASCII) == -1) {
1068 reply_nterror(req, NT_STATUS_NO_MEMORY);
1069 END_PROFILE(SMBtconX);
1073 /* NT sets the fstype of IPC$ to the null string */
1074 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1076 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1077 /* Return permissions. */
1081 reply_outbuf(req, 7, 0);
1084 perm1 = FILE_ALL_ACCESS;
1085 perm2 = FILE_ALL_ACCESS;
1087 perm1 = conn->share_access;
1090 SIVAL(req->outbuf, smb_vwv3, perm1);
1091 SIVAL(req->outbuf, smb_vwv5, perm2);
1093 reply_outbuf(req, 3, 0);
1096 if ((message_push_string(&req->outbuf, server_devicetype,
1097 STR_TERMINATE|STR_ASCII) == -1)
1098 || (message_push_string(&req->outbuf, fstype,
1099 STR_TERMINATE) == -1)) {
1100 reply_nterror(req, NT_STATUS_NO_MEMORY);
1101 END_PROFILE(SMBtconX);
1105 /* what does setting this bit do? It is set by NT4 and
1106 may affect the ability to autorun mounted cdroms */
1107 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1109 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1111 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1112 DEBUG(2,("Serving %s as a Dfs root\n",
1113 lp_servicename(ctx, SNUM(conn)) ));
1114 optional_support |= SMB_SHARE_IN_DFS;
1117 SSVAL(req->outbuf, smb_vwv2, optional_support);
1120 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1121 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1123 DEBUG(3,("tconX service=%s \n",
1126 /* set the incoming and outgoing tid to the just created one */
1127 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1128 SSVAL(req->outbuf,smb_tid,conn->cnum);
1130 END_PROFILE(SMBtconX);
1132 req->tid = conn->cnum;
1135 /****************************************************************************
1136 Reply to an unknown type.
1137 ****************************************************************************/
1139 void reply_unknown_new(struct smb_request *req, uint8_t type)
1141 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1142 smb_fn_name(type), type, type));
1143 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1147 /****************************************************************************
1149 conn POINTER CAN BE NULL HERE !
1150 ****************************************************************************/
1152 void reply_ioctl(struct smb_request *req)
1154 connection_struct *conn = req->conn;
1157 uint32_t ioctl_code;
1161 START_PROFILE(SMBioctl);
1164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1165 END_PROFILE(SMBioctl);
1169 device = SVAL(req->vwv+1, 0);
1170 function = SVAL(req->vwv+2, 0);
1171 ioctl_code = (device << 16) + function;
1173 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1175 switch (ioctl_code) {
1176 case IOCTL_QUERY_JOB_INFO:
1180 reply_force_doserror(req, ERRSRV, ERRnosupport);
1181 END_PROFILE(SMBioctl);
1185 reply_outbuf(req, 8, replysize+1);
1186 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1187 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1188 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1189 p = smb_buf(req->outbuf);
1190 memset(p, '\0', replysize+1); /* valgrind-safe. */
1191 p += 1; /* Allow for alignment */
1193 switch (ioctl_code) {
1194 case IOCTL_QUERY_JOB_INFO:
1198 files_struct *fsp = file_fsp(
1199 req, SVAL(req->vwv+0, 0));
1201 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1202 END_PROFILE(SMBioctl);
1206 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1208 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1209 lp_netbios_name(), 15,
1210 STR_TERMINATE|STR_ASCII, &len);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 reply_nterror(req, status);
1213 END_PROFILE(SMBioctl);
1217 status = srvstr_push((char *)req->outbuf, req->flags2,
1219 lp_servicename(talloc_tos(),
1221 13, STR_TERMINATE|STR_ASCII, &len);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 reply_nterror(req, status);
1224 END_PROFILE(SMBioctl);
1228 memset(p+18, 0, 13);
1234 END_PROFILE(SMBioctl);
1238 /****************************************************************************
1239 Strange checkpath NTSTATUS mapping.
1240 ****************************************************************************/
1242 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1244 /* Strange DOS error code semantics only for checkpath... */
1245 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1246 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1247 /* We need to map to ERRbadpath */
1248 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1254 /****************************************************************************
1255 Reply to a checkpath.
1256 ****************************************************************************/
1258 void reply_checkpath(struct smb_request *req)
1260 connection_struct *conn = req->conn;
1261 struct smb_filename *smb_fname = NULL;
1264 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1265 TALLOC_CTX *ctx = talloc_tos();
1267 START_PROFILE(SMBcheckpath);
1269 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1270 STR_TERMINATE, &status);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 status = map_checkpath_error(req->flags2, status);
1274 reply_nterror(req, status);
1275 END_PROFILE(SMBcheckpath);
1279 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1281 status = filename_convert(ctx,
1283 req->flags2 & FLAGS2_DFS_PATHNAMES,
1289 if (!NT_STATUS_IS_OK(status)) {
1290 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1291 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1292 ERRSRV, ERRbadpath);
1293 END_PROFILE(SMBcheckpath);
1299 if (!VALID_STAT(smb_fname->st) &&
1300 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1301 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1302 smb_fname_str_dbg(smb_fname), strerror(errno)));
1303 status = map_nt_error_from_unix(errno);
1307 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1308 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1309 ERRDOS, ERRbadpath);
1313 reply_outbuf(req, 0, 0);
1316 /* We special case this - as when a Windows machine
1317 is parsing a path is steps through the components
1318 one at a time - if a component fails it expects
1319 ERRbadpath, not ERRbadfile.
1321 status = map_checkpath_error(req->flags2, status);
1322 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1324 * Windows returns different error codes if
1325 * the parent directory is valid but not the
1326 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1327 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1328 * if the path is invalid.
1330 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1331 ERRDOS, ERRbadpath);
1335 reply_nterror(req, status);
1338 TALLOC_FREE(smb_fname);
1339 END_PROFILE(SMBcheckpath);
1343 /****************************************************************************
1345 ****************************************************************************/
1347 void reply_getatr(struct smb_request *req)
1349 connection_struct *conn = req->conn;
1350 struct smb_filename *smb_fname = NULL;
1357 TALLOC_CTX *ctx = talloc_tos();
1358 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1360 START_PROFILE(SMBgetatr);
1362 p = (const char *)req->buf + 1;
1363 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 reply_nterror(req, status);
1369 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1370 under WfWg - weird! */
1371 if (*fname == '\0') {
1372 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1373 if (!CAN_WRITE(conn)) {
1374 mode |= FILE_ATTRIBUTE_READONLY;
1379 uint32_t ucf_flags = (lp_posix_pathnames() ?
1380 UCF_POSIX_PATHNAMES : 0);
1381 status = filename_convert(ctx,
1383 req->flags2 & FLAGS2_DFS_PATHNAMES,
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1390 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1391 ERRSRV, ERRbadpath);
1394 reply_nterror(req, status);
1397 if (!VALID_STAT(smb_fname->st) &&
1398 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1399 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1400 smb_fname_str_dbg(smb_fname),
1402 reply_nterror(req, map_nt_error_from_unix(errno));
1406 mode = dos_mode(conn, smb_fname);
1407 size = smb_fname->st.st_ex_size;
1409 if (ask_sharemode) {
1410 struct timespec write_time_ts;
1411 struct file_id fileid;
1413 ZERO_STRUCT(write_time_ts);
1414 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1415 get_file_infos(fileid, 0, NULL, &write_time_ts);
1416 if (!null_timespec(write_time_ts)) {
1417 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1421 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1422 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1427 reply_outbuf(req, 10, 0);
1429 SSVAL(req->outbuf,smb_vwv0,mode);
1430 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1431 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1433 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1435 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1437 if (get_Protocol() >= PROTOCOL_NT1) {
1438 SSVAL(req->outbuf, smb_flg2,
1439 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1442 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1443 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1446 TALLOC_FREE(smb_fname);
1448 END_PROFILE(SMBgetatr);
1452 /****************************************************************************
1454 ****************************************************************************/
1456 void reply_setatr(struct smb_request *req)
1458 struct smb_file_time ft;
1459 connection_struct *conn = req->conn;
1460 struct smb_filename *smb_fname = NULL;
1466 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1467 TALLOC_CTX *ctx = talloc_tos();
1469 START_PROFILE(SMBsetatr);
1474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1478 p = (const char *)req->buf + 1;
1479 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 reply_nterror(req, status);
1485 status = filename_convert(ctx,
1487 req->flags2 & FLAGS2_DFS_PATHNAMES,
1492 if (!NT_STATUS_IS_OK(status)) {
1493 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1494 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1495 ERRSRV, ERRbadpath);
1498 reply_nterror(req, status);
1502 if (smb_fname->base_name[0] == '.' &&
1503 smb_fname->base_name[1] == '\0') {
1505 * Not sure here is the right place to catch this
1506 * condition. Might be moved to somewhere else later -- vl
1508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1512 mode = SVAL(req->vwv+0, 0);
1513 mtime = srv_make_unix_date3(req->vwv+1);
1515 if (mode != FILE_ATTRIBUTE_NORMAL) {
1516 if (VALID_STAT_OF_DIR(smb_fname->st))
1517 mode |= FILE_ATTRIBUTE_DIRECTORY;
1519 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1521 status = check_access(conn, NULL, smb_fname,
1522 FILE_WRITE_ATTRIBUTES);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 reply_nterror(req, status);
1528 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1530 reply_nterror(req, map_nt_error_from_unix(errno));
1535 ft.mtime = convert_time_t_to_timespec(mtime);
1536 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 reply_nterror(req, status);
1542 reply_outbuf(req, 0, 0);
1544 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1547 TALLOC_FREE(smb_fname);
1548 END_PROFILE(SMBsetatr);
1552 /****************************************************************************
1554 ****************************************************************************/
1556 void reply_dskattr(struct smb_request *req)
1558 connection_struct *conn = req->conn;
1560 uint64_t dfree,dsize,bsize;
1561 START_PROFILE(SMBdskattr);
1563 ret = get_dfree_info(conn, ".", &bsize, &dfree, &dsize);
1564 if (ret == (uint64_t)-1) {
1565 reply_nterror(req, map_nt_error_from_unix(errno));
1566 END_PROFILE(SMBdskattr);
1571 * Force max to fit in 16 bit fields.
1573 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1577 if (bsize > (WORDMAX*512)) {
1578 bsize = (WORDMAX*512);
1579 if (dsize > WORDMAX)
1581 if (dfree > WORDMAX)
1587 reply_outbuf(req, 5, 0);
1589 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1590 double total_space, free_space;
1591 /* we need to scale this to a number that DOS6 can handle. We
1592 use floating point so we can handle large drives on systems
1593 that don't have 64 bit integers
1595 we end up displaying a maximum of 2G to DOS systems
1597 total_space = dsize * (double)bsize;
1598 free_space = dfree * (double)bsize;
1600 dsize = (uint64_t)((total_space+63*512) / (64*512));
1601 dfree = (uint64_t)((free_space+63*512) / (64*512));
1603 if (dsize > 0xFFFF) dsize = 0xFFFF;
1604 if (dfree > 0xFFFF) dfree = 0xFFFF;
1606 SSVAL(req->outbuf,smb_vwv0,dsize);
1607 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1608 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1609 SSVAL(req->outbuf,smb_vwv3,dfree);
1611 SSVAL(req->outbuf,smb_vwv0,dsize);
1612 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1613 SSVAL(req->outbuf,smb_vwv2,512);
1614 SSVAL(req->outbuf,smb_vwv3,dfree);
1617 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1619 END_PROFILE(SMBdskattr);
1624 * Utility function to split the filename from the directory.
1626 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1627 char **fname_dir_out,
1628 char **fname_mask_out)
1630 const char *p = NULL;
1631 char *fname_dir = NULL;
1632 char *fname_mask = NULL;
1634 p = strrchr_m(fname_in, '/');
1636 fname_dir = talloc_strdup(ctx, ".");
1637 fname_mask = talloc_strdup(ctx, fname_in);
1639 fname_dir = talloc_strndup(ctx, fname_in,
1640 PTR_DIFF(p, fname_in));
1641 fname_mask = talloc_strdup(ctx, p+1);
1644 if (!fname_dir || !fname_mask) {
1645 TALLOC_FREE(fname_dir);
1646 TALLOC_FREE(fname_mask);
1647 return NT_STATUS_NO_MEMORY;
1650 *fname_dir_out = fname_dir;
1651 *fname_mask_out = fname_mask;
1652 return NT_STATUS_OK;
1655 /****************************************************************************
1657 ****************************************************************************/
1659 static bool make_dir_struct(TALLOC_CTX *ctx,
1669 char *mask2 = talloc_strdup(ctx, mask);
1675 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1679 memset(buf+1,' ',11);
1680 if ((p = strchr_m(mask2,'.')) != NULL) {
1682 push_ascii(buf+1,mask2,8, 0);
1683 push_ascii(buf+9,p+1,3, 0);
1686 push_ascii(buf+1,mask2,11, 0);
1689 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1691 srv_put_dos_date(buf,22,date);
1692 SSVAL(buf,26,size & 0xFFFF);
1693 SSVAL(buf,28,(size >> 16)&0xFFFF);
1694 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1695 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1696 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1697 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1701 /****************************************************************************
1703 Can be called from SMBsearch, SMBffirst or SMBfunique.
1704 ****************************************************************************/
1706 void reply_search(struct smb_request *req)
1708 connection_struct *conn = req->conn;
1711 char *directory = NULL;
1712 struct smb_filename *smb_fname = NULL;
1716 struct timespec date;
1718 unsigned int numentries = 0;
1719 unsigned int maxentries = 0;
1720 bool finished = False;
1725 bool check_descend = False;
1726 bool expect_close = False;
1728 bool mask_contains_wcard = False;
1729 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1730 TALLOC_CTX *ctx = talloc_tos();
1731 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1732 struct dptr_struct *dirptr = NULL;
1733 struct smbXsrv_connection *xconn = req->xconn;
1734 struct smbd_server_connection *sconn = req->sconn;
1736 START_PROFILE(SMBsearch);
1739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1743 if (lp_posix_pathnames()) {
1744 reply_unknown_new(req, req->cmd);
1748 /* If we were called as SMBffirst then we must expect close. */
1749 if(req->cmd == SMBffirst) {
1750 expect_close = True;
1753 reply_outbuf(req, 1, 3);
1754 maxentries = SVAL(req->vwv+0, 0);
1755 dirtype = SVAL(req->vwv+1, 0);
1756 p = (const char *)req->buf + 1;
1757 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1758 &nt_status, &mask_contains_wcard);
1759 if (!NT_STATUS_IS_OK(nt_status)) {
1760 reply_nterror(req, nt_status);
1765 status_len = SVAL(p, 0);
1768 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1770 if (status_len == 0) {
1771 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1772 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
1773 nt_status = filename_convert(ctx, conn,
1774 req->flags2 & FLAGS2_DFS_PATHNAMES,
1777 &mask_contains_wcard,
1779 if (!NT_STATUS_IS_OK(nt_status)) {
1780 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1781 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1782 ERRSRV, ERRbadpath);
1785 reply_nterror(req, nt_status);
1789 directory = smb_fname->base_name;
1791 p = strrchr_m(directory,'/');
1792 if ((p != NULL) && (*directory != '/')) {
1793 mask = talloc_strdup(ctx, p + 1);
1794 directory = talloc_strndup(ctx, directory,
1795 PTR_DIFF(p, directory));
1797 mask = talloc_strdup(ctx, directory);
1798 directory = talloc_strdup(ctx,".");
1802 reply_nterror(req, NT_STATUS_NO_MEMORY);
1806 memset((char *)status,'\0',21);
1807 SCVAL(status,0,(dirtype & 0x1F));
1809 nt_status = dptr_create(conn,
1817 mask_contains_wcard,
1820 if (!NT_STATUS_IS_OK(nt_status)) {
1821 reply_nterror(req, nt_status);
1824 dptr_num = dptr_dnum(dirptr);
1827 const char *dirpath;
1829 memcpy(status,p,21);
1830 status_dirtype = CVAL(status,0) & 0x1F;
1831 if (status_dirtype != (dirtype & 0x1F)) {
1832 dirtype = status_dirtype;
1835 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1839 dirpath = dptr_path(sconn, dptr_num);
1840 directory = talloc_strdup(ctx, dirpath);
1842 reply_nterror(req, NT_STATUS_NO_MEMORY);
1846 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1851 * For a 'continue' search we have no string. So
1852 * check from the initial saved string.
1854 if (!lp_posix_pathnames()) {
1855 mask_contains_wcard = ms_has_wild(mask);
1857 dirtype = dptr_attr(sconn, dptr_num);
1860 DEBUG(4,("dptr_num is %d\n",dptr_num));
1862 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1863 dptr_init_search_op(dirptr);
1865 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1866 char buf[DIR_STRUCT_SIZE];
1867 memcpy(buf,status,21);
1868 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1869 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1870 reply_nterror(req, NT_STATUS_NO_MEMORY);
1873 dptr_fill(sconn, buf+12,dptr_num);
1874 if (dptr_zero(buf+12) && (status_len==0)) {
1879 if (message_push_blob(&req->outbuf,
1880 data_blob_const(buf, sizeof(buf)))
1882 reply_nterror(req, NT_STATUS_NO_MEMORY);
1887 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1888 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1890 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1892 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1893 directory,lp_dont_descend(ctx, SNUM(conn))));
1894 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1895 check_descend = True;
1898 for (i=numentries;(i<maxentries) && !finished;i++) {
1899 finished = !get_dir_entry(ctx,
1910 char buf[DIR_STRUCT_SIZE];
1911 memcpy(buf,status,21);
1912 if (!make_dir_struct(ctx,
1918 convert_timespec_to_time_t(date),
1919 !allow_long_path_components)) {
1920 reply_nterror(req, NT_STATUS_NO_MEMORY);
1923 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1926 if (message_push_blob(&req->outbuf,
1927 data_blob_const(buf, sizeof(buf)))
1929 reply_nterror(req, NT_STATUS_NO_MEMORY);
1939 /* If we were called as SMBffirst with smb_search_id == NULL
1940 and no entries were found then return error and close dirptr
1943 if (numentries == 0) {
1944 dptr_close(sconn, &dptr_num);
1945 } else if(expect_close && status_len == 0) {
1946 /* Close the dptr - we know it's gone */
1947 dptr_close(sconn, &dptr_num);
1950 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1951 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1952 dptr_close(sconn, &dptr_num);
1955 if ((numentries == 0) && !mask_contains_wcard) {
1956 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1960 SSVAL(req->outbuf,smb_vwv0,numentries);
1961 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1962 SCVAL(smb_buf(req->outbuf),0,5);
1963 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1965 /* The replies here are never long name. */
1966 SSVAL(req->outbuf, smb_flg2,
1967 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1968 if (!allow_long_path_components) {
1969 SSVAL(req->outbuf, smb_flg2,
1970 SVAL(req->outbuf, smb_flg2)
1971 & (~FLAGS2_LONG_PATH_COMPONENTS));
1974 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1975 SSVAL(req->outbuf, smb_flg2,
1976 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1978 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1979 smb_fn_name(req->cmd),
1986 TALLOC_FREE(directory);
1988 TALLOC_FREE(smb_fname);
1989 END_PROFILE(SMBsearch);
1993 /****************************************************************************
1994 Reply to a fclose (stop directory search).
1995 ****************************************************************************/
1997 void reply_fclose(struct smb_request *req)
2005 bool path_contains_wcard = False;
2006 TALLOC_CTX *ctx = talloc_tos();
2007 struct smbd_server_connection *sconn = req->sconn;
2009 START_PROFILE(SMBfclose);
2011 if (lp_posix_pathnames()) {
2012 reply_unknown_new(req, req->cmd);
2013 END_PROFILE(SMBfclose);
2017 p = (const char *)req->buf + 1;
2018 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2019 &err, &path_contains_wcard);
2020 if (!NT_STATUS_IS_OK(err)) {
2021 reply_nterror(req, err);
2022 END_PROFILE(SMBfclose);
2026 status_len = SVAL(p,0);
2029 if (status_len == 0) {
2030 reply_force_doserror(req, ERRSRV, ERRsrverror);
2031 END_PROFILE(SMBfclose);
2035 memcpy(status,p,21);
2037 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2038 /* Close the dptr - we know it's gone */
2039 dptr_close(sconn, &dptr_num);
2042 reply_outbuf(req, 1, 0);
2043 SSVAL(req->outbuf,smb_vwv0,0);
2045 DEBUG(3,("search close\n"));
2047 END_PROFILE(SMBfclose);
2051 /****************************************************************************
2053 ****************************************************************************/
2055 void reply_open(struct smb_request *req)
2057 connection_struct *conn = req->conn;
2058 struct smb_filename *smb_fname = NULL;
2068 uint32_t access_mask;
2069 uint32_t share_mode;
2070 uint32_t create_disposition;
2071 uint32_t create_options = 0;
2072 uint32_t private_flags = 0;
2074 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2075 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2076 TALLOC_CTX *ctx = talloc_tos();
2078 START_PROFILE(SMBopen);
2081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2085 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2086 deny_mode = SVAL(req->vwv+0, 0);
2087 dos_attr = SVAL(req->vwv+1, 0);
2089 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2090 STR_TERMINATE, &status);
2091 if (!NT_STATUS_IS_OK(status)) {
2092 reply_nterror(req, status);
2096 if (!map_open_params_to_ntcreate(fname, deny_mode,
2097 OPENX_FILE_EXISTS_OPEN, &access_mask,
2098 &share_mode, &create_disposition,
2099 &create_options, &private_flags)) {
2100 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2104 status = filename_convert(ctx,
2106 req->flags2 & FLAGS2_DFS_PATHNAMES,
2111 if (!NT_STATUS_IS_OK(status)) {
2112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2113 reply_botherror(req,
2114 NT_STATUS_PATH_NOT_COVERED,
2115 ERRSRV, ERRbadpath);
2118 reply_nterror(req, status);
2122 status = SMB_VFS_CREATE_FILE(
2125 0, /* root_dir_fid */
2126 smb_fname, /* fname */
2127 access_mask, /* access_mask */
2128 share_mode, /* share_access */
2129 create_disposition, /* create_disposition*/
2130 create_options, /* create_options */
2131 dos_attr, /* file_attributes */
2132 oplock_request, /* oplock_request */
2134 0, /* allocation_size */
2140 NULL, NULL); /* create context */
2142 if (!NT_STATUS_IS_OK(status)) {
2143 if (open_was_deferred(req->xconn, req->mid)) {
2144 /* We have re-scheduled this call. */
2147 reply_openerror(req, status);
2151 /* Ensure we're pointing at the correct stat struct. */
2152 TALLOC_FREE(smb_fname);
2153 smb_fname = fsp->fsp_name;
2155 size = smb_fname->st.st_ex_size;
2156 fattr = dos_mode(conn, smb_fname);
2158 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2160 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2161 DEBUG(3,("attempt to open a directory %s\n",
2163 close_file(req, fsp, ERROR_CLOSE);
2164 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2165 ERRDOS, ERRnoaccess);
2169 reply_outbuf(req, 7, 0);
2170 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2171 SSVAL(req->outbuf,smb_vwv1,fattr);
2172 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2173 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2175 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2177 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2178 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2180 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2181 SCVAL(req->outbuf,smb_flg,
2182 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2185 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2186 SCVAL(req->outbuf,smb_flg,
2187 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2190 END_PROFILE(SMBopen);
2194 /****************************************************************************
2195 Reply to an open and X.
2196 ****************************************************************************/
2198 void reply_open_and_X(struct smb_request *req)
2200 connection_struct *conn = req->conn;
2201 struct smb_filename *smb_fname = NULL;
2203 uint16_t open_flags;
2206 /* Breakout the oplock request bits so we can set the
2207 reply bits separately. */
2208 int ex_oplock_request;
2209 int core_oplock_request;
2212 int smb_sattr = SVAL(req->vwv+4, 0);
2213 uint32_t smb_time = make_unix_date3(req->vwv+6);
2221 uint64_t allocation_size;
2222 ssize_t retval = -1;
2223 uint32_t access_mask;
2224 uint32_t share_mode;
2225 uint32_t create_disposition;
2226 uint32_t create_options = 0;
2227 uint32_t private_flags = 0;
2228 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2229 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2230 TALLOC_CTX *ctx = talloc_tos();
2232 START_PROFILE(SMBopenX);
2234 if (req->wct < 15) {
2235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 open_flags = SVAL(req->vwv+2, 0);
2240 deny_mode = SVAL(req->vwv+3, 0);
2241 smb_attr = SVAL(req->vwv+5, 0);
2242 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2243 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2244 oplock_request = ex_oplock_request | core_oplock_request;
2245 smb_ofun = SVAL(req->vwv+8, 0);
2246 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2248 /* If it's an IPC, pass off the pipe handler. */
2250 if (lp_nt_pipe_support()) {
2251 reply_open_pipe_and_X(conn, req);
2253 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2258 /* XXXX we need to handle passed times, sattr and flags */
2259 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2260 STR_TERMINATE, &status);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 reply_nterror(req, status);
2266 if (!map_open_params_to_ntcreate(fname, deny_mode,
2268 &access_mask, &share_mode,
2269 &create_disposition,
2272 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2276 status = filename_convert(ctx,
2278 req->flags2 & FLAGS2_DFS_PATHNAMES,
2283 if (!NT_STATUS_IS_OK(status)) {
2284 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2285 reply_botherror(req,
2286 NT_STATUS_PATH_NOT_COVERED,
2287 ERRSRV, ERRbadpath);
2290 reply_nterror(req, status);
2294 status = SMB_VFS_CREATE_FILE(
2297 0, /* root_dir_fid */
2298 smb_fname, /* fname */
2299 access_mask, /* access_mask */
2300 share_mode, /* share_access */
2301 create_disposition, /* create_disposition*/
2302 create_options, /* create_options */
2303 smb_attr, /* file_attributes */
2304 oplock_request, /* oplock_request */
2306 0, /* allocation_size */
2311 &smb_action, /* pinfo */
2312 NULL, NULL); /* create context */
2314 if (!NT_STATUS_IS_OK(status)) {
2315 if (open_was_deferred(req->xconn, req->mid)) {
2316 /* We have re-scheduled this call. */
2319 reply_openerror(req, status);
2323 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2324 if the file is truncated or created. */
2325 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2326 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2327 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2328 close_file(req, fsp, ERROR_CLOSE);
2329 reply_nterror(req, NT_STATUS_DISK_FULL);
2332 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2334 close_file(req, fsp, ERROR_CLOSE);
2335 reply_nterror(req, NT_STATUS_DISK_FULL);
2338 status = vfs_stat_fsp(fsp);
2339 if (!NT_STATUS_IS_OK(status)) {
2340 close_file(req, fsp, ERROR_CLOSE);
2341 reply_nterror(req, status);
2346 fattr = dos_mode(conn, fsp->fsp_name);
2347 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2348 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2349 close_file(req, fsp, ERROR_CLOSE);
2350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2354 /* If the caller set the extended oplock request bit
2355 and we granted one (by whatever means) - set the
2356 correct bit for extended oplock reply.
2359 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2360 smb_action |= EXTENDED_OPLOCK_GRANTED;
2363 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2364 smb_action |= EXTENDED_OPLOCK_GRANTED;
2367 /* If the caller set the core oplock request bit
2368 and we granted one (by whatever means) - set the
2369 correct bit for core oplock reply.
2372 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2373 reply_outbuf(req, 19, 0);
2375 reply_outbuf(req, 15, 0);
2378 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2379 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2381 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2382 SCVAL(req->outbuf, smb_flg,
2383 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2386 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2387 SCVAL(req->outbuf, smb_flg,
2388 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2391 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2392 SSVAL(req->outbuf,smb_vwv3,fattr);
2393 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2394 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2396 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2398 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2399 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2400 SSVAL(req->outbuf,smb_vwv11,smb_action);
2402 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2403 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2407 TALLOC_FREE(smb_fname);
2408 END_PROFILE(SMBopenX);
2412 /****************************************************************************
2413 Reply to a SMBulogoffX.
2414 ****************************************************************************/
2416 void reply_ulogoffX(struct smb_request *req)
2418 struct smbd_server_connection *sconn = req->sconn;
2419 struct user_struct *vuser;
2420 struct smbXsrv_session *session = NULL;
2423 START_PROFILE(SMBulogoffX);
2425 vuser = get_valid_user_struct(sconn, req->vuid);
2428 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2429 (unsigned long long)req->vuid));
2431 req->vuid = UID_FIELD_INVALID;
2432 reply_force_doserror(req, ERRSRV, ERRbaduid);
2433 END_PROFILE(SMBulogoffX);
2437 session = vuser->session;
2441 * TODO: cancel all outstanding requests on the session
2443 status = smbXsrv_session_logoff(session);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 DEBUG(0, ("reply_ulogoff: "
2446 "smbXsrv_session_logoff() failed: %s\n",
2447 nt_errstr(status)));
2449 * If we hit this case, there is something completely
2450 * wrong, so we better disconnect the transport connection.
2452 END_PROFILE(SMBulogoffX);
2453 exit_server(__location__ ": smbXsrv_session_logoff failed");
2457 TALLOC_FREE(session);
2459 reply_outbuf(req, 2, 0);
2460 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2461 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2463 DEBUG(3, ("ulogoffX vuid=%llu\n",
2464 (unsigned long long)req->vuid));
2466 END_PROFILE(SMBulogoffX);
2467 req->vuid = UID_FIELD_INVALID;
2470 /****************************************************************************
2471 Reply to a mknew or a create.
2472 ****************************************************************************/
2474 void reply_mknew(struct smb_request *req)
2476 connection_struct *conn = req->conn;
2477 struct smb_filename *smb_fname = NULL;
2480 struct smb_file_time ft;
2482 int oplock_request = 0;
2484 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2485 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2486 uint32_t create_disposition;
2487 uint32_t create_options = 0;
2488 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2489 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2490 TALLOC_CTX *ctx = talloc_tos();
2492 START_PROFILE(SMBcreate);
2496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2500 fattr = SVAL(req->vwv+0, 0);
2501 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2504 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2506 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2507 STR_TERMINATE, &status);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 reply_nterror(req, status);
2513 status = filename_convert(ctx,
2515 req->flags2 & FLAGS2_DFS_PATHNAMES,
2520 if (!NT_STATUS_IS_OK(status)) {
2521 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2522 reply_botherror(req,
2523 NT_STATUS_PATH_NOT_COVERED,
2524 ERRSRV, ERRbadpath);
2527 reply_nterror(req, status);
2531 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2532 DEBUG(0,("Attempt to create file (%s) with volid set - "
2533 "please report this\n",
2534 smb_fname_str_dbg(smb_fname)));
2537 if(req->cmd == SMBmknew) {
2538 /* We should fail if file exists. */
2539 create_disposition = FILE_CREATE;
2541 /* Create if file doesn't exist, truncate if it does. */
2542 create_disposition = FILE_OVERWRITE_IF;
2545 status = SMB_VFS_CREATE_FILE(
2548 0, /* root_dir_fid */
2549 smb_fname, /* fname */
2550 access_mask, /* access_mask */
2551 share_mode, /* share_access */
2552 create_disposition, /* create_disposition*/
2553 create_options, /* create_options */
2554 fattr, /* file_attributes */
2555 oplock_request, /* oplock_request */
2557 0, /* allocation_size */
2558 0, /* private_flags */
2563 NULL, NULL); /* create context */
2565 if (!NT_STATUS_IS_OK(status)) {
2566 if (open_was_deferred(req->xconn, req->mid)) {
2567 /* We have re-scheduled this call. */
2570 reply_openerror(req, status);
2574 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2575 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2576 if (!NT_STATUS_IS_OK(status)) {
2577 END_PROFILE(SMBcreate);
2581 reply_outbuf(req, 1, 0);
2582 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2584 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2585 SCVAL(req->outbuf,smb_flg,
2586 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2589 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2590 SCVAL(req->outbuf,smb_flg,
2591 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2594 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2595 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2596 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2597 (unsigned int)fattr));
2600 TALLOC_FREE(smb_fname);
2601 END_PROFILE(SMBcreate);
2605 /****************************************************************************
2606 Reply to a create temporary file.
2607 ****************************************************************************/
2609 void reply_ctemp(struct smb_request *req)
2611 connection_struct *conn = req->conn;
2612 struct smb_filename *smb_fname = NULL;
2613 char *wire_name = NULL;
2621 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2622 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
2623 TALLOC_CTX *ctx = talloc_tos();
2625 START_PROFILE(SMBctemp);
2628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2632 fattr = SVAL(req->vwv+0, 0);
2633 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2635 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2636 STR_TERMINATE, &status);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 reply_nterror(req, status);
2642 for (i = 0; i < 10; i++) {
2644 fname = talloc_asprintf(ctx,
2647 generate_random_str_list(ctx, 5, "0123456789"));
2649 fname = talloc_asprintf(ctx,
2651 generate_random_str_list(ctx, 5, "0123456789"));
2655 reply_nterror(req, NT_STATUS_NO_MEMORY);
2659 status = filename_convert(ctx, conn,
2660 req->flags2 & FLAGS2_DFS_PATHNAMES,
2665 if (!NT_STATUS_IS_OK(status)) {
2666 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2667 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2668 ERRSRV, ERRbadpath);
2671 reply_nterror(req, status);
2675 /* Create the file. */
2676 status = SMB_VFS_CREATE_FILE(
2679 0, /* root_dir_fid */
2680 smb_fname, /* fname */
2681 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2682 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2683 FILE_CREATE, /* create_disposition*/
2684 0, /* create_options */
2685 fattr, /* file_attributes */
2686 oplock_request, /* oplock_request */
2688 0, /* allocation_size */
2689 0, /* private_flags */
2694 NULL, NULL); /* create context */
2696 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2698 TALLOC_FREE(smb_fname);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 if (open_was_deferred(req->xconn, req->mid)) {
2704 /* We have re-scheduled this call. */
2707 reply_openerror(req, status);
2715 /* Collision after 10 times... */
2716 reply_nterror(req, status);
2720 reply_outbuf(req, 1, 0);
2721 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2723 /* the returned filename is relative to the directory */
2724 s = strrchr_m(fsp->fsp_name->base_name, '/');
2726 s = fsp->fsp_name->base_name;
2732 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2733 thing in the byte section. JRA */
2734 SSVALS(p, 0, -1); /* what is this? not in spec */
2736 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2738 reply_nterror(req, NT_STATUS_NO_MEMORY);
2742 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2743 SCVAL(req->outbuf, smb_flg,
2744 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2747 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2748 SCVAL(req->outbuf, smb_flg,
2749 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2752 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2753 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2754 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2756 TALLOC_FREE(smb_fname);
2757 TALLOC_FREE(wire_name);
2758 END_PROFILE(SMBctemp);
2762 /*******************************************************************
2763 Check if a user is allowed to rename a file.
2764 ********************************************************************/
2766 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2769 if (!CAN_WRITE(conn)) {
2770 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2773 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2774 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2775 /* Only bother to read the DOS attribute if we might deny the
2776 rename on the grounds of attribute mismatch. */
2777 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2778 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2779 return NT_STATUS_NO_SUCH_FILE;
2783 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2784 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2785 return NT_STATUS_OK;
2788 /* If no pathnames are open below this
2789 directory, allow the rename. */
2791 if (lp_strict_rename(SNUM(conn))) {
2793 * Strict rename, check open file db.
2795 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2796 return NT_STATUS_ACCESS_DENIED;
2798 } else if (file_find_subpath(fsp)) {
2800 * No strict rename, just look in local process.
2802 return NT_STATUS_ACCESS_DENIED;
2804 return NT_STATUS_OK;
2807 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2808 return NT_STATUS_OK;
2811 return NT_STATUS_ACCESS_DENIED;
2814 /*******************************************************************
2815 * unlink a file with all relevant access checks
2816 *******************************************************************/
2818 static NTSTATUS do_unlink(connection_struct *conn,
2819 struct smb_request *req,
2820 struct smb_filename *smb_fname,
2825 uint32_t dirtype_orig = dirtype;
2828 bool posix_paths = lp_posix_pathnames();
2830 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2831 smb_fname_str_dbg(smb_fname),
2834 if (!CAN_WRITE(conn)) {
2835 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2839 ret = SMB_VFS_LSTAT(conn, smb_fname);
2841 ret = SMB_VFS_STAT(conn, smb_fname);
2844 return map_nt_error_from_unix(errno);
2847 fattr = dos_mode(conn, smb_fname);
2849 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2850 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2853 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2855 return NT_STATUS_NO_SUCH_FILE;
2858 if (!dir_check_ftype(fattr, dirtype)) {
2859 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2860 return NT_STATUS_FILE_IS_A_DIRECTORY;
2862 return NT_STATUS_NO_SUCH_FILE;
2865 if (dirtype_orig & 0x8000) {
2866 /* These will never be set for POSIX. */
2867 return NT_STATUS_NO_SUCH_FILE;
2871 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2872 return NT_STATUS_FILE_IS_A_DIRECTORY;
2875 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2876 return NT_STATUS_NO_SUCH_FILE;
2879 if (dirtype & 0xFF00) {
2880 /* These will never be set for POSIX. */
2881 return NT_STATUS_NO_SUCH_FILE;
2886 return NT_STATUS_NO_SUCH_FILE;
2889 /* Can't delete a directory. */
2890 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2891 return NT_STATUS_FILE_IS_A_DIRECTORY;
2896 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2897 return NT_STATUS_OBJECT_NAME_INVALID;
2898 #endif /* JRATEST */
2900 /* On open checks the open itself will check the share mode, so
2901 don't do it here as we'll get it wrong. */
2903 status = SMB_VFS_CREATE_FILE
2906 0, /* root_dir_fid */
2907 smb_fname, /* fname */
2908 DELETE_ACCESS, /* access_mask */
2909 FILE_SHARE_NONE, /* share_access */
2910 FILE_OPEN, /* create_disposition*/
2911 FILE_NON_DIRECTORY_FILE, /* create_options */
2912 /* file_attributes */
2913 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2914 FILE_ATTRIBUTE_NORMAL,
2915 0, /* oplock_request */
2917 0, /* allocation_size */
2918 0, /* private_flags */
2923 NULL, NULL); /* create context */
2925 if (!NT_STATUS_IS_OK(status)) {
2926 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2927 nt_errstr(status)));
2931 status = can_set_delete_on_close(fsp, fattr);
2932 if (!NT_STATUS_IS_OK(status)) {
2933 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2935 smb_fname_str_dbg(smb_fname),
2936 nt_errstr(status)));
2937 close_file(req, fsp, NORMAL_CLOSE);
2941 /* The set is across all open files on this dev/inode pair. */
2942 if (!set_delete_on_close(fsp, True,
2943 conn->session_info->security_token,
2944 conn->session_info->unix_token)) {
2945 close_file(req, fsp, NORMAL_CLOSE);
2946 return NT_STATUS_ACCESS_DENIED;
2949 return close_file(req, fsp, NORMAL_CLOSE);
2952 /****************************************************************************
2953 The guts of the unlink command, split out so it may be called by the NT SMB
2955 ****************************************************************************/
2957 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2958 uint32_t dirtype, struct smb_filename *smb_fname,
2961 char *fname_dir = NULL;
2962 char *fname_mask = NULL;
2964 NTSTATUS status = NT_STATUS_OK;
2965 TALLOC_CTX *ctx = talloc_tos();
2967 /* Split up the directory from the filename/mask. */
2968 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2969 &fname_dir, &fname_mask);
2970 if (!NT_STATUS_IS_OK(status)) {
2975 * We should only check the mangled cache
2976 * here if unix_convert failed. This means
2977 * that the path in 'mask' doesn't exist
2978 * on the file system and so we need to look
2979 * for a possible mangle. This patch from
2980 * Tine Smukavec <valentin.smukavec@hermes.si>.
2983 if (!VALID_STAT(smb_fname->st) &&
2984 mangle_is_mangled(fname_mask, conn->params)) {
2985 char *new_mask = NULL;
2986 mangle_lookup_name_from_8_3(ctx, fname_mask,
2987 &new_mask, conn->params);
2989 TALLOC_FREE(fname_mask);
2990 fname_mask = new_mask;
2997 * Only one file needs to be unlinked. Append the mask back
2998 * onto the directory.
3000 TALLOC_FREE(smb_fname->base_name);
3001 if (ISDOT(fname_dir)) {
3002 /* Ensure we use canonical names on open. */
3003 smb_fname->base_name = talloc_asprintf(smb_fname,
3007 smb_fname->base_name = talloc_asprintf(smb_fname,
3012 if (!smb_fname->base_name) {
3013 status = NT_STATUS_NO_MEMORY;
3017 dirtype = FILE_ATTRIBUTE_NORMAL;
3020 status = check_name(conn, smb_fname->base_name);
3021 if (!NT_STATUS_IS_OK(status)) {
3025 status = do_unlink(conn, req, smb_fname, dirtype);
3026 if (!NT_STATUS_IS_OK(status)) {
3032 struct smb_Dir *dir_hnd = NULL;
3034 const char *dname = NULL;
3035 char *talloced = NULL;
3037 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3038 status = NT_STATUS_OBJECT_NAME_INVALID;
3042 dirtype = FILE_ATTRIBUTE_NORMAL;
3045 if (strequal(fname_mask,"????????.???")) {
3046 TALLOC_FREE(fname_mask);
3047 fname_mask = talloc_strdup(ctx, "*");
3049 status = NT_STATUS_NO_MEMORY;
3054 status = check_name(conn, fname_dir);
3055 if (!NT_STATUS_IS_OK(status)) {
3059 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
3061 if (dir_hnd == NULL) {
3062 status = map_nt_error_from_unix(errno);
3066 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3067 the pattern matches against the long name, otherwise the short name
3068 We don't implement this yet XXXX
3071 status = NT_STATUS_NO_SUCH_FILE;
3073 while ((dname = ReadDirName(dir_hnd, &offset,
3074 &smb_fname->st, &talloced))) {
3075 TALLOC_CTX *frame = talloc_stackframe();
3077 if (!is_visible_file(conn, fname_dir, dname,
3078 &smb_fname->st, true)) {
3080 TALLOC_FREE(talloced);
3084 /* Quick check for "." and ".." */
3085 if (ISDOT(dname) || ISDOTDOT(dname)) {
3087 TALLOC_FREE(talloced);
3091 if(!mask_match(dname, fname_mask,
3092 conn->case_sensitive)) {
3094 TALLOC_FREE(talloced);
3098 TALLOC_FREE(smb_fname->base_name);
3099 if (ISDOT(fname_dir)) {
3100 /* Ensure we use canonical names on open. */
3101 smb_fname->base_name =
3102 talloc_asprintf(smb_fname, "%s",
3105 smb_fname->base_name =
3106 talloc_asprintf(smb_fname, "%s/%s",
3110 if (!smb_fname->base_name) {
3111 TALLOC_FREE(dir_hnd);
3112 status = NT_STATUS_NO_MEMORY;
3114 TALLOC_FREE(talloced);
3118 status = check_name(conn, smb_fname->base_name);
3119 if (!NT_STATUS_IS_OK(status)) {
3120 TALLOC_FREE(dir_hnd);
3122 TALLOC_FREE(talloced);
3126 status = do_unlink(conn, req, smb_fname, dirtype);
3127 if (!NT_STATUS_IS_OK(status)) {
3128 TALLOC_FREE(dir_hnd);
3130 TALLOC_FREE(talloced);
3135 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3136 smb_fname->base_name));
3139 TALLOC_FREE(talloced);
3141 TALLOC_FREE(dir_hnd);
3144 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3145 status = map_nt_error_from_unix(errno);
3149 TALLOC_FREE(fname_dir);
3150 TALLOC_FREE(fname_mask);
3154 /****************************************************************************
3156 ****************************************************************************/
3158 void reply_unlink(struct smb_request *req)
3160 connection_struct *conn = req->conn;
3162 struct smb_filename *smb_fname = NULL;
3165 bool path_contains_wcard = False;
3166 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3167 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
3168 TALLOC_CTX *ctx = talloc_tos();
3170 START_PROFILE(SMBunlink);
3173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3177 dirtype = SVAL(req->vwv+0, 0);
3179 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3180 STR_TERMINATE, &status,
3181 &path_contains_wcard);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 reply_nterror(req, status);
3187 status = filename_convert(ctx, conn,
3188 req->flags2 & FLAGS2_DFS_PATHNAMES,
3191 &path_contains_wcard,
3193 if (!NT_STATUS_IS_OK(status)) {
3194 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3195 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3196 ERRSRV, ERRbadpath);
3199 reply_nterror(req, status);
3203 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3205 status = unlink_internals(conn, req, dirtype, smb_fname,
3206 path_contains_wcard);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 if (open_was_deferred(req->xconn, req->mid)) {
3209 /* We have re-scheduled this call. */
3212 reply_nterror(req, status);
3216 reply_outbuf(req, 0, 0);
3218 TALLOC_FREE(smb_fname);
3219 END_PROFILE(SMBunlink);
3223 /****************************************************************************
3225 ****************************************************************************/
3227 static void fail_readraw(void)
3229 const char *errstr = talloc_asprintf(talloc_tos(),
3230 "FAIL ! reply_readbraw: socket write fail (%s)",
3235 exit_server_cleanly(errstr);
3238 /****************************************************************************
3239 Fake (read/write) sendfile. Returns -1 on read or write fail.
3240 ****************************************************************************/
3242 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3243 off_t startpos, size_t nread)
3246 size_t tosend = nread;
3253 bufsize = MIN(nread, 65536);
3255 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3259 while (tosend > 0) {
3263 cur_read = MIN(tosend, bufsize);
3264 ret = read_file(fsp,buf,startpos,cur_read);
3270 /* If we had a short read, fill with zeros. */
3271 if (ret < cur_read) {
3272 memset(buf + ret, '\0', cur_read - ret);
3275 ret = write_data(xconn->transport.sock, buf, cur_read);
3276 if (ret != cur_read) {
3277 int saved_errno = errno;
3279 * Try and give an error message saying what
3282 DEBUG(0, ("write_data failed for client %s. "
3284 smbXsrv_connection_dbg(xconn),
3285 strerror(saved_errno)));
3287 errno = saved_errno;
3291 startpos += cur_read;
3295 return (ssize_t)nread;
3298 /****************************************************************************
3299 Deal with the case of sendfile reading less bytes from the file than
3300 requested. Fill with zeros (all we can do). Returns 0 on success
3301 ****************************************************************************/
3303 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3309 #define SHORT_SEND_BUFSIZE 1024
3310 if (nread < headersize) {
3311 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3312 "header for file %s (%s). Terminating\n",
3313 fsp_str_dbg(fsp), strerror(errno)));
3317 nread -= headersize;
3319 if (nread < smb_maxcnt) {
3320 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3322 DEBUG(0,("sendfile_short_send: malloc failed "
3323 "for file %s (%s). Terminating\n",
3324 fsp_str_dbg(fsp), strerror(errno)));
3328 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3329 "with zeros !\n", fsp_str_dbg(fsp)));
3331 while (nread < smb_maxcnt) {
3333 * We asked for the real file size and told sendfile
3334 * to not go beyond the end of the file. But it can
3335 * happen that in between our fstat call and the
3336 * sendfile call the file was truncated. This is very
3337 * bad because we have already announced the larger
3338 * number of bytes to the client.
3340 * The best we can do now is to send 0-bytes, just as
3341 * a read from a hole in a sparse file would do.
3343 * This should happen rarely enough that I don't care
3344 * about efficiency here :-)
3349 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3350 ret = write_data(xconn->transport.sock, buf, to_write);
3351 if (ret != to_write) {
3352 int saved_errno = errno;
3354 * Try and give an error message saying what
3357 DEBUG(0, ("write_data failed for client %s. "
3359 smbXsrv_connection_dbg(xconn),
3360 strerror(saved_errno)));
3361 errno = saved_errno;
3372 /****************************************************************************
3373 Return a readbraw error (4 bytes of zero).
3374 ****************************************************************************/
3376 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3382 smbd_lock_socket(xconn);
3383 if (write_data(xconn->transport.sock,header,4) != 4) {
3384 int saved_errno = errno;
3386 * Try and give an error message saying what
3389 DEBUG(0, ("write_data failed for client %s. "
3391 smbXsrv_connection_dbg(xconn),
3392 strerror(saved_errno)));
3393 errno = saved_errno;
3397 smbd_unlock_socket(xconn);
3400 /****************************************************************************
3401 Use sendfile in readbraw.
3402 ****************************************************************************/
3404 static void send_file_readbraw(connection_struct *conn,
3405 struct smb_request *req,
3411 struct smbXsrv_connection *xconn = req->xconn;
3412 char *outbuf = NULL;
3416 * We can only use sendfile on a non-chained packet
3417 * but we can use on a non-oplocked file. tridge proved this
3418 * on a train in Germany :-). JRA.
3419 * reply_readbraw has already checked the length.
3422 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3423 (fsp->wcp == NULL) &&
3424 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3425 ssize_t sendfile_read = -1;
3427 DATA_BLOB header_blob;
3429 _smb_setlen(header,nread);
3430 header_blob = data_blob_const(header, 4);
3432 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3433 &header_blob, startpos,
3435 if (sendfile_read == -1) {
3436 /* Returning ENOSYS means no data at all was sent.
3437 * Do this as a normal read. */
3438 if (errno == ENOSYS) {
3439 goto normal_readbraw;
3443 * Special hack for broken Linux with no working sendfile. If we
3444 * return EINTR we sent the header but not the rest of the data.
3445 * Fake this up by doing read/write calls.
3447 if (errno == EINTR) {
3448 /* Ensure we don't do this again. */
3449 set_use_sendfile(SNUM(conn), False);
3450 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3452 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3453 DEBUG(0,("send_file_readbraw: "
3454 "fake_sendfile failed for "
3458 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3463 DEBUG(0,("send_file_readbraw: sendfile failed for "
3464 "file %s (%s). Terminating\n",
3465 fsp_str_dbg(fsp), strerror(errno)));
3466 exit_server_cleanly("send_file_readbraw sendfile failed");
3467 } else if (sendfile_read == 0) {
3469 * Some sendfile implementations return 0 to indicate
3470 * that there was a short read, but nothing was
3471 * actually written to the socket. In this case,
3472 * fallback to the normal read path so the header gets
3473 * the correct byte count.
3475 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3476 "bytes falling back to the normal read: "
3477 "%s\n", fsp_str_dbg(fsp)));
3478 goto normal_readbraw;
3481 /* Deal with possible short send. */
3482 if (sendfile_read != 4+nread) {
3483 ret = sendfile_short_send(xconn, fsp,
3484 sendfile_read, 4, nread);
3494 outbuf = talloc_array(NULL, char, nread+4);
3496 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3497 (unsigned)(nread+4)));
3498 reply_readbraw_error(xconn);
3503 ret = read_file(fsp,outbuf+4,startpos,nread);
3504 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3513 _smb_setlen(outbuf,ret);
3514 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3515 int saved_errno = errno;
3517 * Try and give an error message saying what
3520 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3521 smbXsrv_connection_dbg(xconn),
3522 strerror(saved_errno)));
3523 errno = saved_errno;
3528 TALLOC_FREE(outbuf);
3531 /****************************************************************************
3532 Reply to a readbraw (core+ protocol).
3533 ****************************************************************************/
3535 void reply_readbraw(struct smb_request *req)
3537 connection_struct *conn = req->conn;
3538 struct smbXsrv_connection *xconn = req->xconn;
3539 ssize_t maxcount,mincount;
3543 struct lock_struct lock;
3546 START_PROFILE(SMBreadbraw);
3548 if (srv_is_signing_active(xconn) || req->encrypted) {
3549 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3550 "raw reads/writes are disallowed.");
3554 reply_readbraw_error(xconn);
3555 END_PROFILE(SMBreadbraw);
3559 if (xconn->smb1.echo_handler.trusted_fde) {
3560 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3561 "'async smb echo handler = yes'\n"));
3562 reply_readbraw_error(xconn);
3563 END_PROFILE(SMBreadbraw);
3568 * Special check if an oplock break has been issued
3569 * and the readraw request croses on the wire, we must
3570 * return a zero length response here.
3573 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3576 * We have to do a check_fsp by hand here, as
3577 * we must always return 4 zero bytes on error,
3581 if (!fsp || !conn || conn != fsp->conn ||
3582 req->vuid != fsp->vuid ||
3583 fsp->is_directory || fsp->fh->fd == -1) {
3585 * fsp could be NULL here so use the value from the packet. JRA.
3587 DEBUG(3,("reply_readbraw: fnum %d not valid "
3589 (int)SVAL(req->vwv+0, 0)));
3590 reply_readbraw_error(xconn);
3591 END_PROFILE(SMBreadbraw);
3595 /* Do a "by hand" version of CHECK_READ. */
3596 if (!(fsp->can_read ||
3597 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3598 (fsp->access_mask & FILE_EXECUTE)))) {
3599 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3600 (int)SVAL(req->vwv+0, 0)));
3601 reply_readbraw_error(xconn);
3602 END_PROFILE(SMBreadbraw);
3606 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3608 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3609 if(req->wct == 10) {
3611 * This is a large offset (64 bit) read.
3614 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3617 DEBUG(0,("reply_readbraw: negative 64 bit "
3618 "readraw offset (%.0f) !\n",
3619 (double)startpos ));
3620 reply_readbraw_error(xconn);
3621 END_PROFILE(SMBreadbraw);
3626 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3627 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3629 /* ensure we don't overrun the packet size */
3630 maxcount = MIN(65535,maxcount);
3632 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3633 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3636 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3637 reply_readbraw_error(xconn);
3638 END_PROFILE(SMBreadbraw);
3642 if (fsp_stat(fsp) == 0) {
3643 size = fsp->fsp_name->st.st_ex_size;
3646 if (startpos >= size) {
3649 nread = MIN(maxcount,(size - startpos));
3652 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3653 if (nread < mincount)
3657 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3658 "min=%lu nread=%lu\n",
3659 fsp_fnum_dbg(fsp), (double)startpos,
3660 (unsigned long)maxcount,
3661 (unsigned long)mincount,
3662 (unsigned long)nread ) );
3664 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3666 DEBUG(5,("reply_readbraw finished\n"));
3668 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3670 END_PROFILE(SMBreadbraw);
3675 #define DBGC_CLASS DBGC_LOCKING
3677 /****************************************************************************
3678 Reply to a lockread (core+ protocol).
3679 ****************************************************************************/
3681 void reply_lockread(struct smb_request *req)
3683 connection_struct *conn = req->conn;
3691 struct byte_range_lock *br_lck = NULL;
3693 struct smbXsrv_connection *xconn = req->xconn;
3695 START_PROFILE(SMBlockread);
3698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3699 END_PROFILE(SMBlockread);
3703 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3705 if (!check_fsp(conn, req, fsp)) {
3706 END_PROFILE(SMBlockread);
3710 if (!CHECK_READ(fsp,req)) {
3711 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3712 END_PROFILE(SMBlockread);
3716 numtoread = SVAL(req->vwv+1, 0);
3717 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3720 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3721 * protocol request that predates the read/write lock concept.
3722 * Thus instead of asking for a read lock here we need to ask
3723 * for a write lock. JRA.
3724 * Note that the requested lock size is unaffected by max_send.
3727 br_lck = do_lock(req->sconn->msg_ctx,
3729 (uint64_t)req->smbpid,
3730 (uint64_t)numtoread,
3734 False, /* Non-blocking lock. */
3737 TALLOC_FREE(br_lck);
3739 if (NT_STATUS_V(status)) {
3740 reply_nterror(req, status);
3741 END_PROFILE(SMBlockread);
3746 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3748 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3750 if (numtoread > maxtoread) {
3751 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3752 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3753 (unsigned int)numtoread, (unsigned int)maxtoread,
3754 (unsigned int)xconn->smb1.sessions.max_send));
3755 numtoread = maxtoread;
3758 reply_outbuf(req, 5, numtoread + 3);
3760 data = smb_buf(req->outbuf) + 3;
3762 nread = read_file(fsp,data,startpos,numtoread);
3765 reply_nterror(req, map_nt_error_from_unix(errno));
3766 END_PROFILE(SMBlockread);
3770 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3772 SSVAL(req->outbuf,smb_vwv0,nread);
3773 SSVAL(req->outbuf,smb_vwv5,nread+3);
3774 p = smb_buf(req->outbuf);
3775 SCVAL(p,0,0); /* pad byte. */
3778 DEBUG(3,("lockread %s num=%d nread=%d\n",
3779 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3781 END_PROFILE(SMBlockread);
3786 #define DBGC_CLASS DBGC_ALL
3788 /****************************************************************************
3790 ****************************************************************************/
3792 void reply_read(struct smb_request *req)
3794 connection_struct *conn = req->conn;
3801 struct lock_struct lock;
3802 struct smbXsrv_connection *xconn = req->xconn;
3804 START_PROFILE(SMBread);
3807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3808 END_PROFILE(SMBread);
3812 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3814 if (!check_fsp(conn, req, fsp)) {
3815 END_PROFILE(SMBread);
3819 if (!CHECK_READ(fsp,req)) {
3820 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3821 END_PROFILE(SMBread);
3825 numtoread = SVAL(req->vwv+1, 0);
3826 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3829 * The requested read size cannot be greater than max_send. JRA.
3831 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3833 if (numtoread > maxtoread) {
3834 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3835 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3836 (unsigned int)numtoread, (unsigned int)maxtoread,
3837 (unsigned int)xconn->smb1.sessions.max_send));
3838 numtoread = maxtoread;
3841 reply_outbuf(req, 5, numtoread+3);
3843 data = smb_buf(req->outbuf) + 3;
3845 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3846 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3849 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3850 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3851 END_PROFILE(SMBread);
3856 nread = read_file(fsp,data,startpos,numtoread);
3859 reply_nterror(req, map_nt_error_from_unix(errno));
3863 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3865 SSVAL(req->outbuf,smb_vwv0,nread);
3866 SSVAL(req->outbuf,smb_vwv5,nread+3);
3867 SCVAL(smb_buf(req->outbuf),0,1);
3868 SSVAL(smb_buf(req->outbuf),1,nread);
3870 DEBUG(3, ("read %s num=%d nread=%d\n",
3871 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3874 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3876 END_PROFILE(SMBread);
3880 /****************************************************************************
3882 ****************************************************************************/
3884 static int setup_readX_header(struct smb_request *req, char *outbuf,
3889 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3892 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3894 SCVAL(outbuf,smb_vwv0,0xFF);
3895 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3896 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3897 SSVAL(outbuf,smb_vwv6,
3898 (smb_wct - 4) /* offset from smb header to wct */
3899 + 1 /* the wct field */
3900 + 12 * sizeof(uint16_t) /* vwv */
3901 + 2 /* the buflen field */
3902 + 1); /* padding byte */
3903 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3904 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3905 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3906 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3907 _smb_setlen_large(outbuf,
3908 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3912 /****************************************************************************
3913 Reply to a read and X - possibly using sendfile.
3914 ****************************************************************************/
3916 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3917 files_struct *fsp, off_t startpos,
3920 struct smbXsrv_connection *xconn = req->xconn;
3922 struct lock_struct lock;
3923 int saved_errno = 0;
3925 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3926 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3929 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3930 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3935 * We can only use sendfile on a non-chained packet
3936 * but we can use on a non-oplocked file. tridge proved this
3937 * on a train in Germany :-). JRA.
3940 if (!req_is_in_chain(req) &&
3942 (fsp->base_fsp == NULL) &&
3943 (fsp->wcp == NULL) &&
3944 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3945 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3948 if(fsp_stat(fsp) == -1) {
3949 reply_nterror(req, map_nt_error_from_unix(errno));
3953 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3954 (startpos > fsp->fsp_name->st.st_ex_size) ||
3955 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3957 * We already know that we would do a short read, so don't
3958 * try the sendfile() path.
3960 goto nosendfile_read;
3964 * Set up the packet header before send. We
3965 * assume here the sendfile will work (get the
3966 * correct amount of data).
3969 header = data_blob_const(headerbuf, sizeof(headerbuf));
3971 construct_reply_common_req(req, (char *)headerbuf);
3972 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3974 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3975 startpos, smb_maxcnt);
3977 saved_errno = errno;
3979 /* Returning ENOSYS means no data at all was sent.
3980 Do this as a normal read. */
3981 if (errno == ENOSYS) {
3986 * Special hack for broken Linux with no working sendfile. If we
3987 * return EINTR we sent the header but not the rest of the data.
3988 * Fake this up by doing read/write calls.
3991 if (errno == EINTR) {
3992 /* Ensure we don't do this again. */
3993 set_use_sendfile(SNUM(conn), False);
3994 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3995 nread = fake_sendfile(xconn, fsp, startpos,
3998 saved_errno = errno;
3999 DEBUG(0,("send_file_readX: "
4000 "fake_sendfile failed for "
4001 "file %s (%s) for client %s. "
4004 smbXsrv_connection_dbg(xconn),
4005 strerror(saved_errno)));
4006 errno = saved_errno;
4007 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4009 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4010 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4011 /* No outbuf here means successful sendfile. */
4015 DEBUG(0,("send_file_readX: sendfile failed for file "
4016 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4018 exit_server_cleanly("send_file_readX sendfile failed");
4019 } else if (nread == 0) {
4021 * Some sendfile implementations return 0 to indicate
4022 * that there was a short read, but nothing was
4023 * actually written to the socket. In this case,
4024 * fallback to the normal read path so the header gets
4025 * the correct byte count.
4027 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4028 "falling back to the normal read: %s\n",
4033 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4034 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4036 /* Deal with possible short send. */
4037 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4040 ret = sendfile_short_send(xconn, fsp, nread,
4041 sizeof(headerbuf), smb_maxcnt);
4044 r = "send_file_readX: sendfile_short_send failed";
4045 DEBUG(0,("%s for file %s (%s).\n",
4046 r, fsp_str_dbg(fsp), strerror(errno)));
4047 exit_server_cleanly(r);
4050 /* No outbuf here means successful sendfile. */
4051 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4052 SMB_PERFCOUNT_END(&req->pcd);
4058 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4059 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4062 construct_reply_common_req(req, (char *)headerbuf);
4063 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
4065 /* Send out the header. */
4066 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4068 if (ret != sizeof(headerbuf)) {
4069 saved_errno = errno;
4071 * Try and give an error message saying what
4074 DEBUG(0,("send_file_readX: write_data failed for file "
4075 "%s (%s) for client %s. Terminating\n",
4077 smbXsrv_connection_dbg(xconn),
4078 strerror(saved_errno)));
4079 errno = saved_errno;
4080 exit_server_cleanly("send_file_readX sendfile failed");
4082 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4084 saved_errno = errno;
4085 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4086 "%s (%s) for client %s. Terminating\n",
4088 smbXsrv_connection_dbg(xconn),
4089 strerror(saved_errno)));
4090 errno = saved_errno;
4091 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4098 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4099 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4100 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4102 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4103 startpos, smb_maxcnt);
4104 saved_errno = errno;
4106 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4109 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4113 setup_readX_header(req, (char *)req->outbuf, nread);
4115 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4116 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4120 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4121 TALLOC_FREE(req->outbuf);
4125 /****************************************************************************
4126 Work out how much space we have for a read return.
4127 ****************************************************************************/
4129 static size_t calc_max_read_pdu(const struct smb_request *req)
4131 struct smbXsrv_connection *xconn = req->xconn;
4133 if (xconn->protocol < PROTOCOL_NT1) {
4134 return xconn->smb1.sessions.max_send;
4137 if (!lp_large_readwrite()) {
4138 return xconn->smb1.sessions.max_send;
4141 if (req_is_in_chain(req)) {
4142 return xconn->smb1.sessions.max_send;
4145 if (req->encrypted) {
4147 * Don't take encrypted traffic up to the
4148 * limit. There are padding considerations
4149 * that make that tricky.
4151 return xconn->smb1.sessions.max_send;
4154 if (srv_is_signing_active(xconn)) {
4158 if (!lp_unix_extensions()) {
4163 * We can do ultra-large POSIX reads.
4168 /****************************************************************************
4169 Calculate how big a read can be. Copes with all clients. It's always
4170 safe to return a short read - Windows does this.
4171 ****************************************************************************/
4173 static size_t calc_read_size(const struct smb_request *req,
4177 struct smbXsrv_connection *xconn = req->xconn;
4178 size_t max_pdu = calc_max_read_pdu(req);
4179 size_t total_size = 0;
4180 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4181 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4184 * Windows explicitly ignores upper size of 0xFFFF.
4185 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4186 * We must do the same as these will never fit even in
4187 * an extended size NetBIOS packet.
4189 if (upper_size == 0xFFFF) {
4193 if (xconn->protocol < PROTOCOL_NT1) {
4197 total_size = ((upper_size<<16) | lower_size);
4200 * LARGE_READX test shows it's always safe to return
4201 * a short read. Windows does so.
4203 return MIN(total_size, max_len);
4206 /****************************************************************************
4207 Reply to a read and X.
4208 ****************************************************************************/
4210 void reply_read_and_X(struct smb_request *req)
4212 connection_struct *conn = req->conn;
4217 bool big_readX = False;
4219 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4222 START_PROFILE(SMBreadX);
4224 if ((req->wct != 10) && (req->wct != 12)) {
4225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4229 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4230 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4231 smb_maxcnt = SVAL(req->vwv+5, 0);
4233 /* If it's an IPC, pass off the pipe handler. */
4235 reply_pipe_read_and_X(req);
4236 END_PROFILE(SMBreadX);
4240 if (!check_fsp(conn, req, fsp)) {
4241 END_PROFILE(SMBreadX);
4245 if (!CHECK_READ(fsp,req)) {
4246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4247 END_PROFILE(SMBreadX);
4251 upper_size = SVAL(req->vwv+7, 0);
4252 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4253 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4255 * This is a heuristic to avoid keeping large
4256 * outgoing buffers around over long-lived aio
4262 if (req->wct == 12) {
4264 * This is a large offset (64 bit) read.
4266 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4271 NTSTATUS status = schedule_aio_read_and_X(conn,
4276 if (NT_STATUS_IS_OK(status)) {
4277 /* Read scheduled - we're done. */
4280 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4281 /* Real error - report to client. */
4282 END_PROFILE(SMBreadX);
4283 reply_nterror(req, status);
4286 /* NT_STATUS_RETRY - fall back to sync read. */
4289 smbd_lock_socket(req->xconn);
4290 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4291 smbd_unlock_socket(req->xconn);
4294 END_PROFILE(SMBreadX);
4298 /****************************************************************************
4299 Error replies to writebraw must have smb_wct == 1. Fix this up.
4300 ****************************************************************************/
4302 void error_to_writebrawerr(struct smb_request *req)
4304 uint8_t *old_outbuf = req->outbuf;
4306 reply_outbuf(req, 1, 0);
4308 memcpy(req->outbuf, old_outbuf, smb_size);
4309 TALLOC_FREE(old_outbuf);
4312 /****************************************************************************
4313 Read 4 bytes of a smb packet and return the smb length of the packet.
4314 Store the result in the buffer. This version of the function will
4315 never return a session keepalive (length of zero).
4316 Timeout is in milliseconds.
4317 ****************************************************************************/
4319 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4322 uint8_t msgtype = NBSSkeepalive;
4324 while (msgtype == NBSSkeepalive) {
4327 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4329 if (!NT_STATUS_IS_OK(status)) {
4330 char addr[INET6_ADDRSTRLEN];
4331 /* Try and give an error message
4332 * saying what client failed. */
4333 DEBUG(0, ("read_fd_with_timeout failed for "
4334 "client %s read error = %s.\n",
4335 get_peer_addr(fd,addr,sizeof(addr)),
4336 nt_errstr(status)));
4340 msgtype = CVAL(inbuf, 0);
4343 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4344 (unsigned long)len));
4346 return NT_STATUS_OK;
4349 /****************************************************************************
4350 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4351 ****************************************************************************/
4353 void reply_writebraw(struct smb_request *req)
4355 connection_struct *conn = req->conn;
4356 struct smbXsrv_connection *xconn = req->xconn;
4359 ssize_t total_written=0;
4360 size_t numtowrite=0;
4363 const char *data=NULL;
4366 struct lock_struct lock;
4369 START_PROFILE(SMBwritebraw);
4372 * If we ever reply with an error, it must have the SMB command
4373 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4376 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4378 if (srv_is_signing_active(xconn)) {
4379 END_PROFILE(SMBwritebraw);
4380 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4381 "raw reads/writes are disallowed.");
4384 if (req->wct < 12) {
4385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4386 error_to_writebrawerr(req);
4387 END_PROFILE(SMBwritebraw);
4391 if (xconn->smb1.echo_handler.trusted_fde) {
4392 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4393 "'async smb echo handler = yes'\n"));
4394 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4395 error_to_writebrawerr(req);
4396 END_PROFILE(SMBwritebraw);
4400 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4401 if (!check_fsp(conn, req, fsp)) {
4402 error_to_writebrawerr(req);
4403 END_PROFILE(SMBwritebraw);
4407 if (!CHECK_WRITE(fsp)) {
4408 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4409 error_to_writebrawerr(req);
4410 END_PROFILE(SMBwritebraw);
4414 tcount = IVAL(req->vwv+1, 0);
4415 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4416 write_through = BITSETW(req->vwv+7,0);
4418 /* We have to deal with slightly different formats depending
4419 on whether we are using the core+ or lanman1.0 protocol */
4421 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4422 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4423 data = smb_buf_const(req->inbuf);
4425 numtowrite = SVAL(req->vwv+10, 0);
4426 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4429 /* Ensure we don't write bytes past the end of this packet. */
4430 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4432 error_to_writebrawerr(req);
4433 END_PROFILE(SMBwritebraw);
4437 if (!fsp->print_file) {
4438 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4439 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4442 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4443 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4444 error_to_writebrawerr(req);
4445 END_PROFILE(SMBwritebraw);
4451 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4454 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4455 "wrote=%d sync=%d\n",
4456 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4457 (int)nwritten, (int)write_through));
4459 if (nwritten < (ssize_t)numtowrite) {
4460 reply_nterror(req, NT_STATUS_DISK_FULL);
4461 error_to_writebrawerr(req);
4465 total_written = nwritten;
4467 /* Allocate a buffer of 64k + length. */
4468 buf = talloc_array(NULL, char, 65540);
4470 reply_nterror(req, NT_STATUS_NO_MEMORY);
4471 error_to_writebrawerr(req);
4475 /* Return a SMBwritebraw message to the redirector to tell
4476 * it to send more bytes */
4478 memcpy(buf, req->inbuf, smb_size);
4479 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4480 SCVAL(buf,smb_com,SMBwritebraw);
4481 SSVALS(buf,smb_vwv0,0xFFFF);
4483 if (!srv_send_smb(req->xconn,
4485 false, 0, /* no signing */
4486 IS_CONN_ENCRYPTED(conn),
4488 exit_server_cleanly("reply_writebraw: srv_send_smb "
4492 /* Now read the raw data into the buffer and write it */
4493 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4495 if (!NT_STATUS_IS_OK(status)) {
4496 exit_server_cleanly("secondary writebraw failed");
4499 /* Set up outbuf to return the correct size */
4500 reply_outbuf(req, 1, 0);
4502 if (numtowrite != 0) {
4504 if (numtowrite > 0xFFFF) {
4505 DEBUG(0,("reply_writebraw: Oversize secondary write "
4506 "raw requested (%u). Terminating\n",
4507 (unsigned int)numtowrite ));
4508 exit_server_cleanly("secondary writebraw failed");
4511 if (tcount > nwritten+numtowrite) {
4512 DEBUG(3,("reply_writebraw: Client overestimated the "
4514 (int)tcount,(int)nwritten,(int)numtowrite));
4517 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4520 if (!NT_STATUS_IS_OK(status)) {
4521 /* Try and give an error message
4522 * saying what client failed. */
4523 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4524 "raw read failed (%s) for client %s. "
4525 "Terminating\n", nt_errstr(status),
4526 smbXsrv_connection_dbg(xconn)));
4527 exit_server_cleanly("secondary writebraw failed");
4530 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4531 if (nwritten == -1) {
4533 reply_nterror(req, map_nt_error_from_unix(errno));
4534 error_to_writebrawerr(req);
4538 if (nwritten < (ssize_t)numtowrite) {
4539 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4540 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4544 total_written += nwritten;
4549 SSVAL(req->outbuf,smb_vwv0,total_written);
4551 status = sync_file(conn, fsp, write_through);
4552 if (!NT_STATUS_IS_OK(status)) {
4553 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4554 fsp_str_dbg(fsp), nt_errstr(status)));
4555 reply_nterror(req, status);
4556 error_to_writebrawerr(req);
4560 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4562 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4563 (int)total_written));
4565 if (!fsp->print_file) {
4566 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4569 /* We won't return a status if write through is not selected - this
4570 * follows what WfWg does */
4571 END_PROFILE(SMBwritebraw);
4573 if (!write_through && total_written==tcount) {
4575 #if RABBIT_PELLET_FIX
4577 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4578 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4581 if (!send_keepalive(xconn->transport.sock)) {
4582 exit_server_cleanly("reply_writebraw: send of "
4583 "keepalive failed");
4586 TALLOC_FREE(req->outbuf);
4591 if (!fsp->print_file) {
4592 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4595 END_PROFILE(SMBwritebraw);
4600 #define DBGC_CLASS DBGC_LOCKING
4602 /****************************************************************************
4603 Reply to a writeunlock (core+).
4604 ****************************************************************************/
4606 void reply_writeunlock(struct smb_request *req)
4608 connection_struct *conn = req->conn;
4609 ssize_t nwritten = -1;
4613 NTSTATUS status = NT_STATUS_OK;
4615 struct lock_struct lock;
4616 int saved_errno = 0;
4618 START_PROFILE(SMBwriteunlock);
4621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4622 END_PROFILE(SMBwriteunlock);
4626 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4628 if (!check_fsp(conn, req, fsp)) {
4629 END_PROFILE(SMBwriteunlock);
4633 if (!CHECK_WRITE(fsp)) {
4634 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4635 END_PROFILE(SMBwriteunlock);
4639 numtowrite = SVAL(req->vwv+1, 0);
4640 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4641 data = (const char *)req->buf + 3;
4643 if (!fsp->print_file && numtowrite > 0) {
4644 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4645 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4648 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4649 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4650 END_PROFILE(SMBwriteunlock);
4655 /* The special X/Open SMB protocol handling of
4656 zero length writes is *NOT* done for
4658 if(numtowrite == 0) {
4661 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4662 saved_errno = errno;
4665 status = sync_file(conn, fsp, False /* write through */);
4666 if (!NT_STATUS_IS_OK(status)) {
4667 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4668 fsp_str_dbg(fsp), nt_errstr(status)));
4669 reply_nterror(req, status);
4674 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4678 if((nwritten < numtowrite) && (numtowrite != 0)) {
4679 reply_nterror(req, NT_STATUS_DISK_FULL);
4683 if (numtowrite && !fsp->print_file) {
4684 status = do_unlock(req->sconn->msg_ctx,
4686 (uint64_t)req->smbpid,
4687 (uint64_t)numtowrite,
4691 if (NT_STATUS_V(status)) {
4692 reply_nterror(req, status);
4697 reply_outbuf(req, 1, 0);
4699 SSVAL(req->outbuf,smb_vwv0,nwritten);
4701 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4702 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4705 if (numtowrite && !fsp->print_file) {
4706 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4709 END_PROFILE(SMBwriteunlock);
4714 #define DBGC_CLASS DBGC_ALL
4716 /****************************************************************************
4718 ****************************************************************************/
4720 void reply_write(struct smb_request *req)
4722 connection_struct *conn = req->conn;
4724 ssize_t nwritten = -1;
4728 struct lock_struct lock;
4730 int saved_errno = 0;
4732 START_PROFILE(SMBwrite);
4735 END_PROFILE(SMBwrite);
4736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740 /* If it's an IPC, pass off the pipe handler. */
4742 reply_pipe_write(req);
4743 END_PROFILE(SMBwrite);
4747 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4749 if (!check_fsp(conn, req, fsp)) {
4750 END_PROFILE(SMBwrite);
4754 if (!CHECK_WRITE(fsp)) {
4755 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4756 END_PROFILE(SMBwrite);
4760 numtowrite = SVAL(req->vwv+1, 0);
4761 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4762 data = (const char *)req->buf + 3;
4764 if (!fsp->print_file) {
4765 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4766 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4769 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4770 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4771 END_PROFILE(SMBwrite);
4777 * X/Open SMB protocol says that if smb_vwv1 is
4778 * zero then the file size should be extended or
4779 * truncated to the size given in smb_vwv[2-3].
4782 if(numtowrite == 0) {
4784 * This is actually an allocate call, and set EOF. JRA.
4786 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4788 reply_nterror(req, NT_STATUS_DISK_FULL);
4791 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4793 reply_nterror(req, NT_STATUS_DISK_FULL);
4796 trigger_write_time_update_immediate(fsp);
4798 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4801 status = sync_file(conn, fsp, False);
4802 if (!NT_STATUS_IS_OK(status)) {
4803 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4804 fsp_str_dbg(fsp), nt_errstr(status)));
4805 reply_nterror(req, status);
4810 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4814 if((nwritten == 0) && (numtowrite != 0)) {
4815 reply_nterror(req, NT_STATUS_DISK_FULL);
4819 reply_outbuf(req, 1, 0);
4821 SSVAL(req->outbuf,smb_vwv0,nwritten);
4823 if (nwritten < (ssize_t)numtowrite) {
4824 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4825 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4828 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4831 if (!fsp->print_file) {
4832 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4835 END_PROFILE(SMBwrite);
4839 /****************************************************************************
4840 Ensure a buffer is a valid writeX for recvfile purposes.
4841 ****************************************************************************/
4843 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4844 (2*14) + /* word count (including bcc) */ \
4847 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4848 const uint8_t *inbuf)
4851 unsigned int doff = 0;
4852 size_t len = smb_len_large(inbuf);
4854 struct smbXsrv_open *op = NULL;
4855 struct files_struct *fsp = NULL;
4858 if (is_encrypted_packet(inbuf)) {
4859 /* Can't do this on encrypted
4864 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4868 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4869 CVAL(inbuf,smb_wct) != 14) {
4870 DEBUG(10,("is_valid_writeX_buffer: chained or "
4871 "invalid word length.\n"));
4875 fnum = SVAL(inbuf, smb_vwv2);
4876 status = smb1srv_open_lookup(xconn,
4880 if (!NT_STATUS_IS_OK(status)) {
4881 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4886 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4889 if (fsp->conn == NULL) {
4890 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4894 if (IS_IPC(fsp->conn)) {
4895 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4898 if (IS_PRINT(fsp->conn)) {
4899 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4902 doff = SVAL(inbuf,smb_vwv11);
4904 numtowrite = SVAL(inbuf,smb_vwv10);
4906 if (len > doff && len - doff > 0xFFFF) {
4907 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4910 if (numtowrite == 0) {
4911 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4915 /* Ensure the sizes match up. */
4916 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4917 /* no pad byte...old smbclient :-( */
4918 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4920 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4924 if (len - doff != numtowrite) {
4925 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4926 "len = %u, doff = %u, numtowrite = %u\n",
4929 (unsigned int)numtowrite ));
4933 DEBUG(10,("is_valid_writeX_buffer: true "
4934 "len = %u, doff = %u, numtowrite = %u\n",
4937 (unsigned int)numtowrite ));
4942 /****************************************************************************
4943 Reply to a write and X.
4944 ****************************************************************************/
4946 void reply_write_and_X(struct smb_request *req)
4948 connection_struct *conn = req->conn;
4949 struct smbXsrv_connection *xconn = req->xconn;
4951 struct lock_struct lock;
4956 unsigned int smb_doff;
4957 unsigned int smblen;
4960 int saved_errno = 0;
4962 START_PROFILE(SMBwriteX);
4964 if ((req->wct != 12) && (req->wct != 14)) {
4965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4969 numtowrite = SVAL(req->vwv+10, 0);
4970 smb_doff = SVAL(req->vwv+11, 0);
4971 smblen = smb_len(req->inbuf);
4973 if (req->unread_bytes > 0xFFFF ||
4974 (smblen > smb_doff &&
4975 smblen - smb_doff > 0xFFFF)) {
4976 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4979 if (req->unread_bytes) {
4980 /* Can't do a recvfile write on IPC$ */
4982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 if (numtowrite != req->unread_bytes) {
4986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4991 smb_doff + numtowrite > smblen) {
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4997 /* If it's an IPC, pass off the pipe handler. */
4999 if (req->unread_bytes) {
5000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5003 reply_pipe_write_and_X(req);
5007 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5008 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5009 write_through = BITSETW(req->vwv+7,0);
5011 if (!check_fsp(conn, req, fsp)) {
5015 if (!CHECK_WRITE(fsp)) {
5016 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5020 data = smb_base(req->inbuf) + smb_doff;
5022 if(req->wct == 14) {
5024 * This is a large offset (64 bit) write.
5026 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5030 /* X/Open SMB protocol says that, unlike SMBwrite
5031 if the length is zero then NO truncation is
5032 done, just a write of zero. To truncate a file,
5035 if(numtowrite == 0) {
5038 if (req->unread_bytes == 0) {
5039 status = schedule_aio_write_and_X(conn,
5046 if (NT_STATUS_IS_OK(status)) {
5047 /* write scheduled - we're done. */
5050 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5051 /* Real error - report to client. */
5052 reply_nterror(req, status);
5055 /* NT_STATUS_RETRY - fall through to sync write. */
5058 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5059 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5062 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5063 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5067 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5068 saved_errno = errno;
5070 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5074 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5078 if((nwritten == 0) && (numtowrite != 0)) {
5079 reply_nterror(req, NT_STATUS_DISK_FULL);
5083 reply_outbuf(req, 6, 0);
5084 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5085 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5086 SSVAL(req->outbuf,smb_vwv2,nwritten);
5087 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5089 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5090 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5092 status = sync_file(conn, fsp, write_through);
5093 if (!NT_STATUS_IS_OK(status)) {
5094 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5095 fsp_str_dbg(fsp), nt_errstr(status)));
5096 reply_nterror(req, status);
5100 END_PROFILE(SMBwriteX);
5104 if (req->unread_bytes) {
5105 /* writeX failed. drain socket. */
5106 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5107 req->unread_bytes) {
5108 smb_panic("failed to drain pending bytes");
5110 req->unread_bytes = 0;
5113 END_PROFILE(SMBwriteX);
5117 /****************************************************************************
5119 ****************************************************************************/
5121 void reply_lseek(struct smb_request *req)
5123 connection_struct *conn = req->conn;
5129 START_PROFILE(SMBlseek);
5132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133 END_PROFILE(SMBlseek);
5137 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5139 if (!check_fsp(conn, req, fsp)) {
5143 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5145 mode = SVAL(req->vwv+1, 0) & 3;
5146 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5147 startpos = (off_t)IVALS(req->vwv+2, 0);
5156 res = fsp->fh->pos + startpos;
5167 if (umode == SEEK_END) {
5168 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5169 if(errno == EINVAL) {
5170 off_t current_pos = startpos;
5172 if(fsp_stat(fsp) == -1) {
5174 map_nt_error_from_unix(errno));
5175 END_PROFILE(SMBlseek);
5179 current_pos += fsp->fsp_name->st.st_ex_size;
5181 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5186 reply_nterror(req, map_nt_error_from_unix(errno));
5187 END_PROFILE(SMBlseek);
5194 reply_outbuf(req, 2, 0);
5195 SIVAL(req->outbuf,smb_vwv0,res);
5197 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5198 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5200 END_PROFILE(SMBlseek);
5204 /****************************************************************************
5206 ****************************************************************************/
5208 void reply_flush(struct smb_request *req)
5210 connection_struct *conn = req->conn;
5214 START_PROFILE(SMBflush);
5217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5221 fnum = SVAL(req->vwv+0, 0);
5222 fsp = file_fsp(req, fnum);
5224 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5229 file_sync_all(conn);
5231 NTSTATUS status = sync_file(conn, fsp, True);
5232 if (!NT_STATUS_IS_OK(status)) {
5233 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5234 fsp_str_dbg(fsp), nt_errstr(status)));
5235 reply_nterror(req, status);
5236 END_PROFILE(SMBflush);
5241 reply_outbuf(req, 0, 0);
5243 DEBUG(3,("flush\n"));
5244 END_PROFILE(SMBflush);
5248 /****************************************************************************
5250 conn POINTER CAN BE NULL HERE !
5251 ****************************************************************************/
5253 void reply_exit(struct smb_request *req)
5255 START_PROFILE(SMBexit);
5257 file_close_pid(req->sconn, req->smbpid, req->vuid);
5259 reply_outbuf(req, 0, 0);
5261 DEBUG(3,("exit\n"));
5263 END_PROFILE(SMBexit);
5267 struct reply_close_state {
5269 struct smb_request *smbreq;
5272 static void do_smb1_close(struct tevent_req *req);
5274 void reply_close(struct smb_request *req)
5276 connection_struct *conn = req->conn;
5277 NTSTATUS status = NT_STATUS_OK;
5278 files_struct *fsp = NULL;
5279 START_PROFILE(SMBclose);
5282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5283 END_PROFILE(SMBclose);
5287 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5290 * We can only use check_fsp if we know it's not a directory.
5293 if (!check_fsp_open(conn, req, fsp)) {
5294 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5295 END_PROFILE(SMBclose);
5299 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5300 fsp->is_directory ? "directory" : "file",
5301 fsp->fh->fd, fsp_fnum_dbg(fsp),
5302 conn->num_files_open));
5304 if (!fsp->is_directory) {
5308 * Take care of any time sent in the close.
5311 t = srv_make_unix_date3(req->vwv+1);
5312 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5315 if (fsp->num_aio_requests != 0) {
5317 struct reply_close_state *state;
5319 DEBUG(10, ("closing with aio %u requests pending\n",
5320 fsp->num_aio_requests));
5323 * We depend on the aio_extra destructor to take care of this
5324 * close request once fsp->num_aio_request drops to 0.
5327 fsp->deferred_close = tevent_wait_send(
5328 fsp, fsp->conn->sconn->ev_ctx);
5329 if (fsp->deferred_close == NULL) {
5330 status = NT_STATUS_NO_MEMORY;
5334 state = talloc(fsp, struct reply_close_state);
5335 if (state == NULL) {
5336 TALLOC_FREE(fsp->deferred_close);
5337 status = NT_STATUS_NO_MEMORY;
5341 state->smbreq = talloc_move(fsp, &req);
5342 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5344 END_PROFILE(SMBclose);
5349 * close_file() returns the unix errno if an error was detected on
5350 * close - normally this is due to a disk full error. If not then it
5351 * was probably an I/O error.
5354 status = close_file(req, fsp, NORMAL_CLOSE);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 reply_nterror(req, status);
5358 END_PROFILE(SMBclose);
5362 reply_outbuf(req, 0, 0);
5363 END_PROFILE(SMBclose);
5367 static void do_smb1_close(struct tevent_req *req)
5369 struct reply_close_state *state = tevent_req_callback_data(
5370 req, struct reply_close_state);
5371 struct smb_request *smbreq;
5375 ret = tevent_wait_recv(req);
5378 DEBUG(10, ("tevent_wait_recv returned %s\n",
5381 * Continue anyway, this should never happen
5386 * fsp->smb2_close_request right now is a talloc grandchild of
5387 * fsp. When we close_file(fsp), it would go with it. No chance to
5390 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5392 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5393 if (NT_STATUS_IS_OK(status)) {
5394 reply_outbuf(smbreq, 0, 0);
5396 reply_nterror(smbreq, status);
5398 if (!srv_send_smb(smbreq->xconn,
5399 (char *)smbreq->outbuf,
5402 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5404 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5407 TALLOC_FREE(smbreq);
5410 /****************************************************************************
5411 Reply to a writeclose (Core+ protocol).
5412 ****************************************************************************/
5414 void reply_writeclose(struct smb_request *req)
5416 connection_struct *conn = req->conn;
5418 ssize_t nwritten = -1;
5419 NTSTATUS close_status = NT_STATUS_OK;
5422 struct timespec mtime;
5424 struct lock_struct lock;
5426 START_PROFILE(SMBwriteclose);
5429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5430 END_PROFILE(SMBwriteclose);
5434 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5436 if (!check_fsp(conn, req, fsp)) {
5437 END_PROFILE(SMBwriteclose);
5440 if (!CHECK_WRITE(fsp)) {
5441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5442 END_PROFILE(SMBwriteclose);
5446 numtowrite = SVAL(req->vwv+1, 0);
5447 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5448 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5449 data = (const char *)req->buf + 1;
5451 if (fsp->print_file == NULL) {
5452 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5453 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5456 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5457 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5458 END_PROFILE(SMBwriteclose);
5463 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5465 if (fsp->print_file == NULL) {
5466 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5469 set_close_write_time(fsp, mtime);
5472 * More insanity. W2K only closes the file if writelen > 0.
5476 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5477 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5478 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5481 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5482 "file %s\n", fsp_str_dbg(fsp)));
5483 close_status = close_file(req, fsp, NORMAL_CLOSE);
5487 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5488 reply_nterror(req, NT_STATUS_DISK_FULL);
5492 if(!NT_STATUS_IS_OK(close_status)) {
5493 reply_nterror(req, close_status);
5497 reply_outbuf(req, 1, 0);
5499 SSVAL(req->outbuf,smb_vwv0,nwritten);
5503 END_PROFILE(SMBwriteclose);
5508 #define DBGC_CLASS DBGC_LOCKING
5510 /****************************************************************************
5512 ****************************************************************************/
5514 void reply_lock(struct smb_request *req)
5516 connection_struct *conn = req->conn;
5517 uint64_t count,offset;
5520 struct byte_range_lock *br_lck = NULL;
5522 START_PROFILE(SMBlock);
5525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5526 END_PROFILE(SMBlock);
5530 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5532 if (!check_fsp(conn, req, fsp)) {
5533 END_PROFILE(SMBlock);
5537 count = (uint64_t)IVAL(req->vwv+1, 0);
5538 offset = (uint64_t)IVAL(req->vwv+3, 0);
5540 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5541 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5543 br_lck = do_lock(req->sconn->msg_ctx,
5545 (uint64_t)req->smbpid,
5550 False, /* Non-blocking lock. */
5554 TALLOC_FREE(br_lck);
5556 if (NT_STATUS_V(status)) {
5557 reply_nterror(req, status);
5558 END_PROFILE(SMBlock);
5562 reply_outbuf(req, 0, 0);
5564 END_PROFILE(SMBlock);
5568 /****************************************************************************
5570 ****************************************************************************/
5572 void reply_unlock(struct smb_request *req)
5574 connection_struct *conn = req->conn;
5575 uint64_t count,offset;
5579 START_PROFILE(SMBunlock);
5582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5583 END_PROFILE(SMBunlock);
5587 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5589 if (!check_fsp(conn, req, fsp)) {
5590 END_PROFILE(SMBunlock);
5594 count = (uint64_t)IVAL(req->vwv+1, 0);
5595 offset = (uint64_t)IVAL(req->vwv+3, 0);
5597 status = do_unlock(req->sconn->msg_ctx,
5599 (uint64_t)req->smbpid,
5604 if (NT_STATUS_V(status)) {
5605 reply_nterror(req, status);
5606 END_PROFILE(SMBunlock);
5610 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5611 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5613 reply_outbuf(req, 0, 0);
5615 END_PROFILE(SMBunlock);
5620 #define DBGC_CLASS DBGC_ALL
5622 /****************************************************************************
5624 conn POINTER CAN BE NULL HERE !
5625 ****************************************************************************/
5627 void reply_tdis(struct smb_request *req)
5630 connection_struct *conn = req->conn;
5631 struct smbXsrv_tcon *tcon;
5633 START_PROFILE(SMBtdis);
5636 DEBUG(4,("Invalid connection in tdis\n"));
5637 reply_force_doserror(req, ERRSRV, ERRinvnid);
5638 END_PROFILE(SMBtdis);
5646 * TODO: cancel all outstanding requests on the tcon
5648 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 DEBUG(0, ("reply_tdis: "
5651 "smbXsrv_tcon_disconnect() failed: %s\n",
5652 nt_errstr(status)));
5654 * If we hit this case, there is something completely
5655 * wrong, so we better disconnect the transport connection.
5657 END_PROFILE(SMBtdis);
5658 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5664 reply_outbuf(req, 0, 0);
5665 END_PROFILE(SMBtdis);
5669 /****************************************************************************
5671 conn POINTER CAN BE NULL HERE !
5672 ****************************************************************************/
5674 void reply_echo(struct smb_request *req)
5676 connection_struct *conn = req->conn;
5677 struct smb_perfcount_data local_pcd;
5678 struct smb_perfcount_data *cur_pcd;
5682 START_PROFILE(SMBecho);
5684 smb_init_perfcount_data(&local_pcd);
5687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5688 END_PROFILE(SMBecho);
5692 smb_reverb = SVAL(req->vwv+0, 0);
5694 reply_outbuf(req, 1, req->buflen);
5696 /* copy any incoming data back out */
5697 if (req->buflen > 0) {
5698 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5701 if (smb_reverb > 100) {
5702 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5706 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5708 /* this makes sure we catch the request pcd */
5709 if (seq_num == smb_reverb) {
5710 cur_pcd = &req->pcd;
5712 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5713 cur_pcd = &local_pcd;
5716 SSVAL(req->outbuf,smb_vwv0,seq_num);
5718 show_msg((char *)req->outbuf);
5719 if (!srv_send_smb(req->xconn,
5720 (char *)req->outbuf,
5721 true, req->seqnum+1,
5722 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5724 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5727 DEBUG(3,("echo %d times\n", smb_reverb));
5729 TALLOC_FREE(req->outbuf);
5731 END_PROFILE(SMBecho);
5735 /****************************************************************************
5736 Reply to a printopen.
5737 ****************************************************************************/
5739 void reply_printopen(struct smb_request *req)
5741 connection_struct *conn = req->conn;
5745 START_PROFILE(SMBsplopen);
5748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5749 END_PROFILE(SMBsplopen);
5753 if (!CAN_PRINT(conn)) {
5754 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5755 END_PROFILE(SMBsplopen);
5759 status = file_new(req, conn, &fsp);
5760 if(!NT_STATUS_IS_OK(status)) {
5761 reply_nterror(req, status);
5762 END_PROFILE(SMBsplopen);
5766 /* Open for exclusive use, write only. */
5767 status = print_spool_open(fsp, NULL, req->vuid);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 file_free(req, fsp);
5771 reply_nterror(req, status);
5772 END_PROFILE(SMBsplopen);
5776 reply_outbuf(req, 1, 0);
5777 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5779 DEBUG(3,("openprint fd=%d %s\n",
5780 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5782 END_PROFILE(SMBsplopen);
5786 /****************************************************************************
5787 Reply to a printclose.
5788 ****************************************************************************/
5790 void reply_printclose(struct smb_request *req)
5792 connection_struct *conn = req->conn;
5796 START_PROFILE(SMBsplclose);
5799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5800 END_PROFILE(SMBsplclose);
5804 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5806 if (!check_fsp(conn, req, fsp)) {
5807 END_PROFILE(SMBsplclose);
5811 if (!CAN_PRINT(conn)) {
5812 reply_force_doserror(req, ERRSRV, ERRerror);
5813 END_PROFILE(SMBsplclose);
5817 DEBUG(3,("printclose fd=%d %s\n",
5818 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5820 status = close_file(req, fsp, NORMAL_CLOSE);
5822 if(!NT_STATUS_IS_OK(status)) {
5823 reply_nterror(req, status);
5824 END_PROFILE(SMBsplclose);
5828 reply_outbuf(req, 0, 0);
5830 END_PROFILE(SMBsplclose);
5834 /****************************************************************************
5835 Reply to a printqueue.
5836 ****************************************************************************/
5838 void reply_printqueue(struct smb_request *req)
5840 connection_struct *conn = req->conn;
5844 START_PROFILE(SMBsplretq);
5847 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5848 END_PROFILE(SMBsplretq);
5852 max_count = SVAL(req->vwv+0, 0);
5853 start_index = SVAL(req->vwv+1, 0);
5855 /* we used to allow the client to get the cnum wrong, but that
5856 is really quite gross and only worked when there was only
5857 one printer - I think we should now only accept it if they
5858 get it right (tridge) */
5859 if (!CAN_PRINT(conn)) {
5860 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5861 END_PROFILE(SMBsplretq);
5865 reply_outbuf(req, 2, 3);
5866 SSVAL(req->outbuf,smb_vwv0,0);
5867 SSVAL(req->outbuf,smb_vwv1,0);
5868 SCVAL(smb_buf(req->outbuf),0,1);
5869 SSVAL(smb_buf(req->outbuf),1,0);
5871 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5872 start_index, max_count));
5875 TALLOC_CTX *mem_ctx = talloc_tos();
5878 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5879 struct rpc_pipe_client *cli = NULL;
5880 struct dcerpc_binding_handle *b = NULL;
5881 struct policy_handle handle;
5882 struct spoolss_DevmodeContainer devmode_ctr;
5883 union spoolss_JobInfo *info;
5885 uint32_t num_to_get;
5889 ZERO_STRUCT(handle);
5891 status = rpc_pipe_open_interface(conn,
5894 conn->sconn->remote_address,
5895 conn->sconn->msg_ctx,
5897 if (!NT_STATUS_IS_OK(status)) {
5898 DEBUG(0, ("reply_printqueue: "
5899 "could not connect to spoolss: %s\n",
5900 nt_errstr(status)));
5901 reply_nterror(req, status);
5904 b = cli->binding_handle;
5906 ZERO_STRUCT(devmode_ctr);
5908 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5911 SEC_FLAG_MAXIMUM_ALLOWED,
5914 if (!NT_STATUS_IS_OK(status)) {
5915 reply_nterror(req, status);
5918 if (!W_ERROR_IS_OK(werr)) {
5919 reply_nterror(req, werror_to_ntstatus(werr));
5923 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5931 if (!W_ERROR_IS_OK(werr)) {
5932 reply_nterror(req, werror_to_ntstatus(werr));
5936 if (max_count > 0) {
5937 first = start_index;
5939 first = start_index + max_count + 1;
5942 if (first >= count) {
5945 num_to_get = first + MIN(ABS(max_count), count - first);
5948 for (i = first; i < num_to_get; i++) {
5951 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5954 uint16_t qrapjobid = pjobid_to_rap(sharename,
5955 info[i].info2.job_id);
5957 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5963 srv_put_dos_date2(p, 0, qtime);
5964 SCVAL(p, 4, qstatus);
5965 SSVAL(p, 5, qrapjobid);
5966 SIVAL(p, 7, info[i].info2.size);
5968 status = srvstr_push(blob, req->flags2, p+12,
5969 info[i].info2.notify_name, 16, STR_ASCII, &len);
5970 if (!NT_STATUS_IS_OK(status)) {
5971 reply_nterror(req, status);
5974 if (message_push_blob(
5977 blob, sizeof(blob))) == -1) {
5978 reply_nterror(req, NT_STATUS_NO_MEMORY);
5984 SSVAL(req->outbuf,smb_vwv0,count);
5985 SSVAL(req->outbuf,smb_vwv1,
5986 (max_count>0?first+count:first-1));
5987 SCVAL(smb_buf(req->outbuf),0,1);
5988 SSVAL(smb_buf(req->outbuf),1,28*count);
5992 DEBUG(3, ("%u entries returned in queue\n",
5996 if (b && is_valid_policy_hnd(&handle)) {
5997 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6002 END_PROFILE(SMBsplretq);
6006 /****************************************************************************
6007 Reply to a printwrite.
6008 ****************************************************************************/
6010 void reply_printwrite(struct smb_request *req)
6012 connection_struct *conn = req->conn;
6017 START_PROFILE(SMBsplwr);
6020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6021 END_PROFILE(SMBsplwr);
6025 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6027 if (!check_fsp(conn, req, fsp)) {
6028 END_PROFILE(SMBsplwr);
6032 if (!fsp->print_file) {
6033 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6034 END_PROFILE(SMBsplwr);
6038 if (!CHECK_WRITE(fsp)) {
6039 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6040 END_PROFILE(SMBsplwr);
6044 numtowrite = SVAL(req->buf, 1);
6046 if (req->buflen < numtowrite + 3) {
6047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6048 END_PROFILE(SMBsplwr);
6052 data = (const char *)req->buf + 3;
6054 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6055 reply_nterror(req, map_nt_error_from_unix(errno));
6056 END_PROFILE(SMBsplwr);
6060 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6062 END_PROFILE(SMBsplwr);
6066 /****************************************************************************
6068 ****************************************************************************/
6070 void reply_mkdir(struct smb_request *req)
6072 connection_struct *conn = req->conn;
6073 struct smb_filename *smb_dname = NULL;
6074 char *directory = NULL;
6076 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
6077 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6078 TALLOC_CTX *ctx = talloc_tos();
6080 START_PROFILE(SMBmkdir);
6082 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6083 STR_TERMINATE, &status);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 reply_nterror(req, status);
6089 status = filename_convert(ctx, conn,
6090 req->flags2 & FLAGS2_DFS_PATHNAMES,
6095 if (!NT_STATUS_IS_OK(status)) {
6096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6097 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6098 ERRSRV, ERRbadpath);
6101 reply_nterror(req, status);
6105 status = create_directory(conn, req, smb_dname);
6107 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6109 if (!NT_STATUS_IS_OK(status)) {
6111 if (!use_nt_status()
6112 && NT_STATUS_EQUAL(status,
6113 NT_STATUS_OBJECT_NAME_COLLISION)) {
6115 * Yes, in the DOS error code case we get a
6116 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6117 * samba4 torture test.
6119 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6122 reply_nterror(req, status);
6126 reply_outbuf(req, 0, 0);
6128 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6130 TALLOC_FREE(smb_dname);
6131 END_PROFILE(SMBmkdir);
6135 /****************************************************************************
6137 ****************************************************************************/
6139 void reply_rmdir(struct smb_request *req)
6141 connection_struct *conn = req->conn;
6142 struct smb_filename *smb_dname = NULL;
6143 char *directory = NULL;
6145 TALLOC_CTX *ctx = talloc_tos();
6146 files_struct *fsp = NULL;
6148 uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
6149 struct smbd_server_connection *sconn = req->sconn;
6151 START_PROFILE(SMBrmdir);
6153 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6154 STR_TERMINATE, &status);
6155 if (!NT_STATUS_IS_OK(status)) {
6156 reply_nterror(req, status);
6160 status = filename_convert(ctx, conn,
6161 req->flags2 & FLAGS2_DFS_PATHNAMES,
6166 if (!NT_STATUS_IS_OK(status)) {
6167 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6168 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6169 ERRSRV, ERRbadpath);
6172 reply_nterror(req, status);
6176 if (is_ntfs_stream_smb_fname(smb_dname)) {
6177 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6181 status = SMB_VFS_CREATE_FILE(
6184 0, /* root_dir_fid */
6185 smb_dname, /* fname */
6186 DELETE_ACCESS, /* access_mask */
6187 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6189 FILE_OPEN, /* create_disposition*/
6190 FILE_DIRECTORY_FILE, /* create_options */
6191 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6192 0, /* oplock_request */
6194 0, /* allocation_size */
6195 0, /* private_flags */
6200 NULL, NULL); /* create context */
6202 if (!NT_STATUS_IS_OK(status)) {
6203 if (open_was_deferred(req->xconn, req->mid)) {
6204 /* We have re-scheduled this call. */
6207 reply_nterror(req, status);
6211 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 close_file(req, fsp, ERROR_CLOSE);
6214 reply_nterror(req, status);
6218 if (!set_delete_on_close(fsp, true,
6219 conn->session_info->security_token,
6220 conn->session_info->unix_token)) {
6221 close_file(req, fsp, ERROR_CLOSE);
6222 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6226 status = close_file(req, fsp, NORMAL_CLOSE);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 reply_nterror(req, status);
6230 reply_outbuf(req, 0, 0);
6233 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6235 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6237 TALLOC_FREE(smb_dname);
6238 END_PROFILE(SMBrmdir);
6242 /*******************************************************************
6243 Resolve wildcards in a filename rename.
6244 ********************************************************************/
6246 static bool resolve_wildcards(TALLOC_CTX *ctx,
6251 char *name2_copy = NULL;
6256 char *p,*p2, *pname1, *pname2;
6258 name2_copy = talloc_strdup(ctx, name2);
6263 pname1 = strrchr_m(name1,'/');
6264 pname2 = strrchr_m(name2_copy,'/');
6266 if (!pname1 || !pname2) {
6270 /* Truncate the copy of name2 at the last '/' */
6273 /* Now go past the '/' */
6277 root1 = talloc_strdup(ctx, pname1);
6278 root2 = talloc_strdup(ctx, pname2);
6280 if (!root1 || !root2) {
6284 p = strrchr_m(root1,'.');
6287 ext1 = talloc_strdup(ctx, p+1);
6289 ext1 = talloc_strdup(ctx, "");
6291 p = strrchr_m(root2,'.');
6294 ext2 = talloc_strdup(ctx, p+1);
6296 ext2 = talloc_strdup(ctx, "");
6299 if (!ext1 || !ext2) {
6307 /* Hmmm. Should this be mb-aware ? */
6310 } else if (*p2 == '*') {
6312 root2 = talloc_asprintf(ctx, "%s%s",
6331 /* Hmmm. Should this be mb-aware ? */
6334 } else if (*p2 == '*') {
6336 ext2 = talloc_asprintf(ctx, "%s%s",
6352 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6357 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6369 /****************************************************************************
6370 Ensure open files have their names updated. Updated to notify other smbd's
6372 ****************************************************************************/
6374 static void rename_open_files(connection_struct *conn,
6375 struct share_mode_lock *lck,
6377 uint32_t orig_name_hash,
6378 const struct smb_filename *smb_fname_dst)
6381 bool did_rename = False;
6383 uint32_t new_name_hash = 0;
6385 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6386 fsp = file_find_di_next(fsp)) {
6387 /* fsp_name is a relative path under the fsp. To change this for other
6388 sharepaths we need to manipulate relative paths. */
6389 /* TODO - create the absolute path and manipulate the newname
6390 relative to the sharepath. */
6391 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6394 if (fsp->name_hash != orig_name_hash) {
6397 DEBUG(10, ("rename_open_files: renaming file %s "
6398 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6399 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6400 smb_fname_str_dbg(smb_fname_dst)));
6402 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6403 if (NT_STATUS_IS_OK(status)) {
6405 new_name_hash = fsp->name_hash;
6410 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6411 "for %s\n", file_id_string_tos(&id),
6412 smb_fname_str_dbg(smb_fname_dst)));
6415 /* Send messages to all smbd's (not ourself) that the name has changed. */
6416 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6417 orig_name_hash, new_name_hash,
6422 /****************************************************************************
6423 We need to check if the source path is a parent directory of the destination
6424 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6425 refuse the rename with a sharing violation. Under UNIX the above call can
6426 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6427 probably need to check that the client is a Windows one before disallowing
6428 this as a UNIX client (one with UNIX extensions) can know the source is a
6429 symlink and make this decision intelligently. Found by an excellent bug
6430 report from <AndyLiebman@aol.com>.
6431 ****************************************************************************/
6433 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6434 const struct smb_filename *smb_fname_dst)
6436 const char *psrc = smb_fname_src->base_name;
6437 const char *pdst = smb_fname_dst->base_name;
6440 if (psrc[0] == '.' && psrc[1] == '/') {
6443 if (pdst[0] == '.' && pdst[1] == '/') {
6446 if ((slen = strlen(psrc)) > strlen(pdst)) {
6449 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6453 * Do the notify calls from a rename
6456 static void notify_rename(connection_struct *conn, bool is_dir,
6457 const struct smb_filename *smb_fname_src,
6458 const struct smb_filename *smb_fname_dst)
6460 char *parent_dir_src = NULL;
6461 char *parent_dir_dst = NULL;
6464 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6465 : FILE_NOTIFY_CHANGE_FILE_NAME;
6467 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6468 &parent_dir_src, NULL) ||
6469 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6470 &parent_dir_dst, NULL)) {
6474 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6475 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6476 smb_fname_src->base_name);
6477 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6478 smb_fname_dst->base_name);
6481 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6482 smb_fname_src->base_name);
6483 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6484 smb_fname_dst->base_name);
6487 /* this is a strange one. w2k3 gives an additional event for
6488 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6489 files, but not directories */
6491 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6492 FILE_NOTIFY_CHANGE_ATTRIBUTES
6493 |FILE_NOTIFY_CHANGE_CREATION,
6494 smb_fname_dst->base_name);
6497 TALLOC_FREE(parent_dir_src);
6498 TALLOC_FREE(parent_dir_dst);
6501 /****************************************************************************
6502 Returns an error if the parent directory for a filename is open in an
6504 ****************************************************************************/
6506 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6507 const struct smb_filename *smb_fname_dst_in)
6509 char *parent_dir = NULL;
6510 struct smb_filename smb_fname_parent;
6512 files_struct *fsp = NULL;
6515 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6516 &parent_dir, NULL)) {
6517 return NT_STATUS_NO_MEMORY;
6519 ZERO_STRUCT(smb_fname_parent);
6520 smb_fname_parent.base_name = parent_dir;
6522 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6524 return map_nt_error_from_unix(errno);
6528 * We're only checking on this smbd here, mostly good
6529 * enough.. and will pass tests.
6532 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6533 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6534 fsp = file_find_di_next(fsp)) {
6535 if (fsp->access_mask & DELETE_ACCESS) {
6536 return NT_STATUS_SHARING_VIOLATION;
6539 return NT_STATUS_OK;
6542 /****************************************************************************
6543 Rename an open file - given an fsp.
6544 ****************************************************************************/
6546 NTSTATUS rename_internals_fsp(connection_struct *conn,
6548 const struct smb_filename *smb_fname_dst_in,
6550 bool replace_if_exists)
6552 TALLOC_CTX *ctx = talloc_tos();
6553 struct smb_filename *smb_fname_dst = NULL;
6554 NTSTATUS status = NT_STATUS_OK;
6555 struct share_mode_lock *lck = NULL;
6556 bool dst_exists, old_is_stream, new_is_stream;
6558 status = check_name(conn, smb_fname_dst_in->base_name);
6559 if (!NT_STATUS_IS_OK(status)) {
6563 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6564 if (!NT_STATUS_IS_OK(status)) {
6568 /* Make a copy of the dst smb_fname structs */
6570 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6571 if (smb_fname_dst == NULL) {
6572 status = NT_STATUS_NO_MEMORY;
6577 * Check for special case with case preserving and not
6578 * case sensitive. If the new last component differs from the original
6579 * last component only by case, then we should allow
6580 * the rename (user is trying to change the case of the
6583 if (!conn->case_sensitive && conn->case_preserve &&
6584 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6585 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6587 char *fname_dst_lcomp_base_mod = NULL;
6588 struct smb_filename *smb_fname_orig_lcomp = NULL;
6591 * Get the last component of the destination name.
6593 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6595 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6597 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6599 if (!fname_dst_lcomp_base_mod) {
6600 status = NT_STATUS_NO_MEMORY;
6605 * Create an smb_filename struct using the original last
6606 * component of the destination.
6608 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6609 ctx, smb_fname_dst->original_lcomp, NULL);
6610 if (smb_fname_orig_lcomp == NULL) {
6611 status = NT_STATUS_NO_MEMORY;
6612 TALLOC_FREE(fname_dst_lcomp_base_mod);
6616 /* If the base names only differ by case, use original. */
6617 if(!strcsequal(fname_dst_lcomp_base_mod,
6618 smb_fname_orig_lcomp->base_name)) {
6621 * Replace the modified last component with the
6625 *last_slash = '\0'; /* Truncate at the '/' */
6626 tmp = talloc_asprintf(smb_fname_dst,
6628 smb_fname_dst->base_name,
6629 smb_fname_orig_lcomp->base_name);
6631 tmp = talloc_asprintf(smb_fname_dst,
6633 smb_fname_orig_lcomp->base_name);
6636 status = NT_STATUS_NO_MEMORY;
6637 TALLOC_FREE(fname_dst_lcomp_base_mod);
6638 TALLOC_FREE(smb_fname_orig_lcomp);
6641 TALLOC_FREE(smb_fname_dst->base_name);
6642 smb_fname_dst->base_name = tmp;
6645 /* If the stream_names only differ by case, use original. */
6646 if(!strcsequal(smb_fname_dst->stream_name,
6647 smb_fname_orig_lcomp->stream_name)) {
6649 /* Use the original stream. */
6650 tmp = talloc_strdup(smb_fname_dst,
6651 smb_fname_orig_lcomp->stream_name);
6653 status = NT_STATUS_NO_MEMORY;
6654 TALLOC_FREE(fname_dst_lcomp_base_mod);
6655 TALLOC_FREE(smb_fname_orig_lcomp);
6658 TALLOC_FREE(smb_fname_dst->stream_name);
6659 smb_fname_dst->stream_name = tmp;
6661 TALLOC_FREE(fname_dst_lcomp_base_mod);
6662 TALLOC_FREE(smb_fname_orig_lcomp);
6666 * If the src and dest names are identical - including case,
6667 * don't do the rename, just return success.
6670 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6671 strcsequal(fsp->fsp_name->stream_name,
6672 smb_fname_dst->stream_name)) {
6673 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6674 "- returning success\n",
6675 smb_fname_str_dbg(smb_fname_dst)));
6676 status = NT_STATUS_OK;
6680 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6681 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6683 /* Return the correct error code if both names aren't streams. */
6684 if (!old_is_stream && new_is_stream) {
6685 status = NT_STATUS_OBJECT_NAME_INVALID;
6689 if (old_is_stream && !new_is_stream) {
6690 status = NT_STATUS_INVALID_PARAMETER;
6694 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6696 if(!replace_if_exists && dst_exists) {
6697 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6698 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6699 smb_fname_str_dbg(smb_fname_dst)));
6700 status = NT_STATUS_OBJECT_NAME_COLLISION;
6705 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6706 &smb_fname_dst->st);
6707 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6709 /* The file can be open when renaming a stream */
6710 if (dst_fsp && !new_is_stream) {
6711 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6712 status = NT_STATUS_ACCESS_DENIED;
6717 /* Ensure we have a valid stat struct for the source. */
6718 status = vfs_stat_fsp(fsp);
6719 if (!NT_STATUS_IS_OK(status)) {
6723 status = can_rename(conn, fsp, attrs);
6725 if (!NT_STATUS_IS_OK(status)) {
6726 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6727 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6728 smb_fname_str_dbg(smb_fname_dst)));
6729 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6730 status = NT_STATUS_ACCESS_DENIED;
6734 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6735 status = NT_STATUS_ACCESS_DENIED;
6738 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6741 * We have the file open ourselves, so not being able to get the
6742 * corresponding share mode lock is a fatal error.
6745 SMB_ASSERT(lck != NULL);
6747 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6748 uint32_t create_options = fsp->fh->private_options;
6750 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6751 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6752 smb_fname_str_dbg(smb_fname_dst)));
6754 if (!fsp->is_directory &&
6755 !lp_posix_pathnames() &&
6756 (lp_map_archive(SNUM(conn)) ||
6757 lp_store_dos_attributes(SNUM(conn)))) {
6758 /* We must set the archive bit on the newly
6760 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6761 uint32_t old_dosmode = dos_mode(conn,
6763 file_set_dosmode(conn,
6765 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6771 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6774 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6778 * A rename acts as a new file create w.r.t. allowing an initial delete
6779 * on close, probably because in Windows there is a new handle to the
6780 * new file. If initial delete on close was requested but not
6781 * originally set, we need to set it here. This is probably not 100% correct,
6782 * but will work for the CIFSFS client which in non-posix mode
6783 * depends on these semantics. JRA.
6786 if (create_options & FILE_DELETE_ON_CLOSE) {
6787 status = can_set_delete_on_close(fsp, 0);
6789 if (NT_STATUS_IS_OK(status)) {
6790 /* Note that here we set the *inital* delete on close flag,
6791 * not the regular one. The magic gets handled in close. */
6792 fsp->initial_delete_on_close = True;
6796 status = NT_STATUS_OK;
6802 if (errno == ENOTDIR || errno == EISDIR) {
6803 status = NT_STATUS_OBJECT_NAME_COLLISION;
6805 status = map_nt_error_from_unix(errno);
6808 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6809 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6810 smb_fname_str_dbg(smb_fname_dst)));
6813 TALLOC_FREE(smb_fname_dst);
6818 /****************************************************************************
6819 The guts of the rename command, split out so it may be called by the NT SMB
6821 ****************************************************************************/
6823 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6824 connection_struct *conn,
6825 struct smb_request *req,
6826 struct smb_filename *smb_fname_src,
6827 struct smb_filename *smb_fname_dst,
6829 bool replace_if_exists,
6832 uint32_t access_mask)
6834 char *fname_src_dir = NULL;
6835 char *fname_src_mask = NULL;
6837 NTSTATUS status = NT_STATUS_OK;
6838 struct smb_Dir *dir_hnd = NULL;
6839 const char *dname = NULL;
6840 char *talloced = NULL;
6842 int create_options = 0;
6843 bool posix_pathnames = lp_posix_pathnames();
6847 * Split the old name into directory and last component
6848 * strings. Note that unix_convert may have stripped off a
6849 * leading ./ from both name and newname if the rename is
6850 * at the root of the share. We need to make sure either both
6851 * name and newname contain a / character or neither of them do
6852 * as this is checked in resolve_wildcards().
6855 /* Split up the directory from the filename/mask. */
6856 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6857 &fname_src_dir, &fname_src_mask);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 status = NT_STATUS_NO_MEMORY;
6864 * We should only check the mangled cache
6865 * here if unix_convert failed. This means
6866 * that the path in 'mask' doesn't exist
6867 * on the file system and so we need to look
6868 * for a possible mangle. This patch from
6869 * Tine Smukavec <valentin.smukavec@hermes.si>.
6872 if (!VALID_STAT(smb_fname_src->st) &&
6873 mangle_is_mangled(fname_src_mask, conn->params)) {
6874 char *new_mask = NULL;
6875 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6878 TALLOC_FREE(fname_src_mask);
6879 fname_src_mask = new_mask;
6883 if (!src_has_wild) {
6887 * Only one file needs to be renamed. Append the mask back
6888 * onto the directory.
6890 TALLOC_FREE(smb_fname_src->base_name);
6891 if (ISDOT(fname_src_dir)) {
6892 /* Ensure we use canonical names on open. */
6893 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6897 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6902 if (!smb_fname_src->base_name) {
6903 status = NT_STATUS_NO_MEMORY;
6907 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6908 "case_preserve = %d, short case preserve = %d, "
6909 "directory = %s, newname = %s, "
6910 "last_component_dest = %s\n",
6911 conn->case_sensitive, conn->case_preserve,
6912 conn->short_case_preserve,
6913 smb_fname_str_dbg(smb_fname_src),
6914 smb_fname_str_dbg(smb_fname_dst),
6915 smb_fname_dst->original_lcomp));
6917 /* The dest name still may have wildcards. */
6918 if (dest_has_wild) {
6919 char *fname_dst_mod = NULL;
6920 if (!resolve_wildcards(smb_fname_dst,
6921 smb_fname_src->base_name,
6922 smb_fname_dst->base_name,
6924 DEBUG(6, ("rename_internals: resolve_wildcards "
6926 smb_fname_src->base_name,
6927 smb_fname_dst->base_name));
6928 status = NT_STATUS_NO_MEMORY;
6931 TALLOC_FREE(smb_fname_dst->base_name);
6932 smb_fname_dst->base_name = fname_dst_mod;
6935 ZERO_STRUCT(smb_fname_src->st);
6936 if (posix_pathnames) {
6937 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6939 rc = SMB_VFS_STAT(conn, smb_fname_src);
6942 status = map_nt_error_from_unix_common(errno);
6946 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6947 create_options |= FILE_DIRECTORY_FILE;
6950 status = SMB_VFS_CREATE_FILE(
6953 0, /* root_dir_fid */
6954 smb_fname_src, /* fname */
6955 access_mask, /* access_mask */
6956 (FILE_SHARE_READ | /* share_access */
6958 FILE_OPEN, /* create_disposition*/
6959 create_options, /* create_options */
6960 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6961 0, /* oplock_request */
6963 0, /* allocation_size */
6964 0, /* private_flags */
6969 NULL, NULL); /* create context */
6971 if (!NT_STATUS_IS_OK(status)) {
6972 DEBUG(3, ("Could not open rename source %s: %s\n",
6973 smb_fname_str_dbg(smb_fname_src),
6974 nt_errstr(status)));
6978 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6979 attrs, replace_if_exists);
6981 close_file(req, fsp, NORMAL_CLOSE);
6983 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6984 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6985 smb_fname_str_dbg(smb_fname_dst)));
6991 * Wildcards - process each file that matches.
6993 if (strequal(fname_src_mask, "????????.???")) {
6994 TALLOC_FREE(fname_src_mask);
6995 fname_src_mask = talloc_strdup(ctx, "*");
6996 if (!fname_src_mask) {
6997 status = NT_STATUS_NO_MEMORY;
7002 status = check_name(conn, fname_src_dir);
7003 if (!NT_STATUS_IS_OK(status)) {
7007 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
7009 if (dir_hnd == NULL) {
7010 status = map_nt_error_from_unix(errno);
7014 status = NT_STATUS_NO_SUCH_FILE;
7016 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7017 * - gentest fix. JRA
7020 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7022 files_struct *fsp = NULL;
7023 char *destname = NULL;
7024 bool sysdir_entry = False;
7026 /* Quick check for "." and ".." */
7027 if (ISDOT(dname) || ISDOTDOT(dname)) {
7028 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7029 sysdir_entry = True;
7031 TALLOC_FREE(talloced);
7036 if (!is_visible_file(conn, fname_src_dir, dname,
7037 &smb_fname_src->st, false)) {
7038 TALLOC_FREE(talloced);
7042 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7043 TALLOC_FREE(talloced);
7048 status = NT_STATUS_OBJECT_NAME_INVALID;
7052 TALLOC_FREE(smb_fname_src->base_name);
7053 if (ISDOT(fname_src_dir)) {
7054 /* Ensure we use canonical names on open. */
7055 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7059 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7064 if (!smb_fname_src->base_name) {
7065 status = NT_STATUS_NO_MEMORY;
7069 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7070 smb_fname_dst->base_name,
7072 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7073 smb_fname_src->base_name, destname));
7074 TALLOC_FREE(talloced);
7078 status = NT_STATUS_NO_MEMORY;
7082 TALLOC_FREE(smb_fname_dst->base_name);
7083 smb_fname_dst->base_name = destname;
7085 ZERO_STRUCT(smb_fname_src->st);
7086 if (posix_pathnames) {
7087 SMB_VFS_LSTAT(conn, smb_fname_src);
7089 SMB_VFS_STAT(conn, smb_fname_src);
7094 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7095 create_options |= FILE_DIRECTORY_FILE;
7098 status = SMB_VFS_CREATE_FILE(
7101 0, /* root_dir_fid */
7102 smb_fname_src, /* fname */
7103 access_mask, /* access_mask */
7104 (FILE_SHARE_READ | /* share_access */
7106 FILE_OPEN, /* create_disposition*/
7107 create_options, /* create_options */
7108 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7109 0, /* oplock_request */
7111 0, /* allocation_size */
7112 0, /* private_flags */
7117 NULL, NULL); /* create context */
7119 if (!NT_STATUS_IS_OK(status)) {
7120 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7121 "returned %s rename %s -> %s\n",
7123 smb_fname_str_dbg(smb_fname_src),
7124 smb_fname_str_dbg(smb_fname_dst)));
7128 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7130 if (!smb_fname_dst->original_lcomp) {
7131 status = NT_STATUS_NO_MEMORY;
7135 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7136 attrs, replace_if_exists);
7138 close_file(req, fsp, NORMAL_CLOSE);
7140 if (!NT_STATUS_IS_OK(status)) {
7141 DEBUG(3, ("rename_internals_fsp returned %s for "
7142 "rename %s -> %s\n", nt_errstr(status),
7143 smb_fname_str_dbg(smb_fname_src),
7144 smb_fname_str_dbg(smb_fname_dst)));
7150 DEBUG(3,("rename_internals: doing rename on %s -> "
7151 "%s\n", smb_fname_str_dbg(smb_fname_src),
7152 smb_fname_str_dbg(smb_fname_src)));
7153 TALLOC_FREE(talloced);
7155 TALLOC_FREE(dir_hnd);
7157 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7158 status = map_nt_error_from_unix(errno);
7162 TALLOC_FREE(talloced);
7163 TALLOC_FREE(fname_src_dir);
7164 TALLOC_FREE(fname_src_mask);
7168 /****************************************************************************
7170 ****************************************************************************/
7172 void reply_mv(struct smb_request *req)
7174 connection_struct *conn = req->conn;
7176 char *newname = NULL;
7180 bool src_has_wcard = False;
7181 bool dest_has_wcard = False;
7182 TALLOC_CTX *ctx = talloc_tos();
7183 struct smb_filename *smb_fname_src = NULL;
7184 struct smb_filename *smb_fname_dst = NULL;
7185 uint32_t src_ucf_flags = (lp_posix_pathnames() ?
7186 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7187 UCF_COND_ALLOW_WCARD_LCOMP);
7188 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7189 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES :
7190 UCF_COND_ALLOW_WCARD_LCOMP);
7191 bool stream_rename = false;
7193 START_PROFILE(SMBmv);
7196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7200 attrs = SVAL(req->vwv+0, 0);
7202 p = (const char *)req->buf + 1;
7203 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7204 &status, &src_has_wcard);
7205 if (!NT_STATUS_IS_OK(status)) {
7206 reply_nterror(req, status);
7210 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7211 &status, &dest_has_wcard);
7212 if (!NT_STATUS_IS_OK(status)) {
7213 reply_nterror(req, status);
7217 if (!lp_posix_pathnames()) {
7218 /* The newname must begin with a ':' if the
7219 name contains a ':'. */
7220 if (strchr_m(name, ':')) {
7221 if (newname[0] != ':') {
7222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7225 stream_rename = true;
7229 status = filename_convert(ctx,
7231 req->flags2 & FLAGS2_DFS_PATHNAMES,
7237 if (!NT_STATUS_IS_OK(status)) {
7238 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7239 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7240 ERRSRV, ERRbadpath);
7243 reply_nterror(req, status);
7247 status = filename_convert(ctx,
7249 req->flags2 & FLAGS2_DFS_PATHNAMES,
7255 if (!NT_STATUS_IS_OK(status)) {
7256 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7257 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7258 ERRSRV, ERRbadpath);
7261 reply_nterror(req, status);
7265 if (stream_rename) {
7266 /* smb_fname_dst->base_name must be the same as
7267 smb_fname_src->base_name. */
7268 TALLOC_FREE(smb_fname_dst->base_name);
7269 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7270 smb_fname_src->base_name);
7271 if (!smb_fname_dst->base_name) {
7272 reply_nterror(req, NT_STATUS_NO_MEMORY);
7277 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7278 smb_fname_str_dbg(smb_fname_dst)));
7280 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7281 attrs, False, src_has_wcard, dest_has_wcard,
7283 if (!NT_STATUS_IS_OK(status)) {
7284 if (open_was_deferred(req->xconn, req->mid)) {
7285 /* We have re-scheduled this call. */
7288 reply_nterror(req, status);
7292 reply_outbuf(req, 0, 0);
7294 TALLOC_FREE(smb_fname_src);
7295 TALLOC_FREE(smb_fname_dst);
7300 /*******************************************************************
7301 Copy a file as part of a reply_copy.
7302 ******************************************************************/
7305 * TODO: check error codes on all callers
7308 NTSTATUS copy_file(TALLOC_CTX *ctx,
7309 connection_struct *conn,
7310 struct smb_filename *smb_fname_src,
7311 struct smb_filename *smb_fname_dst,
7314 bool target_is_directory)
7316 struct smb_filename *smb_fname_dst_tmp = NULL;
7318 files_struct *fsp1,*fsp2;
7320 uint32_t new_create_disposition;
7324 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7325 if (smb_fname_dst_tmp == NULL) {
7326 return NT_STATUS_NO_MEMORY;
7330 * If the target is a directory, extract the last component from the
7331 * src filename and append it to the dst filename
7333 if (target_is_directory) {
7336 /* dest/target can't be a stream if it's a directory. */
7337 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7339 p = strrchr_m(smb_fname_src->base_name,'/');
7343 p = smb_fname_src->base_name;
7345 smb_fname_dst_tmp->base_name =
7346 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7348 if (!smb_fname_dst_tmp->base_name) {
7349 status = NT_STATUS_NO_MEMORY;
7354 status = vfs_file_exist(conn, smb_fname_src);
7355 if (!NT_STATUS_IS_OK(status)) {
7359 if (!target_is_directory && count) {
7360 new_create_disposition = FILE_OPEN;
7362 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7365 &new_create_disposition,
7368 status = NT_STATUS_INVALID_PARAMETER;
7373 /* Open the src file for reading. */
7374 status = SMB_VFS_CREATE_FILE(
7377 0, /* root_dir_fid */
7378 smb_fname_src, /* fname */
7379 FILE_GENERIC_READ, /* access_mask */
7380 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7381 FILE_OPEN, /* create_disposition*/
7382 0, /* create_options */
7383 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7384 INTERNAL_OPEN_ONLY, /* oplock_request */
7386 0, /* allocation_size */
7387 0, /* private_flags */
7392 NULL, NULL); /* create context */
7394 if (!NT_STATUS_IS_OK(status)) {
7398 dosattrs = dos_mode(conn, smb_fname_src);
7400 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7401 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7404 /* Open the dst file for writing. */
7405 status = SMB_VFS_CREATE_FILE(
7408 0, /* root_dir_fid */
7409 smb_fname_dst, /* fname */
7410 FILE_GENERIC_WRITE, /* access_mask */
7411 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7412 new_create_disposition, /* create_disposition*/
7413 0, /* create_options */
7414 dosattrs, /* file_attributes */
7415 INTERNAL_OPEN_ONLY, /* oplock_request */
7417 0, /* allocation_size */
7418 0, /* private_flags */
7423 NULL, NULL); /* create context */
7425 if (!NT_STATUS_IS_OK(status)) {
7426 close_file(NULL, fsp1, ERROR_CLOSE);
7430 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7431 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7433 DEBUG(0, ("error - vfs lseek returned error %s\n",
7435 status = map_nt_error_from_unix(errno);
7436 close_file(NULL, fsp1, ERROR_CLOSE);
7437 close_file(NULL, fsp2, ERROR_CLOSE);
7442 /* Do the actual copy. */
7443 if (smb_fname_src->st.st_ex_size) {
7444 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7449 close_file(NULL, fsp1, NORMAL_CLOSE);
7451 /* Ensure the modtime is set correctly on the destination file. */
7452 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7455 * As we are opening fsp1 read-only we only expect
7456 * an error on close on fsp2 if we are out of space.
7457 * Thus we don't look at the error return from the
7460 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7462 if (!NT_STATUS_IS_OK(status)) {
7466 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7467 status = NT_STATUS_DISK_FULL;
7471 status = NT_STATUS_OK;
7474 TALLOC_FREE(smb_fname_dst_tmp);
7478 /****************************************************************************
7479 Reply to a file copy.
7480 ****************************************************************************/
7482 void reply_copy(struct smb_request *req)
7484 connection_struct *conn = req->conn;
7485 struct smb_filename *smb_fname_src = NULL;
7486 struct smb_filename *smb_fname_dst = NULL;
7487 char *fname_src = NULL;
7488 char *fname_dst = NULL;
7489 char *fname_src_mask = NULL;
7490 char *fname_src_dir = NULL;
7493 int error = ERRnoaccess;
7497 bool target_is_directory=False;
7498 bool source_has_wild = False;
7499 bool dest_has_wild = False;
7501 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7502 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
7503 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7504 (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
7505 TALLOC_CTX *ctx = talloc_tos();
7507 START_PROFILE(SMBcopy);
7510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7514 tid2 = SVAL(req->vwv+0, 0);
7515 ofun = SVAL(req->vwv+1, 0);
7516 flags = SVAL(req->vwv+2, 0);
7518 p = (const char *)req->buf;
7519 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7520 &status, &source_has_wild);
7521 if (!NT_STATUS_IS_OK(status)) {
7522 reply_nterror(req, status);
7525 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7526 &status, &dest_has_wild);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 reply_nterror(req, status);
7532 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7534 if (tid2 != conn->cnum) {
7535 /* can't currently handle inter share copies XXXX */
7536 DEBUG(3,("Rejecting inter-share copy\n"));
7537 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7541 status = filename_convert(ctx, conn,
7542 req->flags2 & FLAGS2_DFS_PATHNAMES,
7547 if (!NT_STATUS_IS_OK(status)) {
7548 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7549 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7550 ERRSRV, ERRbadpath);
7553 reply_nterror(req, status);
7557 status = filename_convert(ctx, conn,
7558 req->flags2 & FLAGS2_DFS_PATHNAMES,
7563 if (!NT_STATUS_IS_OK(status)) {
7564 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7565 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7566 ERRSRV, ERRbadpath);
7569 reply_nterror(req, status);
7573 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7575 if ((flags&1) && target_is_directory) {
7576 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7580 if ((flags&2) && !target_is_directory) {
7581 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7585 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7586 /* wants a tree copy! XXXX */
7587 DEBUG(3,("Rejecting tree copy\n"));
7588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7592 /* Split up the directory from the filename/mask. */
7593 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7594 &fname_src_dir, &fname_src_mask);
7595 if (!NT_STATUS_IS_OK(status)) {
7596 reply_nterror(req, NT_STATUS_NO_MEMORY);
7601 * We should only check the mangled cache
7602 * here if unix_convert failed. This means
7603 * that the path in 'mask' doesn't exist
7604 * on the file system and so we need to look
7605 * for a possible mangle. This patch from
7606 * Tine Smukavec <valentin.smukavec@hermes.si>.
7608 if (!VALID_STAT(smb_fname_src->st) &&
7609 mangle_is_mangled(fname_src_mask, conn->params)) {
7610 char *new_mask = NULL;
7611 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7612 &new_mask, conn->params);
7614 /* Use demangled name if one was successfully found. */
7616 TALLOC_FREE(fname_src_mask);
7617 fname_src_mask = new_mask;
7621 if (!source_has_wild) {
7624 * Only one file needs to be copied. Append the mask back onto
7627 TALLOC_FREE(smb_fname_src->base_name);
7628 if (ISDOT(fname_src_dir)) {
7629 /* Ensure we use canonical names on open. */
7630 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7634 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7639 if (!smb_fname_src->base_name) {
7640 reply_nterror(req, NT_STATUS_NO_MEMORY);
7644 if (dest_has_wild) {
7645 char *fname_dst_mod = NULL;
7646 if (!resolve_wildcards(smb_fname_dst,
7647 smb_fname_src->base_name,
7648 smb_fname_dst->base_name,
7650 reply_nterror(req, NT_STATUS_NO_MEMORY);
7653 TALLOC_FREE(smb_fname_dst->base_name);
7654 smb_fname_dst->base_name = fname_dst_mod;
7657 status = check_name(conn, smb_fname_src->base_name);
7658 if (!NT_STATUS_IS_OK(status)) {
7659 reply_nterror(req, status);
7663 status = check_name(conn, smb_fname_dst->base_name);
7664 if (!NT_STATUS_IS_OK(status)) {
7665 reply_nterror(req, status);
7669 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7670 ofun, count, target_is_directory);
7672 if(!NT_STATUS_IS_OK(status)) {
7673 reply_nterror(req, status);
7679 struct smb_Dir *dir_hnd = NULL;
7680 const char *dname = NULL;
7681 char *talloced = NULL;
7685 * There is a wildcard that requires us to actually read the
7686 * src dir and copy each file matching the mask to the dst.
7687 * Right now streams won't be copied, but this could
7688 * presumably be added with a nested loop for reach dir entry.
7690 SMB_ASSERT(!smb_fname_src->stream_name);
7691 SMB_ASSERT(!smb_fname_dst->stream_name);
7693 smb_fname_src->stream_name = NULL;
7694 smb_fname_dst->stream_name = NULL;
7696 if (strequal(fname_src_mask,"????????.???")) {
7697 TALLOC_FREE(fname_src_mask);
7698 fname_src_mask = talloc_strdup(ctx, "*");
7699 if (!fname_src_mask) {
7700 reply_nterror(req, NT_STATUS_NO_MEMORY);
7705 status = check_name(conn, fname_src_dir);
7706 if (!NT_STATUS_IS_OK(status)) {
7707 reply_nterror(req, status);
7711 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7712 if (dir_hnd == NULL) {
7713 status = map_nt_error_from_unix(errno);
7714 reply_nterror(req, status);
7720 /* Iterate over the src dir copying each entry to the dst. */
7721 while ((dname = ReadDirName(dir_hnd, &offset,
7722 &smb_fname_src->st, &talloced))) {
7723 char *destname = NULL;
7725 if (ISDOT(dname) || ISDOTDOT(dname)) {
7726 TALLOC_FREE(talloced);
7730 if (!is_visible_file(conn, fname_src_dir, dname,
7731 &smb_fname_src->st, false)) {
7732 TALLOC_FREE(talloced);
7736 if(!mask_match(dname, fname_src_mask,
7737 conn->case_sensitive)) {
7738 TALLOC_FREE(talloced);
7742 error = ERRnoaccess;
7744 /* Get the src smb_fname struct setup. */
7745 TALLOC_FREE(smb_fname_src->base_name);
7746 if (ISDOT(fname_src_dir)) {
7747 /* Ensure we use canonical names on open. */
7748 smb_fname_src->base_name =
7749 talloc_asprintf(smb_fname_src, "%s",
7752 smb_fname_src->base_name =
7753 talloc_asprintf(smb_fname_src, "%s/%s",
7754 fname_src_dir, dname);
7757 if (!smb_fname_src->base_name) {
7758 TALLOC_FREE(dir_hnd);
7759 TALLOC_FREE(talloced);
7760 reply_nterror(req, NT_STATUS_NO_MEMORY);
7764 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7765 smb_fname_dst->base_name,
7767 TALLOC_FREE(talloced);
7771 TALLOC_FREE(dir_hnd);
7772 TALLOC_FREE(talloced);
7773 reply_nterror(req, NT_STATUS_NO_MEMORY);
7777 TALLOC_FREE(smb_fname_dst->base_name);
7778 smb_fname_dst->base_name = destname;
7780 status = check_name(conn, smb_fname_src->base_name);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 TALLOC_FREE(dir_hnd);
7783 TALLOC_FREE(talloced);
7784 reply_nterror(req, status);
7788 status = check_name(conn, smb_fname_dst->base_name);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 TALLOC_FREE(dir_hnd);
7791 TALLOC_FREE(talloced);
7792 reply_nterror(req, status);
7796 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7797 smb_fname_src->base_name,
7798 smb_fname_dst->base_name));
7800 status = copy_file(ctx, conn, smb_fname_src,
7801 smb_fname_dst, ofun, count,
7802 target_is_directory);
7803 if (NT_STATUS_IS_OK(status)) {
7807 TALLOC_FREE(talloced);
7809 TALLOC_FREE(dir_hnd);
7813 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7817 reply_outbuf(req, 1, 0);
7818 SSVAL(req->outbuf,smb_vwv0,count);
7820 TALLOC_FREE(smb_fname_src);
7821 TALLOC_FREE(smb_fname_dst);
7822 TALLOC_FREE(fname_src);
7823 TALLOC_FREE(fname_dst);
7824 TALLOC_FREE(fname_src_mask);
7825 TALLOC_FREE(fname_src_dir);
7827 END_PROFILE(SMBcopy);
7832 #define DBGC_CLASS DBGC_LOCKING
7834 /****************************************************************************
7835 Get a lock pid, dealing with large count requests.
7836 ****************************************************************************/
7838 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7839 bool large_file_format)
7841 if(!large_file_format)
7842 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7844 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7847 /****************************************************************************
7848 Get a lock count, dealing with large count requests.
7849 ****************************************************************************/
7851 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7852 bool large_file_format)
7856 if(!large_file_format) {
7857 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7860 * No BVAL, this is reversed!
7862 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7863 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7869 /****************************************************************************
7870 Get a lock offset, dealing with large offset requests.
7871 ****************************************************************************/
7873 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7874 bool large_file_format)
7876 uint64_t offset = 0;
7878 if(!large_file_format) {
7879 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7882 * No BVAL, this is reversed!
7884 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7885 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7891 NTSTATUS smbd_do_locking(struct smb_request *req,
7896 struct smbd_lock_element *locks,
7899 connection_struct *conn = req->conn;
7901 NTSTATUS status = NT_STATUS_OK;
7905 /* Setup the timeout in seconds. */
7907 if (!lp_blocking_locks(SNUM(conn))) {
7911 for(i = 0; i < (int)num_locks; i++) {
7912 struct smbd_lock_element *e = &locks[i];
7914 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7915 "%llu, file %s timeout = %d\n",
7918 (unsigned long long)e->smblctx,
7922 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7923 struct blocking_lock_record *blr = NULL;
7925 if (num_locks > 1) {
7927 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7928 * if the lock vector contains one entry. When given multiple cancel
7929 * requests in a single PDU we expect the server to return an
7930 * error. Windows servers seem to accept the request but only
7931 * cancel the first lock.
7932 * JRA - Do what Windows does (tm) :-).
7936 /* MS-CIFS (2.2.4.32.1) behavior. */
7937 return NT_STATUS_DOS(ERRDOS,
7938 ERRcancelviolation);
7940 /* Windows behavior. */
7942 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7943 "cancel request\n"));
7949 if (lp_blocking_locks(SNUM(conn))) {
7951 /* Schedule a message to ourselves to
7952 remove the blocking lock record and
7953 return the right error. */
7955 blr = blocking_lock_cancel_smb1(fsp,
7961 NT_STATUS_FILE_LOCK_CONFLICT);
7963 return NT_STATUS_DOS(
7965 ERRcancelviolation);
7968 /* Remove a matching pending lock. */
7969 status = do_lock_cancel(fsp,
7975 bool blocking_lock = timeout ? true : false;
7976 bool defer_lock = false;
7977 struct byte_range_lock *br_lck;
7978 uint64_t block_smblctx;
7980 br_lck = do_lock(req->sconn->msg_ctx,
7991 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7992 /* Windows internal resolution for blocking locks seems
7993 to be about 200ms... Don't wait for less than that. JRA. */
7994 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7995 timeout = lp_lock_spin_time();
8000 /* If a lock sent with timeout of zero would fail, and
8001 * this lock has been requested multiple times,
8002 * according to brl_lock_failed() we convert this
8003 * request to a blocking lock with a timeout of between
8004 * 150 - 300 milliseconds.
8006 * If lp_lock_spin_time() has been set to 0, we skip
8007 * this blocking retry and fail immediately.
8009 * Replacement for do_lock_spin(). JRA. */
8011 if (!req->sconn->using_smb2 &&
8012 br_lck && lp_blocking_locks(SNUM(conn)) &&
8013 lp_lock_spin_time() && !blocking_lock &&
8014 NT_STATUS_EQUAL((status),
8015 NT_STATUS_FILE_LOCK_CONFLICT))
8018 timeout = lp_lock_spin_time();
8021 if (br_lck && defer_lock) {
8023 * A blocking lock was requested. Package up
8024 * this smb into a queued request and push it
8025 * onto the blocking lock queue.
8027 if(push_blocking_lock_request(br_lck,
8038 TALLOC_FREE(br_lck);
8040 return NT_STATUS_OK;
8044 TALLOC_FREE(br_lck);
8047 if (!NT_STATUS_IS_OK(status)) {
8052 /* If any of the above locks failed, then we must unlock
8053 all of the previous locks (X/Open spec). */
8055 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8057 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8058 i = -1; /* we want to skip the for loop */
8062 * Ensure we don't do a remove on the lock that just failed,
8063 * as under POSIX rules, if we have a lock already there, we
8064 * will delete it (and we shouldn't) .....
8066 for(i--; i >= 0; i--) {
8067 struct smbd_lock_element *e = &locks[i];
8069 do_unlock(req->sconn->msg_ctx,
8079 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8080 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8082 return NT_STATUS_OK;
8085 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8087 uint16_t num_ulocks,
8088 struct smbd_lock_element *ulocks)
8092 for(i = 0; i < (int)num_ulocks; i++) {
8093 struct smbd_lock_element *e = &ulocks[i];
8096 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8097 "pid %u, file %s\n", __func__,
8100 (unsigned int)e->smblctx,
8103 if (e->brltype != UNLOCK_LOCK) {
8104 /* this can only happen with SMB2 */
8105 return NT_STATUS_INVALID_PARAMETER;
8108 status = do_unlock(req->sconn->msg_ctx,
8115 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8116 nt_errstr(status)));
8118 if (!NT_STATUS_IS_OK(status)) {
8123 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8126 return NT_STATUS_OK;
8129 /****************************************************************************
8130 Reply to a lockingX request.
8131 ****************************************************************************/
8133 void reply_lockingX(struct smb_request *req)
8135 connection_struct *conn = req->conn;
8137 unsigned char locktype;
8138 unsigned char oplocklevel;
8139 uint16_t num_ulocks;
8141 int32_t lock_timeout;
8143 const uint8_t *data;
8144 bool large_file_format;
8145 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8146 struct smbd_lock_element *ulocks;
8147 struct smbd_lock_element *locks;
8150 START_PROFILE(SMBlockingX);
8153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8154 END_PROFILE(SMBlockingX);
8158 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8159 locktype = CVAL(req->vwv+3, 0);
8160 oplocklevel = CVAL(req->vwv+3, 1);
8161 num_ulocks = SVAL(req->vwv+6, 0);
8162 num_locks = SVAL(req->vwv+7, 0);
8163 lock_timeout = IVAL(req->vwv+4, 0);
8164 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8166 if (!check_fsp(conn, req, fsp)) {
8167 END_PROFILE(SMBlockingX);
8173 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8174 /* we don't support these - and CANCEL_LOCK makes w2k
8175 and XP reboot so I don't really want to be
8176 compatible! (tridge) */
8177 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8178 END_PROFILE(SMBlockingX);
8182 /* Check if this is an oplock break on a file
8183 we have granted an oplock on.
8185 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8186 /* Client can insist on breaking to none. */
8187 bool break_to_none = (oplocklevel == 0);
8190 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8191 "for %s\n", (unsigned int)oplocklevel,
8192 fsp_fnum_dbg(fsp)));
8195 * Make sure we have granted an exclusive or batch oplock on
8199 if (fsp->oplock_type == 0) {
8201 /* The Samba4 nbench simulator doesn't understand
8202 the difference between break to level2 and break
8203 to none from level2 - it sends oplock break
8204 replies in both cases. Don't keep logging an error
8205 message here - just ignore it. JRA. */
8207 DEBUG(5,("reply_lockingX: Error : oplock break from "
8208 "client for %s (oplock=%d) and no "
8209 "oplock granted on this file (%s).\n",
8210 fsp_fnum_dbg(fsp), fsp->oplock_type,
8213 /* if this is a pure oplock break request then don't
8215 if (num_locks == 0 && num_ulocks == 0) {
8216 END_PROFILE(SMBlockingX);
8219 END_PROFILE(SMBlockingX);
8220 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8225 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8227 result = remove_oplock(fsp);
8229 result = downgrade_oplock(fsp);
8233 DEBUG(0, ("reply_lockingX: error in removing "
8234 "oplock on file %s\n", fsp_str_dbg(fsp)));
8235 /* Hmmm. Is this panic justified? */
8236 smb_panic("internal tdb error");
8239 /* if this is a pure oplock break request then don't send a
8241 if (num_locks == 0 && num_ulocks == 0) {
8242 /* Sanity check - ensure a pure oplock break is not a
8244 if (CVAL(req->vwv+0, 0) != 0xff) {
8245 DEBUG(0,("reply_lockingX: Error : pure oplock "
8246 "break is a chained %d request !\n",
8247 (unsigned int)CVAL(req->vwv+0, 0)));
8249 END_PROFILE(SMBlockingX);
8255 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 END_PROFILE(SMBlockingX);
8261 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8262 if (ulocks == NULL) {
8263 reply_nterror(req, NT_STATUS_NO_MEMORY);
8264 END_PROFILE(SMBlockingX);
8268 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8269 if (locks == NULL) {
8270 reply_nterror(req, NT_STATUS_NO_MEMORY);
8271 END_PROFILE(SMBlockingX);
8275 /* Data now points at the beginning of the list
8276 of smb_unlkrng structs */
8277 for(i = 0; i < (int)num_ulocks; i++) {
8278 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8279 ulocks[i].count = get_lock_count(data, i, large_file_format);
8280 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8281 ulocks[i].brltype = UNLOCK_LOCK;
8284 /* Now do any requested locks */
8285 data += ((large_file_format ? 20 : 10)*num_ulocks);
8287 /* Data now points at the beginning of the list
8288 of smb_lkrng structs */
8290 for(i = 0; i < (int)num_locks; i++) {
8291 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8292 locks[i].count = get_lock_count(data, i, large_file_format);
8293 locks[i].offset = get_lock_offset(data, i, large_file_format);
8295 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8296 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8297 locks[i].brltype = PENDING_READ_LOCK;
8299 locks[i].brltype = READ_LOCK;
8302 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8303 locks[i].brltype = PENDING_WRITE_LOCK;
8305 locks[i].brltype = WRITE_LOCK;
8310 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8311 if (!NT_STATUS_IS_OK(status)) {
8312 END_PROFILE(SMBlockingX);
8313 reply_nterror(req, status);
8317 status = smbd_do_locking(req, fsp,
8318 locktype, lock_timeout,
8321 if (!NT_STATUS_IS_OK(status)) {
8322 END_PROFILE(SMBlockingX);
8323 reply_nterror(req, status);
8327 END_PROFILE(SMBlockingX);
8331 reply_outbuf(req, 2, 0);
8332 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8333 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8335 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8336 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8338 END_PROFILE(SMBlockingX);
8342 #define DBGC_CLASS DBGC_ALL
8344 /****************************************************************************
8345 Reply to a SMBreadbmpx (read block multiplex) request.
8346 Always reply with an error, if someone has a platform really needs this,
8347 please contact vl@samba.org
8348 ****************************************************************************/
8350 void reply_readbmpx(struct smb_request *req)
8352 START_PROFILE(SMBreadBmpx);
8353 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8354 END_PROFILE(SMBreadBmpx);
8358 /****************************************************************************
8359 Reply to a SMBreadbs (read block multiplex secondary) request.
8360 Always reply with an error, if someone has a platform really needs this,
8361 please contact vl@samba.org
8362 ****************************************************************************/
8364 void reply_readbs(struct smb_request *req)
8366 START_PROFILE(SMBreadBs);
8367 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8368 END_PROFILE(SMBreadBs);
8372 /****************************************************************************
8373 Reply to a SMBsetattrE.
8374 ****************************************************************************/
8376 void reply_setattrE(struct smb_request *req)
8378 connection_struct *conn = req->conn;
8379 struct smb_file_time ft;
8383 START_PROFILE(SMBsetattrE);
8387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8391 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8393 if(!fsp || (fsp->conn != conn)) {
8394 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8399 * Convert the DOS times into unix times.
8402 ft.atime = convert_time_t_to_timespec(
8403 srv_make_unix_date2(req->vwv+3));
8404 ft.mtime = convert_time_t_to_timespec(
8405 srv_make_unix_date2(req->vwv+5));
8406 ft.create_time = convert_time_t_to_timespec(
8407 srv_make_unix_date2(req->vwv+1));
8409 reply_outbuf(req, 0, 0);
8412 * Patch from Ray Frush <frush@engr.colostate.edu>
8413 * Sometimes times are sent as zero - ignore them.
8416 /* Ensure we have a valid stat struct for the source. */
8417 status = vfs_stat_fsp(fsp);
8418 if (!NT_STATUS_IS_OK(status)) {
8419 reply_nterror(req, status);
8423 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8428 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8429 if (!NT_STATUS_IS_OK(status)) {
8430 reply_nterror(req, status);
8434 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8437 (unsigned int)ft.atime.tv_sec,
8438 (unsigned int)ft.mtime.tv_sec,
8439 (unsigned int)ft.create_time.tv_sec
8442 END_PROFILE(SMBsetattrE);
8447 /* Back from the dead for OS/2..... JRA. */
8449 /****************************************************************************
8450 Reply to a SMBwritebmpx (write block multiplex primary) request.
8451 Always reply with an error, if someone has a platform really needs this,
8452 please contact vl@samba.org
8453 ****************************************************************************/
8455 void reply_writebmpx(struct smb_request *req)
8457 START_PROFILE(SMBwriteBmpx);
8458 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8459 END_PROFILE(SMBwriteBmpx);
8463 /****************************************************************************
8464 Reply to a SMBwritebs (write block multiplex secondary) request.
8465 Always reply with an error, if someone has a platform really needs this,
8466 please contact vl@samba.org
8467 ****************************************************************************/
8469 void reply_writebs(struct smb_request *req)
8471 START_PROFILE(SMBwriteBs);
8472 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8473 END_PROFILE(SMBwriteBs);
8477 /****************************************************************************
8478 Reply to a SMBgetattrE.
8479 ****************************************************************************/
8481 void reply_getattrE(struct smb_request *req)
8483 connection_struct *conn = req->conn;
8486 struct timespec create_ts;
8488 START_PROFILE(SMBgetattrE);
8491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8492 END_PROFILE(SMBgetattrE);
8496 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8498 if(!fsp || (fsp->conn != conn)) {
8499 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8500 END_PROFILE(SMBgetattrE);
8504 /* Do an fstat on this file */
8506 reply_nterror(req, map_nt_error_from_unix(errno));
8507 END_PROFILE(SMBgetattrE);
8511 mode = dos_mode(conn, fsp->fsp_name);
8514 * Convert the times into dos times. Set create
8515 * date to be last modify date as UNIX doesn't save
8519 reply_outbuf(req, 11, 0);
8521 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8522 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8523 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8524 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8525 /* Should we check pending modtime here ? JRA */
8526 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8527 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8529 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8530 SIVAL(req->outbuf, smb_vwv6, 0);
8531 SIVAL(req->outbuf, smb_vwv8, 0);
8533 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8534 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8535 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8537 SSVAL(req->outbuf,smb_vwv10, mode);
8539 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8541 END_PROFILE(SMBgetattrE);