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"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS check_path_syntax_internal(char *path,
60 bool *p_last_component_contains_wcard)
64 NTSTATUS ret = NT_STATUS_OK;
65 bool start_of_name_component = True;
66 bool stream_started = false;
68 *p_last_component_contains_wcard = False;
75 return NT_STATUS_OBJECT_NAME_INVALID;
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 if (strchr_m(&s[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
87 if ((*s == ':') && !posix_path && !stream_started) {
88 if (*p_last_component_contains_wcard) {
89 return NT_STATUS_OBJECT_NAME_INVALID;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started = true;
98 start_of_name_component = false;
102 return NT_STATUS_OBJECT_NAME_INVALID;
106 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s,posix_path)) {
115 if ((d != path) && (*s != '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component = True;
122 *p_last_component_contains_wcard = False;
126 if (start_of_name_component) {
127 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d > path) && (*(d-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d--; d > path; d--) {
153 s += 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
169 if (*s <= 0x1f || *s == '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID;
178 *p_last_component_contains_wcard = True;
187 /* Get the size of the next MB character. */
188 next_codepoint(s,&siz);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER;
211 start_of_name_component = False;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax(char *path)
227 return check_path_syntax_internal(path, False, &ignore);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 return check_path_syntax_internal(path, False, p_contains_wcard);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS check_path_syntax_posix(char *path)
250 return check_path_syntax_internal(path, True, &ignore);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
258 const char *base_ptr,
265 bool *contains_wcard)
271 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275 *err = NT_STATUS_INVALID_PARAMETER;
279 *contains_wcard = False;
281 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err = check_path_syntax_posix(*pp_dest);
293 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX *ctx,
304 const char *base_ptr,
313 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
314 src_len, flags, err, &ignore);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
319 NTSTATUS *err, bool *contains_wcard)
321 ssize_t bufrem = smbreq_bufrem(req, src);
324 *err = NT_STATUS_INVALID_PARAMETER;
328 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
329 req->flags2, pp_dest, src, bufrem, flags,
330 err, contains_wcard);
333 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
334 char **pp_dest, const char *src, int flags,
338 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
339 flags, err, &ignore);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
348 char **dest, const uint8_t *src, int flags)
350 ssize_t bufrem = smbreq_bufrem(req, src);
356 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
367 if ((fsp == NULL) || (conn == NULL)) {
368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
371 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct *conn, struct smb_request *req,
385 if (!check_fsp_open(conn, req, fsp)) {
388 if (fsp->is_directory) {
389 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
392 if (fsp->fh->fd == -1) {
393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
396 fsp->num_smb_operations++;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
408 if (!check_fsp_open(conn, req, fsp)) {
412 if (fsp->is_directory) {
416 if (fsp->fake_file_handle == NULL) {
420 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
424 if (fsp->fake_file_handle->private_data == NULL) {
431 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
432 const char *name, int name_type)
435 char *trim_name_type;
436 const char *retarget_parm;
439 int retarget_type = 0x20;
440 int retarget_port = NBT_SMB_PORT;
441 struct sockaddr_storage retarget_addr;
442 struct sockaddr_in *in_addr;
446 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
450 trim_name = talloc_strdup(talloc_tos(), name);
451 if (trim_name == NULL) {
454 trim_char(trim_name, ' ', ' ');
456 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
458 if (trim_name_type == NULL) {
462 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
463 trim_name_type, NULL);
464 if (retarget_parm == NULL) {
465 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
468 if (retarget_parm == NULL) {
472 retarget = talloc_strdup(trim_name, retarget_parm);
473 if (retarget == NULL) {
477 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
479 p = strchr(retarget, ':');
482 retarget_port = atoi(p);
485 p = strchr_m(retarget, '#');
488 if (sscanf(p, "%x", &retarget_type) != 1) {
493 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
495 DEBUG(10, ("could not resolve %s\n", retarget));
499 if (retarget_addr.ss_family != AF_INET) {
500 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
504 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
506 _smb_setlen(outbuf, 6);
507 SCVAL(outbuf, 0, 0x84);
508 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
509 *(uint16_t *)(outbuf+8) = htons(retarget_port);
511 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
513 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
519 TALLOC_FREE(trim_name);
523 static void reply_called_name_not_present(char *outbuf)
525 smb_setlen(outbuf, 1);
526 SCVAL(outbuf, 0, 0x83);
527 SCVAL(outbuf, 4, 0x82);
530 /****************************************************************************
531 Reply to a (netbios-level) special message.
532 ****************************************************************************/
534 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
536 int msg_type = CVAL(inbuf,0);
537 int msg_flags = CVAL(inbuf,1);
539 * We only really use 4 bytes of the outbuf, but for the smb_setlen
540 * calculation & friends (srv_send_smb uses that) we need the full smb
543 char outbuf[smb_size];
545 memset(outbuf, '\0', sizeof(outbuf));
547 smb_setlen(outbuf,0);
550 case NBSSrequest: /* session request */
552 /* inbuf_size is guarenteed to be at least 4. */
554 int name_type1, name_type2;
555 int name_len1, name_len2;
559 if (sconn->nbt.got_session) {
560 exit_server_cleanly("multiple session request not permitted");
563 SCVAL(outbuf,0,NBSSpositive);
566 /* inbuf_size is guaranteed to be at least 4. */
567 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
568 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
569 DEBUG(0,("Invalid name length in session request\n"));
570 reply_called_name_not_present(outbuf);
573 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
574 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
575 DEBUG(0,("Invalid name length in session request\n"));
576 reply_called_name_not_present(outbuf);
580 name_type1 = name_extract((unsigned char *)inbuf,
581 inbuf_size,(unsigned int)4,name1);
582 name_type2 = name_extract((unsigned char *)inbuf,
583 inbuf_size,(unsigned int)(4 + name_len1),name2);
585 if (name_type1 == -1 || name_type2 == -1) {
586 DEBUG(0,("Invalid name type in session request\n"));
587 reply_called_name_not_present(outbuf);
591 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
592 name1, name_type1, name2, name_type2));
594 if (netbios_session_retarget(sconn, name1, name_type1)) {
595 exit_server_cleanly("retargeted client");
599 * Windows NT/2k uses "*SMBSERVER" and XP uses
600 * "*SMBSERV" arrggg!!!
602 if (strequal(name1, "*SMBSERVER ")
603 || strequal(name1, "*SMBSERV ")) {
606 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
609 exit_server_cleanly("could not allocate raddr");
612 fstrcpy(name1, raddr);
615 set_local_machine_name(name1, True);
616 set_remote_machine_name(name2, True);
618 if (is_ipaddress(sconn->remote_hostname)) {
619 char *p = discard_const_p(char, sconn->remote_hostname);
623 sconn->remote_hostname = talloc_strdup(sconn,
624 get_remote_machine_name());
625 if (sconn->remote_hostname == NULL) {
626 exit_server_cleanly("could not copy remote name");
628 sconn->conn->remote_hostname = sconn->remote_hostname;
631 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
632 get_local_machine_name(), get_remote_machine_name(),
635 if (name_type2 == 'R') {
636 /* We are being asked for a pathworks session ---
638 reply_called_name_not_present(outbuf);
642 reload_services(sconn, conn_snum_used, true);
645 sconn->nbt.got_session = true;
649 case 0x89: /* session keepalive request
650 (some old clients produce this?) */
651 SCVAL(outbuf,0,NBSSkeepalive);
655 case NBSSpositive: /* positive session response */
656 case NBSSnegative: /* negative session response */
657 case NBSSretarget: /* retarget session response */
658 DEBUG(0,("Unexpected session response\n"));
661 case NBSSkeepalive: /* session keepalive */
666 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
667 msg_type, msg_flags));
669 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
671 if (CVAL(outbuf, 0) != 0x82) {
672 exit_server_cleanly("invalid netbios session");
677 /****************************************************************************
679 conn POINTER CAN BE NULL HERE !
680 ****************************************************************************/
682 void reply_tcon(struct smb_request *req)
684 connection_struct *conn = req->conn;
686 char *service_buf = NULL;
687 char *password = NULL;
693 TALLOC_CTX *ctx = talloc_tos();
694 struct smbd_server_connection *sconn = req->sconn;
695 NTTIME now = timeval_to_nttime(&req->request_time);
697 START_PROFILE(SMBtcon);
699 if (req->buflen < 4) {
700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
701 END_PROFILE(SMBtcon);
706 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
708 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
710 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
713 if (service_buf == NULL || password == NULL || dev == NULL) {
714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
715 END_PROFILE(SMBtcon);
718 p2 = strrchr_m(service_buf,'\\');
722 service = service_buf;
725 conn = make_connection(sconn, now, service, dev,
726 req->vuid,&nt_status);
730 reply_nterror(req, nt_status);
731 END_PROFILE(SMBtcon);
735 reply_outbuf(req, 2, 0);
736 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
737 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
738 SSVAL(req->outbuf,smb_tid,conn->cnum);
740 DEBUG(3,("tcon service=%s cnum=%d\n",
741 service, conn->cnum));
743 END_PROFILE(SMBtcon);
747 /****************************************************************************
748 Reply to a tcon and X.
749 conn POINTER CAN BE NULL HERE !
750 ****************************************************************************/
752 void reply_tcon_and_X(struct smb_request *req)
754 connection_struct *conn = req->conn;
755 const char *service = NULL;
756 TALLOC_CTX *ctx = talloc_tos();
757 /* what the cleint thinks the device is */
758 char *client_devicetype = NULL;
759 /* what the server tells the client the share represents */
760 const char *server_devicetype;
767 struct smbXsrv_session *session = NULL;
768 NTTIME now = timeval_to_nttime(&req->request_time);
769 bool session_key_updated = false;
770 uint16_t optional_support = 0;
771 struct smbd_server_connection *sconn = req->sconn;
773 START_PROFILE(SMBtconX);
776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
777 END_PROFILE(SMBtconX);
781 passlen = SVAL(req->vwv+3, 0);
782 tcon_flags = SVAL(req->vwv+2, 0);
784 /* we might have to close an old one */
785 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
786 struct smbXsrv_tcon *tcon;
794 * TODO: cancel all outstanding requests on the tcon
796 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
797 if (!NT_STATUS_IS_OK(status)) {
798 DEBUG(0, ("reply_tcon_and_X: "
799 "smbXsrv_tcon_disconnect() failed: %s\n",
802 * If we hit this case, there is something completely
803 * wrong, so we better disconnect the transport connection.
805 END_PROFILE(SMBtconX);
806 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
813 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
814 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
815 END_PROFILE(SMBtconX);
819 if (sconn->smb1.negprot.encrypted_passwords) {
820 p = req->buf + passlen;
822 p = req->buf + passlen + 1;
825 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
829 END_PROFILE(SMBtconX);
834 * the service name can be either: \\server\share
835 * or share directly like on the DELL PowerVault 705
838 q = strchr_m(path+2,'\\');
840 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
841 END_PROFILE(SMBtconX);
849 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
850 &client_devicetype, p,
851 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
853 if (client_devicetype == NULL) {
854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
855 END_PROFILE(SMBtconX);
859 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
861 nt_status = smb1srv_session_lookup(req->sconn->conn,
862 req->vuid, now, &session);
863 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
864 reply_force_doserror(req, ERRSRV, ERRbaduid);
865 END_PROFILE(SMBtconX);
868 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
869 reply_nterror(req, nt_status);
870 END_PROFILE(SMBtconX);
873 if (!NT_STATUS_IS_OK(nt_status)) {
874 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
875 END_PROFILE(SMBtconX);
879 if (session->global->auth_session_info == NULL) {
880 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
881 END_PROFILE(SMBtconX);
886 * If there is no application key defined yet
889 * This means we setup the application key on the
890 * first tcon that happens via the given session.
892 * Once the application key is defined, it does not
895 if (session->global->application_key.length == 0 &&
896 session->global->signing_key.length > 0)
898 struct smbXsrv_session *x = session;
899 struct auth_session_info *session_info =
900 session->global->auth_session_info;
901 uint8_t session_key[16];
903 ZERO_STRUCT(session_key);
904 memcpy(session_key, x->global->signing_key.data,
905 MIN(x->global->signing_key.length, sizeof(session_key)));
908 * The application key is truncated/padded to 16 bytes
910 x->global->application_key = data_blob_talloc(x->global,
912 sizeof(session_key));
913 ZERO_STRUCT(session_key);
914 if (x->global->application_key.data == NULL) {
915 reply_nterror(req, NT_STATUS_NO_MEMORY);
916 END_PROFILE(SMBtconX);
920 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
921 smb_key_derivation(x->global->application_key.data,
922 x->global->application_key.length,
923 x->global->application_key.data);
924 optional_support |= SMB_EXTENDED_SIGNATURES;
928 * Place the application key into the session_info
930 data_blob_clear_free(&session_info->session_key);
931 session_info->session_key = data_blob_dup_talloc(session_info,
932 x->global->application_key);
933 if (session_info->session_key.data == NULL) {
934 data_blob_clear_free(&x->global->application_key);
935 reply_nterror(req, NT_STATUS_NO_MEMORY);
936 END_PROFILE(SMBtconX);
939 session_key_updated = true;
942 conn = make_connection(sconn, now, service, client_devicetype,
943 req->vuid, &nt_status);
947 if (session_key_updated) {
948 struct smbXsrv_session *x = session;
949 struct auth_session_info *session_info =
950 session->global->auth_session_info;
951 data_blob_clear_free(&x->global->application_key);
952 data_blob_clear_free(&session_info->session_key);
954 reply_nterror(req, nt_status);
955 END_PROFILE(SMBtconX);
960 server_devicetype = "IPC";
961 else if ( IS_PRINT(conn) )
962 server_devicetype = "LPT1:";
964 server_devicetype = "A:";
966 if (get_Protocol() < PROTOCOL_NT1) {
967 reply_outbuf(req, 2, 0);
968 if (message_push_string(&req->outbuf, server_devicetype,
969 STR_TERMINATE|STR_ASCII) == -1) {
970 reply_nterror(req, NT_STATUS_NO_MEMORY);
971 END_PROFILE(SMBtconX);
975 /* NT sets the fstype of IPC$ to the null string */
976 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
978 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
979 /* Return permissions. */
983 reply_outbuf(req, 7, 0);
986 perm1 = FILE_ALL_ACCESS;
987 perm2 = FILE_ALL_ACCESS;
989 perm1 = conn->share_access;
992 SIVAL(req->outbuf, smb_vwv3, perm1);
993 SIVAL(req->outbuf, smb_vwv5, perm2);
995 reply_outbuf(req, 3, 0);
998 if ((message_push_string(&req->outbuf, server_devicetype,
999 STR_TERMINATE|STR_ASCII) == -1)
1000 || (message_push_string(&req->outbuf, fstype,
1001 STR_TERMINATE) == -1)) {
1002 reply_nterror(req, NT_STATUS_NO_MEMORY);
1003 END_PROFILE(SMBtconX);
1007 /* what does setting this bit do? It is set by NT4 and
1008 may affect the ability to autorun mounted cdroms */
1009 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1011 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1013 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1014 DEBUG(2,("Serving %s as a Dfs root\n",
1015 lp_servicename(ctx, SNUM(conn)) ));
1016 optional_support |= SMB_SHARE_IN_DFS;
1019 SSVAL(req->outbuf, smb_vwv2, optional_support);
1022 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1023 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1025 DEBUG(3,("tconX service=%s \n",
1028 /* set the incoming and outgoing tid to the just created one */
1029 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1030 SSVAL(req->outbuf,smb_tid,conn->cnum);
1032 END_PROFILE(SMBtconX);
1034 req->tid = conn->cnum;
1037 /****************************************************************************
1038 Reply to an unknown type.
1039 ****************************************************************************/
1041 void reply_unknown_new(struct smb_request *req, uint8 type)
1043 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1044 smb_fn_name(type), type, type));
1045 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1049 /****************************************************************************
1051 conn POINTER CAN BE NULL HERE !
1052 ****************************************************************************/
1054 void reply_ioctl(struct smb_request *req)
1056 connection_struct *conn = req->conn;
1063 START_PROFILE(SMBioctl);
1066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1067 END_PROFILE(SMBioctl);
1071 device = SVAL(req->vwv+1, 0);
1072 function = SVAL(req->vwv+2, 0);
1073 ioctl_code = (device << 16) + function;
1075 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1077 switch (ioctl_code) {
1078 case IOCTL_QUERY_JOB_INFO:
1082 reply_force_doserror(req, ERRSRV, ERRnosupport);
1083 END_PROFILE(SMBioctl);
1087 reply_outbuf(req, 8, replysize+1);
1088 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1089 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1090 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1091 p = smb_buf(req->outbuf);
1092 memset(p, '\0', replysize+1); /* valgrind-safe. */
1093 p += 1; /* Allow for alignment */
1095 switch (ioctl_code) {
1096 case IOCTL_QUERY_JOB_INFO:
1098 files_struct *fsp = file_fsp(
1099 req, SVAL(req->vwv+0, 0));
1101 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1102 END_PROFILE(SMBioctl);
1106 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1108 srvstr_push((char *)req->outbuf, req->flags2, p+2,
1109 lp_netbios_name(), 15,
1110 STR_TERMINATE|STR_ASCII);
1112 srvstr_push((char *)req->outbuf, req->flags2,
1114 lp_servicename(talloc_tos(),
1116 13, STR_TERMINATE|STR_ASCII);
1118 memset(p+18, 0, 13);
1124 END_PROFILE(SMBioctl);
1128 /****************************************************************************
1129 Strange checkpath NTSTATUS mapping.
1130 ****************************************************************************/
1132 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1134 /* Strange DOS error code semantics only for checkpath... */
1135 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1136 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1137 /* We need to map to ERRbadpath */
1138 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1144 /****************************************************************************
1145 Reply to a checkpath.
1146 ****************************************************************************/
1148 void reply_checkpath(struct smb_request *req)
1150 connection_struct *conn = req->conn;
1151 struct smb_filename *smb_fname = NULL;
1154 TALLOC_CTX *ctx = talloc_tos();
1156 START_PROFILE(SMBcheckpath);
1158 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1159 STR_TERMINATE, &status);
1161 if (!NT_STATUS_IS_OK(status)) {
1162 status = map_checkpath_error(req->flags2, status);
1163 reply_nterror(req, status);
1164 END_PROFILE(SMBcheckpath);
1168 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1170 status = filename_convert(ctx,
1172 req->flags2 & FLAGS2_DFS_PATHNAMES,
1178 if (!NT_STATUS_IS_OK(status)) {
1179 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1180 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1181 ERRSRV, ERRbadpath);
1182 END_PROFILE(SMBcheckpath);
1188 if (!VALID_STAT(smb_fname->st) &&
1189 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1190 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1191 smb_fname_str_dbg(smb_fname), strerror(errno)));
1192 status = map_nt_error_from_unix(errno);
1196 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1197 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1198 ERRDOS, ERRbadpath);
1202 reply_outbuf(req, 0, 0);
1205 /* We special case this - as when a Windows machine
1206 is parsing a path is steps through the components
1207 one at a time - if a component fails it expects
1208 ERRbadpath, not ERRbadfile.
1210 status = map_checkpath_error(req->flags2, status);
1211 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1213 * Windows returns different error codes if
1214 * the parent directory is valid but not the
1215 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1216 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1217 * if the path is invalid.
1219 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1220 ERRDOS, ERRbadpath);
1224 reply_nterror(req, status);
1227 TALLOC_FREE(smb_fname);
1228 END_PROFILE(SMBcheckpath);
1232 /****************************************************************************
1234 ****************************************************************************/
1236 void reply_getatr(struct smb_request *req)
1238 connection_struct *conn = req->conn;
1239 struct smb_filename *smb_fname = NULL;
1246 TALLOC_CTX *ctx = talloc_tos();
1247 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1249 START_PROFILE(SMBgetatr);
1251 p = (const char *)req->buf + 1;
1252 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 reply_nterror(req, status);
1258 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1259 under WfWg - weird! */
1260 if (*fname == '\0') {
1261 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1262 if (!CAN_WRITE(conn)) {
1263 mode |= FILE_ATTRIBUTE_READONLY;
1268 status = filename_convert(ctx,
1270 req->flags2 & FLAGS2_DFS_PATHNAMES,
1275 if (!NT_STATUS_IS_OK(status)) {
1276 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1277 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1278 ERRSRV, ERRbadpath);
1281 reply_nterror(req, status);
1284 if (!VALID_STAT(smb_fname->st) &&
1285 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1286 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1287 smb_fname_str_dbg(smb_fname),
1289 reply_nterror(req, map_nt_error_from_unix(errno));
1293 mode = dos_mode(conn, smb_fname);
1294 size = smb_fname->st.st_ex_size;
1296 if (ask_sharemode) {
1297 struct timespec write_time_ts;
1298 struct file_id fileid;
1300 ZERO_STRUCT(write_time_ts);
1301 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1302 get_file_infos(fileid, 0, NULL, &write_time_ts);
1303 if (!null_timespec(write_time_ts)) {
1304 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1308 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1309 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1314 reply_outbuf(req, 10, 0);
1316 SSVAL(req->outbuf,smb_vwv0,mode);
1317 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1318 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1320 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1322 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1324 if (get_Protocol() >= PROTOCOL_NT1) {
1325 SSVAL(req->outbuf, smb_flg2,
1326 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1329 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1330 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1333 TALLOC_FREE(smb_fname);
1335 END_PROFILE(SMBgetatr);
1339 /****************************************************************************
1341 ****************************************************************************/
1343 void reply_setatr(struct smb_request *req)
1345 struct smb_file_time ft;
1346 connection_struct *conn = req->conn;
1347 struct smb_filename *smb_fname = NULL;
1353 TALLOC_CTX *ctx = talloc_tos();
1355 START_PROFILE(SMBsetatr);
1360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1364 p = (const char *)req->buf + 1;
1365 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 reply_nterror(req, status);
1371 status = filename_convert(ctx,
1373 req->flags2 & FLAGS2_DFS_PATHNAMES,
1378 if (!NT_STATUS_IS_OK(status)) {
1379 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1380 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1381 ERRSRV, ERRbadpath);
1384 reply_nterror(req, status);
1388 if (smb_fname->base_name[0] == '.' &&
1389 smb_fname->base_name[1] == '\0') {
1391 * Not sure here is the right place to catch this
1392 * condition. Might be moved to somewhere else later -- vl
1394 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1398 mode = SVAL(req->vwv+0, 0);
1399 mtime = srv_make_unix_date3(req->vwv+1);
1401 if (mode != FILE_ATTRIBUTE_NORMAL) {
1402 if (VALID_STAT_OF_DIR(smb_fname->st))
1403 mode |= FILE_ATTRIBUTE_DIRECTORY;
1405 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1407 status = check_access(conn, NULL, smb_fname,
1408 FILE_WRITE_ATTRIBUTES);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 reply_nterror(req, status);
1414 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1416 reply_nterror(req, map_nt_error_from_unix(errno));
1421 ft.mtime = convert_time_t_to_timespec(mtime);
1422 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 reply_nterror(req, status);
1428 reply_outbuf(req, 0, 0);
1430 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1433 TALLOC_FREE(smb_fname);
1434 END_PROFILE(SMBsetatr);
1438 /****************************************************************************
1440 ****************************************************************************/
1442 void reply_dskattr(struct smb_request *req)
1444 connection_struct *conn = req->conn;
1445 uint64_t dfree,dsize,bsize;
1446 START_PROFILE(SMBdskattr);
1448 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1449 reply_nterror(req, map_nt_error_from_unix(errno));
1450 END_PROFILE(SMBdskattr);
1454 reply_outbuf(req, 5, 0);
1456 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1457 double total_space, free_space;
1458 /* we need to scale this to a number that DOS6 can handle. We
1459 use floating point so we can handle large drives on systems
1460 that don't have 64 bit integers
1462 we end up displaying a maximum of 2G to DOS systems
1464 total_space = dsize * (double)bsize;
1465 free_space = dfree * (double)bsize;
1467 dsize = (uint64_t)((total_space+63*512) / (64*512));
1468 dfree = (uint64_t)((free_space+63*512) / (64*512));
1470 if (dsize > 0xFFFF) dsize = 0xFFFF;
1471 if (dfree > 0xFFFF) dfree = 0xFFFF;
1473 SSVAL(req->outbuf,smb_vwv0,dsize);
1474 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1475 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1476 SSVAL(req->outbuf,smb_vwv3,dfree);
1478 SSVAL(req->outbuf,smb_vwv0,dsize);
1479 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1480 SSVAL(req->outbuf,smb_vwv2,512);
1481 SSVAL(req->outbuf,smb_vwv3,dfree);
1484 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1486 END_PROFILE(SMBdskattr);
1491 * Utility function to split the filename from the directory.
1493 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1494 char **fname_dir_out,
1495 char **fname_mask_out)
1497 const char *p = NULL;
1498 char *fname_dir = NULL;
1499 char *fname_mask = NULL;
1501 p = strrchr_m(fname_in, '/');
1503 fname_dir = talloc_strdup(ctx, ".");
1504 fname_mask = talloc_strdup(ctx, fname_in);
1506 fname_dir = talloc_strndup(ctx, fname_in,
1507 PTR_DIFF(p, fname_in));
1508 fname_mask = talloc_strdup(ctx, p+1);
1511 if (!fname_dir || !fname_mask) {
1512 TALLOC_FREE(fname_dir);
1513 TALLOC_FREE(fname_mask);
1514 return NT_STATUS_NO_MEMORY;
1517 *fname_dir_out = fname_dir;
1518 *fname_mask_out = fname_mask;
1519 return NT_STATUS_OK;
1522 /****************************************************************************
1524 Can be called from SMBsearch, SMBffirst or SMBfunique.
1525 ****************************************************************************/
1527 void reply_search(struct smb_request *req)
1529 connection_struct *conn = req->conn;
1531 const char *mask = NULL;
1532 char *directory = NULL;
1533 struct smb_filename *smb_fname = NULL;
1537 struct timespec date;
1539 unsigned int numentries = 0;
1540 unsigned int maxentries = 0;
1541 bool finished = False;
1546 bool check_descend = False;
1547 bool expect_close = False;
1549 bool mask_contains_wcard = False;
1550 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1551 TALLOC_CTX *ctx = talloc_tos();
1552 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1553 struct dptr_struct *dirptr = NULL;
1554 struct smbd_server_connection *sconn = req->sconn;
1556 START_PROFILE(SMBsearch);
1559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1563 if (lp_posix_pathnames()) {
1564 reply_unknown_new(req, req->cmd);
1568 /* If we were called as SMBffirst then we must expect close. */
1569 if(req->cmd == SMBffirst) {
1570 expect_close = True;
1573 reply_outbuf(req, 1, 3);
1574 maxentries = SVAL(req->vwv+0, 0);
1575 dirtype = SVAL(req->vwv+1, 0);
1576 p = (const char *)req->buf + 1;
1577 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1578 &nt_status, &mask_contains_wcard);
1579 if (!NT_STATUS_IS_OK(nt_status)) {
1580 reply_nterror(req, nt_status);
1585 status_len = SVAL(p, 0);
1588 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1590 if (status_len == 0) {
1591 nt_status = filename_convert(ctx, conn,
1592 req->flags2 & FLAGS2_DFS_PATHNAMES,
1594 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1595 &mask_contains_wcard,
1597 if (!NT_STATUS_IS_OK(nt_status)) {
1598 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1599 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1600 ERRSRV, ERRbadpath);
1603 reply_nterror(req, nt_status);
1607 directory = smb_fname->base_name;
1609 p = strrchr_m(directory,'/');
1610 if ((p != NULL) && (*directory != '/')) {
1612 directory = talloc_strndup(ctx, directory,
1613 PTR_DIFF(p, directory));
1616 directory = talloc_strdup(ctx,".");
1620 reply_nterror(req, NT_STATUS_NO_MEMORY);
1624 memset((char *)status,'\0',21);
1625 SCVAL(status,0,(dirtype & 0x1F));
1627 nt_status = dptr_create(conn,
1635 mask_contains_wcard,
1638 if (!NT_STATUS_IS_OK(nt_status)) {
1639 reply_nterror(req, nt_status);
1642 dptr_num = dptr_dnum(dirptr);
1645 const char *dirpath;
1647 memcpy(status,p,21);
1648 status_dirtype = CVAL(status,0) & 0x1F;
1649 if (status_dirtype != (dirtype & 0x1F)) {
1650 dirtype = status_dirtype;
1653 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1657 dirpath = dptr_path(sconn, dptr_num);
1658 directory = talloc_strdup(ctx, dirpath);
1660 reply_nterror(req, NT_STATUS_NO_MEMORY);
1664 mask = dptr_wcard(sconn, dptr_num);
1669 * For a 'continue' search we have no string. So
1670 * check from the initial saved string.
1672 mask_contains_wcard = ms_has_wild(mask);
1673 dirtype = dptr_attr(sconn, dptr_num);
1676 DEBUG(4,("dptr_num is %d\n",dptr_num));
1678 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1679 dptr_init_search_op(dirptr);
1681 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1682 char buf[DIR_STRUCT_SIZE];
1683 memcpy(buf,status,21);
1684 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1685 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1686 reply_nterror(req, NT_STATUS_NO_MEMORY);
1689 dptr_fill(sconn, buf+12,dptr_num);
1690 if (dptr_zero(buf+12) && (status_len==0)) {
1695 if (message_push_blob(&req->outbuf,
1696 data_blob_const(buf, sizeof(buf)))
1698 reply_nterror(req, NT_STATUS_NO_MEMORY);
1703 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1704 size_t available_space = sconn->smb1.sessions.max_send - hdr_size;
1706 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1708 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1709 directory,lp_dont_descend(ctx, SNUM(conn))));
1710 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1711 check_descend = True;
1714 for (i=numentries;(i<maxentries) && !finished;i++) {
1715 finished = !get_dir_entry(ctx,
1726 char buf[DIR_STRUCT_SIZE];
1727 memcpy(buf,status,21);
1728 if (!make_dir_struct(ctx,
1734 convert_timespec_to_time_t(date),
1735 !allow_long_path_components)) {
1736 reply_nterror(req, NT_STATUS_NO_MEMORY);
1739 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1742 if (message_push_blob(&req->outbuf,
1743 data_blob_const(buf, sizeof(buf)))
1745 reply_nterror(req, NT_STATUS_NO_MEMORY);
1755 /* If we were called as SMBffirst with smb_search_id == NULL
1756 and no entries were found then return error and close dirptr
1759 if (numentries == 0) {
1760 dptr_close(sconn, &dptr_num);
1761 } else if(expect_close && status_len == 0) {
1762 /* Close the dptr - we know it's gone */
1763 dptr_close(sconn, &dptr_num);
1766 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1767 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1768 dptr_close(sconn, &dptr_num);
1771 if ((numentries == 0) && !mask_contains_wcard) {
1772 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1776 SSVAL(req->outbuf,smb_vwv0,numentries);
1777 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1778 SCVAL(smb_buf(req->outbuf),0,5);
1779 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1781 /* The replies here are never long name. */
1782 SSVAL(req->outbuf, smb_flg2,
1783 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1784 if (!allow_long_path_components) {
1785 SSVAL(req->outbuf, smb_flg2,
1786 SVAL(req->outbuf, smb_flg2)
1787 & (~FLAGS2_LONG_PATH_COMPONENTS));
1790 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1791 SSVAL(req->outbuf, smb_flg2,
1792 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1794 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1795 smb_fn_name(req->cmd),
1802 TALLOC_FREE(directory);
1803 TALLOC_FREE(smb_fname);
1804 END_PROFILE(SMBsearch);
1808 /****************************************************************************
1809 Reply to a fclose (stop directory search).
1810 ****************************************************************************/
1812 void reply_fclose(struct smb_request *req)
1820 bool path_contains_wcard = False;
1821 TALLOC_CTX *ctx = talloc_tos();
1822 struct smbd_server_connection *sconn = req->sconn;
1824 START_PROFILE(SMBfclose);
1826 if (lp_posix_pathnames()) {
1827 reply_unknown_new(req, req->cmd);
1828 END_PROFILE(SMBfclose);
1832 p = (const char *)req->buf + 1;
1833 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1834 &err, &path_contains_wcard);
1835 if (!NT_STATUS_IS_OK(err)) {
1836 reply_nterror(req, err);
1837 END_PROFILE(SMBfclose);
1841 status_len = SVAL(p,0);
1844 if (status_len == 0) {
1845 reply_force_doserror(req, ERRSRV, ERRsrverror);
1846 END_PROFILE(SMBfclose);
1850 memcpy(status,p,21);
1852 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1853 /* Close the dptr - we know it's gone */
1854 dptr_close(sconn, &dptr_num);
1857 reply_outbuf(req, 1, 0);
1858 SSVAL(req->outbuf,smb_vwv0,0);
1860 DEBUG(3,("search close\n"));
1862 END_PROFILE(SMBfclose);
1866 /****************************************************************************
1868 ****************************************************************************/
1870 void reply_open(struct smb_request *req)
1872 connection_struct *conn = req->conn;
1873 struct smb_filename *smb_fname = NULL;
1885 uint32 create_disposition;
1886 uint32 create_options = 0;
1887 uint32_t private_flags = 0;
1889 TALLOC_CTX *ctx = talloc_tos();
1891 START_PROFILE(SMBopen);
1894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1899 deny_mode = SVAL(req->vwv+0, 0);
1900 dos_attr = SVAL(req->vwv+1, 0);
1902 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1903 STR_TERMINATE, &status);
1904 if (!NT_STATUS_IS_OK(status)) {
1905 reply_nterror(req, status);
1909 if (!map_open_params_to_ntcreate(fname, deny_mode,
1910 OPENX_FILE_EXISTS_OPEN, &access_mask,
1911 &share_mode, &create_disposition,
1912 &create_options, &private_flags)) {
1913 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1917 status = filename_convert(ctx,
1919 req->flags2 & FLAGS2_DFS_PATHNAMES,
1921 UCF_PREP_CREATEFILE,
1924 if (!NT_STATUS_IS_OK(status)) {
1925 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1926 reply_botherror(req,
1927 NT_STATUS_PATH_NOT_COVERED,
1928 ERRSRV, ERRbadpath);
1931 reply_nterror(req, status);
1935 status = SMB_VFS_CREATE_FILE(
1938 0, /* root_dir_fid */
1939 smb_fname, /* fname */
1940 access_mask, /* access_mask */
1941 share_mode, /* share_access */
1942 create_disposition, /* create_disposition*/
1943 create_options, /* create_options */
1944 dos_attr, /* file_attributes */
1945 oplock_request, /* oplock_request */
1946 0, /* allocation_size */
1953 if (!NT_STATUS_IS_OK(status)) {
1954 if (open_was_deferred(req->sconn, req->mid)) {
1955 /* We have re-scheduled this call. */
1958 reply_openerror(req, status);
1962 /* Ensure we're pointing at the correct stat struct. */
1963 TALLOC_FREE(smb_fname);
1964 smb_fname = fsp->fsp_name;
1966 size = smb_fname->st.st_ex_size;
1967 fattr = dos_mode(conn, smb_fname);
1969 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1971 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1972 DEBUG(3,("attempt to open a directory %s\n",
1974 close_file(req, fsp, ERROR_CLOSE);
1975 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1976 ERRDOS, ERRnoaccess);
1980 reply_outbuf(req, 7, 0);
1981 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1982 SSVAL(req->outbuf,smb_vwv1,fattr);
1983 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1984 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1986 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1988 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1989 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1991 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1992 SCVAL(req->outbuf,smb_flg,
1993 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1996 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1997 SCVAL(req->outbuf,smb_flg,
1998 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2001 END_PROFILE(SMBopen);
2005 /****************************************************************************
2006 Reply to an open and X.
2007 ****************************************************************************/
2009 void reply_open_and_X(struct smb_request *req)
2011 connection_struct *conn = req->conn;
2012 struct smb_filename *smb_fname = NULL;
2017 /* Breakout the oplock request bits so we can set the
2018 reply bits separately. */
2019 int ex_oplock_request;
2020 int core_oplock_request;
2023 int smb_sattr = SVAL(req->vwv+4, 0);
2024 uint32 smb_time = make_unix_date3(req->vwv+6);
2032 uint64_t allocation_size;
2033 ssize_t retval = -1;
2036 uint32 create_disposition;
2037 uint32 create_options = 0;
2038 uint32_t private_flags = 0;
2039 TALLOC_CTX *ctx = talloc_tos();
2041 START_PROFILE(SMBopenX);
2043 if (req->wct < 15) {
2044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2048 open_flags = SVAL(req->vwv+2, 0);
2049 deny_mode = SVAL(req->vwv+3, 0);
2050 smb_attr = SVAL(req->vwv+5, 0);
2051 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2052 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2053 oplock_request = ex_oplock_request | core_oplock_request;
2054 smb_ofun = SVAL(req->vwv+8, 0);
2055 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2057 /* If it's an IPC, pass off the pipe handler. */
2059 if (lp_nt_pipe_support()) {
2060 reply_open_pipe_and_X(conn, req);
2062 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2067 /* XXXX we need to handle passed times, sattr and flags */
2068 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2069 STR_TERMINATE, &status);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 reply_nterror(req, status);
2075 if (!map_open_params_to_ntcreate(fname, deny_mode,
2077 &access_mask, &share_mode,
2078 &create_disposition,
2081 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2085 status = filename_convert(ctx,
2087 req->flags2 & FLAGS2_DFS_PATHNAMES,
2089 UCF_PREP_CREATEFILE,
2092 if (!NT_STATUS_IS_OK(status)) {
2093 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2094 reply_botherror(req,
2095 NT_STATUS_PATH_NOT_COVERED,
2096 ERRSRV, ERRbadpath);
2099 reply_nterror(req, status);
2103 status = SMB_VFS_CREATE_FILE(
2106 0, /* root_dir_fid */
2107 smb_fname, /* fname */
2108 access_mask, /* access_mask */
2109 share_mode, /* share_access */
2110 create_disposition, /* create_disposition*/
2111 create_options, /* create_options */
2112 smb_attr, /* file_attributes */
2113 oplock_request, /* oplock_request */
2114 0, /* allocation_size */
2119 &smb_action); /* pinfo */
2121 if (!NT_STATUS_IS_OK(status)) {
2122 if (open_was_deferred(req->sconn, req->mid)) {
2123 /* We have re-scheduled this call. */
2126 reply_openerror(req, status);
2130 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2131 if the file is truncated or created. */
2132 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2133 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2134 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2135 close_file(req, fsp, ERROR_CLOSE);
2136 reply_nterror(req, NT_STATUS_DISK_FULL);
2139 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2141 close_file(req, fsp, ERROR_CLOSE);
2142 reply_nterror(req, NT_STATUS_DISK_FULL);
2145 status = vfs_stat_fsp(fsp);
2146 if (!NT_STATUS_IS_OK(status)) {
2147 close_file(req, fsp, ERROR_CLOSE);
2148 reply_nterror(req, status);
2153 fattr = dos_mode(conn, fsp->fsp_name);
2154 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2155 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2156 close_file(req, fsp, ERROR_CLOSE);
2157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2161 /* If the caller set the extended oplock request bit
2162 and we granted one (by whatever means) - set the
2163 correct bit for extended oplock reply.
2166 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2167 smb_action |= EXTENDED_OPLOCK_GRANTED;
2170 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2171 smb_action |= EXTENDED_OPLOCK_GRANTED;
2174 /* If the caller set the core oplock request bit
2175 and we granted one (by whatever means) - set the
2176 correct bit for core oplock reply.
2179 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2180 reply_outbuf(req, 19, 0);
2182 reply_outbuf(req, 15, 0);
2185 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2186 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2188 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2189 SCVAL(req->outbuf, smb_flg,
2190 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2193 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2194 SCVAL(req->outbuf, smb_flg,
2195 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2198 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2199 SSVAL(req->outbuf,smb_vwv3,fattr);
2200 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2201 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2203 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2205 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2206 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2207 SSVAL(req->outbuf,smb_vwv11,smb_action);
2209 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2210 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2214 TALLOC_FREE(smb_fname);
2215 END_PROFILE(SMBopenX);
2219 /****************************************************************************
2220 Reply to a SMBulogoffX.
2221 ****************************************************************************/
2223 void reply_ulogoffX(struct smb_request *req)
2225 struct smbd_server_connection *sconn = req->sconn;
2226 struct user_struct *vuser;
2227 struct smbXsrv_session *session = NULL;
2230 START_PROFILE(SMBulogoffX);
2232 vuser = get_valid_user_struct(sconn, req->vuid);
2235 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2236 (unsigned long long)req->vuid));
2238 req->vuid = UID_FIELD_INVALID;
2239 reply_force_doserror(req, ERRSRV, ERRbaduid);
2240 END_PROFILE(SMBulogoffX);
2244 session = vuser->session;
2248 * TODO: cancel all outstanding requests on the session
2250 status = smbXsrv_session_logoff(session);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 DEBUG(0, ("reply_ulogoff: "
2253 "smbXsrv_session_logoff() failed: %s\n",
2254 nt_errstr(status)));
2256 * If we hit this case, there is something completely
2257 * wrong, so we better disconnect the transport connection.
2259 END_PROFILE(SMBulogoffX);
2260 exit_server(__location__ ": smbXsrv_session_logoff failed");
2264 TALLOC_FREE(session);
2266 reply_outbuf(req, 2, 0);
2267 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2268 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2270 DEBUG(3, ("ulogoffX vuid=%llu\n",
2271 (unsigned long long)req->vuid));
2273 END_PROFILE(SMBulogoffX);
2274 req->vuid = UID_FIELD_INVALID;
2277 /****************************************************************************
2278 Reply to a mknew or a create.
2279 ****************************************************************************/
2281 void reply_mknew(struct smb_request *req)
2283 connection_struct *conn = req->conn;
2284 struct smb_filename *smb_fname = NULL;
2287 struct smb_file_time ft;
2289 int oplock_request = 0;
2291 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2292 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2293 uint32 create_disposition;
2294 uint32 create_options = 0;
2295 TALLOC_CTX *ctx = talloc_tos();
2297 START_PROFILE(SMBcreate);
2301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2305 fattr = SVAL(req->vwv+0, 0);
2306 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2309 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2311 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2312 STR_TERMINATE, &status);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 reply_nterror(req, status);
2318 status = filename_convert(ctx,
2320 req->flags2 & FLAGS2_DFS_PATHNAMES,
2322 UCF_PREP_CREATEFILE,
2325 if (!NT_STATUS_IS_OK(status)) {
2326 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2327 reply_botherror(req,
2328 NT_STATUS_PATH_NOT_COVERED,
2329 ERRSRV, ERRbadpath);
2332 reply_nterror(req, status);
2336 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2337 DEBUG(0,("Attempt to create file (%s) with volid set - "
2338 "please report this\n",
2339 smb_fname_str_dbg(smb_fname)));
2342 if(req->cmd == SMBmknew) {
2343 /* We should fail if file exists. */
2344 create_disposition = FILE_CREATE;
2346 /* Create if file doesn't exist, truncate if it does. */
2347 create_disposition = FILE_OVERWRITE_IF;
2350 status = SMB_VFS_CREATE_FILE(
2353 0, /* root_dir_fid */
2354 smb_fname, /* fname */
2355 access_mask, /* access_mask */
2356 share_mode, /* share_access */
2357 create_disposition, /* create_disposition*/
2358 create_options, /* create_options */
2359 fattr, /* file_attributes */
2360 oplock_request, /* oplock_request */
2361 0, /* allocation_size */
2362 0, /* private_flags */
2368 if (!NT_STATUS_IS_OK(status)) {
2369 if (open_was_deferred(req->sconn, req->mid)) {
2370 /* We have re-scheduled this call. */
2373 reply_openerror(req, status);
2377 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2378 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 END_PROFILE(SMBcreate);
2384 reply_outbuf(req, 1, 0);
2385 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2387 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2388 SCVAL(req->outbuf,smb_flg,
2389 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2392 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2393 SCVAL(req->outbuf,smb_flg,
2394 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2397 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2398 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2399 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2400 (unsigned int)fattr));
2403 TALLOC_FREE(smb_fname);
2404 END_PROFILE(SMBcreate);
2408 /****************************************************************************
2409 Reply to a create temporary file.
2410 ****************************************************************************/
2412 void reply_ctemp(struct smb_request *req)
2414 connection_struct *conn = req->conn;
2415 struct smb_filename *smb_fname = NULL;
2416 char *wire_name = NULL;
2424 TALLOC_CTX *ctx = talloc_tos();
2426 START_PROFILE(SMBctemp);
2429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2433 fattr = SVAL(req->vwv+0, 0);
2434 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2436 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2437 STR_TERMINATE, &status);
2438 if (!NT_STATUS_IS_OK(status)) {
2439 reply_nterror(req, status);
2443 for (i = 0; i < 10; i++) {
2445 fname = talloc_asprintf(ctx,
2448 generate_random_str_list(ctx, 5, "0123456789"));
2450 fname = talloc_asprintf(ctx,
2452 generate_random_str_list(ctx, 5, "0123456789"));
2456 reply_nterror(req, NT_STATUS_NO_MEMORY);
2460 status = filename_convert(ctx, conn,
2461 req->flags2 & FLAGS2_DFS_PATHNAMES,
2463 UCF_PREP_CREATEFILE,
2466 if (!NT_STATUS_IS_OK(status)) {
2467 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2468 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2469 ERRSRV, ERRbadpath);
2472 reply_nterror(req, status);
2476 /* Create the file. */
2477 status = SMB_VFS_CREATE_FILE(
2480 0, /* root_dir_fid */
2481 smb_fname, /* fname */
2482 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2483 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2484 FILE_CREATE, /* create_disposition*/
2485 0, /* create_options */
2486 fattr, /* file_attributes */
2487 oplock_request, /* oplock_request */
2488 0, /* allocation_size */
2489 0, /* private_flags */
2495 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2497 TALLOC_FREE(smb_fname);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 if (open_was_deferred(req->sconn, req->mid)) {
2503 /* We have re-scheduled this call. */
2506 reply_openerror(req, status);
2514 /* Collision after 10 times... */
2515 reply_nterror(req, status);
2519 reply_outbuf(req, 1, 0);
2520 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2522 /* the returned filename is relative to the directory */
2523 s = strrchr_m(fsp->fsp_name->base_name, '/');
2525 s = fsp->fsp_name->base_name;
2531 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2532 thing in the byte section. JRA */
2533 SSVALS(p, 0, -1); /* what is this? not in spec */
2535 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2537 reply_nterror(req, NT_STATUS_NO_MEMORY);
2541 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2542 SCVAL(req->outbuf, smb_flg,
2543 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2546 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2547 SCVAL(req->outbuf, smb_flg,
2548 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2551 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2552 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2553 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2555 TALLOC_FREE(smb_fname);
2556 TALLOC_FREE(wire_name);
2557 END_PROFILE(SMBctemp);
2561 /*******************************************************************
2562 Check if a user is allowed to rename a file.
2563 ********************************************************************/
2565 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2568 if (!CAN_WRITE(conn)) {
2569 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2572 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2573 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2574 /* Only bother to read the DOS attribute if we might deny the
2575 rename on the grounds of attribute missmatch. */
2576 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2577 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2578 return NT_STATUS_NO_SUCH_FILE;
2582 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2583 if (fsp->posix_open) {
2584 return NT_STATUS_OK;
2587 /* If no pathnames are open below this
2588 directory, allow the rename. */
2590 if (file_find_subpath(fsp)) {
2591 return NT_STATUS_ACCESS_DENIED;
2593 return NT_STATUS_OK;
2596 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2597 return NT_STATUS_OK;
2600 return NT_STATUS_ACCESS_DENIED;
2603 /*******************************************************************
2604 * unlink a file with all relevant access checks
2605 *******************************************************************/
2607 static NTSTATUS do_unlink(connection_struct *conn,
2608 struct smb_request *req,
2609 struct smb_filename *smb_fname,
2614 uint32 dirtype_orig = dirtype;
2617 bool posix_paths = lp_posix_pathnames();
2619 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2620 smb_fname_str_dbg(smb_fname),
2623 if (!CAN_WRITE(conn)) {
2624 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2628 ret = SMB_VFS_LSTAT(conn, smb_fname);
2630 ret = SMB_VFS_STAT(conn, smb_fname);
2633 return map_nt_error_from_unix(errno);
2636 fattr = dos_mode(conn, smb_fname);
2638 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2639 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2642 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2644 return NT_STATUS_NO_SUCH_FILE;
2647 if (!dir_check_ftype(fattr, dirtype)) {
2648 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2649 return NT_STATUS_FILE_IS_A_DIRECTORY;
2651 return NT_STATUS_NO_SUCH_FILE;
2654 if (dirtype_orig & 0x8000) {
2655 /* These will never be set for POSIX. */
2656 return NT_STATUS_NO_SUCH_FILE;
2660 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2661 return NT_STATUS_FILE_IS_A_DIRECTORY;
2664 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2665 return NT_STATUS_NO_SUCH_FILE;
2668 if (dirtype & 0xFF00) {
2669 /* These will never be set for POSIX. */
2670 return NT_STATUS_NO_SUCH_FILE;
2675 return NT_STATUS_NO_SUCH_FILE;
2678 /* Can't delete a directory. */
2679 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2680 return NT_STATUS_FILE_IS_A_DIRECTORY;
2685 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2686 return NT_STATUS_OBJECT_NAME_INVALID;
2687 #endif /* JRATEST */
2689 /* On open checks the open itself will check the share mode, so
2690 don't do it here as we'll get it wrong. */
2692 status = SMB_VFS_CREATE_FILE
2695 0, /* root_dir_fid */
2696 smb_fname, /* fname */
2697 DELETE_ACCESS, /* access_mask */
2698 FILE_SHARE_NONE, /* share_access */
2699 FILE_OPEN, /* create_disposition*/
2700 FILE_NON_DIRECTORY_FILE, /* create_options */
2701 /* file_attributes */
2702 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2703 FILE_ATTRIBUTE_NORMAL,
2704 0, /* oplock_request */
2705 0, /* allocation_size */
2706 0, /* private_flags */
2712 if (!NT_STATUS_IS_OK(status)) {
2713 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2714 nt_errstr(status)));
2718 status = can_set_delete_on_close(fsp, fattr);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2722 smb_fname_str_dbg(smb_fname),
2723 nt_errstr(status)));
2724 close_file(req, fsp, NORMAL_CLOSE);
2728 /* The set is across all open files on this dev/inode pair. */
2729 if (!set_delete_on_close(fsp, True,
2730 conn->session_info->security_token,
2731 conn->session_info->unix_token)) {
2732 close_file(req, fsp, NORMAL_CLOSE);
2733 return NT_STATUS_ACCESS_DENIED;
2736 return close_file(req, fsp, NORMAL_CLOSE);
2739 /****************************************************************************
2740 The guts of the unlink command, split out so it may be called by the NT SMB
2742 ****************************************************************************/
2744 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2745 uint32 dirtype, struct smb_filename *smb_fname,
2748 char *fname_dir = NULL;
2749 char *fname_mask = NULL;
2751 NTSTATUS status = NT_STATUS_OK;
2752 TALLOC_CTX *ctx = talloc_tos();
2754 /* Split up the directory from the filename/mask. */
2755 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2756 &fname_dir, &fname_mask);
2757 if (!NT_STATUS_IS_OK(status)) {
2762 * We should only check the mangled cache
2763 * here if unix_convert failed. This means
2764 * that the path in 'mask' doesn't exist
2765 * on the file system and so we need to look
2766 * for a possible mangle. This patch from
2767 * Tine Smukavec <valentin.smukavec@hermes.si>.
2770 if (!VALID_STAT(smb_fname->st) &&
2771 mangle_is_mangled(fname_mask, conn->params)) {
2772 char *new_mask = NULL;
2773 mangle_lookup_name_from_8_3(ctx, fname_mask,
2774 &new_mask, conn->params);
2776 TALLOC_FREE(fname_mask);
2777 fname_mask = new_mask;
2784 * Only one file needs to be unlinked. Append the mask back
2785 * onto the directory.
2787 TALLOC_FREE(smb_fname->base_name);
2788 if (ISDOT(fname_dir)) {
2789 /* Ensure we use canonical names on open. */
2790 smb_fname->base_name = talloc_asprintf(smb_fname,
2794 smb_fname->base_name = talloc_asprintf(smb_fname,
2799 if (!smb_fname->base_name) {
2800 status = NT_STATUS_NO_MEMORY;
2804 dirtype = FILE_ATTRIBUTE_NORMAL;
2807 status = check_name(conn, smb_fname->base_name);
2808 if (!NT_STATUS_IS_OK(status)) {
2812 status = do_unlink(conn, req, smb_fname, dirtype);
2813 if (!NT_STATUS_IS_OK(status)) {
2819 struct smb_Dir *dir_hnd = NULL;
2821 const char *dname = NULL;
2822 char *talloced = NULL;
2824 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2825 status = NT_STATUS_OBJECT_NAME_INVALID;
2829 if (strequal(fname_mask,"????????.???")) {
2830 TALLOC_FREE(fname_mask);
2831 fname_mask = talloc_strdup(ctx, "*");
2833 status = NT_STATUS_NO_MEMORY;
2838 status = check_name(conn, fname_dir);
2839 if (!NT_STATUS_IS_OK(status)) {
2843 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2845 if (dir_hnd == NULL) {
2846 status = map_nt_error_from_unix(errno);
2850 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2851 the pattern matches against the long name, otherwise the short name
2852 We don't implement this yet XXXX
2855 status = NT_STATUS_NO_SUCH_FILE;
2857 while ((dname = ReadDirName(dir_hnd, &offset,
2858 &smb_fname->st, &talloced))) {
2859 TALLOC_CTX *frame = talloc_stackframe();
2861 if (!is_visible_file(conn, fname_dir, dname,
2862 &smb_fname->st, true)) {
2864 TALLOC_FREE(talloced);
2868 /* Quick check for "." and ".." */
2869 if (ISDOT(dname) || ISDOTDOT(dname)) {
2871 TALLOC_FREE(talloced);
2875 if(!mask_match(dname, fname_mask,
2876 conn->case_sensitive)) {
2878 TALLOC_FREE(talloced);
2882 TALLOC_FREE(smb_fname->base_name);
2883 if (ISDOT(fname_dir)) {
2884 /* Ensure we use canonical names on open. */
2885 smb_fname->base_name =
2886 talloc_asprintf(smb_fname, "%s",
2889 smb_fname->base_name =
2890 talloc_asprintf(smb_fname, "%s/%s",
2894 if (!smb_fname->base_name) {
2895 TALLOC_FREE(dir_hnd);
2896 status = NT_STATUS_NO_MEMORY;
2898 TALLOC_FREE(talloced);
2902 status = check_name(conn, smb_fname->base_name);
2903 if (!NT_STATUS_IS_OK(status)) {
2904 TALLOC_FREE(dir_hnd);
2906 TALLOC_FREE(talloced);
2910 status = do_unlink(conn, req, smb_fname, dirtype);
2911 if (!NT_STATUS_IS_OK(status)) {
2912 TALLOC_FREE(dir_hnd);
2914 TALLOC_FREE(talloced);
2919 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2920 smb_fname->base_name));
2923 TALLOC_FREE(talloced);
2925 TALLOC_FREE(dir_hnd);
2928 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2929 status = map_nt_error_from_unix(errno);
2933 TALLOC_FREE(fname_dir);
2934 TALLOC_FREE(fname_mask);
2938 /****************************************************************************
2940 ****************************************************************************/
2942 void reply_unlink(struct smb_request *req)
2944 connection_struct *conn = req->conn;
2946 struct smb_filename *smb_fname = NULL;
2949 bool path_contains_wcard = False;
2950 TALLOC_CTX *ctx = talloc_tos();
2952 START_PROFILE(SMBunlink);
2955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2959 dirtype = SVAL(req->vwv+0, 0);
2961 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2962 STR_TERMINATE, &status,
2963 &path_contains_wcard);
2964 if (!NT_STATUS_IS_OK(status)) {
2965 reply_nterror(req, status);
2969 status = filename_convert(ctx, conn,
2970 req->flags2 & FLAGS2_DFS_PATHNAMES,
2972 UCF_COND_ALLOW_WCARD_LCOMP,
2973 &path_contains_wcard,
2975 if (!NT_STATUS_IS_OK(status)) {
2976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2977 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2978 ERRSRV, ERRbadpath);
2981 reply_nterror(req, status);
2985 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2987 status = unlink_internals(conn, req, dirtype, smb_fname,
2988 path_contains_wcard);
2989 if (!NT_STATUS_IS_OK(status)) {
2990 if (open_was_deferred(req->sconn, req->mid)) {
2991 /* We have re-scheduled this call. */
2994 reply_nterror(req, status);
2998 reply_outbuf(req, 0, 0);
3000 TALLOC_FREE(smb_fname);
3001 END_PROFILE(SMBunlink);
3005 /****************************************************************************
3007 ****************************************************************************/
3009 static void fail_readraw(void)
3011 const char *errstr = talloc_asprintf(talloc_tos(),
3012 "FAIL ! reply_readbraw: socket write fail (%s)",
3017 exit_server_cleanly(errstr);
3020 /****************************************************************************
3021 Fake (read/write) sendfile. Returns -1 on read or write fail.
3022 ****************************************************************************/
3024 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
3026 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3028 size_t tosend = nread;
3035 bufsize = MIN(nread, 65536);
3037 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3041 while (tosend > 0) {
3045 if (tosend > bufsize) {
3050 ret = read_file(fsp,buf,startpos,cur_read);
3056 /* If we had a short read, fill with zeros. */
3057 if (ret < cur_read) {
3058 memset(buf + ret, '\0', cur_read - ret);
3061 ret = write_data(xconn->sconn->sock, buf, cur_read);
3062 if (ret != cur_read) {
3063 int saved_errno = errno;
3065 * Try and give an error message saying what
3068 DEBUG(0, ("write_data failed for client %s. "
3070 smbXsrv_connection_dbg(xconn),
3071 strerror(saved_errno)));
3073 errno = saved_errno;
3077 startpos += cur_read;
3081 return (ssize_t)nread;
3084 /****************************************************************************
3085 Deal with the case of sendfile reading less bytes from the file than
3086 requested. Fill with zeros (all we can do).
3087 ****************************************************************************/
3089 void sendfile_short_send(files_struct *fsp,
3094 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3096 #define SHORT_SEND_BUFSIZE 1024
3097 if (nread < headersize) {
3098 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3099 "header for file %s (%s). Terminating\n",
3100 fsp_str_dbg(fsp), strerror(errno)));
3101 exit_server_cleanly("sendfile_short_send failed");
3104 nread -= headersize;
3106 if (nread < smb_maxcnt) {
3107 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3109 exit_server_cleanly("sendfile_short_send: "
3113 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3114 "with zeros !\n", fsp_str_dbg(fsp)));
3116 while (nread < smb_maxcnt) {
3118 * We asked for the real file size and told sendfile
3119 * to not go beyond the end of the file. But it can
3120 * happen that in between our fstat call and the
3121 * sendfile call the file was truncated. This is very
3122 * bad because we have already announced the larger
3123 * number of bytes to the client.
3125 * The best we can do now is to send 0-bytes, just as
3126 * a read from a hole in a sparse file would do.
3128 * This should happen rarely enough that I don't care
3129 * about efficiency here :-)
3134 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3135 ret = write_data(xconn->sconn->sock, buf, to_write);
3136 if (ret != to_write) {
3137 int saved_errno = errno;
3139 * Try and give an error message saying what
3142 DEBUG(0, ("write_data failed for client %s. "
3144 smbXsrv_connection_dbg(xconn),
3145 strerror(saved_errno)));
3146 errno = saved_errno;
3147 exit_server_cleanly("sendfile_short_send: "
3148 "write_data failed");
3156 /****************************************************************************
3157 Return a readbraw error (4 bytes of zero).
3158 ****************************************************************************/
3160 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3162 struct smbXsrv_connection *xconn = sconn->conn;
3167 smbd_lock_socket(sconn);
3168 if (write_data(sconn->sock,header,4) != 4) {
3169 int saved_errno = errno;
3171 * Try and give an error message saying what
3174 DEBUG(0, ("write_data failed for client %s. "
3176 smbXsrv_connection_dbg(xconn),
3177 strerror(saved_errno)));
3178 errno = saved_errno;
3182 smbd_unlock_socket(sconn);
3185 /****************************************************************************
3186 Use sendfile in readbraw.
3187 ****************************************************************************/
3189 static void send_file_readbraw(connection_struct *conn,
3190 struct smb_request *req,
3196 struct smbd_server_connection *sconn = req->sconn;
3197 struct smbXsrv_connection *xconn = sconn->conn;
3198 char *outbuf = NULL;
3202 * We can only use sendfile on a non-chained packet
3203 * but we can use on a non-oplocked file. tridge proved this
3204 * on a train in Germany :-). JRA.
3205 * reply_readbraw has already checked the length.
3208 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3209 (fsp->wcp == NULL) &&
3210 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3211 ssize_t sendfile_read = -1;
3213 DATA_BLOB header_blob;
3215 _smb_setlen(header,nread);
3216 header_blob = data_blob_const(header, 4);
3218 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3219 &header_blob, startpos,
3221 if (sendfile_read == -1) {
3222 /* Returning ENOSYS means no data at all was sent.
3223 * Do this as a normal read. */
3224 if (errno == ENOSYS) {
3225 goto normal_readbraw;
3229 * Special hack for broken Linux with no working sendfile. If we
3230 * return EINTR we sent the header but not the rest of the data.
3231 * Fake this up by doing read/write calls.
3233 if (errno == EINTR) {
3234 /* Ensure we don't do this again. */
3235 set_use_sendfile(SNUM(conn), False);
3236 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3238 if (fake_sendfile(fsp, startpos, nread) == -1) {
3239 DEBUG(0,("send_file_readbraw: "
3240 "fake_sendfile failed for "
3244 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3249 DEBUG(0,("send_file_readbraw: sendfile failed for "
3250 "file %s (%s). Terminating\n",
3251 fsp_str_dbg(fsp), strerror(errno)));
3252 exit_server_cleanly("send_file_readbraw sendfile failed");
3253 } else if (sendfile_read == 0) {
3255 * Some sendfile implementations return 0 to indicate
3256 * that there was a short read, but nothing was
3257 * actually written to the socket. In this case,
3258 * fallback to the normal read path so the header gets
3259 * the correct byte count.
3261 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3262 "bytes falling back to the normal read: "
3263 "%s\n", fsp_str_dbg(fsp)));
3264 goto normal_readbraw;
3267 /* Deal with possible short send. */
3268 if (sendfile_read != 4+nread) {
3269 sendfile_short_send(fsp, sendfile_read, 4, nread);
3276 outbuf = talloc_array(NULL, char, nread+4);
3278 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3279 (unsigned)(nread+4)));
3280 reply_readbraw_error(sconn);
3285 ret = read_file(fsp,outbuf+4,startpos,nread);
3286 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3295 _smb_setlen(outbuf,ret);
3296 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3297 int saved_errno = errno;
3299 * Try and give an error message saying what
3302 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3303 smbXsrv_connection_dbg(xconn),
3304 strerror(saved_errno)));
3305 errno = saved_errno;
3310 TALLOC_FREE(outbuf);
3313 /****************************************************************************
3314 Reply to a readbraw (core+ protocol).
3315 ****************************************************************************/
3317 void reply_readbraw(struct smb_request *req)
3319 connection_struct *conn = req->conn;
3320 struct smbd_server_connection *sconn = req->sconn;
3321 ssize_t maxcount,mincount;
3325 struct lock_struct lock;
3328 START_PROFILE(SMBreadbraw);
3330 if (srv_is_signing_active(sconn) || req->encrypted) {
3331 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3332 "raw reads/writes are disallowed.");
3336 reply_readbraw_error(sconn);
3337 END_PROFILE(SMBreadbraw);
3341 if (sconn->smb1.echo_handler.trusted_fde) {
3342 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3343 "'async smb echo handler = yes'\n"));
3344 reply_readbraw_error(sconn);
3345 END_PROFILE(SMBreadbraw);
3350 * Special check if an oplock break has been issued
3351 * and the readraw request croses on the wire, we must
3352 * return a zero length response here.
3355 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3358 * We have to do a check_fsp by hand here, as
3359 * we must always return 4 zero bytes on error,
3363 if (!fsp || !conn || conn != fsp->conn ||
3364 req->vuid != fsp->vuid ||
3365 fsp->is_directory || fsp->fh->fd == -1) {
3367 * fsp could be NULL here so use the value from the packet. JRA.
3369 DEBUG(3,("reply_readbraw: fnum %d not valid "
3371 (int)SVAL(req->vwv+0, 0)));
3372 reply_readbraw_error(sconn);
3373 END_PROFILE(SMBreadbraw);
3377 /* Do a "by hand" version of CHECK_READ. */
3378 if (!(fsp->can_read ||
3379 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3380 (fsp->access_mask & FILE_EXECUTE)))) {
3381 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3382 (int)SVAL(req->vwv+0, 0)));
3383 reply_readbraw_error(sconn);
3384 END_PROFILE(SMBreadbraw);
3388 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3390 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3391 if(req->wct == 10) {
3393 * This is a large offset (64 bit) read.
3396 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3399 DEBUG(0,("reply_readbraw: negative 64 bit "
3400 "readraw offset (%.0f) !\n",
3401 (double)startpos ));
3402 reply_readbraw_error(sconn);
3403 END_PROFILE(SMBreadbraw);
3408 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3409 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3411 /* ensure we don't overrun the packet size */
3412 maxcount = MIN(65535,maxcount);
3414 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3415 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3418 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3419 reply_readbraw_error(sconn);
3420 END_PROFILE(SMBreadbraw);
3424 if (fsp_stat(fsp) == 0) {
3425 size = fsp->fsp_name->st.st_ex_size;
3428 if (startpos >= size) {
3431 nread = MIN(maxcount,(size - startpos));
3434 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3435 if (nread < mincount)
3439 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3440 "min=%lu nread=%lu\n",
3441 fsp_fnum_dbg(fsp), (double)startpos,
3442 (unsigned long)maxcount,
3443 (unsigned long)mincount,
3444 (unsigned long)nread ) );
3446 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3448 DEBUG(5,("reply_readbraw finished\n"));
3450 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3452 END_PROFILE(SMBreadbraw);
3457 #define DBGC_CLASS DBGC_LOCKING
3459 /****************************************************************************
3460 Reply to a lockread (core+ protocol).
3461 ****************************************************************************/
3463 void reply_lockread(struct smb_request *req)
3465 connection_struct *conn = req->conn;
3473 struct byte_range_lock *br_lck = NULL;
3475 struct smbd_server_connection *sconn = req->sconn;
3477 START_PROFILE(SMBlockread);
3480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3481 END_PROFILE(SMBlockread);
3485 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3487 if (!check_fsp(conn, req, fsp)) {
3488 END_PROFILE(SMBlockread);
3492 if (!CHECK_READ(fsp,req)) {
3493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3494 END_PROFILE(SMBlockread);
3498 numtoread = SVAL(req->vwv+1, 0);
3499 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3502 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3503 * protocol request that predates the read/write lock concept.
3504 * Thus instead of asking for a read lock here we need to ask
3505 * for a write lock. JRA.
3506 * Note that the requested lock size is unaffected by max_send.
3509 br_lck = do_lock(req->sconn->msg_ctx,
3511 (uint64_t)req->smbpid,
3512 (uint64_t)numtoread,
3516 False, /* Non-blocking lock. */
3519 TALLOC_FREE(br_lck);
3521 if (NT_STATUS_V(status)) {
3522 reply_nterror(req, status);
3523 END_PROFILE(SMBlockread);
3528 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3530 maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3532 if (numtoread > maxtoread) {
3533 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3534 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3535 (unsigned int)numtoread, (unsigned int)maxtoread,
3536 (unsigned int)sconn->smb1.sessions.max_send));
3537 numtoread = maxtoread;
3540 reply_outbuf(req, 5, numtoread + 3);
3542 data = smb_buf(req->outbuf) + 3;
3544 nread = read_file(fsp,data,startpos,numtoread);
3547 reply_nterror(req, map_nt_error_from_unix(errno));
3548 END_PROFILE(SMBlockread);
3552 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3554 SSVAL(req->outbuf,smb_vwv0,nread);
3555 SSVAL(req->outbuf,smb_vwv5,nread+3);
3556 p = smb_buf(req->outbuf);
3557 SCVAL(p,0,0); /* pad byte. */
3560 DEBUG(3,("lockread %s num=%d nread=%d\n",
3561 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3563 END_PROFILE(SMBlockread);
3568 #define DBGC_CLASS DBGC_ALL
3570 /****************************************************************************
3572 ****************************************************************************/
3574 void reply_read(struct smb_request *req)
3576 connection_struct *conn = req->conn;
3583 struct lock_struct lock;
3584 struct smbd_server_connection *sconn = req->sconn;
3586 START_PROFILE(SMBread);
3589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3590 END_PROFILE(SMBread);
3594 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3596 if (!check_fsp(conn, req, fsp)) {
3597 END_PROFILE(SMBread);
3601 if (!CHECK_READ(fsp,req)) {
3602 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3603 END_PROFILE(SMBread);
3607 numtoread = SVAL(req->vwv+1, 0);
3608 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3611 * The requested read size cannot be greater than max_send. JRA.
3613 maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3615 if (numtoread > maxtoread) {
3616 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3617 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3618 (unsigned int)numtoread, (unsigned int)maxtoread,
3619 (unsigned int)sconn->smb1.sessions.max_send));
3620 numtoread = maxtoread;
3623 reply_outbuf(req, 5, numtoread+3);
3625 data = smb_buf(req->outbuf) + 3;
3627 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3628 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3631 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3632 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3633 END_PROFILE(SMBread);
3638 nread = read_file(fsp,data,startpos,numtoread);
3641 reply_nterror(req, map_nt_error_from_unix(errno));
3645 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3647 SSVAL(req->outbuf,smb_vwv0,nread);
3648 SSVAL(req->outbuf,smb_vwv5,nread+3);
3649 SCVAL(smb_buf(req->outbuf),0,1);
3650 SSVAL(smb_buf(req->outbuf),1,nread);
3652 DEBUG(3, ("read %s num=%d nread=%d\n",
3653 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3656 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3658 END_PROFILE(SMBread);
3662 /****************************************************************************
3664 ****************************************************************************/
3666 static int setup_readX_header(struct smb_request *req, char *outbuf,
3671 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3673 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3675 SCVAL(outbuf,smb_vwv0,0xFF);
3676 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3677 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3678 SSVAL(outbuf,smb_vwv6,
3679 (smb_wct - 4) /* offset from smb header to wct */
3680 + 1 /* the wct field */
3681 + 12 * sizeof(uint16_t) /* vwv */
3682 + 2); /* the buflen field */
3683 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3684 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3685 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3686 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3690 /****************************************************************************
3691 Reply to a read and X - possibly using sendfile.
3692 ****************************************************************************/
3694 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3695 files_struct *fsp, off_t startpos,
3698 struct smbXsrv_connection *xconn = req->sconn->conn;
3700 struct lock_struct lock;
3701 int saved_errno = 0;
3703 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3704 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3707 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3708 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3713 * We can only use sendfile on a non-chained packet
3714 * but we can use on a non-oplocked file. tridge proved this
3715 * on a train in Germany :-). JRA.
3718 if (!req_is_in_chain(req) &&
3720 (fsp->base_fsp == NULL) &&
3721 (fsp->wcp == NULL) &&
3722 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3723 uint8 headerbuf[smb_size + 12 * 2];
3726 if(fsp_stat(fsp) == -1) {
3727 reply_nterror(req, map_nt_error_from_unix(errno));
3731 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3732 (startpos > fsp->fsp_name->st.st_ex_size) ||
3733 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3735 * We already know that we would do a short read, so don't
3736 * try the sendfile() path.
3738 goto nosendfile_read;
3742 * Set up the packet header before send. We
3743 * assume here the sendfile will work (get the
3744 * correct amount of data).
3747 header = data_blob_const(headerbuf, sizeof(headerbuf));
3749 construct_reply_common_req(req, (char *)headerbuf);
3750 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3752 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3753 startpos, smb_maxcnt);
3755 saved_errno = errno;
3757 /* Returning ENOSYS means no data at all was sent.
3758 Do this as a normal read. */
3759 if (errno == ENOSYS) {
3764 * Special hack for broken Linux with no working sendfile. If we
3765 * return EINTR we sent the header but not the rest of the data.
3766 * Fake this up by doing read/write calls.
3769 if (errno == EINTR) {
3770 /* Ensure we don't do this again. */
3771 set_use_sendfile(SNUM(conn), False);
3772 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3773 nread = fake_sendfile(fsp, startpos,
3776 saved_errno = errno;
3777 DEBUG(0,("send_file_readX: "
3778 "fake_sendfile failed for "
3779 "file %s (%s) for client %s. "
3782 smbXsrv_connection_dbg(xconn),
3783 strerror(saved_errno)));
3784 errno = saved_errno;
3785 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3787 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3788 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3789 /* No outbuf here means successful sendfile. */
3793 DEBUG(0,("send_file_readX: sendfile failed for file "
3794 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3796 exit_server_cleanly("send_file_readX sendfile failed");
3797 } else if (nread == 0) {
3799 * Some sendfile implementations return 0 to indicate
3800 * that there was a short read, but nothing was
3801 * actually written to the socket. In this case,
3802 * fallback to the normal read path so the header gets
3803 * the correct byte count.
3805 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3806 "falling back to the normal read: %s\n",
3811 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3812 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3814 /* Deal with possible short send. */
3815 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3816 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3818 /* No outbuf here means successful sendfile. */
3819 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3820 SMB_PERFCOUNT_END(&req->pcd);
3826 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3827 uint8 headerbuf[smb_size + 2*12];
3830 construct_reply_common_req(req, (char *)headerbuf);
3831 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3833 /* Send out the header. */
3834 ret = write_data(req->sconn->sock, (char *)headerbuf,
3836 if (ret != sizeof(headerbuf)) {
3837 saved_errno = errno;
3839 * Try and give an error message saying what
3842 DEBUG(0,("send_file_readX: write_data failed for file "
3843 "%s (%s) for client %s. Terminating\n",
3845 smbXsrv_connection_dbg(xconn),
3846 strerror(saved_errno)));
3847 errno = saved_errno;
3848 exit_server_cleanly("send_file_readX sendfile failed");
3850 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3852 saved_errno = errno;
3853 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3854 "%s (%s) for client %s. Terminating\n",
3856 smbXsrv_connection_dbg(xconn),
3857 strerror(saved_errno)));
3858 errno = saved_errno;
3859 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3866 reply_outbuf(req, 12, smb_maxcnt);
3867 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3868 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3870 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3871 saved_errno = errno;
3873 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3876 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3880 setup_readX_header(req, (char *)req->outbuf, nread);
3882 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3883 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3887 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3888 TALLOC_FREE(req->outbuf);
3892 /****************************************************************************
3893 Work out how much space we have for a read return.
3894 ****************************************************************************/
3896 static size_t calc_max_read_pdu(const struct smb_request *req)
3898 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3899 return req->sconn->smb1.sessions.max_send;
3902 if (!lp_large_readwrite()) {
3903 return req->sconn->smb1.sessions.max_send;
3906 if (req_is_in_chain(req)) {
3907 return req->sconn->smb1.sessions.max_send;
3910 if (req->encrypted) {
3912 * Don't take encrypted traffic up to the
3913 * limit. There are padding considerations
3914 * that make that tricky.
3916 return req->sconn->smb1.sessions.max_send;
3919 if (srv_is_signing_active(req->sconn)) {
3923 if (!lp_unix_extensions()) {
3928 * We can do ultra-large POSIX reads.
3933 /****************************************************************************
3934 Calculate how big a read can be. Copes with all clients. It's always
3935 safe to return a short read - Windows does this.
3936 ****************************************************************************/
3938 static size_t calc_read_size(const struct smb_request *req,
3942 size_t max_pdu = calc_max_read_pdu(req);
3943 size_t total_size = 0;
3944 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3945 size_t max_len = max_pdu - hdr_len;
3948 * Windows explicitly ignores upper size of 0xFFFF.
3949 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3950 * We must do the same as these will never fit even in
3951 * an extended size NetBIOS packet.
3953 if (upper_size == 0xFFFF) {
3957 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3961 total_size = ((upper_size<<16) | lower_size);
3964 * LARGE_READX test shows it's always safe to return
3965 * a short read. Windows does so.
3967 return MIN(total_size, max_len);
3970 /****************************************************************************
3971 Reply to a read and X.
3972 ****************************************************************************/
3974 void reply_read_and_X(struct smb_request *req)
3976 connection_struct *conn = req->conn;
3981 bool big_readX = False;
3983 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3986 START_PROFILE(SMBreadX);
3988 if ((req->wct != 10) && (req->wct != 12)) {
3989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3993 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3994 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3995 smb_maxcnt = SVAL(req->vwv+5, 0);
3997 /* If it's an IPC, pass off the pipe handler. */
3999 reply_pipe_read_and_X(req);
4000 END_PROFILE(SMBreadX);
4004 if (!check_fsp(conn, req, fsp)) {
4005 END_PROFILE(SMBreadX);
4009 if (!CHECK_READ(fsp,req)) {
4010 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4011 END_PROFILE(SMBreadX);
4015 upper_size = SVAL(req->vwv+7, 0);
4016 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4017 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4019 * This is a heuristic to avoid keeping large
4020 * outgoing buffers around over long-lived aio
4026 if (req->wct == 12) {
4028 * This is a large offset (64 bit) read.
4030 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4035 NTSTATUS status = schedule_aio_read_and_X(conn,
4040 if (NT_STATUS_IS_OK(status)) {
4041 /* Read scheduled - we're done. */
4044 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4045 /* Real error - report to client. */
4046 END_PROFILE(SMBreadX);
4047 reply_nterror(req, status);
4050 /* NT_STATUS_RETRY - fall back to sync read. */
4053 smbd_lock_socket(req->sconn);
4054 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4055 smbd_unlock_socket(req->sconn);
4058 END_PROFILE(SMBreadX);
4062 /****************************************************************************
4063 Error replies to writebraw must have smb_wct == 1. Fix this up.
4064 ****************************************************************************/
4066 void error_to_writebrawerr(struct smb_request *req)
4068 uint8 *old_outbuf = req->outbuf;
4070 reply_outbuf(req, 1, 0);
4072 memcpy(req->outbuf, old_outbuf, smb_size);
4073 TALLOC_FREE(old_outbuf);
4076 /****************************************************************************
4077 Read 4 bytes of a smb packet and return the smb length of the packet.
4078 Store the result in the buffer. This version of the function will
4079 never return a session keepalive (length of zero).
4080 Timeout is in milliseconds.
4081 ****************************************************************************/
4083 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4086 uint8_t msgtype = NBSSkeepalive;
4088 while (msgtype == NBSSkeepalive) {
4091 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4093 if (!NT_STATUS_IS_OK(status)) {
4094 char addr[INET6_ADDRSTRLEN];
4095 /* Try and give an error message
4096 * saying what client failed. */
4097 DEBUG(0, ("read_fd_with_timeout failed for "
4098 "client %s read error = %s.\n",
4099 get_peer_addr(fd,addr,sizeof(addr)),
4100 nt_errstr(status)));
4104 msgtype = CVAL(inbuf, 0);
4107 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4108 (unsigned long)len));
4110 return NT_STATUS_OK;
4113 /****************************************************************************
4114 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4115 ****************************************************************************/
4117 void reply_writebraw(struct smb_request *req)
4119 connection_struct *conn = req->conn;
4120 struct smbXsrv_connection *xconn = req->sconn->conn;
4123 ssize_t total_written=0;
4124 size_t numtowrite=0;
4127 const char *data=NULL;
4130 struct lock_struct lock;
4133 START_PROFILE(SMBwritebraw);
4136 * If we ever reply with an error, it must have the SMB command
4137 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4140 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4142 if (srv_is_signing_active(req->sconn)) {
4143 END_PROFILE(SMBwritebraw);
4144 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4145 "raw reads/writes are disallowed.");
4148 if (req->wct < 12) {
4149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4150 error_to_writebrawerr(req);
4151 END_PROFILE(SMBwritebraw);
4155 if (req->sconn->smb1.echo_handler.trusted_fde) {
4156 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4157 "'async smb echo handler = yes'\n"));
4158 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4159 error_to_writebrawerr(req);
4160 END_PROFILE(SMBwritebraw);
4164 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4165 if (!check_fsp(conn, req, fsp)) {
4166 error_to_writebrawerr(req);
4167 END_PROFILE(SMBwritebraw);
4171 if (!CHECK_WRITE(fsp)) {
4172 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4173 error_to_writebrawerr(req);
4174 END_PROFILE(SMBwritebraw);
4178 tcount = IVAL(req->vwv+1, 0);
4179 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4180 write_through = BITSETW(req->vwv+7,0);
4182 /* We have to deal with slightly different formats depending
4183 on whether we are using the core+ or lanman1.0 protocol */
4185 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4186 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4187 data = smb_buf_const(req->inbuf);
4189 numtowrite = SVAL(req->vwv+10, 0);
4190 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4193 /* Ensure we don't write bytes past the end of this packet. */
4194 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4196 error_to_writebrawerr(req);
4197 END_PROFILE(SMBwritebraw);
4201 if (!fsp->print_file) {
4202 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4203 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4206 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4207 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4208 error_to_writebrawerr(req);
4209 END_PROFILE(SMBwritebraw);
4215 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4218 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4219 "wrote=%d sync=%d\n",
4220 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4221 (int)nwritten, (int)write_through));
4223 if (nwritten < (ssize_t)numtowrite) {
4224 reply_nterror(req, NT_STATUS_DISK_FULL);
4225 error_to_writebrawerr(req);
4229 total_written = nwritten;
4231 /* Allocate a buffer of 64k + length. */
4232 buf = talloc_array(NULL, char, 65540);
4234 reply_nterror(req, NT_STATUS_NO_MEMORY);
4235 error_to_writebrawerr(req);
4239 /* Return a SMBwritebraw message to the redirector to tell
4240 * it to send more bytes */
4242 memcpy(buf, req->inbuf, smb_size);
4243 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4244 SCVAL(buf,smb_com,SMBwritebraw);
4245 SSVALS(buf,smb_vwv0,0xFFFF);
4247 if (!srv_send_smb(req->sconn,
4249 false, 0, /* no signing */
4250 IS_CONN_ENCRYPTED(conn),
4252 exit_server_cleanly("reply_writebraw: srv_send_smb "
4256 /* Now read the raw data into the buffer and write it */
4257 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4259 if (!NT_STATUS_IS_OK(status)) {
4260 exit_server_cleanly("secondary writebraw failed");
4263 /* Set up outbuf to return the correct size */
4264 reply_outbuf(req, 1, 0);
4266 if (numtowrite != 0) {
4268 if (numtowrite > 0xFFFF) {
4269 DEBUG(0,("reply_writebraw: Oversize secondary write "
4270 "raw requested (%u). Terminating\n",
4271 (unsigned int)numtowrite ));
4272 exit_server_cleanly("secondary writebraw failed");
4275 if (tcount > nwritten+numtowrite) {
4276 DEBUG(3,("reply_writebraw: Client overestimated the "
4278 (int)tcount,(int)nwritten,(int)numtowrite));
4281 status = read_data(req->sconn->sock, buf+4, numtowrite);
4283 if (!NT_STATUS_IS_OK(status)) {
4284 /* Try and give an error message
4285 * saying what client failed. */
4286 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4287 "raw read failed (%s) for client %s. "
4288 "Terminating\n", nt_errstr(status),
4289 smbXsrv_connection_dbg(xconn)));
4290 exit_server_cleanly("secondary writebraw failed");
4293 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4294 if (nwritten == -1) {
4296 reply_nterror(req, map_nt_error_from_unix(errno));
4297 error_to_writebrawerr(req);
4301 if (nwritten < (ssize_t)numtowrite) {
4302 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4303 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4307 total_written += nwritten;
4312 SSVAL(req->outbuf,smb_vwv0,total_written);
4314 status = sync_file(conn, fsp, write_through);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4317 fsp_str_dbg(fsp), nt_errstr(status)));
4318 reply_nterror(req, status);
4319 error_to_writebrawerr(req);
4323 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4325 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4326 (int)total_written));
4328 if (!fsp->print_file) {
4329 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4332 /* We won't return a status if write through is not selected - this
4333 * follows what WfWg does */
4334 END_PROFILE(SMBwritebraw);
4336 if (!write_through && total_written==tcount) {
4338 #if RABBIT_PELLET_FIX
4340 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4341 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4344 if (!send_keepalive(req->sconn->sock)) {
4345 exit_server_cleanly("reply_writebraw: send of "
4346 "keepalive failed");
4349 TALLOC_FREE(req->outbuf);
4354 if (!fsp->print_file) {
4355 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4358 END_PROFILE(SMBwritebraw);
4363 #define DBGC_CLASS DBGC_LOCKING
4365 /****************************************************************************
4366 Reply to a writeunlock (core+).
4367 ****************************************************************************/
4369 void reply_writeunlock(struct smb_request *req)
4371 connection_struct *conn = req->conn;
4372 ssize_t nwritten = -1;
4376 NTSTATUS status = NT_STATUS_OK;
4378 struct lock_struct lock;
4379 int saved_errno = 0;
4381 START_PROFILE(SMBwriteunlock);
4384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4385 END_PROFILE(SMBwriteunlock);
4389 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4391 if (!check_fsp(conn, req, fsp)) {
4392 END_PROFILE(SMBwriteunlock);
4396 if (!CHECK_WRITE(fsp)) {
4397 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4398 END_PROFILE(SMBwriteunlock);
4402 numtowrite = SVAL(req->vwv+1, 0);
4403 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4404 data = (const char *)req->buf + 3;
4406 if (!fsp->print_file && numtowrite > 0) {
4407 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4408 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4411 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4412 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4413 END_PROFILE(SMBwriteunlock);
4418 /* The special X/Open SMB protocol handling of
4419 zero length writes is *NOT* done for
4421 if(numtowrite == 0) {
4424 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4425 saved_errno = errno;
4428 status = sync_file(conn, fsp, False /* write through */);
4429 if (!NT_STATUS_IS_OK(status)) {
4430 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4431 fsp_str_dbg(fsp), nt_errstr(status)));
4432 reply_nterror(req, status);
4437 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4441 if((nwritten < numtowrite) && (numtowrite != 0)) {
4442 reply_nterror(req, NT_STATUS_DISK_FULL);
4446 if (numtowrite && !fsp->print_file) {
4447 status = do_unlock(req->sconn->msg_ctx,
4449 (uint64_t)req->smbpid,
4450 (uint64_t)numtowrite,
4454 if (NT_STATUS_V(status)) {
4455 reply_nterror(req, status);
4460 reply_outbuf(req, 1, 0);
4462 SSVAL(req->outbuf,smb_vwv0,nwritten);
4464 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4465 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4468 if (numtowrite && !fsp->print_file) {
4469 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4472 END_PROFILE(SMBwriteunlock);
4477 #define DBGC_CLASS DBGC_ALL
4479 /****************************************************************************
4481 ****************************************************************************/
4483 void reply_write(struct smb_request *req)
4485 connection_struct *conn = req->conn;
4487 ssize_t nwritten = -1;
4491 struct lock_struct lock;
4493 int saved_errno = 0;
4495 START_PROFILE(SMBwrite);
4498 END_PROFILE(SMBwrite);
4499 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4503 /* If it's an IPC, pass off the pipe handler. */
4505 reply_pipe_write(req);
4506 END_PROFILE(SMBwrite);
4510 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4512 if (!check_fsp(conn, req, fsp)) {
4513 END_PROFILE(SMBwrite);
4517 if (!CHECK_WRITE(fsp)) {
4518 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4519 END_PROFILE(SMBwrite);
4523 numtowrite = SVAL(req->vwv+1, 0);
4524 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4525 data = (const char *)req->buf + 3;
4527 if (!fsp->print_file) {
4528 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4529 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4532 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4533 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4534 END_PROFILE(SMBwrite);
4540 * X/Open SMB protocol says that if smb_vwv1 is
4541 * zero then the file size should be extended or
4542 * truncated to the size given in smb_vwv[2-3].
4545 if(numtowrite == 0) {
4547 * This is actually an allocate call, and set EOF. JRA.
4549 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4551 reply_nterror(req, NT_STATUS_DISK_FULL);
4554 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4556 reply_nterror(req, NT_STATUS_DISK_FULL);
4559 trigger_write_time_update_immediate(fsp);
4561 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4564 status = sync_file(conn, fsp, False);
4565 if (!NT_STATUS_IS_OK(status)) {
4566 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4567 fsp_str_dbg(fsp), nt_errstr(status)));
4568 reply_nterror(req, status);
4573 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4577 if((nwritten == 0) && (numtowrite != 0)) {
4578 reply_nterror(req, NT_STATUS_DISK_FULL);
4582 reply_outbuf(req, 1, 0);
4584 SSVAL(req->outbuf,smb_vwv0,nwritten);
4586 if (nwritten < (ssize_t)numtowrite) {
4587 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4588 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4591 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4594 if (!fsp->print_file) {
4595 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4598 END_PROFILE(SMBwrite);
4602 /****************************************************************************
4603 Ensure a buffer is a valid writeX for recvfile purposes.
4604 ****************************************************************************/
4606 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4607 (2*14) + /* word count (including bcc) */ \
4610 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4611 const uint8_t *inbuf)
4614 unsigned int doff = 0;
4615 size_t len = smb_len_large(inbuf);
4617 struct smbXsrv_open *op = NULL;
4618 struct files_struct *fsp = NULL;
4621 if (is_encrypted_packet(sconn, inbuf)) {
4622 /* Can't do this on encrypted
4627 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4631 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4632 CVAL(inbuf,smb_wct) != 14) {
4633 DEBUG(10,("is_valid_writeX_buffer: chained or "
4634 "invalid word length.\n"));
4638 fnum = SVAL(inbuf, smb_vwv2);
4639 status = smb1srv_open_lookup(sconn->conn,
4643 if (!NT_STATUS_IS_OK(status)) {
4644 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4649 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4652 if (fsp->conn == NULL) {
4653 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4657 if (IS_IPC(fsp->conn)) {
4658 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4661 if (IS_PRINT(fsp->conn)) {
4662 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4665 doff = SVAL(inbuf,smb_vwv11);
4667 numtowrite = SVAL(inbuf,smb_vwv10);
4669 if (len > doff && len - doff > 0xFFFF) {
4670 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4673 if (numtowrite == 0) {
4674 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4678 /* Ensure the sizes match up. */
4679 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4680 /* no pad byte...old smbclient :-( */
4681 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4683 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4687 if (len - doff != numtowrite) {
4688 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4689 "len = %u, doff = %u, numtowrite = %u\n",
4692 (unsigned int)numtowrite ));
4696 DEBUG(10,("is_valid_writeX_buffer: true "
4697 "len = %u, doff = %u, numtowrite = %u\n",
4700 (unsigned int)numtowrite ));
4705 /****************************************************************************
4706 Reply to a write and X.
4707 ****************************************************************************/
4709 void reply_write_and_X(struct smb_request *req)
4711 connection_struct *conn = req->conn;
4713 struct lock_struct lock;
4718 unsigned int smb_doff;
4719 unsigned int smblen;
4722 int saved_errno = 0;
4724 START_PROFILE(SMBwriteX);
4726 if ((req->wct != 12) && (req->wct != 14)) {
4727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4731 numtowrite = SVAL(req->vwv+10, 0);
4732 smb_doff = SVAL(req->vwv+11, 0);
4733 smblen = smb_len(req->inbuf);
4735 if (req->unread_bytes > 0xFFFF ||
4736 (smblen > smb_doff &&
4737 smblen - smb_doff > 0xFFFF)) {
4738 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4741 if (req->unread_bytes) {
4742 /* Can't do a recvfile write on IPC$ */
4744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4747 if (numtowrite != req->unread_bytes) {
4748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4752 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4753 smb_doff + numtowrite > smblen) {
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4759 /* If it's an IPC, pass off the pipe handler. */
4761 if (req->unread_bytes) {
4762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4765 reply_pipe_write_and_X(req);
4769 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4770 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4771 write_through = BITSETW(req->vwv+7,0);
4773 if (!check_fsp(conn, req, fsp)) {
4777 if (!CHECK_WRITE(fsp)) {
4778 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4782 data = smb_base(req->inbuf) + smb_doff;
4784 if(req->wct == 14) {
4786 * This is a large offset (64 bit) write.
4788 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4792 /* X/Open SMB protocol says that, unlike SMBwrite
4793 if the length is zero then NO truncation is
4794 done, just a write of zero. To truncate a file,
4797 if(numtowrite == 0) {
4800 if (req->unread_bytes == 0) {
4801 status = schedule_aio_write_and_X(conn,
4808 if (NT_STATUS_IS_OK(status)) {
4809 /* write scheduled - we're done. */
4812 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4813 /* Real error - report to client. */
4814 reply_nterror(req, status);
4817 /* NT_STATUS_RETRY - fall through to sync write. */
4820 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4821 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4824 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4825 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4829 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4830 saved_errno = errno;
4832 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4836 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4840 if((nwritten == 0) && (numtowrite != 0)) {
4841 reply_nterror(req, NT_STATUS_DISK_FULL);
4845 reply_outbuf(req, 6, 0);
4846 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4847 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4848 SSVAL(req->outbuf,smb_vwv2,nwritten);
4849 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4851 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4852 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4854 status = sync_file(conn, fsp, write_through);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4857 fsp_str_dbg(fsp), nt_errstr(status)));
4858 reply_nterror(req, status);
4862 END_PROFILE(SMBwriteX);
4866 if (req->unread_bytes) {
4867 /* writeX failed. drain socket. */
4868 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4869 req->unread_bytes) {
4870 smb_panic("failed to drain pending bytes");
4872 req->unread_bytes = 0;
4875 END_PROFILE(SMBwriteX);
4879 /****************************************************************************
4881 ****************************************************************************/
4883 void reply_lseek(struct smb_request *req)
4885 connection_struct *conn = req->conn;
4891 START_PROFILE(SMBlseek);
4894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4895 END_PROFILE(SMBlseek);
4899 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4901 if (!check_fsp(conn, req, fsp)) {
4905 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4907 mode = SVAL(req->vwv+1, 0) & 3;
4908 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4909 startpos = (off_t)IVALS(req->vwv+2, 0);
4918 res = fsp->fh->pos + startpos;
4929 if (umode == SEEK_END) {
4930 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4931 if(errno == EINVAL) {
4932 off_t current_pos = startpos;
4934 if(fsp_stat(fsp) == -1) {
4936 map_nt_error_from_unix(errno));
4937 END_PROFILE(SMBlseek);
4941 current_pos += fsp->fsp_name->st.st_ex_size;
4943 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4948 reply_nterror(req, map_nt_error_from_unix(errno));
4949 END_PROFILE(SMBlseek);
4956 reply_outbuf(req, 2, 0);
4957 SIVAL(req->outbuf,smb_vwv0,res);
4959 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4960 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4962 END_PROFILE(SMBlseek);
4966 /****************************************************************************
4968 ****************************************************************************/
4970 void reply_flush(struct smb_request *req)
4972 connection_struct *conn = req->conn;
4976 START_PROFILE(SMBflush);
4979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 fnum = SVAL(req->vwv+0, 0);
4984 fsp = file_fsp(req, fnum);
4986 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4991 file_sync_all(conn);
4993 NTSTATUS status = sync_file(conn, fsp, True);
4994 if (!NT_STATUS_IS_OK(status)) {
4995 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4996 fsp_str_dbg(fsp), nt_errstr(status)));
4997 reply_nterror(req, status);
4998 END_PROFILE(SMBflush);
5003 reply_outbuf(req, 0, 0);
5005 DEBUG(3,("flush\n"));
5006 END_PROFILE(SMBflush);
5010 /****************************************************************************
5012 conn POINTER CAN BE NULL HERE !
5013 ****************************************************************************/
5015 void reply_exit(struct smb_request *req)
5017 START_PROFILE(SMBexit);
5019 file_close_pid(req->sconn, req->smbpid, req->vuid);
5021 reply_outbuf(req, 0, 0);
5023 DEBUG(3,("exit\n"));
5025 END_PROFILE(SMBexit);
5029 struct reply_close_state {
5031 struct smb_request *smbreq;
5034 static void do_smb1_close(struct tevent_req *req);
5036 void reply_close(struct smb_request *req)
5038 connection_struct *conn = req->conn;
5039 NTSTATUS status = NT_STATUS_OK;
5040 files_struct *fsp = NULL;
5041 START_PROFILE(SMBclose);
5044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5045 END_PROFILE(SMBclose);
5049 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5052 * We can only use check_fsp if we know it's not a directory.
5055 if (!check_fsp_open(conn, req, fsp)) {
5056 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5057 END_PROFILE(SMBclose);
5061 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5062 fsp->is_directory ? "directory" : "file",
5063 fsp->fh->fd, fsp_fnum_dbg(fsp),
5064 conn->num_files_open));
5066 if (!fsp->is_directory) {
5070 * Take care of any time sent in the close.
5073 t = srv_make_unix_date3(req->vwv+1);
5074 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5077 if (fsp->num_aio_requests != 0) {
5079 struct reply_close_state *state;
5081 DEBUG(10, ("closing with aio %u requests pending\n",
5082 fsp->num_aio_requests));
5085 * We depend on the aio_extra destructor to take care of this
5086 * close request once fsp->num_aio_request drops to 0.
5089 fsp->deferred_close = tevent_wait_send(
5090 fsp, fsp->conn->sconn->ev_ctx);
5091 if (fsp->deferred_close == NULL) {
5092 status = NT_STATUS_NO_MEMORY;
5096 state = talloc(fsp, struct reply_close_state);
5097 if (state == NULL) {
5098 TALLOC_FREE(fsp->deferred_close);
5099 status = NT_STATUS_NO_MEMORY;
5103 state->smbreq = talloc_move(fsp, &req);
5104 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5106 END_PROFILE(SMBclose);
5111 * close_file() returns the unix errno if an error was detected on
5112 * close - normally this is due to a disk full error. If not then it
5113 * was probably an I/O error.
5116 status = close_file(req, fsp, NORMAL_CLOSE);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 reply_nterror(req, status);
5120 END_PROFILE(SMBclose);
5124 reply_outbuf(req, 0, 0);
5125 END_PROFILE(SMBclose);
5129 static void do_smb1_close(struct tevent_req *req)
5131 struct reply_close_state *state = tevent_req_callback_data(
5132 req, struct reply_close_state);
5133 struct smb_request *smbreq;
5137 ret = tevent_wait_recv(req);
5140 DEBUG(10, ("tevent_wait_recv returned %s\n",
5143 * Continue anyway, this should never happen
5148 * fsp->smb2_close_request right now is a talloc grandchild of
5149 * fsp. When we close_file(fsp), it would go with it. No chance to
5152 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5154 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5155 if (NT_STATUS_IS_OK(status)) {
5156 reply_outbuf(smbreq, 0, 0);
5158 reply_nterror(smbreq, status);
5160 if (!srv_send_smb(smbreq->sconn,
5161 (char *)smbreq->outbuf,
5164 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5166 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5169 TALLOC_FREE(smbreq);
5172 /****************************************************************************
5173 Reply to a writeclose (Core+ protocol).
5174 ****************************************************************************/
5176 void reply_writeclose(struct smb_request *req)
5178 connection_struct *conn = req->conn;
5180 ssize_t nwritten = -1;
5181 NTSTATUS close_status = NT_STATUS_OK;
5184 struct timespec mtime;
5186 struct lock_struct lock;
5188 START_PROFILE(SMBwriteclose);
5191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5192 END_PROFILE(SMBwriteclose);
5196 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5198 if (!check_fsp(conn, req, fsp)) {
5199 END_PROFILE(SMBwriteclose);
5202 if (!CHECK_WRITE(fsp)) {
5203 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5204 END_PROFILE(SMBwriteclose);
5208 numtowrite = SVAL(req->vwv+1, 0);
5209 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5210 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5211 data = (const char *)req->buf + 1;
5213 if (fsp->print_file == NULL) {
5214 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5215 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5218 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5219 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5220 END_PROFILE(SMBwriteclose);
5225 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5227 if (fsp->print_file == NULL) {
5228 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5231 set_close_write_time(fsp, mtime);
5234 * More insanity. W2K only closes the file if writelen > 0.
5238 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5239 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5240 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5243 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5244 "file %s\n", fsp_str_dbg(fsp)));
5245 close_status = close_file(req, fsp, NORMAL_CLOSE);
5249 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5250 reply_nterror(req, NT_STATUS_DISK_FULL);
5254 if(!NT_STATUS_IS_OK(close_status)) {
5255 reply_nterror(req, close_status);
5259 reply_outbuf(req, 1, 0);
5261 SSVAL(req->outbuf,smb_vwv0,nwritten);
5265 END_PROFILE(SMBwriteclose);
5270 #define DBGC_CLASS DBGC_LOCKING
5272 /****************************************************************************
5274 ****************************************************************************/
5276 void reply_lock(struct smb_request *req)
5278 connection_struct *conn = req->conn;
5279 uint64_t count,offset;
5282 struct byte_range_lock *br_lck = NULL;
5284 START_PROFILE(SMBlock);
5287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5288 END_PROFILE(SMBlock);
5292 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5294 if (!check_fsp(conn, req, fsp)) {
5295 END_PROFILE(SMBlock);
5299 count = (uint64_t)IVAL(req->vwv+1, 0);
5300 offset = (uint64_t)IVAL(req->vwv+3, 0);
5302 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5303 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5305 br_lck = do_lock(req->sconn->msg_ctx,
5307 (uint64_t)req->smbpid,
5312 False, /* Non-blocking lock. */
5316 TALLOC_FREE(br_lck);
5318 if (NT_STATUS_V(status)) {
5319 reply_nterror(req, status);
5320 END_PROFILE(SMBlock);
5324 reply_outbuf(req, 0, 0);
5326 END_PROFILE(SMBlock);
5330 /****************************************************************************
5332 ****************************************************************************/
5334 void reply_unlock(struct smb_request *req)
5336 connection_struct *conn = req->conn;
5337 uint64_t count,offset;
5341 START_PROFILE(SMBunlock);
5344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5345 END_PROFILE(SMBunlock);
5349 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5351 if (!check_fsp(conn, req, fsp)) {
5352 END_PROFILE(SMBunlock);
5356 count = (uint64_t)IVAL(req->vwv+1, 0);
5357 offset = (uint64_t)IVAL(req->vwv+3, 0);
5359 status = do_unlock(req->sconn->msg_ctx,
5361 (uint64_t)req->smbpid,
5366 if (NT_STATUS_V(status)) {
5367 reply_nterror(req, status);
5368 END_PROFILE(SMBunlock);
5372 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5373 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5375 reply_outbuf(req, 0, 0);
5377 END_PROFILE(SMBunlock);
5382 #define DBGC_CLASS DBGC_ALL
5384 /****************************************************************************
5386 conn POINTER CAN BE NULL HERE !
5387 ****************************************************************************/
5389 void reply_tdis(struct smb_request *req)
5392 connection_struct *conn = req->conn;
5393 struct smbXsrv_tcon *tcon;
5395 START_PROFILE(SMBtdis);
5398 DEBUG(4,("Invalid connection in tdis\n"));
5399 reply_force_doserror(req, ERRSRV, ERRinvnid);
5400 END_PROFILE(SMBtdis);
5408 * TODO: cancel all outstanding requests on the tcon
5410 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5411 if (!NT_STATUS_IS_OK(status)) {
5412 DEBUG(0, ("reply_tdis: "
5413 "smbXsrv_tcon_disconnect() failed: %s\n",
5414 nt_errstr(status)));
5416 * If we hit this case, there is something completely
5417 * wrong, so we better disconnect the transport connection.
5419 END_PROFILE(SMBtdis);
5420 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5426 reply_outbuf(req, 0, 0);
5427 END_PROFILE(SMBtdis);
5431 /****************************************************************************
5433 conn POINTER CAN BE NULL HERE !
5434 ****************************************************************************/
5436 void reply_echo(struct smb_request *req)
5438 connection_struct *conn = req->conn;
5439 struct smb_perfcount_data local_pcd;
5440 struct smb_perfcount_data *cur_pcd;
5444 START_PROFILE(SMBecho);
5446 smb_init_perfcount_data(&local_pcd);
5449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5450 END_PROFILE(SMBecho);
5454 smb_reverb = SVAL(req->vwv+0, 0);
5456 reply_outbuf(req, 1, req->buflen);
5458 /* copy any incoming data back out */
5459 if (req->buflen > 0) {
5460 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5463 if (smb_reverb > 100) {
5464 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5468 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5470 /* this makes sure we catch the request pcd */
5471 if (seq_num == smb_reverb) {
5472 cur_pcd = &req->pcd;
5474 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5475 cur_pcd = &local_pcd;
5478 SSVAL(req->outbuf,smb_vwv0,seq_num);
5480 show_msg((char *)req->outbuf);
5481 if (!srv_send_smb(req->sconn,
5482 (char *)req->outbuf,
5483 true, req->seqnum+1,
5484 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5486 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5489 DEBUG(3,("echo %d times\n", smb_reverb));
5491 TALLOC_FREE(req->outbuf);
5493 END_PROFILE(SMBecho);
5497 /****************************************************************************
5498 Reply to a printopen.
5499 ****************************************************************************/
5501 void reply_printopen(struct smb_request *req)
5503 connection_struct *conn = req->conn;
5507 START_PROFILE(SMBsplopen);
5510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5511 END_PROFILE(SMBsplopen);
5515 if (!CAN_PRINT(conn)) {
5516 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5517 END_PROFILE(SMBsplopen);
5521 status = file_new(req, conn, &fsp);
5522 if(!NT_STATUS_IS_OK(status)) {
5523 reply_nterror(req, status);
5524 END_PROFILE(SMBsplopen);
5528 /* Open for exclusive use, write only. */
5529 status = print_spool_open(fsp, NULL, req->vuid);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 file_free(req, fsp);
5533 reply_nterror(req, status);
5534 END_PROFILE(SMBsplopen);
5538 reply_outbuf(req, 1, 0);
5539 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5541 DEBUG(3,("openprint fd=%d %s\n",
5542 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5544 END_PROFILE(SMBsplopen);
5548 /****************************************************************************
5549 Reply to a printclose.
5550 ****************************************************************************/
5552 void reply_printclose(struct smb_request *req)
5554 connection_struct *conn = req->conn;
5558 START_PROFILE(SMBsplclose);
5561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5562 END_PROFILE(SMBsplclose);
5566 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5568 if (!check_fsp(conn, req, fsp)) {
5569 END_PROFILE(SMBsplclose);
5573 if (!CAN_PRINT(conn)) {
5574 reply_force_doserror(req, ERRSRV, ERRerror);
5575 END_PROFILE(SMBsplclose);
5579 DEBUG(3,("printclose fd=%d %s\n",
5580 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5582 status = close_file(req, fsp, NORMAL_CLOSE);
5584 if(!NT_STATUS_IS_OK(status)) {
5585 reply_nterror(req, status);
5586 END_PROFILE(SMBsplclose);
5590 reply_outbuf(req, 0, 0);
5592 END_PROFILE(SMBsplclose);
5596 /****************************************************************************
5597 Reply to a printqueue.
5598 ****************************************************************************/
5600 void reply_printqueue(struct smb_request *req)
5602 connection_struct *conn = req->conn;
5606 START_PROFILE(SMBsplretq);
5609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5610 END_PROFILE(SMBsplretq);
5614 max_count = SVAL(req->vwv+0, 0);
5615 start_index = SVAL(req->vwv+1, 0);
5617 /* we used to allow the client to get the cnum wrong, but that
5618 is really quite gross and only worked when there was only
5619 one printer - I think we should now only accept it if they
5620 get it right (tridge) */
5621 if (!CAN_PRINT(conn)) {
5622 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5623 END_PROFILE(SMBsplretq);
5627 reply_outbuf(req, 2, 3);
5628 SSVAL(req->outbuf,smb_vwv0,0);
5629 SSVAL(req->outbuf,smb_vwv1,0);
5630 SCVAL(smb_buf(req->outbuf),0,1);
5631 SSVAL(smb_buf(req->outbuf),1,0);
5633 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5634 start_index, max_count));
5637 TALLOC_CTX *mem_ctx = talloc_tos();
5640 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5641 struct rpc_pipe_client *cli = NULL;
5642 struct dcerpc_binding_handle *b = NULL;
5643 struct policy_handle handle;
5644 struct spoolss_DevmodeContainer devmode_ctr;
5645 union spoolss_JobInfo *info;
5647 uint32_t num_to_get;
5651 ZERO_STRUCT(handle);
5653 status = rpc_pipe_open_interface(conn,
5656 conn->sconn->remote_address,
5657 conn->sconn->msg_ctx,
5659 if (!NT_STATUS_IS_OK(status)) {
5660 DEBUG(0, ("reply_printqueue: "
5661 "could not connect to spoolss: %s\n",
5662 nt_errstr(status)));
5663 reply_nterror(req, status);
5666 b = cli->binding_handle;
5668 ZERO_STRUCT(devmode_ctr);
5670 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5673 SEC_FLAG_MAXIMUM_ALLOWED,
5676 if (!NT_STATUS_IS_OK(status)) {
5677 reply_nterror(req, status);
5680 if (!W_ERROR_IS_OK(werr)) {
5681 reply_nterror(req, werror_to_ntstatus(werr));
5685 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5693 if (!W_ERROR_IS_OK(werr)) {
5694 reply_nterror(req, werror_to_ntstatus(werr));
5698 if (max_count > 0) {
5699 first = start_index;
5701 first = start_index + max_count + 1;
5704 if (first >= count) {
5707 num_to_get = first + MIN(ABS(max_count), count - first);
5710 for (i = first; i < num_to_get; i++) {
5713 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5715 uint16_t qrapjobid = pjobid_to_rap(sharename,
5716 info[i].info2.job_id);
5718 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5724 srv_put_dos_date2(p, 0, qtime);
5725 SCVAL(p, 4, qstatus);
5726 SSVAL(p, 5, qrapjobid);
5727 SIVAL(p, 7, info[i].info2.size);
5729 srvstr_push(blob, req->flags2, p+12,
5730 info[i].info2.notify_name, 16, STR_ASCII);
5732 if (message_push_blob(
5735 blob, sizeof(blob))) == -1) {
5736 reply_nterror(req, NT_STATUS_NO_MEMORY);
5742 SSVAL(req->outbuf,smb_vwv0,count);
5743 SSVAL(req->outbuf,smb_vwv1,
5744 (max_count>0?first+count:first-1));
5745 SCVAL(smb_buf(req->outbuf),0,1);
5746 SSVAL(smb_buf(req->outbuf),1,28*count);
5750 DEBUG(3, ("%u entries returned in queue\n",
5754 if (b && is_valid_policy_hnd(&handle)) {
5755 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5760 END_PROFILE(SMBsplretq);
5764 /****************************************************************************
5765 Reply to a printwrite.
5766 ****************************************************************************/
5768 void reply_printwrite(struct smb_request *req)
5770 connection_struct *conn = req->conn;
5775 START_PROFILE(SMBsplwr);
5778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5779 END_PROFILE(SMBsplwr);
5783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5785 if (!check_fsp(conn, req, fsp)) {
5786 END_PROFILE(SMBsplwr);
5790 if (!fsp->print_file) {
5791 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5792 END_PROFILE(SMBsplwr);
5796 if (!CHECK_WRITE(fsp)) {
5797 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5798 END_PROFILE(SMBsplwr);
5802 numtowrite = SVAL(req->buf, 1);
5804 if (req->buflen < numtowrite + 3) {
5805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5806 END_PROFILE(SMBsplwr);
5810 data = (const char *)req->buf + 3;
5812 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5813 reply_nterror(req, map_nt_error_from_unix(errno));
5814 END_PROFILE(SMBsplwr);
5818 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5820 END_PROFILE(SMBsplwr);
5824 /****************************************************************************
5826 ****************************************************************************/
5828 void reply_mkdir(struct smb_request *req)
5830 connection_struct *conn = req->conn;
5831 struct smb_filename *smb_dname = NULL;
5832 char *directory = NULL;
5834 TALLOC_CTX *ctx = talloc_tos();
5836 START_PROFILE(SMBmkdir);
5838 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5839 STR_TERMINATE, &status);
5840 if (!NT_STATUS_IS_OK(status)) {
5841 reply_nterror(req, status);
5845 status = filename_convert(ctx, conn,
5846 req->flags2 & FLAGS2_DFS_PATHNAMES,
5848 UCF_PREP_CREATEFILE,
5851 if (!NT_STATUS_IS_OK(status)) {
5852 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5853 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5854 ERRSRV, ERRbadpath);
5857 reply_nterror(req, status);
5861 status = create_directory(conn, req, smb_dname);
5863 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5865 if (!NT_STATUS_IS_OK(status)) {
5867 if (!use_nt_status()
5868 && NT_STATUS_EQUAL(status,
5869 NT_STATUS_OBJECT_NAME_COLLISION)) {
5871 * Yes, in the DOS error code case we get a
5872 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5873 * samba4 torture test.
5875 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5878 reply_nterror(req, status);
5882 reply_outbuf(req, 0, 0);
5884 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5886 TALLOC_FREE(smb_dname);
5887 END_PROFILE(SMBmkdir);
5891 /****************************************************************************
5893 ****************************************************************************/
5895 void reply_rmdir(struct smb_request *req)
5897 connection_struct *conn = req->conn;
5898 struct smb_filename *smb_dname = NULL;
5899 char *directory = NULL;
5901 TALLOC_CTX *ctx = talloc_tos();
5902 files_struct *fsp = NULL;
5904 struct smbd_server_connection *sconn = req->sconn;
5906 START_PROFILE(SMBrmdir);
5908 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5909 STR_TERMINATE, &status);
5910 if (!NT_STATUS_IS_OK(status)) {
5911 reply_nterror(req, status);
5915 status = filename_convert(ctx, conn,
5916 req->flags2 & FLAGS2_DFS_PATHNAMES,
5921 if (!NT_STATUS_IS_OK(status)) {
5922 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5923 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5924 ERRSRV, ERRbadpath);
5927 reply_nterror(req, status);
5931 if (is_ntfs_stream_smb_fname(smb_dname)) {
5932 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5936 status = SMB_VFS_CREATE_FILE(
5939 0, /* root_dir_fid */
5940 smb_dname, /* fname */
5941 DELETE_ACCESS, /* access_mask */
5942 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5944 FILE_OPEN, /* create_disposition*/
5945 FILE_DIRECTORY_FILE, /* create_options */
5946 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5947 0, /* oplock_request */
5948 0, /* allocation_size */
5949 0, /* private_flags */
5955 if (!NT_STATUS_IS_OK(status)) {
5956 if (open_was_deferred(req->sconn, req->mid)) {
5957 /* We have re-scheduled this call. */
5960 reply_nterror(req, status);
5964 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5965 if (!NT_STATUS_IS_OK(status)) {
5966 close_file(req, fsp, ERROR_CLOSE);
5967 reply_nterror(req, status);
5971 if (!set_delete_on_close(fsp, true,
5972 conn->session_info->security_token,
5973 conn->session_info->unix_token)) {
5974 close_file(req, fsp, ERROR_CLOSE);
5975 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5979 status = close_file(req, fsp, NORMAL_CLOSE);
5980 if (!NT_STATUS_IS_OK(status)) {
5981 reply_nterror(req, status);
5983 reply_outbuf(req, 0, 0);
5986 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5988 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5990 TALLOC_FREE(smb_dname);
5991 END_PROFILE(SMBrmdir);
5995 /*******************************************************************
5996 Resolve wildcards in a filename rename.
5997 ********************************************************************/
5999 static bool resolve_wildcards(TALLOC_CTX *ctx,
6004 char *name2_copy = NULL;
6009 char *p,*p2, *pname1, *pname2;
6011 name2_copy = talloc_strdup(ctx, name2);
6016 pname1 = strrchr_m(name1,'/');
6017 pname2 = strrchr_m(name2_copy,'/');
6019 if (!pname1 || !pname2) {
6023 /* Truncate the copy of name2 at the last '/' */
6026 /* Now go past the '/' */
6030 root1 = talloc_strdup(ctx, pname1);
6031 root2 = talloc_strdup(ctx, pname2);
6033 if (!root1 || !root2) {
6037 p = strrchr_m(root1,'.');
6040 ext1 = talloc_strdup(ctx, p+1);
6042 ext1 = talloc_strdup(ctx, "");
6044 p = strrchr_m(root2,'.');
6047 ext2 = talloc_strdup(ctx, p+1);
6049 ext2 = talloc_strdup(ctx, "");
6052 if (!ext1 || !ext2) {
6060 /* Hmmm. Should this be mb-aware ? */
6063 } else if (*p2 == '*') {
6065 root2 = talloc_asprintf(ctx, "%s%s",
6084 /* Hmmm. Should this be mb-aware ? */
6087 } else if (*p2 == '*') {
6089 ext2 = talloc_asprintf(ctx, "%s%s",
6105 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6110 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6122 /****************************************************************************
6123 Ensure open files have their names updated. Updated to notify other smbd's
6125 ****************************************************************************/
6127 static void rename_open_files(connection_struct *conn,
6128 struct share_mode_lock *lck,
6130 uint32_t orig_name_hash,
6131 const struct smb_filename *smb_fname_dst)
6134 bool did_rename = False;
6136 uint32_t new_name_hash = 0;
6138 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6139 fsp = file_find_di_next(fsp)) {
6140 /* fsp_name is a relative path under the fsp. To change this for other
6141 sharepaths we need to manipulate relative paths. */
6142 /* TODO - create the absolute path and manipulate the newname
6143 relative to the sharepath. */
6144 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6147 if (fsp->name_hash != orig_name_hash) {
6150 DEBUG(10, ("rename_open_files: renaming file %s "
6151 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6152 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6153 smb_fname_str_dbg(smb_fname_dst)));
6155 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6156 if (NT_STATUS_IS_OK(status)) {
6158 new_name_hash = fsp->name_hash;
6163 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6164 "for %s\n", file_id_string_tos(&id),
6165 smb_fname_str_dbg(smb_fname_dst)));
6168 /* Send messages to all smbd's (not ourself) that the name has changed. */
6169 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6170 orig_name_hash, new_name_hash,
6175 /****************************************************************************
6176 We need to check if the source path is a parent directory of the destination
6177 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6178 refuse the rename with a sharing violation. Under UNIX the above call can
6179 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6180 probably need to check that the client is a Windows one before disallowing
6181 this as a UNIX client (one with UNIX extensions) can know the source is a
6182 symlink and make this decision intelligently. Found by an excellent bug
6183 report from <AndyLiebman@aol.com>.
6184 ****************************************************************************/
6186 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6187 const struct smb_filename *smb_fname_dst)
6189 const char *psrc = smb_fname_src->base_name;
6190 const char *pdst = smb_fname_dst->base_name;
6193 if (psrc[0] == '.' && psrc[1] == '/') {
6196 if (pdst[0] == '.' && pdst[1] == '/') {
6199 if ((slen = strlen(psrc)) > strlen(pdst)) {
6202 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6206 * Do the notify calls from a rename
6209 static void notify_rename(connection_struct *conn, bool is_dir,
6210 const struct smb_filename *smb_fname_src,
6211 const struct smb_filename *smb_fname_dst)
6213 char *parent_dir_src = NULL;
6214 char *parent_dir_dst = NULL;
6217 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6218 : FILE_NOTIFY_CHANGE_FILE_NAME;
6220 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6221 &parent_dir_src, NULL) ||
6222 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6223 &parent_dir_dst, NULL)) {
6227 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6228 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6229 smb_fname_src->base_name);
6230 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6231 smb_fname_dst->base_name);
6234 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6235 smb_fname_src->base_name);
6236 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6237 smb_fname_dst->base_name);
6240 /* this is a strange one. w2k3 gives an additional event for
6241 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6242 files, but not directories */
6244 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6245 FILE_NOTIFY_CHANGE_ATTRIBUTES
6246 |FILE_NOTIFY_CHANGE_CREATION,
6247 smb_fname_dst->base_name);
6250 TALLOC_FREE(parent_dir_src);
6251 TALLOC_FREE(parent_dir_dst);
6254 /****************************************************************************
6255 Returns an error if the parent directory for a filename is open in an
6257 ****************************************************************************/
6259 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6260 const struct smb_filename *smb_fname_dst_in)
6262 char *parent_dir = NULL;
6263 struct smb_filename smb_fname_parent;
6265 files_struct *fsp = NULL;
6268 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6269 &parent_dir, NULL)) {
6270 return NT_STATUS_NO_MEMORY;
6272 ZERO_STRUCT(smb_fname_parent);
6273 smb_fname_parent.base_name = parent_dir;
6275 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6277 return map_nt_error_from_unix(errno);
6281 * We're only checking on this smbd here, mostly good
6282 * enough.. and will pass tests.
6285 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6286 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6287 fsp = file_find_di_next(fsp)) {
6288 if (fsp->access_mask & DELETE_ACCESS) {
6289 return NT_STATUS_SHARING_VIOLATION;
6292 return NT_STATUS_OK;
6295 /****************************************************************************
6296 Rename an open file - given an fsp.
6297 ****************************************************************************/
6299 NTSTATUS rename_internals_fsp(connection_struct *conn,
6301 const struct smb_filename *smb_fname_dst_in,
6303 bool replace_if_exists)
6305 TALLOC_CTX *ctx = talloc_tos();
6306 struct smb_filename *smb_fname_dst = NULL;
6307 NTSTATUS status = NT_STATUS_OK;
6308 struct share_mode_lock *lck = NULL;
6309 bool dst_exists, old_is_stream, new_is_stream;
6311 status = check_name(conn, smb_fname_dst_in->base_name);
6312 if (!NT_STATUS_IS_OK(status)) {
6316 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6317 if (!NT_STATUS_IS_OK(status)) {
6321 /* Make a copy of the dst smb_fname structs */
6323 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6324 if (smb_fname_dst == NULL) {
6325 status = NT_STATUS_NO_MEMORY;
6330 * Check for special case with case preserving and not
6331 * case sensitive. If the old last component differs from the original
6332 * last component only by case, then we should allow
6333 * the rename (user is trying to change the case of the
6336 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6337 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6338 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6340 char *fname_dst_lcomp_base_mod = NULL;
6341 struct smb_filename *smb_fname_orig_lcomp = NULL;
6344 * Get the last component of the destination name.
6346 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6348 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6350 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6352 if (!fname_dst_lcomp_base_mod) {
6353 status = NT_STATUS_NO_MEMORY;
6358 * Create an smb_filename struct using the original last
6359 * component of the destination.
6361 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6362 ctx, smb_fname_dst->original_lcomp, NULL);
6363 if (smb_fname_orig_lcomp == NULL) {
6364 status = NT_STATUS_NO_MEMORY;
6365 TALLOC_FREE(fname_dst_lcomp_base_mod);
6369 /* If the base names only differ by case, use original. */
6370 if(!strcsequal(fname_dst_lcomp_base_mod,
6371 smb_fname_orig_lcomp->base_name)) {
6374 * Replace the modified last component with the
6378 *last_slash = '\0'; /* Truncate at the '/' */
6379 tmp = talloc_asprintf(smb_fname_dst,
6381 smb_fname_dst->base_name,
6382 smb_fname_orig_lcomp->base_name);
6384 tmp = talloc_asprintf(smb_fname_dst,
6386 smb_fname_orig_lcomp->base_name);
6389 status = NT_STATUS_NO_MEMORY;
6390 TALLOC_FREE(fname_dst_lcomp_base_mod);
6391 TALLOC_FREE(smb_fname_orig_lcomp);
6394 TALLOC_FREE(smb_fname_dst->base_name);
6395 smb_fname_dst->base_name = tmp;
6398 /* If the stream_names only differ by case, use original. */
6399 if(!strcsequal(smb_fname_dst->stream_name,
6400 smb_fname_orig_lcomp->stream_name)) {
6402 /* Use the original stream. */
6403 tmp = talloc_strdup(smb_fname_dst,
6404 smb_fname_orig_lcomp->stream_name);
6406 status = NT_STATUS_NO_MEMORY;
6407 TALLOC_FREE(fname_dst_lcomp_base_mod);
6408 TALLOC_FREE(smb_fname_orig_lcomp);
6411 TALLOC_FREE(smb_fname_dst->stream_name);
6412 smb_fname_dst->stream_name = tmp;
6414 TALLOC_FREE(fname_dst_lcomp_base_mod);
6415 TALLOC_FREE(smb_fname_orig_lcomp);
6419 * If the src and dest names are identical - including case,
6420 * don't do the rename, just return success.
6423 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6424 strcsequal(fsp->fsp_name->stream_name,
6425 smb_fname_dst->stream_name)) {
6426 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6427 "- returning success\n",
6428 smb_fname_str_dbg(smb_fname_dst)));
6429 status = NT_STATUS_OK;
6433 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6434 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6436 /* Return the correct error code if both names aren't streams. */
6437 if (!old_is_stream && new_is_stream) {
6438 status = NT_STATUS_OBJECT_NAME_INVALID;
6442 if (old_is_stream && !new_is_stream) {
6443 status = NT_STATUS_INVALID_PARAMETER;
6447 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6449 if(!replace_if_exists && dst_exists) {
6450 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6451 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6452 smb_fname_str_dbg(smb_fname_dst)));
6453 status = NT_STATUS_OBJECT_NAME_COLLISION;
6458 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6459 &smb_fname_dst->st);
6460 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6462 /* The file can be open when renaming a stream */
6463 if (dst_fsp && !new_is_stream) {
6464 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6465 status = NT_STATUS_ACCESS_DENIED;
6470 /* Ensure we have a valid stat struct for the source. */
6471 status = vfs_stat_fsp(fsp);
6472 if (!NT_STATUS_IS_OK(status)) {
6476 status = can_rename(conn, fsp, attrs);
6478 if (!NT_STATUS_IS_OK(status)) {
6479 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6480 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6481 smb_fname_str_dbg(smb_fname_dst)));
6482 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6483 status = NT_STATUS_ACCESS_DENIED;
6487 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6488 status = NT_STATUS_ACCESS_DENIED;
6491 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6494 * We have the file open ourselves, so not being able to get the
6495 * corresponding share mode lock is a fatal error.
6498 SMB_ASSERT(lck != NULL);
6500 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6501 uint32 create_options = fsp->fh->private_options;
6503 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6504 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6505 smb_fname_str_dbg(smb_fname_dst)));
6507 if (!fsp->is_directory &&
6508 !lp_posix_pathnames() &&
6509 (lp_map_archive(SNUM(conn)) ||
6510 lp_store_dos_attributes(SNUM(conn)))) {
6511 /* We must set the archive bit on the newly
6513 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6514 uint32_t old_dosmode = dos_mode(conn,
6516 file_set_dosmode(conn,
6518 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6524 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6527 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6531 * A rename acts as a new file create w.r.t. allowing an initial delete
6532 * on close, probably because in Windows there is a new handle to the
6533 * new file. If initial delete on close was requested but not
6534 * originally set, we need to set it here. This is probably not 100% correct,
6535 * but will work for the CIFSFS client which in non-posix mode
6536 * depends on these semantics. JRA.
6539 if (create_options & FILE_DELETE_ON_CLOSE) {
6540 status = can_set_delete_on_close(fsp, 0);
6542 if (NT_STATUS_IS_OK(status)) {
6543 /* Note that here we set the *inital* delete on close flag,
6544 * not the regular one. The magic gets handled in close. */
6545 fsp->initial_delete_on_close = True;
6549 status = NT_STATUS_OK;
6555 if (errno == ENOTDIR || errno == EISDIR) {
6556 status = NT_STATUS_OBJECT_NAME_COLLISION;
6558 status = map_nt_error_from_unix(errno);
6561 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6562 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6563 smb_fname_str_dbg(smb_fname_dst)));
6566 TALLOC_FREE(smb_fname_dst);
6571 /****************************************************************************
6572 The guts of the rename command, split out so it may be called by the NT SMB
6574 ****************************************************************************/
6576 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6577 connection_struct *conn,
6578 struct smb_request *req,
6579 struct smb_filename *smb_fname_src,
6580 struct smb_filename *smb_fname_dst,
6582 bool replace_if_exists,
6585 uint32_t access_mask)
6587 char *fname_src_dir = NULL;
6588 char *fname_src_mask = NULL;
6590 NTSTATUS status = NT_STATUS_OK;
6591 struct smb_Dir *dir_hnd = NULL;
6592 const char *dname = NULL;
6593 char *talloced = NULL;
6595 int create_options = 0;
6596 bool posix_pathnames = lp_posix_pathnames();
6600 * Split the old name into directory and last component
6601 * strings. Note that unix_convert may have stripped off a
6602 * leading ./ from both name and newname if the rename is
6603 * at the root of the share. We need to make sure either both
6604 * name and newname contain a / character or neither of them do
6605 * as this is checked in resolve_wildcards().
6608 /* Split up the directory from the filename/mask. */
6609 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6610 &fname_src_dir, &fname_src_mask);
6611 if (!NT_STATUS_IS_OK(status)) {
6612 status = NT_STATUS_NO_MEMORY;
6617 * We should only check the mangled cache
6618 * here if unix_convert failed. This means
6619 * that the path in 'mask' doesn't exist
6620 * on the file system and so we need to look
6621 * for a possible mangle. This patch from
6622 * Tine Smukavec <valentin.smukavec@hermes.si>.
6625 if (!VALID_STAT(smb_fname_src->st) &&
6626 mangle_is_mangled(fname_src_mask, conn->params)) {
6627 char *new_mask = NULL;
6628 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6631 TALLOC_FREE(fname_src_mask);
6632 fname_src_mask = new_mask;
6636 if (!src_has_wild) {
6640 * Only one file needs to be renamed. Append the mask back
6641 * onto the directory.
6643 TALLOC_FREE(smb_fname_src->base_name);
6644 if (ISDOT(fname_src_dir)) {
6645 /* Ensure we use canonical names on open. */
6646 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6650 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6655 if (!smb_fname_src->base_name) {
6656 status = NT_STATUS_NO_MEMORY;
6660 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6661 "case_preserve = %d, short case preserve = %d, "
6662 "directory = %s, newname = %s, "
6663 "last_component_dest = %s\n",
6664 conn->case_sensitive, conn->case_preserve,
6665 conn->short_case_preserve,
6666 smb_fname_str_dbg(smb_fname_src),
6667 smb_fname_str_dbg(smb_fname_dst),
6668 smb_fname_dst->original_lcomp));
6670 /* The dest name still may have wildcards. */
6671 if (dest_has_wild) {
6672 char *fname_dst_mod = NULL;
6673 if (!resolve_wildcards(smb_fname_dst,
6674 smb_fname_src->base_name,
6675 smb_fname_dst->base_name,
6677 DEBUG(6, ("rename_internals: resolve_wildcards "
6679 smb_fname_src->base_name,
6680 smb_fname_dst->base_name));
6681 status = NT_STATUS_NO_MEMORY;
6684 TALLOC_FREE(smb_fname_dst->base_name);
6685 smb_fname_dst->base_name = fname_dst_mod;
6688 ZERO_STRUCT(smb_fname_src->st);
6689 if (posix_pathnames) {
6690 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6692 rc = SMB_VFS_STAT(conn, smb_fname_src);
6695 status = map_nt_error_from_unix_common(errno);
6699 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6700 create_options |= FILE_DIRECTORY_FILE;
6703 status = SMB_VFS_CREATE_FILE(
6706 0, /* root_dir_fid */
6707 smb_fname_src, /* fname */
6708 access_mask, /* access_mask */
6709 (FILE_SHARE_READ | /* share_access */
6711 FILE_OPEN, /* create_disposition*/
6712 create_options, /* create_options */
6713 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6714 0, /* oplock_request */
6715 0, /* allocation_size */
6716 0, /* private_flags */
6722 if (!NT_STATUS_IS_OK(status)) {
6723 DEBUG(3, ("Could not open rename source %s: %s\n",
6724 smb_fname_str_dbg(smb_fname_src),
6725 nt_errstr(status)));
6729 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6730 attrs, replace_if_exists);
6732 close_file(req, fsp, NORMAL_CLOSE);
6734 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6735 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6736 smb_fname_str_dbg(smb_fname_dst)));
6742 * Wildcards - process each file that matches.
6744 if (strequal(fname_src_mask, "????????.???")) {
6745 TALLOC_FREE(fname_src_mask);
6746 fname_src_mask = talloc_strdup(ctx, "*");
6747 if (!fname_src_mask) {
6748 status = NT_STATUS_NO_MEMORY;
6753 status = check_name(conn, fname_src_dir);
6754 if (!NT_STATUS_IS_OK(status)) {
6758 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6760 if (dir_hnd == NULL) {
6761 status = map_nt_error_from_unix(errno);
6765 status = NT_STATUS_NO_SUCH_FILE;
6767 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6768 * - gentest fix. JRA
6771 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6773 files_struct *fsp = NULL;
6774 char *destname = NULL;
6775 bool sysdir_entry = False;
6777 /* Quick check for "." and ".." */
6778 if (ISDOT(dname) || ISDOTDOT(dname)) {
6779 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6780 sysdir_entry = True;
6782 TALLOC_FREE(talloced);
6787 if (!is_visible_file(conn, fname_src_dir, dname,
6788 &smb_fname_src->st, false)) {
6789 TALLOC_FREE(talloced);
6793 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6794 TALLOC_FREE(talloced);
6799 status = NT_STATUS_OBJECT_NAME_INVALID;
6803 TALLOC_FREE(smb_fname_src->base_name);
6804 if (ISDOT(fname_src_dir)) {
6805 /* Ensure we use canonical names on open. */
6806 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6810 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6815 if (!smb_fname_src->base_name) {
6816 status = NT_STATUS_NO_MEMORY;
6820 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6821 smb_fname_dst->base_name,
6823 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6824 smb_fname_src->base_name, destname));
6825 TALLOC_FREE(talloced);
6829 status = NT_STATUS_NO_MEMORY;
6833 TALLOC_FREE(smb_fname_dst->base_name);
6834 smb_fname_dst->base_name = destname;
6836 ZERO_STRUCT(smb_fname_src->st);
6837 if (posix_pathnames) {
6838 SMB_VFS_LSTAT(conn, smb_fname_src);
6840 SMB_VFS_STAT(conn, smb_fname_src);
6845 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6846 create_options |= FILE_DIRECTORY_FILE;
6849 status = SMB_VFS_CREATE_FILE(
6852 0, /* root_dir_fid */
6853 smb_fname_src, /* fname */
6854 access_mask, /* access_mask */
6855 (FILE_SHARE_READ | /* share_access */
6857 FILE_OPEN, /* create_disposition*/
6858 create_options, /* create_options */
6859 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6860 0, /* oplock_request */
6861 0, /* allocation_size */
6862 0, /* private_flags */
6868 if (!NT_STATUS_IS_OK(status)) {
6869 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6870 "returned %s rename %s -> %s\n",
6872 smb_fname_str_dbg(smb_fname_src),
6873 smb_fname_str_dbg(smb_fname_dst)));
6877 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6879 if (!smb_fname_dst->original_lcomp) {
6880 status = NT_STATUS_NO_MEMORY;
6884 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6885 attrs, replace_if_exists);
6887 close_file(req, fsp, NORMAL_CLOSE);
6889 if (!NT_STATUS_IS_OK(status)) {
6890 DEBUG(3, ("rename_internals_fsp returned %s for "
6891 "rename %s -> %s\n", nt_errstr(status),
6892 smb_fname_str_dbg(smb_fname_src),
6893 smb_fname_str_dbg(smb_fname_dst)));
6899 DEBUG(3,("rename_internals: doing rename on %s -> "
6900 "%s\n", smb_fname_str_dbg(smb_fname_src),
6901 smb_fname_str_dbg(smb_fname_src)));
6902 TALLOC_FREE(talloced);
6904 TALLOC_FREE(dir_hnd);
6906 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6907 status = map_nt_error_from_unix(errno);
6911 TALLOC_FREE(talloced);
6912 TALLOC_FREE(fname_src_dir);
6913 TALLOC_FREE(fname_src_mask);
6917 /****************************************************************************
6919 ****************************************************************************/
6921 void reply_mv(struct smb_request *req)
6923 connection_struct *conn = req->conn;
6925 char *newname = NULL;
6929 bool src_has_wcard = False;
6930 bool dest_has_wcard = False;
6931 TALLOC_CTX *ctx = talloc_tos();
6932 struct smb_filename *smb_fname_src = NULL;
6933 struct smb_filename *smb_fname_dst = NULL;
6934 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6935 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6936 bool stream_rename = false;
6938 START_PROFILE(SMBmv);
6941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6945 attrs = SVAL(req->vwv+0, 0);
6947 p = (const char *)req->buf + 1;
6948 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6949 &status, &src_has_wcard);
6950 if (!NT_STATUS_IS_OK(status)) {
6951 reply_nterror(req, status);
6955 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6956 &status, &dest_has_wcard);
6957 if (!NT_STATUS_IS_OK(status)) {
6958 reply_nterror(req, status);
6962 if (!lp_posix_pathnames()) {
6963 /* The newname must begin with a ':' if the
6964 name contains a ':'. */
6965 if (strchr_m(name, ':')) {
6966 if (newname[0] != ':') {
6967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6970 stream_rename = true;
6974 status = filename_convert(ctx,
6976 req->flags2 & FLAGS2_DFS_PATHNAMES,
6982 if (!NT_STATUS_IS_OK(status)) {
6983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6984 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6985 ERRSRV, ERRbadpath);
6988 reply_nterror(req, status);
6992 status = filename_convert(ctx,
6994 req->flags2 & FLAGS2_DFS_PATHNAMES,
7000 if (!NT_STATUS_IS_OK(status)) {
7001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7003 ERRSRV, ERRbadpath);
7006 reply_nterror(req, status);
7010 if (stream_rename) {
7011 /* smb_fname_dst->base_name must be the same as
7012 smb_fname_src->base_name. */
7013 TALLOC_FREE(smb_fname_dst->base_name);
7014 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7015 smb_fname_src->base_name);
7016 if (!smb_fname_dst->base_name) {
7017 reply_nterror(req, NT_STATUS_NO_MEMORY);
7022 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7023 smb_fname_str_dbg(smb_fname_dst)));
7025 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7026 attrs, False, src_has_wcard, dest_has_wcard,
7028 if (!NT_STATUS_IS_OK(status)) {
7029 if (open_was_deferred(req->sconn, req->mid)) {
7030 /* We have re-scheduled this call. */
7033 reply_nterror(req, status);
7037 reply_outbuf(req, 0, 0);
7039 TALLOC_FREE(smb_fname_src);
7040 TALLOC_FREE(smb_fname_dst);
7045 /*******************************************************************
7046 Copy a file as part of a reply_copy.
7047 ******************************************************************/
7050 * TODO: check error codes on all callers
7053 NTSTATUS copy_file(TALLOC_CTX *ctx,
7054 connection_struct *conn,
7055 struct smb_filename *smb_fname_src,
7056 struct smb_filename *smb_fname_dst,
7059 bool target_is_directory)
7061 struct smb_filename *smb_fname_dst_tmp = NULL;
7063 files_struct *fsp1,*fsp2;
7065 uint32 new_create_disposition;
7069 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7070 if (smb_fname_dst_tmp == NULL) {
7071 return NT_STATUS_NO_MEMORY;
7075 * If the target is a directory, extract the last component from the
7076 * src filename and append it to the dst filename
7078 if (target_is_directory) {
7081 /* dest/target can't be a stream if it's a directory. */
7082 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7084 p = strrchr_m(smb_fname_src->base_name,'/');
7088 p = smb_fname_src->base_name;
7090 smb_fname_dst_tmp->base_name =
7091 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7093 if (!smb_fname_dst_tmp->base_name) {
7094 status = NT_STATUS_NO_MEMORY;
7099 status = vfs_file_exist(conn, smb_fname_src);
7100 if (!NT_STATUS_IS_OK(status)) {
7104 if (!target_is_directory && count) {
7105 new_create_disposition = FILE_OPEN;
7107 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7110 &new_create_disposition,
7113 status = NT_STATUS_INVALID_PARAMETER;
7118 /* Open the src file for reading. */
7119 status = SMB_VFS_CREATE_FILE(
7122 0, /* root_dir_fid */
7123 smb_fname_src, /* fname */
7124 FILE_GENERIC_READ, /* access_mask */
7125 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7126 FILE_OPEN, /* create_disposition*/
7127 0, /* create_options */
7128 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7129 INTERNAL_OPEN_ONLY, /* oplock_request */
7130 0, /* allocation_size */
7131 0, /* private_flags */
7137 if (!NT_STATUS_IS_OK(status)) {
7141 dosattrs = dos_mode(conn, smb_fname_src);
7143 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7144 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7147 /* Open the dst file for writing. */
7148 status = SMB_VFS_CREATE_FILE(
7151 0, /* root_dir_fid */
7152 smb_fname_dst, /* fname */
7153 FILE_GENERIC_WRITE, /* access_mask */
7154 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7155 new_create_disposition, /* create_disposition*/
7156 0, /* create_options */
7157 dosattrs, /* file_attributes */
7158 INTERNAL_OPEN_ONLY, /* oplock_request */
7159 0, /* allocation_size */
7160 0, /* private_flags */
7166 if (!NT_STATUS_IS_OK(status)) {
7167 close_file(NULL, fsp1, ERROR_CLOSE);
7171 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7172 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7174 DEBUG(0, ("error - vfs lseek returned error %s\n",
7176 status = map_nt_error_from_unix(errno);
7177 close_file(NULL, fsp1, ERROR_CLOSE);
7178 close_file(NULL, fsp2, ERROR_CLOSE);
7183 /* Do the actual copy. */
7184 if (smb_fname_src->st.st_ex_size) {
7185 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7190 close_file(NULL, fsp1, NORMAL_CLOSE);
7192 /* Ensure the modtime is set correctly on the destination file. */
7193 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7196 * As we are opening fsp1 read-only we only expect
7197 * an error on close on fsp2 if we are out of space.
7198 * Thus we don't look at the error return from the
7201 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7203 if (!NT_STATUS_IS_OK(status)) {
7207 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7208 status = NT_STATUS_DISK_FULL;
7212 status = NT_STATUS_OK;
7215 TALLOC_FREE(smb_fname_dst_tmp);
7219 /****************************************************************************
7220 Reply to a file copy.
7221 ****************************************************************************/
7223 void reply_copy(struct smb_request *req)
7225 connection_struct *conn = req->conn;
7226 struct smb_filename *smb_fname_src = NULL;
7227 struct smb_filename *smb_fname_dst = NULL;
7228 char *fname_src = NULL;
7229 char *fname_dst = NULL;
7230 char *fname_src_mask = NULL;
7231 char *fname_src_dir = NULL;
7234 int error = ERRnoaccess;
7238 bool target_is_directory=False;
7239 bool source_has_wild = False;
7240 bool dest_has_wild = False;
7242 TALLOC_CTX *ctx = talloc_tos();
7244 START_PROFILE(SMBcopy);
7247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7251 tid2 = SVAL(req->vwv+0, 0);
7252 ofun = SVAL(req->vwv+1, 0);
7253 flags = SVAL(req->vwv+2, 0);
7255 p = (const char *)req->buf;
7256 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7257 &status, &source_has_wild);
7258 if (!NT_STATUS_IS_OK(status)) {
7259 reply_nterror(req, status);
7262 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7263 &status, &dest_has_wild);
7264 if (!NT_STATUS_IS_OK(status)) {
7265 reply_nterror(req, status);
7269 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7271 if (tid2 != conn->cnum) {
7272 /* can't currently handle inter share copies XXXX */
7273 DEBUG(3,("Rejecting inter-share copy\n"));
7274 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7278 status = filename_convert(ctx, conn,
7279 req->flags2 & FLAGS2_DFS_PATHNAMES,
7281 UCF_COND_ALLOW_WCARD_LCOMP,
7284 if (!NT_STATUS_IS_OK(status)) {
7285 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7286 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7287 ERRSRV, ERRbadpath);
7290 reply_nterror(req, status);
7294 status = filename_convert(ctx, conn,
7295 req->flags2 & FLAGS2_DFS_PATHNAMES,
7297 UCF_COND_ALLOW_WCARD_LCOMP,
7300 if (!NT_STATUS_IS_OK(status)) {
7301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7302 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7303 ERRSRV, ERRbadpath);
7306 reply_nterror(req, status);
7310 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7312 if ((flags&1) && target_is_directory) {
7313 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7317 if ((flags&2) && !target_is_directory) {
7318 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7322 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7323 /* wants a tree copy! XXXX */
7324 DEBUG(3,("Rejecting tree copy\n"));
7325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7329 /* Split up the directory from the filename/mask. */
7330 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7331 &fname_src_dir, &fname_src_mask);
7332 if (!NT_STATUS_IS_OK(status)) {
7333 reply_nterror(req, NT_STATUS_NO_MEMORY);
7338 * We should only check the mangled cache
7339 * here if unix_convert failed. This means
7340 * that the path in 'mask' doesn't exist
7341 * on the file system and so we need to look
7342 * for a possible mangle. This patch from
7343 * Tine Smukavec <valentin.smukavec@hermes.si>.
7345 if (!VALID_STAT(smb_fname_src->st) &&
7346 mangle_is_mangled(fname_src_mask, conn->params)) {
7347 char *new_mask = NULL;
7348 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7349 &new_mask, conn->params);
7351 /* Use demangled name if one was successfully found. */
7353 TALLOC_FREE(fname_src_mask);
7354 fname_src_mask = new_mask;
7358 if (!source_has_wild) {
7361 * Only one file needs to be copied. Append the mask back onto
7364 TALLOC_FREE(smb_fname_src->base_name);
7365 if (ISDOT(fname_src_dir)) {
7366 /* Ensure we use canonical names on open. */
7367 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7371 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7376 if (!smb_fname_src->base_name) {
7377 reply_nterror(req, NT_STATUS_NO_MEMORY);
7381 if (dest_has_wild) {
7382 char *fname_dst_mod = NULL;
7383 if (!resolve_wildcards(smb_fname_dst,
7384 smb_fname_src->base_name,
7385 smb_fname_dst->base_name,
7387 reply_nterror(req, NT_STATUS_NO_MEMORY);
7390 TALLOC_FREE(smb_fname_dst->base_name);
7391 smb_fname_dst->base_name = fname_dst_mod;
7394 status = check_name(conn, smb_fname_src->base_name);
7395 if (!NT_STATUS_IS_OK(status)) {
7396 reply_nterror(req, status);
7400 status = check_name(conn, smb_fname_dst->base_name);
7401 if (!NT_STATUS_IS_OK(status)) {
7402 reply_nterror(req, status);
7406 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7407 ofun, count, target_is_directory);
7409 if(!NT_STATUS_IS_OK(status)) {
7410 reply_nterror(req, status);
7416 struct smb_Dir *dir_hnd = NULL;
7417 const char *dname = NULL;
7418 char *talloced = NULL;
7422 * There is a wildcard that requires us to actually read the
7423 * src dir and copy each file matching the mask to the dst.
7424 * Right now streams won't be copied, but this could
7425 * presumably be added with a nested loop for reach dir entry.
7427 SMB_ASSERT(!smb_fname_src->stream_name);
7428 SMB_ASSERT(!smb_fname_dst->stream_name);
7430 smb_fname_src->stream_name = NULL;
7431 smb_fname_dst->stream_name = NULL;
7433 if (strequal(fname_src_mask,"????????.???")) {
7434 TALLOC_FREE(fname_src_mask);
7435 fname_src_mask = talloc_strdup(ctx, "*");
7436 if (!fname_src_mask) {
7437 reply_nterror(req, NT_STATUS_NO_MEMORY);
7442 status = check_name(conn, fname_src_dir);
7443 if (!NT_STATUS_IS_OK(status)) {
7444 reply_nterror(req, status);
7448 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7449 if (dir_hnd == NULL) {
7450 status = map_nt_error_from_unix(errno);
7451 reply_nterror(req, status);
7457 /* Iterate over the src dir copying each entry to the dst. */
7458 while ((dname = ReadDirName(dir_hnd, &offset,
7459 &smb_fname_src->st, &talloced))) {
7460 char *destname = NULL;
7462 if (ISDOT(dname) || ISDOTDOT(dname)) {
7463 TALLOC_FREE(talloced);
7467 if (!is_visible_file(conn, fname_src_dir, dname,
7468 &smb_fname_src->st, false)) {
7469 TALLOC_FREE(talloced);
7473 if(!mask_match(dname, fname_src_mask,
7474 conn->case_sensitive)) {
7475 TALLOC_FREE(talloced);
7479 error = ERRnoaccess;
7481 /* Get the src smb_fname struct setup. */
7482 TALLOC_FREE(smb_fname_src->base_name);
7483 if (ISDOT(fname_src_dir)) {
7484 /* Ensure we use canonical names on open. */
7485 smb_fname_src->base_name =
7486 talloc_asprintf(smb_fname_src, "%s",
7489 smb_fname_src->base_name =
7490 talloc_asprintf(smb_fname_src, "%s/%s",
7491 fname_src_dir, dname);
7494 if (!smb_fname_src->base_name) {
7495 TALLOC_FREE(dir_hnd);
7496 TALLOC_FREE(talloced);
7497 reply_nterror(req, NT_STATUS_NO_MEMORY);
7501 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7502 smb_fname_dst->base_name,
7504 TALLOC_FREE(talloced);
7508 TALLOC_FREE(dir_hnd);
7509 TALLOC_FREE(talloced);
7510 reply_nterror(req, NT_STATUS_NO_MEMORY);
7514 TALLOC_FREE(smb_fname_dst->base_name);
7515 smb_fname_dst->base_name = destname;
7517 status = check_name(conn, smb_fname_src->base_name);
7518 if (!NT_STATUS_IS_OK(status)) {
7519 TALLOC_FREE(dir_hnd);
7520 TALLOC_FREE(talloced);
7521 reply_nterror(req, status);
7525 status = check_name(conn, smb_fname_dst->base_name);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 TALLOC_FREE(dir_hnd);
7528 TALLOC_FREE(talloced);
7529 reply_nterror(req, status);
7533 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7534 smb_fname_src->base_name,
7535 smb_fname_dst->base_name));
7537 status = copy_file(ctx, conn, smb_fname_src,
7538 smb_fname_dst, ofun, count,
7539 target_is_directory);
7540 if (NT_STATUS_IS_OK(status)) {
7544 TALLOC_FREE(talloced);
7546 TALLOC_FREE(dir_hnd);
7550 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7554 reply_outbuf(req, 1, 0);
7555 SSVAL(req->outbuf,smb_vwv0,count);
7557 TALLOC_FREE(smb_fname_src);
7558 TALLOC_FREE(smb_fname_dst);
7559 TALLOC_FREE(fname_src);
7560 TALLOC_FREE(fname_dst);
7561 TALLOC_FREE(fname_src_mask);
7562 TALLOC_FREE(fname_src_dir);
7564 END_PROFILE(SMBcopy);
7569 #define DBGC_CLASS DBGC_LOCKING
7571 /****************************************************************************
7572 Get a lock pid, dealing with large count requests.
7573 ****************************************************************************/
7575 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7576 bool large_file_format)
7578 if(!large_file_format)
7579 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7581 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7584 /****************************************************************************
7585 Get a lock count, dealing with large count requests.
7586 ****************************************************************************/
7588 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7589 bool large_file_format)
7593 if(!large_file_format) {
7594 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7597 * No BVAL, this is reversed!
7599 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7600 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7606 /****************************************************************************
7607 Get a lock offset, dealing with large offset requests.
7608 ****************************************************************************/
7610 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7611 bool large_file_format)
7613 uint64_t offset = 0;
7615 if(!large_file_format) {
7616 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7619 * No BVAL, this is reversed!
7621 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7622 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7628 NTSTATUS smbd_do_locking(struct smb_request *req,
7633 struct smbd_lock_element *locks,
7636 connection_struct *conn = req->conn;
7638 NTSTATUS status = NT_STATUS_OK;
7642 /* Setup the timeout in seconds. */
7644 if (!lp_blocking_locks(SNUM(conn))) {
7648 for(i = 0; i < (int)num_locks; i++) {
7649 struct smbd_lock_element *e = &locks[i];
7651 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7652 "%llu, file %s timeout = %d\n",
7655 (unsigned long long)e->smblctx,
7659 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7660 struct blocking_lock_record *blr = NULL;
7662 if (num_locks > 1) {
7664 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7665 * if the lock vector contains one entry. When given multiple cancel
7666 * requests in a single PDU we expect the server to return an
7667 * error. Windows servers seem to accept the request but only
7668 * cancel the first lock.
7669 * JRA - Do what Windows does (tm) :-).
7673 /* MS-CIFS (2.2.4.32.1) behavior. */
7674 return NT_STATUS_DOS(ERRDOS,
7675 ERRcancelviolation);
7677 /* Windows behavior. */
7679 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7680 "cancel request\n"));
7686 if (lp_blocking_locks(SNUM(conn))) {
7688 /* Schedule a message to ourselves to
7689 remove the blocking lock record and
7690 return the right error. */
7692 blr = blocking_lock_cancel_smb1(fsp,
7698 NT_STATUS_FILE_LOCK_CONFLICT);
7700 return NT_STATUS_DOS(
7702 ERRcancelviolation);
7705 /* Remove a matching pending lock. */
7706 status = do_lock_cancel(fsp,
7712 bool blocking_lock = timeout ? true : false;
7713 bool defer_lock = false;
7714 struct byte_range_lock *br_lck;
7715 uint64_t block_smblctx;
7717 br_lck = do_lock(req->sconn->msg_ctx,
7728 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7729 /* Windows internal resolution for blocking locks seems
7730 to be about 200ms... Don't wait for less than that. JRA. */
7731 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7732 timeout = lp_lock_spin_time();
7737 /* If a lock sent with timeout of zero would fail, and
7738 * this lock has been requested multiple times,
7739 * according to brl_lock_failed() we convert this
7740 * request to a blocking lock with a timeout of between
7741 * 150 - 300 milliseconds.
7743 * If lp_lock_spin_time() has been set to 0, we skip
7744 * this blocking retry and fail immediately.
7746 * Replacement for do_lock_spin(). JRA. */
7748 if (!req->sconn->using_smb2 &&
7749 br_lck && lp_blocking_locks(SNUM(conn)) &&
7750 lp_lock_spin_time() && !blocking_lock &&
7751 NT_STATUS_EQUAL((status),
7752 NT_STATUS_FILE_LOCK_CONFLICT))
7755 timeout = lp_lock_spin_time();
7758 if (br_lck && defer_lock) {
7760 * A blocking lock was requested. Package up
7761 * this smb into a queued request and push it
7762 * onto the blocking lock queue.
7764 if(push_blocking_lock_request(br_lck,
7775 TALLOC_FREE(br_lck);
7777 return NT_STATUS_OK;
7781 TALLOC_FREE(br_lck);
7784 if (!NT_STATUS_IS_OK(status)) {
7789 /* If any of the above locks failed, then we must unlock
7790 all of the previous locks (X/Open spec). */
7792 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7794 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7795 i = -1; /* we want to skip the for loop */
7799 * Ensure we don't do a remove on the lock that just failed,
7800 * as under POSIX rules, if we have a lock already there, we
7801 * will delete it (and we shouldn't) .....
7803 for(i--; i >= 0; i--) {
7804 struct smbd_lock_element *e = &locks[i];
7806 do_unlock(req->sconn->msg_ctx,
7816 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7817 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7819 return NT_STATUS_OK;
7822 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7824 uint16_t num_ulocks,
7825 struct smbd_lock_element *ulocks)
7829 for(i = 0; i < (int)num_ulocks; i++) {
7830 struct smbd_lock_element *e = &ulocks[i];
7833 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7834 "pid %u, file %s\n", __func__,
7837 (unsigned int)e->smblctx,
7840 if (e->brltype != UNLOCK_LOCK) {
7841 /* this can only happen with SMB2 */
7842 return NT_STATUS_INVALID_PARAMETER;
7845 status = do_unlock(req->sconn->msg_ctx,
7852 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7853 nt_errstr(status)));
7855 if (!NT_STATUS_IS_OK(status)) {
7860 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7863 return NT_STATUS_OK;
7866 /****************************************************************************
7867 Reply to a lockingX request.
7868 ****************************************************************************/
7870 void reply_lockingX(struct smb_request *req)
7872 connection_struct *conn = req->conn;
7874 unsigned char locktype;
7875 unsigned char oplocklevel;
7880 const uint8_t *data;
7881 bool large_file_format;
7882 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7883 struct smbd_lock_element *ulocks;
7884 struct smbd_lock_element *locks;
7887 START_PROFILE(SMBlockingX);
7890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7891 END_PROFILE(SMBlockingX);
7895 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7896 locktype = CVAL(req->vwv+3, 0);
7897 oplocklevel = CVAL(req->vwv+3, 1);
7898 num_ulocks = SVAL(req->vwv+6, 0);
7899 num_locks = SVAL(req->vwv+7, 0);
7900 lock_timeout = IVAL(req->vwv+4, 0);
7901 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7903 if (!check_fsp(conn, req, fsp)) {
7904 END_PROFILE(SMBlockingX);
7910 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7911 /* we don't support these - and CANCEL_LOCK makes w2k
7912 and XP reboot so I don't really want to be
7913 compatible! (tridge) */
7914 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7915 END_PROFILE(SMBlockingX);
7919 /* Check if this is an oplock break on a file
7920 we have granted an oplock on.
7922 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7923 /* Client can insist on breaking to none. */
7924 bool break_to_none = (oplocklevel == 0);
7927 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7928 "for %s\n", (unsigned int)oplocklevel,
7929 fsp_fnum_dbg(fsp)));
7932 * Make sure we have granted an exclusive or batch oplock on
7936 if (fsp->oplock_type == 0) {
7938 /* The Samba4 nbench simulator doesn't understand
7939 the difference between break to level2 and break
7940 to none from level2 - it sends oplock break
7941 replies in both cases. Don't keep logging an error
7942 message here - just ignore it. JRA. */
7944 DEBUG(5,("reply_lockingX: Error : oplock break from "
7945 "client for %s (oplock=%d) and no "
7946 "oplock granted on this file (%s).\n",
7947 fsp_fnum_dbg(fsp), fsp->oplock_type,
7950 /* if this is a pure oplock break request then don't
7952 if (num_locks == 0 && num_ulocks == 0) {
7953 END_PROFILE(SMBlockingX);
7956 END_PROFILE(SMBlockingX);
7957 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7962 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7964 result = remove_oplock(fsp);
7966 result = downgrade_oplock(fsp);
7970 DEBUG(0, ("reply_lockingX: error in removing "
7971 "oplock on file %s\n", fsp_str_dbg(fsp)));
7972 /* Hmmm. Is this panic justified? */
7973 smb_panic("internal tdb error");
7976 /* if this is a pure oplock break request then don't send a
7978 if (num_locks == 0 && num_ulocks == 0) {
7979 /* Sanity check - ensure a pure oplock break is not a
7981 if (CVAL(req->vwv+0, 0) != 0xff) {
7982 DEBUG(0,("reply_lockingX: Error : pure oplock "
7983 "break is a chained %d request !\n",
7984 (unsigned int)CVAL(req->vwv+0, 0)));
7986 END_PROFILE(SMBlockingX);
7992 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7994 END_PROFILE(SMBlockingX);
7998 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7999 if (ulocks == NULL) {
8000 reply_nterror(req, NT_STATUS_NO_MEMORY);
8001 END_PROFILE(SMBlockingX);
8005 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8006 if (locks == NULL) {
8007 reply_nterror(req, NT_STATUS_NO_MEMORY);
8008 END_PROFILE(SMBlockingX);
8012 /* Data now points at the beginning of the list
8013 of smb_unlkrng structs */
8014 for(i = 0; i < (int)num_ulocks; i++) {
8015 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8016 ulocks[i].count = get_lock_count(data, i, large_file_format);
8017 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8018 ulocks[i].brltype = UNLOCK_LOCK;
8021 /* Now do any requested locks */
8022 data += ((large_file_format ? 20 : 10)*num_ulocks);
8024 /* Data now points at the beginning of the list
8025 of smb_lkrng structs */
8027 for(i = 0; i < (int)num_locks; i++) {
8028 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8029 locks[i].count = get_lock_count(data, i, large_file_format);
8030 locks[i].offset = get_lock_offset(data, i, large_file_format);
8032 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8033 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8034 locks[i].brltype = PENDING_READ_LOCK;
8036 locks[i].brltype = READ_LOCK;
8039 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8040 locks[i].brltype = PENDING_WRITE_LOCK;
8042 locks[i].brltype = WRITE_LOCK;
8047 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8048 if (!NT_STATUS_IS_OK(status)) {
8049 END_PROFILE(SMBlockingX);
8050 reply_nterror(req, status);
8054 status = smbd_do_locking(req, fsp,
8055 locktype, lock_timeout,
8058 if (!NT_STATUS_IS_OK(status)) {
8059 END_PROFILE(SMBlockingX);
8060 reply_nterror(req, status);
8064 END_PROFILE(SMBlockingX);
8068 reply_outbuf(req, 2, 0);
8069 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8070 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8072 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8073 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8075 END_PROFILE(SMBlockingX);
8079 #define DBGC_CLASS DBGC_ALL
8081 /****************************************************************************
8082 Reply to a SMBreadbmpx (read block multiplex) request.
8083 Always reply with an error, if someone has a platform really needs this,
8084 please contact vl@samba.org
8085 ****************************************************************************/
8087 void reply_readbmpx(struct smb_request *req)
8089 START_PROFILE(SMBreadBmpx);
8090 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8091 END_PROFILE(SMBreadBmpx);
8095 /****************************************************************************
8096 Reply to a SMBreadbs (read block multiplex secondary) request.
8097 Always reply with an error, if someone has a platform really needs this,
8098 please contact vl@samba.org
8099 ****************************************************************************/
8101 void reply_readbs(struct smb_request *req)
8103 START_PROFILE(SMBreadBs);
8104 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8105 END_PROFILE(SMBreadBs);
8109 /****************************************************************************
8110 Reply to a SMBsetattrE.
8111 ****************************************************************************/
8113 void reply_setattrE(struct smb_request *req)
8115 connection_struct *conn = req->conn;
8116 struct smb_file_time ft;
8120 START_PROFILE(SMBsetattrE);
8124 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8128 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8130 if(!fsp || (fsp->conn != conn)) {
8131 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8136 * Convert the DOS times into unix times.
8139 ft.atime = convert_time_t_to_timespec(
8140 srv_make_unix_date2(req->vwv+3));
8141 ft.mtime = convert_time_t_to_timespec(
8142 srv_make_unix_date2(req->vwv+5));
8143 ft.create_time = convert_time_t_to_timespec(
8144 srv_make_unix_date2(req->vwv+1));
8146 reply_outbuf(req, 0, 0);
8149 * Patch from Ray Frush <frush@engr.colostate.edu>
8150 * Sometimes times are sent as zero - ignore them.
8153 /* Ensure we have a valid stat struct for the source. */
8154 status = vfs_stat_fsp(fsp);
8155 if (!NT_STATUS_IS_OK(status)) {
8156 reply_nterror(req, status);
8160 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8165 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8166 if (!NT_STATUS_IS_OK(status)) {
8167 reply_nterror(req, status);
8171 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8174 (unsigned int)ft.atime.tv_sec,
8175 (unsigned int)ft.mtime.tv_sec,
8176 (unsigned int)ft.create_time.tv_sec
8179 END_PROFILE(SMBsetattrE);
8184 /* Back from the dead for OS/2..... JRA. */
8186 /****************************************************************************
8187 Reply to a SMBwritebmpx (write block multiplex primary) request.
8188 Always reply with an error, if someone has a platform really needs this,
8189 please contact vl@samba.org
8190 ****************************************************************************/
8192 void reply_writebmpx(struct smb_request *req)
8194 START_PROFILE(SMBwriteBmpx);
8195 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8196 END_PROFILE(SMBwriteBmpx);
8200 /****************************************************************************
8201 Reply to a SMBwritebs (write block multiplex secondary) request.
8202 Always reply with an error, if someone has a platform really needs this,
8203 please contact vl@samba.org
8204 ****************************************************************************/
8206 void reply_writebs(struct smb_request *req)
8208 START_PROFILE(SMBwriteBs);
8209 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8210 END_PROFILE(SMBwriteBs);
8214 /****************************************************************************
8215 Reply to a SMBgetattrE.
8216 ****************************************************************************/
8218 void reply_getattrE(struct smb_request *req)
8220 connection_struct *conn = req->conn;
8223 struct timespec create_ts;
8225 START_PROFILE(SMBgetattrE);
8228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8229 END_PROFILE(SMBgetattrE);
8233 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8235 if(!fsp || (fsp->conn != conn)) {
8236 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8237 END_PROFILE(SMBgetattrE);
8241 /* Do an fstat on this file */
8243 reply_nterror(req, map_nt_error_from_unix(errno));
8244 END_PROFILE(SMBgetattrE);
8248 mode = dos_mode(conn, fsp->fsp_name);
8251 * Convert the times into dos times. Set create
8252 * date to be last modify date as UNIX doesn't save
8256 reply_outbuf(req, 11, 0);
8258 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8259 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8260 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8261 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8262 /* Should we check pending modtime here ? JRA */
8263 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8264 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8266 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8267 SIVAL(req->outbuf, smb_vwv6, 0);
8268 SIVAL(req->outbuf, smb_vwv8, 0);
8270 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8271 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8272 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8274 SSVAL(req->outbuf,smb_vwv10, mode);
8276 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8278 END_PROFILE(SMBgetattrE);