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);
342 /* pull a string from the smb_buf part of a packet. In this case the
343 string can either be null terminated or it can be terminated by the
344 end of the smbbuf area
346 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
347 char **dest, const char *src, int flags)
349 ssize_t bufrem = smbreq_bufrem(req, src);
355 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
359 /****************************************************************************
360 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
361 ****************************************************************************/
363 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
366 if ((fsp == NULL) || (conn == NULL)) {
367 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
370 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
371 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
377 /****************************************************************************
378 Check if we have a correct fsp pointing to a file.
379 ****************************************************************************/
381 bool check_fsp(connection_struct *conn, struct smb_request *req,
384 if (!check_fsp_open(conn, req, fsp)) {
387 if (fsp->is_directory) {
388 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
391 if (fsp->fh->fd == -1) {
392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
395 fsp->num_smb_operations++;
399 /****************************************************************************
400 Check if we have a correct fsp pointing to a quota fake file. Replacement for
401 the CHECK_NTQUOTA_HANDLE_OK macro.
402 ****************************************************************************/
404 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
407 if (!check_fsp_open(conn, req, fsp)) {
411 if (fsp->is_directory) {
415 if (fsp->fake_file_handle == NULL) {
419 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
423 if (fsp->fake_file_handle->private_data == NULL) {
430 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
431 const char *name, int name_type)
434 char *trim_name_type;
435 const char *retarget_parm;
438 int retarget_type = 0x20;
439 int retarget_port = NBT_SMB_PORT;
440 struct sockaddr_storage retarget_addr;
441 struct sockaddr_in *in_addr;
445 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
449 trim_name = talloc_strdup(talloc_tos(), name);
450 if (trim_name == NULL) {
453 trim_char(trim_name, ' ', ' ');
455 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
457 if (trim_name_type == NULL) {
461 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
462 trim_name_type, NULL);
463 if (retarget_parm == NULL) {
464 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
467 if (retarget_parm == NULL) {
471 retarget = talloc_strdup(trim_name, retarget_parm);
472 if (retarget == NULL) {
476 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
478 p = strchr(retarget, ':');
481 retarget_port = atoi(p);
484 p = strchr_m(retarget, '#');
487 if (sscanf(p, "%x", &retarget_type) != 1) {
492 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
494 DEBUG(10, ("could not resolve %s\n", retarget));
498 if (retarget_addr.ss_family != AF_INET) {
499 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
503 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
505 _smb_setlen(outbuf, 6);
506 SCVAL(outbuf, 0, 0x84);
507 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
508 *(uint16_t *)(outbuf+8) = htons(retarget_port);
510 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
512 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
518 TALLOC_FREE(trim_name);
522 static void reply_called_name_not_present(char *outbuf)
524 smb_setlen(outbuf, 1);
525 SCVAL(outbuf, 0, 0x83);
526 SCVAL(outbuf, 4, 0x82);
529 /****************************************************************************
530 Reply to a (netbios-level) special message.
531 ****************************************************************************/
533 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
535 int msg_type = CVAL(inbuf,0);
536 int msg_flags = CVAL(inbuf,1);
538 * We only really use 4 bytes of the outbuf, but for the smb_setlen
539 * calculation & friends (srv_send_smb uses that) we need the full smb
542 char outbuf[smb_size];
544 memset(outbuf, '\0', sizeof(outbuf));
546 smb_setlen(outbuf,0);
549 case NBSSrequest: /* session request */
551 /* inbuf_size is guarenteed to be at least 4. */
553 int name_type1, name_type2;
554 int name_len1, name_len2;
558 if (sconn->nbt.got_session) {
559 exit_server_cleanly("multiple session request not permitted");
562 SCVAL(outbuf,0,NBSSpositive);
565 /* inbuf_size is guaranteed to be at least 4. */
566 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
567 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
568 DEBUG(0,("Invalid name length in session request\n"));
569 reply_called_name_not_present(outbuf);
572 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
573 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
574 DEBUG(0,("Invalid name length in session request\n"));
575 reply_called_name_not_present(outbuf);
579 name_type1 = name_extract((unsigned char *)inbuf,
580 inbuf_size,(unsigned int)4,name1);
581 name_type2 = name_extract((unsigned char *)inbuf,
582 inbuf_size,(unsigned int)(4 + name_len1),name2);
584 if (name_type1 == -1 || name_type2 == -1) {
585 DEBUG(0,("Invalid name type in session request\n"));
586 reply_called_name_not_present(outbuf);
590 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
591 name1, name_type1, name2, name_type2));
593 if (netbios_session_retarget(sconn, name1, name_type1)) {
594 exit_server_cleanly("retargeted client");
598 * Windows NT/2k uses "*SMBSERVER" and XP uses
599 * "*SMBSERV" arrggg!!!
601 if (strequal(name1, "*SMBSERVER ")
602 || strequal(name1, "*SMBSERV ")) {
605 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
608 exit_server_cleanly("could not allocate raddr");
611 fstrcpy(name1, raddr);
614 set_local_machine_name(name1, True);
615 set_remote_machine_name(name2, True);
617 if (is_ipaddress(sconn->remote_hostname)) {
618 char *p = discard_const_p(char, sconn->remote_hostname);
622 sconn->remote_hostname = talloc_strdup(sconn,
623 get_remote_machine_name());
624 if (sconn->remote_hostname == NULL) {
625 exit_server_cleanly("could not copy remote name");
627 sconn->conn->remote_hostname = sconn->remote_hostname;
630 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
631 get_local_machine_name(), get_remote_machine_name(),
634 if (name_type2 == 'R') {
635 /* We are being asked for a pathworks session ---
637 reply_called_name_not_present(outbuf);
641 reload_services(sconn, conn_snum_used, true);
644 sconn->nbt.got_session = true;
648 case 0x89: /* session keepalive request
649 (some old clients produce this?) */
650 SCVAL(outbuf,0,NBSSkeepalive);
654 case NBSSpositive: /* positive session response */
655 case NBSSnegative: /* negative session response */
656 case NBSSretarget: /* retarget session response */
657 DEBUG(0,("Unexpected session response\n"));
660 case NBSSkeepalive: /* session keepalive */
665 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
666 msg_type, msg_flags));
668 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
670 if (CVAL(outbuf, 0) != 0x82) {
671 exit_server_cleanly("invalid netbios session");
676 /****************************************************************************
678 conn POINTER CAN BE NULL HERE !
679 ****************************************************************************/
681 void reply_tcon(struct smb_request *req)
683 connection_struct *conn = req->conn;
685 char *service_buf = NULL;
686 char *password = NULL;
691 TALLOC_CTX *ctx = talloc_tos();
692 struct smbd_server_connection *sconn = req->sconn;
693 NTTIME now = timeval_to_nttime(&req->request_time);
695 START_PROFILE(SMBtcon);
697 if (req->buflen < 4) {
698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
699 END_PROFILE(SMBtcon);
703 p = (const char *)req->buf + 1;
704 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
706 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
708 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
711 if (service_buf == NULL || password == NULL || dev == NULL) {
712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
713 END_PROFILE(SMBtcon);
716 p = strrchr_m(service_buf,'\\');
720 service = service_buf;
723 conn = make_connection(sconn, now, service, dev,
724 req->vuid,&nt_status);
728 reply_nterror(req, nt_status);
729 END_PROFILE(SMBtcon);
733 reply_outbuf(req, 2, 0);
734 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
735 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
736 SSVAL(req->outbuf,smb_tid,conn->cnum);
738 DEBUG(3,("tcon service=%s cnum=%d\n",
739 service, conn->cnum));
741 END_PROFILE(SMBtcon);
745 /****************************************************************************
746 Reply to a tcon and X.
747 conn POINTER CAN BE NULL HERE !
748 ****************************************************************************/
750 void reply_tcon_and_X(struct smb_request *req)
752 connection_struct *conn = req->conn;
753 const char *service = NULL;
754 TALLOC_CTX *ctx = talloc_tos();
755 /* what the cleint thinks the device is */
756 char *client_devicetype = NULL;
757 /* what the server tells the client the share represents */
758 const char *server_devicetype;
764 struct smbXsrv_session *session = NULL;
765 NTTIME now = timeval_to_nttime(&req->request_time);
766 bool session_key_updated = false;
767 uint16_t optional_support = 0;
768 struct smbd_server_connection *sconn = req->sconn;
770 START_PROFILE(SMBtconX);
773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
774 END_PROFILE(SMBtconX);
778 passlen = SVAL(req->vwv+3, 0);
779 tcon_flags = SVAL(req->vwv+2, 0);
781 /* we might have to close an old one */
782 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
783 struct smbXsrv_tcon *tcon;
791 * TODO: cancel all outstanding requests on the tcon
793 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
794 if (!NT_STATUS_IS_OK(status)) {
795 DEBUG(0, ("reply_tcon_and_X: "
796 "smbXsrv_tcon_disconnect() failed: %s\n",
799 * If we hit this case, there is something completely
800 * wrong, so we better disconnect the transport connection.
802 END_PROFILE(SMBtconX);
803 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
810 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
811 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
812 END_PROFILE(SMBtconX);
816 if (sconn->smb1.negprot.encrypted_passwords) {
817 p = (const char *)req->buf + passlen;
819 p = (const char *)req->buf + passlen + 1;
822 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
826 END_PROFILE(SMBtconX);
831 * the service name can be either: \\server\share
832 * or share directly like on the DELL PowerVault 705
835 q = strchr_m(path+2,'\\');
837 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
838 END_PROFILE(SMBtconX);
846 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
847 &client_devicetype, p,
848 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
850 if (client_devicetype == NULL) {
851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
852 END_PROFILE(SMBtconX);
856 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
858 nt_status = smb1srv_session_lookup(req->sconn->conn,
859 req->vuid, now, &session);
860 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
861 reply_force_doserror(req, ERRSRV, ERRbaduid);
862 END_PROFILE(SMBtconX);
865 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
866 reply_nterror(req, nt_status);
867 END_PROFILE(SMBtconX);
870 if (!NT_STATUS_IS_OK(nt_status)) {
871 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
872 END_PROFILE(SMBtconX);
876 if (session->global->auth_session_info == NULL) {
877 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
878 END_PROFILE(SMBtconX);
883 * If there is no application key defined yet
886 * This means we setup the application key on the
887 * first tcon that happens via the given session.
889 * Once the application key is defined, it does not
892 if (session->global->application_key.length == 0 &&
893 session->global->signing_key.length > 0)
895 struct smbXsrv_session *x = session;
896 struct auth_session_info *session_info =
897 session->global->auth_session_info;
898 uint8_t session_key[16];
900 ZERO_STRUCT(session_key);
901 memcpy(session_key, x->global->signing_key.data,
902 MIN(x->global->signing_key.length, sizeof(session_key)));
905 * The application key is truncated/padded to 16 bytes
907 x->global->application_key = data_blob_talloc(x->global,
909 sizeof(session_key));
910 ZERO_STRUCT(session_key);
911 if (x->global->application_key.data == NULL) {
912 reply_nterror(req, NT_STATUS_NO_MEMORY);
913 END_PROFILE(SMBtconX);
917 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
918 smb_key_derivation(x->global->application_key.data,
919 x->global->application_key.length,
920 x->global->application_key.data);
921 optional_support |= SMB_EXTENDED_SIGNATURES;
925 * Place the application key into the session_info
927 data_blob_clear_free(&session_info->session_key);
928 session_info->session_key = data_blob_dup_talloc(session_info,
929 x->global->application_key);
930 if (session_info->session_key.data == NULL) {
931 data_blob_clear_free(&x->global->application_key);
932 reply_nterror(req, NT_STATUS_NO_MEMORY);
933 END_PROFILE(SMBtconX);
936 session_key_updated = true;
939 conn = make_connection(sconn, now, service, client_devicetype,
940 req->vuid, &nt_status);
944 if (session_key_updated) {
945 struct smbXsrv_session *x = session;
946 struct auth_session_info *session_info =
947 session->global->auth_session_info;
948 data_blob_clear_free(&x->global->application_key);
949 data_blob_clear_free(&session_info->session_key);
951 reply_nterror(req, nt_status);
952 END_PROFILE(SMBtconX);
957 server_devicetype = "IPC";
958 else if ( IS_PRINT(conn) )
959 server_devicetype = "LPT1:";
961 server_devicetype = "A:";
963 if (get_Protocol() < PROTOCOL_NT1) {
964 reply_outbuf(req, 2, 0);
965 if (message_push_string(&req->outbuf, server_devicetype,
966 STR_TERMINATE|STR_ASCII) == -1) {
967 reply_nterror(req, NT_STATUS_NO_MEMORY);
968 END_PROFILE(SMBtconX);
972 /* NT sets the fstype of IPC$ to the null string */
973 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
975 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
976 /* Return permissions. */
980 reply_outbuf(req, 7, 0);
983 perm1 = FILE_ALL_ACCESS;
984 perm2 = FILE_ALL_ACCESS;
986 perm1 = conn->share_access;
989 SIVAL(req->outbuf, smb_vwv3, perm1);
990 SIVAL(req->outbuf, smb_vwv5, perm2);
992 reply_outbuf(req, 3, 0);
995 if ((message_push_string(&req->outbuf, server_devicetype,
996 STR_TERMINATE|STR_ASCII) == -1)
997 || (message_push_string(&req->outbuf, fstype,
998 STR_TERMINATE) == -1)) {
999 reply_nterror(req, NT_STATUS_NO_MEMORY);
1000 END_PROFILE(SMBtconX);
1004 /* what does setting this bit do? It is set by NT4 and
1005 may affect the ability to autorun mounted cdroms */
1006 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1008 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1010 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1011 DEBUG(2,("Serving %s as a Dfs root\n",
1012 lp_servicename(ctx, SNUM(conn)) ));
1013 optional_support |= SMB_SHARE_IN_DFS;
1016 SSVAL(req->outbuf, smb_vwv2, optional_support);
1019 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1020 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1022 DEBUG(3,("tconX service=%s \n",
1025 /* set the incoming and outgoing tid to the just created one */
1026 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1027 SSVAL(req->outbuf,smb_tid,conn->cnum);
1029 END_PROFILE(SMBtconX);
1031 req->tid = conn->cnum;
1034 /****************************************************************************
1035 Reply to an unknown type.
1036 ****************************************************************************/
1038 void reply_unknown_new(struct smb_request *req, uint8 type)
1040 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1041 smb_fn_name(type), type, type));
1042 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1046 /****************************************************************************
1048 conn POINTER CAN BE NULL HERE !
1049 ****************************************************************************/
1051 void reply_ioctl(struct smb_request *req)
1053 connection_struct *conn = req->conn;
1060 START_PROFILE(SMBioctl);
1063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1064 END_PROFILE(SMBioctl);
1068 device = SVAL(req->vwv+1, 0);
1069 function = SVAL(req->vwv+2, 0);
1070 ioctl_code = (device << 16) + function;
1072 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1074 switch (ioctl_code) {
1075 case IOCTL_QUERY_JOB_INFO:
1079 reply_force_doserror(req, ERRSRV, ERRnosupport);
1080 END_PROFILE(SMBioctl);
1084 reply_outbuf(req, 8, replysize+1);
1085 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1086 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1087 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1088 p = smb_buf(req->outbuf);
1089 memset(p, '\0', replysize+1); /* valgrind-safe. */
1090 p += 1; /* Allow for alignment */
1092 switch (ioctl_code) {
1093 case IOCTL_QUERY_JOB_INFO:
1095 files_struct *fsp = file_fsp(
1096 req, SVAL(req->vwv+0, 0));
1098 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1099 END_PROFILE(SMBioctl);
1103 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1105 srvstr_push((char *)req->outbuf, req->flags2, p+2,
1106 lp_netbios_name(), 15,
1107 STR_TERMINATE|STR_ASCII);
1109 srvstr_push((char *)req->outbuf, req->flags2,
1111 lp_servicename(talloc_tos(),
1113 13, STR_TERMINATE|STR_ASCII);
1115 memset(p+18, 0, 13);
1121 END_PROFILE(SMBioctl);
1125 /****************************************************************************
1126 Strange checkpath NTSTATUS mapping.
1127 ****************************************************************************/
1129 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1131 /* Strange DOS error code semantics only for checkpath... */
1132 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1133 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1134 /* We need to map to ERRbadpath */
1135 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1141 /****************************************************************************
1142 Reply to a checkpath.
1143 ****************************************************************************/
1145 void reply_checkpath(struct smb_request *req)
1147 connection_struct *conn = req->conn;
1148 struct smb_filename *smb_fname = NULL;
1151 TALLOC_CTX *ctx = talloc_tos();
1153 START_PROFILE(SMBcheckpath);
1155 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1156 STR_TERMINATE, &status);
1158 if (!NT_STATUS_IS_OK(status)) {
1159 status = map_checkpath_error(req->flags2, status);
1160 reply_nterror(req, status);
1161 END_PROFILE(SMBcheckpath);
1165 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1167 status = filename_convert(ctx,
1169 req->flags2 & FLAGS2_DFS_PATHNAMES,
1175 if (!NT_STATUS_IS_OK(status)) {
1176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1177 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1178 ERRSRV, ERRbadpath);
1179 END_PROFILE(SMBcheckpath);
1185 if (!VALID_STAT(smb_fname->st) &&
1186 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1187 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1188 smb_fname_str_dbg(smb_fname), strerror(errno)));
1189 status = map_nt_error_from_unix(errno);
1193 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1194 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1195 ERRDOS, ERRbadpath);
1199 reply_outbuf(req, 0, 0);
1202 /* We special case this - as when a Windows machine
1203 is parsing a path is steps through the components
1204 one at a time - if a component fails it expects
1205 ERRbadpath, not ERRbadfile.
1207 status = map_checkpath_error(req->flags2, status);
1208 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1210 * Windows returns different error codes if
1211 * the parent directory is valid but not the
1212 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1213 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1214 * if the path is invalid.
1216 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1217 ERRDOS, ERRbadpath);
1221 reply_nterror(req, status);
1224 TALLOC_FREE(smb_fname);
1225 END_PROFILE(SMBcheckpath);
1229 /****************************************************************************
1231 ****************************************************************************/
1233 void reply_getatr(struct smb_request *req)
1235 connection_struct *conn = req->conn;
1236 struct smb_filename *smb_fname = NULL;
1243 TALLOC_CTX *ctx = talloc_tos();
1244 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1246 START_PROFILE(SMBgetatr);
1248 p = (const char *)req->buf + 1;
1249 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 reply_nterror(req, status);
1255 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1256 under WfWg - weird! */
1257 if (*fname == '\0') {
1258 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1259 if (!CAN_WRITE(conn)) {
1260 mode |= FILE_ATTRIBUTE_READONLY;
1265 status = filename_convert(ctx,
1267 req->flags2 & FLAGS2_DFS_PATHNAMES,
1272 if (!NT_STATUS_IS_OK(status)) {
1273 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1274 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1275 ERRSRV, ERRbadpath);
1278 reply_nterror(req, status);
1281 if (!VALID_STAT(smb_fname->st) &&
1282 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1283 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1284 smb_fname_str_dbg(smb_fname),
1286 reply_nterror(req, map_nt_error_from_unix(errno));
1290 mode = dos_mode(conn, smb_fname);
1291 size = smb_fname->st.st_ex_size;
1293 if (ask_sharemode) {
1294 struct timespec write_time_ts;
1295 struct file_id fileid;
1297 ZERO_STRUCT(write_time_ts);
1298 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1299 get_file_infos(fileid, 0, NULL, &write_time_ts);
1300 if (!null_timespec(write_time_ts)) {
1301 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1305 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1306 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1311 reply_outbuf(req, 10, 0);
1313 SSVAL(req->outbuf,smb_vwv0,mode);
1314 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1315 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1317 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1319 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1321 if (get_Protocol() >= PROTOCOL_NT1) {
1322 SSVAL(req->outbuf, smb_flg2,
1323 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1326 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1327 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1330 TALLOC_FREE(smb_fname);
1332 END_PROFILE(SMBgetatr);
1336 /****************************************************************************
1338 ****************************************************************************/
1340 void reply_setatr(struct smb_request *req)
1342 struct smb_file_time ft;
1343 connection_struct *conn = req->conn;
1344 struct smb_filename *smb_fname = NULL;
1350 TALLOC_CTX *ctx = talloc_tos();
1352 START_PROFILE(SMBsetatr);
1357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1361 p = (const char *)req->buf + 1;
1362 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 reply_nterror(req, status);
1368 status = filename_convert(ctx,
1370 req->flags2 & FLAGS2_DFS_PATHNAMES,
1375 if (!NT_STATUS_IS_OK(status)) {
1376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1377 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1378 ERRSRV, ERRbadpath);
1381 reply_nterror(req, status);
1385 if (smb_fname->base_name[0] == '.' &&
1386 smb_fname->base_name[1] == '\0') {
1388 * Not sure here is the right place to catch this
1389 * condition. Might be moved to somewhere else later -- vl
1391 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1395 mode = SVAL(req->vwv+0, 0);
1396 mtime = srv_make_unix_date3(req->vwv+1);
1398 if (mode != FILE_ATTRIBUTE_NORMAL) {
1399 if (VALID_STAT_OF_DIR(smb_fname->st))
1400 mode |= FILE_ATTRIBUTE_DIRECTORY;
1402 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1404 status = check_access(conn, NULL, smb_fname,
1405 FILE_WRITE_ATTRIBUTES);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 reply_nterror(req, status);
1411 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1413 reply_nterror(req, map_nt_error_from_unix(errno));
1418 ft.mtime = convert_time_t_to_timespec(mtime);
1419 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1420 if (!NT_STATUS_IS_OK(status)) {
1421 reply_nterror(req, status);
1425 reply_outbuf(req, 0, 0);
1427 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1430 TALLOC_FREE(smb_fname);
1431 END_PROFILE(SMBsetatr);
1435 /****************************************************************************
1437 ****************************************************************************/
1439 void reply_dskattr(struct smb_request *req)
1441 connection_struct *conn = req->conn;
1442 uint64_t dfree,dsize,bsize;
1443 START_PROFILE(SMBdskattr);
1445 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1446 reply_nterror(req, map_nt_error_from_unix(errno));
1447 END_PROFILE(SMBdskattr);
1451 reply_outbuf(req, 5, 0);
1453 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1454 double total_space, free_space;
1455 /* we need to scale this to a number that DOS6 can handle. We
1456 use floating point so we can handle large drives on systems
1457 that don't have 64 bit integers
1459 we end up displaying a maximum of 2G to DOS systems
1461 total_space = dsize * (double)bsize;
1462 free_space = dfree * (double)bsize;
1464 dsize = (uint64_t)((total_space+63*512) / (64*512));
1465 dfree = (uint64_t)((free_space+63*512) / (64*512));
1467 if (dsize > 0xFFFF) dsize = 0xFFFF;
1468 if (dfree > 0xFFFF) dfree = 0xFFFF;
1470 SSVAL(req->outbuf,smb_vwv0,dsize);
1471 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1472 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1473 SSVAL(req->outbuf,smb_vwv3,dfree);
1475 SSVAL(req->outbuf,smb_vwv0,dsize);
1476 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1477 SSVAL(req->outbuf,smb_vwv2,512);
1478 SSVAL(req->outbuf,smb_vwv3,dfree);
1481 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1483 END_PROFILE(SMBdskattr);
1488 * Utility function to split the filename from the directory.
1490 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1491 char **fname_dir_out,
1492 char **fname_mask_out)
1494 const char *p = NULL;
1495 char *fname_dir = NULL;
1496 char *fname_mask = NULL;
1498 p = strrchr_m(fname_in, '/');
1500 fname_dir = talloc_strdup(ctx, ".");
1501 fname_mask = talloc_strdup(ctx, fname_in);
1503 fname_dir = talloc_strndup(ctx, fname_in,
1504 PTR_DIFF(p, fname_in));
1505 fname_mask = talloc_strdup(ctx, p+1);
1508 if (!fname_dir || !fname_mask) {
1509 TALLOC_FREE(fname_dir);
1510 TALLOC_FREE(fname_mask);
1511 return NT_STATUS_NO_MEMORY;
1514 *fname_dir_out = fname_dir;
1515 *fname_mask_out = fname_mask;
1516 return NT_STATUS_OK;
1519 /****************************************************************************
1521 Can be called from SMBsearch, SMBffirst or SMBfunique.
1522 ****************************************************************************/
1524 void reply_search(struct smb_request *req)
1526 connection_struct *conn = req->conn;
1528 const char *mask = NULL;
1529 char *directory = NULL;
1530 struct smb_filename *smb_fname = NULL;
1534 struct timespec date;
1536 unsigned int numentries = 0;
1537 unsigned int maxentries = 0;
1538 bool finished = False;
1543 bool check_descend = False;
1544 bool expect_close = False;
1546 bool mask_contains_wcard = False;
1547 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1548 TALLOC_CTX *ctx = talloc_tos();
1549 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1550 struct dptr_struct *dirptr = NULL;
1551 struct smbd_server_connection *sconn = req->sconn;
1553 START_PROFILE(SMBsearch);
1556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1560 if (lp_posix_pathnames()) {
1561 reply_unknown_new(req, req->cmd);
1565 /* If we were called as SMBffirst then we must expect close. */
1566 if(req->cmd == SMBffirst) {
1567 expect_close = True;
1570 reply_outbuf(req, 1, 3);
1571 maxentries = SVAL(req->vwv+0, 0);
1572 dirtype = SVAL(req->vwv+1, 0);
1573 p = (const char *)req->buf + 1;
1574 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1575 &nt_status, &mask_contains_wcard);
1576 if (!NT_STATUS_IS_OK(nt_status)) {
1577 reply_nterror(req, nt_status);
1582 status_len = SVAL(p, 0);
1585 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1587 if (status_len == 0) {
1588 nt_status = filename_convert(ctx, conn,
1589 req->flags2 & FLAGS2_DFS_PATHNAMES,
1591 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1592 &mask_contains_wcard,
1594 if (!NT_STATUS_IS_OK(nt_status)) {
1595 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1596 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1597 ERRSRV, ERRbadpath);
1600 reply_nterror(req, nt_status);
1604 directory = smb_fname->base_name;
1606 p = strrchr_m(directory,'/');
1607 if ((p != NULL) && (*directory != '/')) {
1609 directory = talloc_strndup(ctx, directory,
1610 PTR_DIFF(p, directory));
1613 directory = talloc_strdup(ctx,".");
1617 reply_nterror(req, NT_STATUS_NO_MEMORY);
1621 memset((char *)status,'\0',21);
1622 SCVAL(status,0,(dirtype & 0x1F));
1624 nt_status = dptr_create(conn,
1632 mask_contains_wcard,
1635 if (!NT_STATUS_IS_OK(nt_status)) {
1636 reply_nterror(req, nt_status);
1639 dptr_num = dptr_dnum(dirptr);
1642 const char *dirpath;
1644 memcpy(status,p,21);
1645 status_dirtype = CVAL(status,0) & 0x1F;
1646 if (status_dirtype != (dirtype & 0x1F)) {
1647 dirtype = status_dirtype;
1650 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1654 dirpath = dptr_path(sconn, dptr_num);
1655 directory = talloc_strdup(ctx, dirpath);
1657 reply_nterror(req, NT_STATUS_NO_MEMORY);
1661 mask = dptr_wcard(sconn, dptr_num);
1666 * For a 'continue' search we have no string. So
1667 * check from the initial saved string.
1669 mask_contains_wcard = ms_has_wild(mask);
1670 dirtype = dptr_attr(sconn, dptr_num);
1673 DEBUG(4,("dptr_num is %d\n",dptr_num));
1675 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1676 dptr_init_search_op(dirptr);
1678 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1679 char buf[DIR_STRUCT_SIZE];
1680 memcpy(buf,status,21);
1681 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1682 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1683 reply_nterror(req, NT_STATUS_NO_MEMORY);
1686 dptr_fill(sconn, buf+12,dptr_num);
1687 if (dptr_zero(buf+12) && (status_len==0)) {
1692 if (message_push_blob(&req->outbuf,
1693 data_blob_const(buf, sizeof(buf)))
1695 reply_nterror(req, NT_STATUS_NO_MEMORY);
1703 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1706 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1707 directory,lp_dontdescend(ctx, SNUM(conn))));
1708 if (in_list(directory, lp_dontdescend(ctx, SNUM(conn)),True)) {
1709 check_descend = True;
1712 for (i=numentries;(i<maxentries) && !finished;i++) {
1713 finished = !get_dir_entry(ctx,
1724 char buf[DIR_STRUCT_SIZE];
1725 memcpy(buf,status,21);
1726 if (!make_dir_struct(ctx,
1732 convert_timespec_to_time_t(date),
1733 !allow_long_path_components)) {
1734 reply_nterror(req, NT_STATUS_NO_MEMORY);
1737 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1740 if (message_push_blob(&req->outbuf,
1741 data_blob_const(buf, sizeof(buf)))
1743 reply_nterror(req, NT_STATUS_NO_MEMORY);
1753 /* If we were called as SMBffirst with smb_search_id == NULL
1754 and no entries were found then return error and close dirptr
1757 if (numentries == 0) {
1758 dptr_close(sconn, &dptr_num);
1759 } else if(expect_close && status_len == 0) {
1760 /* Close the dptr - we know it's gone */
1761 dptr_close(sconn, &dptr_num);
1764 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1765 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1766 dptr_close(sconn, &dptr_num);
1769 if ((numentries == 0) && !mask_contains_wcard) {
1770 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1774 SSVAL(req->outbuf,smb_vwv0,numentries);
1775 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1776 SCVAL(smb_buf(req->outbuf),0,5);
1777 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1779 /* The replies here are never long name. */
1780 SSVAL(req->outbuf, smb_flg2,
1781 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1782 if (!allow_long_path_components) {
1783 SSVAL(req->outbuf, smb_flg2,
1784 SVAL(req->outbuf, smb_flg2)
1785 & (~FLAGS2_LONG_PATH_COMPONENTS));
1788 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1789 SSVAL(req->outbuf, smb_flg2,
1790 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1792 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1793 smb_fn_name(req->cmd),
1800 TALLOC_FREE(directory);
1801 TALLOC_FREE(smb_fname);
1802 END_PROFILE(SMBsearch);
1806 /****************************************************************************
1807 Reply to a fclose (stop directory search).
1808 ****************************************************************************/
1810 void reply_fclose(struct smb_request *req)
1818 bool path_contains_wcard = False;
1819 TALLOC_CTX *ctx = talloc_tos();
1820 struct smbd_server_connection *sconn = req->sconn;
1822 START_PROFILE(SMBfclose);
1824 if (lp_posix_pathnames()) {
1825 reply_unknown_new(req, req->cmd);
1826 END_PROFILE(SMBfclose);
1830 p = (const char *)req->buf + 1;
1831 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1832 &err, &path_contains_wcard);
1833 if (!NT_STATUS_IS_OK(err)) {
1834 reply_nterror(req, err);
1835 END_PROFILE(SMBfclose);
1839 status_len = SVAL(p,0);
1842 if (status_len == 0) {
1843 reply_force_doserror(req, ERRSRV, ERRsrverror);
1844 END_PROFILE(SMBfclose);
1848 memcpy(status,p,21);
1850 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1851 /* Close the dptr - we know it's gone */
1852 dptr_close(sconn, &dptr_num);
1855 reply_outbuf(req, 1, 0);
1856 SSVAL(req->outbuf,smb_vwv0,0);
1858 DEBUG(3,("search close\n"));
1860 END_PROFILE(SMBfclose);
1864 /****************************************************************************
1866 ****************************************************************************/
1868 void reply_open(struct smb_request *req)
1870 connection_struct *conn = req->conn;
1871 struct smb_filename *smb_fname = NULL;
1883 uint32 create_disposition;
1884 uint32 create_options = 0;
1885 uint32_t private_flags = 0;
1887 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1888 TALLOC_CTX *ctx = talloc_tos();
1890 START_PROFILE(SMBopen);
1893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1897 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1898 deny_mode = SVAL(req->vwv+0, 0);
1899 dos_attr = SVAL(req->vwv+1, 0);
1901 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1902 STR_TERMINATE, &status);
1903 if (!NT_STATUS_IS_OK(status)) {
1904 reply_nterror(req, status);
1908 if (!map_open_params_to_ntcreate(fname, deny_mode,
1909 OPENX_FILE_EXISTS_OPEN, &access_mask,
1910 &share_mode, &create_disposition,
1911 &create_options, &private_flags)) {
1912 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1916 status = filename_convert(ctx,
1918 req->flags2 & FLAGS2_DFS_PATHNAMES,
1920 UCF_PREP_CREATEFILE,
1923 if (!NT_STATUS_IS_OK(status)) {
1924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1925 reply_botherror(req,
1926 NT_STATUS_PATH_NOT_COVERED,
1927 ERRSRV, ERRbadpath);
1930 reply_nterror(req, status);
1934 status = SMB_VFS_CREATE_FILE(
1937 0, /* root_dir_fid */
1938 smb_fname, /* fname */
1939 access_mask, /* access_mask */
1940 share_mode, /* share_access */
1941 create_disposition, /* create_disposition*/
1942 create_options, /* create_options */
1943 dos_attr, /* file_attributes */
1944 oplock_request, /* oplock_request */
1945 0, /* allocation_size */
1952 if (!NT_STATUS_IS_OK(status)) {
1953 if (open_was_deferred(req->sconn, req->mid)) {
1954 /* We have re-scheduled this call. */
1957 reply_openerror(req, status);
1961 size = smb_fname->st.st_ex_size;
1962 fattr = dos_mode(conn, smb_fname);
1964 /* Deal with other possible opens having a modified
1966 if (ask_sharemode) {
1967 struct timespec write_time_ts;
1969 ZERO_STRUCT(write_time_ts);
1970 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1971 if (!null_timespec(write_time_ts)) {
1972 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1976 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1978 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1979 DEBUG(3,("attempt to open a directory %s\n",
1981 close_file(req, fsp, ERROR_CLOSE);
1982 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1983 ERRDOS, ERRnoaccess);
1987 reply_outbuf(req, 7, 0);
1988 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1989 SSVAL(req->outbuf,smb_vwv1,fattr);
1990 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1991 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1993 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1995 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1996 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1998 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1999 SCVAL(req->outbuf,smb_flg,
2000 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2003 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2004 SCVAL(req->outbuf,smb_flg,
2005 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2008 TALLOC_FREE(smb_fname);
2009 END_PROFILE(SMBopen);
2013 /****************************************************************************
2014 Reply to an open and X.
2015 ****************************************************************************/
2017 void reply_open_and_X(struct smb_request *req)
2019 connection_struct *conn = req->conn;
2020 struct smb_filename *smb_fname = NULL;
2025 /* Breakout the oplock request bits so we can set the
2026 reply bits separately. */
2027 int ex_oplock_request;
2028 int core_oplock_request;
2031 int smb_sattr = SVAL(req->vwv+4, 0);
2032 uint32 smb_time = make_unix_date3(req->vwv+6);
2040 uint64_t allocation_size;
2041 ssize_t retval = -1;
2044 uint32 create_disposition;
2045 uint32 create_options = 0;
2046 uint32_t private_flags = 0;
2047 TALLOC_CTX *ctx = talloc_tos();
2049 START_PROFILE(SMBopenX);
2051 if (req->wct < 15) {
2052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 open_flags = SVAL(req->vwv+2, 0);
2057 deny_mode = SVAL(req->vwv+3, 0);
2058 smb_attr = SVAL(req->vwv+5, 0);
2059 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2060 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2061 oplock_request = ex_oplock_request | core_oplock_request;
2062 smb_ofun = SVAL(req->vwv+8, 0);
2063 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2065 /* If it's an IPC, pass off the pipe handler. */
2067 if (lp_nt_pipe_support()) {
2068 reply_open_pipe_and_X(conn, req);
2070 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2075 /* XXXX we need to handle passed times, sattr and flags */
2076 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2077 STR_TERMINATE, &status);
2078 if (!NT_STATUS_IS_OK(status)) {
2079 reply_nterror(req, status);
2083 if (!map_open_params_to_ntcreate(fname, deny_mode,
2085 &access_mask, &share_mode,
2086 &create_disposition,
2089 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2093 status = filename_convert(ctx,
2095 req->flags2 & FLAGS2_DFS_PATHNAMES,
2097 UCF_PREP_CREATEFILE,
2100 if (!NT_STATUS_IS_OK(status)) {
2101 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2102 reply_botherror(req,
2103 NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2107 reply_nterror(req, status);
2111 status = SMB_VFS_CREATE_FILE(
2114 0, /* root_dir_fid */
2115 smb_fname, /* fname */
2116 access_mask, /* access_mask */
2117 share_mode, /* share_access */
2118 create_disposition, /* create_disposition*/
2119 create_options, /* create_options */
2120 smb_attr, /* file_attributes */
2121 oplock_request, /* oplock_request */
2122 0, /* allocation_size */
2127 &smb_action); /* pinfo */
2129 if (!NT_STATUS_IS_OK(status)) {
2130 if (open_was_deferred(req->sconn, req->mid)) {
2131 /* We have re-scheduled this call. */
2134 reply_openerror(req, status);
2138 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2139 if the file is truncated or created. */
2140 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2141 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2142 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2143 close_file(req, fsp, ERROR_CLOSE);
2144 reply_nterror(req, NT_STATUS_DISK_FULL);
2147 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2149 close_file(req, fsp, ERROR_CLOSE);
2150 reply_nterror(req, NT_STATUS_DISK_FULL);
2153 status = vfs_stat_fsp(fsp);
2154 if (!NT_STATUS_IS_OK(status)) {
2155 close_file(req, fsp, ERROR_CLOSE);
2156 reply_nterror(req, status);
2161 fattr = dos_mode(conn, fsp->fsp_name);
2162 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2163 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2164 close_file(req, fsp, ERROR_CLOSE);
2165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2169 /* If the caller set the extended oplock request bit
2170 and we granted one (by whatever means) - set the
2171 correct bit for extended oplock reply.
2174 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2175 smb_action |= EXTENDED_OPLOCK_GRANTED;
2178 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2179 smb_action |= EXTENDED_OPLOCK_GRANTED;
2182 /* If the caller set the core oplock request bit
2183 and we granted one (by whatever means) - set the
2184 correct bit for core oplock reply.
2187 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2188 reply_outbuf(req, 19, 0);
2190 reply_outbuf(req, 15, 0);
2193 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2194 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2196 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2197 SCVAL(req->outbuf, smb_flg,
2198 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2201 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2202 SCVAL(req->outbuf, smb_flg,
2203 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2206 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2207 SSVAL(req->outbuf,smb_vwv3,fattr);
2208 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2209 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2211 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2213 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2214 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2215 SSVAL(req->outbuf,smb_vwv11,smb_action);
2217 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2218 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2222 TALLOC_FREE(smb_fname);
2223 END_PROFILE(SMBopenX);
2227 /****************************************************************************
2228 Reply to a SMBulogoffX.
2229 ****************************************************************************/
2231 void reply_ulogoffX(struct smb_request *req)
2233 struct smbd_server_connection *sconn = req->sconn;
2234 struct user_struct *vuser;
2235 struct smbXsrv_session *session = NULL;
2238 START_PROFILE(SMBulogoffX);
2240 vuser = get_valid_user_struct(sconn, req->vuid);
2243 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2244 (unsigned long long)req->vuid));
2246 req->vuid = UID_FIELD_INVALID;
2247 reply_force_doserror(req, ERRSRV, ERRbaduid);
2248 END_PROFILE(SMBulogoffX);
2252 session = vuser->session;
2256 * TODO: cancel all outstanding requests on the session
2258 status = smbXsrv_session_logoff(session);
2259 if (!NT_STATUS_IS_OK(status)) {
2260 DEBUG(0, ("reply_ulogoff: "
2261 "smbXsrv_session_logoff() failed: %s\n",
2262 nt_errstr(status)));
2264 * If we hit this case, there is something completely
2265 * wrong, so we better disconnect the transport connection.
2267 END_PROFILE(SMBulogoffX);
2268 exit_server(__location__ ": smbXsrv_session_logoff failed");
2272 TALLOC_FREE(session);
2274 reply_outbuf(req, 2, 0);
2275 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2276 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2278 DEBUG(3, ("ulogoffX vuid=%llu\n",
2279 (unsigned long long)req->vuid));
2281 END_PROFILE(SMBulogoffX);
2282 req->vuid = UID_FIELD_INVALID;
2285 /****************************************************************************
2286 Reply to a mknew or a create.
2287 ****************************************************************************/
2289 void reply_mknew(struct smb_request *req)
2291 connection_struct *conn = req->conn;
2292 struct smb_filename *smb_fname = NULL;
2295 struct smb_file_time ft;
2297 int oplock_request = 0;
2299 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2300 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2301 uint32 create_disposition;
2302 uint32 create_options = 0;
2303 TALLOC_CTX *ctx = talloc_tos();
2305 START_PROFILE(SMBcreate);
2309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2313 fattr = SVAL(req->vwv+0, 0);
2314 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2317 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2319 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2320 STR_TERMINATE, &status);
2321 if (!NT_STATUS_IS_OK(status)) {
2322 reply_nterror(req, status);
2326 status = filename_convert(ctx,
2328 req->flags2 & FLAGS2_DFS_PATHNAMES,
2330 UCF_PREP_CREATEFILE,
2333 if (!NT_STATUS_IS_OK(status)) {
2334 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2335 reply_botherror(req,
2336 NT_STATUS_PATH_NOT_COVERED,
2337 ERRSRV, ERRbadpath);
2340 reply_nterror(req, status);
2344 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2345 DEBUG(0,("Attempt to create file (%s) with volid set - "
2346 "please report this\n",
2347 smb_fname_str_dbg(smb_fname)));
2350 if(req->cmd == SMBmknew) {
2351 /* We should fail if file exists. */
2352 create_disposition = FILE_CREATE;
2354 /* Create if file doesn't exist, truncate if it does. */
2355 create_disposition = FILE_OVERWRITE_IF;
2358 status = SMB_VFS_CREATE_FILE(
2361 0, /* root_dir_fid */
2362 smb_fname, /* fname */
2363 access_mask, /* access_mask */
2364 share_mode, /* share_access */
2365 create_disposition, /* create_disposition*/
2366 create_options, /* create_options */
2367 fattr, /* file_attributes */
2368 oplock_request, /* oplock_request */
2369 0, /* allocation_size */
2370 0, /* private_flags */
2376 if (!NT_STATUS_IS_OK(status)) {
2377 if (open_was_deferred(req->sconn, req->mid)) {
2378 /* We have re-scheduled this call. */
2381 reply_openerror(req, status);
2385 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2386 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 END_PROFILE(SMBcreate);
2392 reply_outbuf(req, 1, 0);
2393 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2395 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2396 SCVAL(req->outbuf,smb_flg,
2397 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2400 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2401 SCVAL(req->outbuf,smb_flg,
2402 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2405 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2406 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2407 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2408 (unsigned int)fattr));
2411 TALLOC_FREE(smb_fname);
2412 END_PROFILE(SMBcreate);
2416 /****************************************************************************
2417 Reply to a create temporary file.
2418 ****************************************************************************/
2420 void reply_ctemp(struct smb_request *req)
2422 connection_struct *conn = req->conn;
2423 struct smb_filename *smb_fname = NULL;
2424 char *wire_name = NULL;
2432 TALLOC_CTX *ctx = talloc_tos();
2434 START_PROFILE(SMBctemp);
2437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2441 fattr = SVAL(req->vwv+0, 0);
2442 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2444 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2445 STR_TERMINATE, &status);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 reply_nterror(req, status);
2451 for (i = 0; i < 10; i++) {
2453 fname = talloc_asprintf(ctx,
2456 generate_random_str_list(ctx, 5, "0123456789"));
2458 fname = talloc_asprintf(ctx,
2460 generate_random_str_list(ctx, 5, "0123456789"));
2464 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 status = filename_convert(ctx, conn,
2469 req->flags2 & FLAGS2_DFS_PATHNAMES,
2471 UCF_PREP_CREATEFILE,
2474 if (!NT_STATUS_IS_OK(status)) {
2475 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2476 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2477 ERRSRV, ERRbadpath);
2480 reply_nterror(req, status);
2484 /* Create the file. */
2485 status = SMB_VFS_CREATE_FILE(
2488 0, /* root_dir_fid */
2489 smb_fname, /* fname */
2490 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2491 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2492 FILE_CREATE, /* create_disposition*/
2493 0, /* create_options */
2494 fattr, /* file_attributes */
2495 oplock_request, /* oplock_request */
2496 0, /* allocation_size */
2497 0, /* private_flags */
2503 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2505 TALLOC_FREE(smb_fname);
2509 if (!NT_STATUS_IS_OK(status)) {
2510 if (open_was_deferred(req->sconn, req->mid)) {
2511 /* We have re-scheduled this call. */
2514 reply_openerror(req, status);
2522 /* Collision after 10 times... */
2523 reply_nterror(req, status);
2527 reply_outbuf(req, 1, 0);
2528 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2530 /* the returned filename is relative to the directory */
2531 s = strrchr_m(fsp->fsp_name->base_name, '/');
2533 s = fsp->fsp_name->base_name;
2539 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2540 thing in the byte section. JRA */
2541 SSVALS(p, 0, -1); /* what is this? not in spec */
2543 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2545 reply_nterror(req, NT_STATUS_NO_MEMORY);
2549 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2550 SCVAL(req->outbuf, smb_flg,
2551 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2554 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2555 SCVAL(req->outbuf, smb_flg,
2556 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2559 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2560 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2561 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2563 TALLOC_FREE(smb_fname);
2564 TALLOC_FREE(wire_name);
2565 END_PROFILE(SMBctemp);
2569 /*******************************************************************
2570 Check if a user is allowed to rename a file.
2571 ********************************************************************/
2573 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2576 if (!CAN_WRITE(conn)) {
2577 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2580 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2581 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2582 /* Only bother to read the DOS attribute if we might deny the
2583 rename on the grounds of attribute missmatch. */
2584 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2585 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2586 return NT_STATUS_NO_SUCH_FILE;
2590 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2591 if (fsp->posix_open) {
2592 return NT_STATUS_OK;
2595 /* If no pathnames are open below this
2596 directory, allow the rename. */
2598 if (file_find_subpath(fsp)) {
2599 return NT_STATUS_ACCESS_DENIED;
2601 return NT_STATUS_OK;
2604 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2605 return NT_STATUS_OK;
2608 return NT_STATUS_ACCESS_DENIED;
2611 /*******************************************************************
2612 * unlink a file with all relevant access checks
2613 *******************************************************************/
2615 static NTSTATUS do_unlink(connection_struct *conn,
2616 struct smb_request *req,
2617 struct smb_filename *smb_fname,
2622 uint32 dirtype_orig = dirtype;
2625 bool posix_paths = lp_posix_pathnames();
2627 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2628 smb_fname_str_dbg(smb_fname),
2631 if (!CAN_WRITE(conn)) {
2632 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2636 ret = SMB_VFS_LSTAT(conn, smb_fname);
2638 ret = SMB_VFS_STAT(conn, smb_fname);
2641 return map_nt_error_from_unix(errno);
2644 fattr = dos_mode(conn, smb_fname);
2646 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2647 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2650 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2652 return NT_STATUS_NO_SUCH_FILE;
2655 if (!dir_check_ftype(conn, fattr, dirtype)) {
2656 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2657 return NT_STATUS_FILE_IS_A_DIRECTORY;
2659 return NT_STATUS_NO_SUCH_FILE;
2662 if (dirtype_orig & 0x8000) {
2663 /* These will never be set for POSIX. */
2664 return NT_STATUS_NO_SUCH_FILE;
2668 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2669 return NT_STATUS_FILE_IS_A_DIRECTORY;
2672 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2673 return NT_STATUS_NO_SUCH_FILE;
2676 if (dirtype & 0xFF00) {
2677 /* These will never be set for POSIX. */
2678 return NT_STATUS_NO_SUCH_FILE;
2683 return NT_STATUS_NO_SUCH_FILE;
2686 /* Can't delete a directory. */
2687 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2688 return NT_STATUS_FILE_IS_A_DIRECTORY;
2693 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2694 return NT_STATUS_OBJECT_NAME_INVALID;
2695 #endif /* JRATEST */
2697 /* On open checks the open itself will check the share mode, so
2698 don't do it here as we'll get it wrong. */
2700 status = SMB_VFS_CREATE_FILE
2703 0, /* root_dir_fid */
2704 smb_fname, /* fname */
2705 DELETE_ACCESS, /* access_mask */
2706 FILE_SHARE_NONE, /* share_access */
2707 FILE_OPEN, /* create_disposition*/
2708 FILE_NON_DIRECTORY_FILE, /* create_options */
2709 /* file_attributes */
2710 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2711 FILE_ATTRIBUTE_NORMAL,
2712 0, /* oplock_request */
2713 0, /* allocation_size */
2714 0, /* private_flags */
2720 if (!NT_STATUS_IS_OK(status)) {
2721 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2722 nt_errstr(status)));
2726 status = can_set_delete_on_close(fsp, fattr);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2730 smb_fname_str_dbg(smb_fname),
2731 nt_errstr(status)));
2732 close_file(req, fsp, NORMAL_CLOSE);
2736 /* The set is across all open files on this dev/inode pair. */
2737 if (!set_delete_on_close(fsp, True,
2738 conn->session_info->security_token,
2739 conn->session_info->unix_token)) {
2740 close_file(req, fsp, NORMAL_CLOSE);
2741 return NT_STATUS_ACCESS_DENIED;
2744 return close_file(req, fsp, NORMAL_CLOSE);
2747 /****************************************************************************
2748 The guts of the unlink command, split out so it may be called by the NT SMB
2750 ****************************************************************************/
2752 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2753 uint32 dirtype, struct smb_filename *smb_fname,
2756 char *fname_dir = NULL;
2757 char *fname_mask = NULL;
2759 NTSTATUS status = NT_STATUS_OK;
2760 TALLOC_CTX *ctx = talloc_tos();
2762 /* Split up the directory from the filename/mask. */
2763 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2764 &fname_dir, &fname_mask);
2765 if (!NT_STATUS_IS_OK(status)) {
2770 * We should only check the mangled cache
2771 * here if unix_convert failed. This means
2772 * that the path in 'mask' doesn't exist
2773 * on the file system and so we need to look
2774 * for a possible mangle. This patch from
2775 * Tine Smukavec <valentin.smukavec@hermes.si>.
2778 if (!VALID_STAT(smb_fname->st) &&
2779 mangle_is_mangled(fname_mask, conn->params)) {
2780 char *new_mask = NULL;
2781 mangle_lookup_name_from_8_3(ctx, fname_mask,
2782 &new_mask, conn->params);
2784 TALLOC_FREE(fname_mask);
2785 fname_mask = new_mask;
2792 * Only one file needs to be unlinked. Append the mask back
2793 * onto the directory.
2795 TALLOC_FREE(smb_fname->base_name);
2796 if (ISDOT(fname_dir)) {
2797 /* Ensure we use canonical names on open. */
2798 smb_fname->base_name = talloc_asprintf(smb_fname,
2802 smb_fname->base_name = talloc_asprintf(smb_fname,
2807 if (!smb_fname->base_name) {
2808 status = NT_STATUS_NO_MEMORY;
2812 dirtype = FILE_ATTRIBUTE_NORMAL;
2815 status = check_name(conn, smb_fname->base_name);
2816 if (!NT_STATUS_IS_OK(status)) {
2820 status = do_unlink(conn, req, smb_fname, dirtype);
2821 if (!NT_STATUS_IS_OK(status)) {
2827 struct smb_Dir *dir_hnd = NULL;
2829 const char *dname = NULL;
2830 char *talloced = NULL;
2832 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2833 status = NT_STATUS_OBJECT_NAME_INVALID;
2837 if (strequal(fname_mask,"????????.???")) {
2838 TALLOC_FREE(fname_mask);
2839 fname_mask = talloc_strdup(ctx, "*");
2841 status = NT_STATUS_NO_MEMORY;
2846 status = check_name(conn, fname_dir);
2847 if (!NT_STATUS_IS_OK(status)) {
2851 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2853 if (dir_hnd == NULL) {
2854 status = map_nt_error_from_unix(errno);
2858 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2859 the pattern matches against the long name, otherwise the short name
2860 We don't implement this yet XXXX
2863 status = NT_STATUS_NO_SUCH_FILE;
2865 while ((dname = ReadDirName(dir_hnd, &offset,
2866 &smb_fname->st, &talloced))) {
2867 TALLOC_CTX *frame = talloc_stackframe();
2869 if (!is_visible_file(conn, fname_dir, dname,
2870 &smb_fname->st, true)) {
2872 TALLOC_FREE(talloced);
2876 /* Quick check for "." and ".." */
2877 if (ISDOT(dname) || ISDOTDOT(dname)) {
2879 TALLOC_FREE(talloced);
2883 if(!mask_match(dname, fname_mask,
2884 conn->case_sensitive)) {
2886 TALLOC_FREE(talloced);
2890 TALLOC_FREE(smb_fname->base_name);
2891 if (ISDOT(fname_dir)) {
2892 /* Ensure we use canonical names on open. */
2893 smb_fname->base_name =
2894 talloc_asprintf(smb_fname, "%s",
2897 smb_fname->base_name =
2898 talloc_asprintf(smb_fname, "%s/%s",
2902 if (!smb_fname->base_name) {
2903 TALLOC_FREE(dir_hnd);
2904 status = NT_STATUS_NO_MEMORY;
2906 TALLOC_FREE(talloced);
2910 status = check_name(conn, smb_fname->base_name);
2911 if (!NT_STATUS_IS_OK(status)) {
2912 TALLOC_FREE(dir_hnd);
2914 TALLOC_FREE(talloced);
2918 status = do_unlink(conn, req, smb_fname, dirtype);
2919 if (!NT_STATUS_IS_OK(status)) {
2921 TALLOC_FREE(talloced);
2926 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2927 smb_fname->base_name));
2930 TALLOC_FREE(talloced);
2932 TALLOC_FREE(dir_hnd);
2935 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2936 status = map_nt_error_from_unix(errno);
2940 TALLOC_FREE(fname_dir);
2941 TALLOC_FREE(fname_mask);
2945 /****************************************************************************
2947 ****************************************************************************/
2949 void reply_unlink(struct smb_request *req)
2951 connection_struct *conn = req->conn;
2953 struct smb_filename *smb_fname = NULL;
2956 bool path_contains_wcard = False;
2957 TALLOC_CTX *ctx = talloc_tos();
2959 START_PROFILE(SMBunlink);
2962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2966 dirtype = SVAL(req->vwv+0, 0);
2968 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2969 STR_TERMINATE, &status,
2970 &path_contains_wcard);
2971 if (!NT_STATUS_IS_OK(status)) {
2972 reply_nterror(req, status);
2976 status = filename_convert(ctx, conn,
2977 req->flags2 & FLAGS2_DFS_PATHNAMES,
2979 UCF_COND_ALLOW_WCARD_LCOMP,
2980 &path_contains_wcard,
2982 if (!NT_STATUS_IS_OK(status)) {
2983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2984 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2985 ERRSRV, ERRbadpath);
2988 reply_nterror(req, status);
2992 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2994 status = unlink_internals(conn, req, dirtype, smb_fname,
2995 path_contains_wcard);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 if (open_was_deferred(req->sconn, req->mid)) {
2998 /* We have re-scheduled this call. */
3001 reply_nterror(req, status);
3005 reply_outbuf(req, 0, 0);
3007 TALLOC_FREE(smb_fname);
3008 END_PROFILE(SMBunlink);
3012 /****************************************************************************
3014 ****************************************************************************/
3016 static void fail_readraw(void)
3018 const char *errstr = talloc_asprintf(talloc_tos(),
3019 "FAIL ! reply_readbraw: socket write fail (%s)",
3024 exit_server_cleanly(errstr);
3027 /****************************************************************************
3028 Fake (read/write) sendfile. Returns -1 on read or write fail.
3029 ****************************************************************************/
3031 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
3034 size_t tosend = nread;
3041 bufsize = MIN(nread, 65536);
3043 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3047 while (tosend > 0) {
3051 if (tosend > bufsize) {
3056 ret = read_file(fsp,buf,startpos,cur_read);
3062 /* If we had a short read, fill with zeros. */
3063 if (ret < cur_read) {
3064 memset(buf + ret, '\0', cur_read - ret);
3067 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
3069 char addr[INET6_ADDRSTRLEN];
3071 * Try and give an error message saying what
3074 DEBUG(0, ("write_data failed for client %s. "
3076 get_peer_addr(fsp->conn->sconn->sock, addr,
3083 startpos += cur_read;
3087 return (ssize_t)nread;
3090 /****************************************************************************
3091 Deal with the case of sendfile reading less bytes from the file than
3092 requested. Fill with zeros (all we can do).
3093 ****************************************************************************/
3095 void sendfile_short_send(files_struct *fsp,
3100 #define SHORT_SEND_BUFSIZE 1024
3101 if (nread < headersize) {
3102 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3103 "header for file %s (%s). Terminating\n",
3104 fsp_str_dbg(fsp), strerror(errno)));
3105 exit_server_cleanly("sendfile_short_send failed");
3108 nread -= headersize;
3110 if (nread < smb_maxcnt) {
3111 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3113 exit_server_cleanly("sendfile_short_send: "
3117 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3118 "with zeros !\n", fsp_str_dbg(fsp)));
3120 while (nread < smb_maxcnt) {
3122 * We asked for the real file size and told sendfile
3123 * to not go beyond the end of the file. But it can
3124 * happen that in between our fstat call and the
3125 * sendfile call the file was truncated. This is very
3126 * bad because we have already announced the larger
3127 * number of bytes to the client.
3129 * The best we can do now is to send 0-bytes, just as
3130 * a read from a hole in a sparse file would do.
3132 * This should happen rarely enough that I don't care
3133 * about efficiency here :-)
3137 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3138 if (write_data(fsp->conn->sconn->sock, buf, to_write)
3140 char addr[INET6_ADDRSTRLEN];
3142 * Try and give an error message saying what
3145 DEBUG(0, ("write_data failed for client %s. "
3148 fsp->conn->sconn->sock, addr,
3151 exit_server_cleanly("sendfile_short_send: "
3152 "write_data failed");
3160 /****************************************************************************
3161 Return a readbraw error (4 bytes of zero).
3162 ****************************************************************************/
3164 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3170 smbd_lock_socket(sconn);
3171 if (write_data(sconn->sock,header,4) != 4) {
3172 char addr[INET6_ADDRSTRLEN];
3174 * Try and give an error message saying what
3177 DEBUG(0, ("write_data failed for client %s. "
3179 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3184 smbd_unlock_socket(sconn);
3187 /****************************************************************************
3188 Use sendfile in readbraw.
3189 ****************************************************************************/
3191 static void send_file_readbraw(connection_struct *conn,
3192 struct smb_request *req,
3198 struct smbd_server_connection *sconn = req->sconn;
3199 char *outbuf = NULL;
3203 * We can only use sendfile on a non-chained packet
3204 * but we can use on a non-oplocked file. tridge proved this
3205 * on a train in Germany :-). JRA.
3206 * reply_readbraw has already checked the length.
3209 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3210 (fsp->wcp == NULL) &&
3211 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3212 ssize_t sendfile_read = -1;
3214 DATA_BLOB header_blob;
3216 _smb_setlen(header,nread);
3217 header_blob = data_blob_const(header, 4);
3219 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3220 &header_blob, startpos,
3222 if (sendfile_read == -1) {
3223 /* Returning ENOSYS means no data at all was sent.
3224 * Do this as a normal read. */
3225 if (errno == ENOSYS) {
3226 goto normal_readbraw;
3230 * Special hack for broken Linux with no working sendfile. If we
3231 * return EINTR we sent the header but not the rest of the data.
3232 * Fake this up by doing read/write calls.
3234 if (errno == EINTR) {
3235 /* Ensure we don't do this again. */
3236 set_use_sendfile(SNUM(conn), False);
3237 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3239 if (fake_sendfile(fsp, startpos, nread) == -1) {
3240 DEBUG(0,("send_file_readbraw: "
3241 "fake_sendfile failed for "
3245 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3250 DEBUG(0,("send_file_readbraw: sendfile failed for "
3251 "file %s (%s). Terminating\n",
3252 fsp_str_dbg(fsp), strerror(errno)));
3253 exit_server_cleanly("send_file_readbraw sendfile failed");
3254 } else if (sendfile_read == 0) {
3256 * Some sendfile implementations return 0 to indicate
3257 * that there was a short read, but nothing was
3258 * actually written to the socket. In this case,
3259 * fallback to the normal read path so the header gets
3260 * the correct byte count.
3262 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3263 "bytes falling back to the normal read: "
3264 "%s\n", fsp_str_dbg(fsp)));
3265 goto normal_readbraw;
3268 /* Deal with possible short send. */
3269 if (sendfile_read != 4+nread) {
3270 sendfile_short_send(fsp, sendfile_read, 4, nread);
3277 outbuf = talloc_array(NULL, char, nread+4);
3279 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3280 (unsigned)(nread+4)));
3281 reply_readbraw_error(sconn);
3286 ret = read_file(fsp,outbuf+4,startpos,nread);
3287 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3296 _smb_setlen(outbuf,ret);
3297 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3298 char addr[INET6_ADDRSTRLEN];
3300 * Try and give an error message saying what
3303 DEBUG(0, ("write_data failed for client %s. "
3305 get_peer_addr(fsp->conn->sconn->sock, addr,
3312 TALLOC_FREE(outbuf);
3315 /****************************************************************************
3316 Reply to a readbraw (core+ protocol).
3317 ****************************************************************************/
3319 void reply_readbraw(struct smb_request *req)
3321 connection_struct *conn = req->conn;
3322 struct smbd_server_connection *sconn = req->sconn;
3323 ssize_t maxcount,mincount;
3327 struct lock_struct lock;
3330 START_PROFILE(SMBreadbraw);
3332 if (srv_is_signing_active(sconn) || req->encrypted) {
3333 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3334 "raw reads/writes are disallowed.");
3338 reply_readbraw_error(sconn);
3339 END_PROFILE(SMBreadbraw);
3343 if (sconn->smb1.echo_handler.trusted_fde) {
3344 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3345 "'async smb echo handler = yes'\n"));
3346 reply_readbraw_error(sconn);
3347 END_PROFILE(SMBreadbraw);
3352 * Special check if an oplock break has been issued
3353 * and the readraw request croses on the wire, we must
3354 * return a zero length response here.
3357 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3360 * We have to do a check_fsp by hand here, as
3361 * we must always return 4 zero bytes on error,
3365 if (!fsp || !conn || conn != fsp->conn ||
3366 req->vuid != fsp->vuid ||
3367 fsp->is_directory || fsp->fh->fd == -1) {
3369 * fsp could be NULL here so use the value from the packet. JRA.
3371 DEBUG(3,("reply_readbraw: fnum %d not valid "
3373 (int)SVAL(req->vwv+0, 0)));
3374 reply_readbraw_error(sconn);
3375 END_PROFILE(SMBreadbraw);
3379 /* Do a "by hand" version of CHECK_READ. */
3380 if (!(fsp->can_read ||
3381 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3382 (fsp->access_mask & FILE_EXECUTE)))) {
3383 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3384 (int)SVAL(req->vwv+0, 0)));
3385 reply_readbraw_error(sconn);
3386 END_PROFILE(SMBreadbraw);
3390 flush_write_cache(fsp, READRAW_FLUSH);
3392 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3393 if(req->wct == 10) {
3395 * This is a large offset (64 bit) read.
3398 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3401 DEBUG(0,("reply_readbraw: negative 64 bit "
3402 "readraw offset (%.0f) !\n",
3403 (double)startpos ));
3404 reply_readbraw_error(sconn);
3405 END_PROFILE(SMBreadbraw);
3410 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3411 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3413 /* ensure we don't overrun the packet size */
3414 maxcount = MIN(65535,maxcount);
3416 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3417 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3420 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3421 reply_readbraw_error(sconn);
3422 END_PROFILE(SMBreadbraw);
3426 if (fsp_stat(fsp) == 0) {
3427 size = fsp->fsp_name->st.st_ex_size;
3430 if (startpos >= size) {
3433 nread = MIN(maxcount,(size - startpos));
3436 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3437 if (nread < mincount)
3441 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3442 "min=%lu nread=%lu\n",
3443 fsp_fnum_dbg(fsp), (double)startpos,
3444 (unsigned long)maxcount,
3445 (unsigned long)mincount,
3446 (unsigned long)nread ) );
3448 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3450 DEBUG(5,("reply_readbraw finished\n"));
3452 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3454 END_PROFILE(SMBreadbraw);
3459 #define DBGC_CLASS DBGC_LOCKING
3461 /****************************************************************************
3462 Reply to a lockread (core+ protocol).
3463 ****************************************************************************/
3465 void reply_lockread(struct smb_request *req)
3467 connection_struct *conn = req->conn;
3475 struct byte_range_lock *br_lck = NULL;
3477 struct smbd_server_connection *sconn = req->sconn;
3479 START_PROFILE(SMBlockread);
3482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3483 END_PROFILE(SMBlockread);
3487 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3489 if (!check_fsp(conn, req, fsp)) {
3490 END_PROFILE(SMBlockread);
3494 if (!CHECK_READ(fsp,req)) {
3495 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3496 END_PROFILE(SMBlockread);
3500 numtoread = SVAL(req->vwv+1, 0);
3501 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3504 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3505 * protocol request that predates the read/write lock concept.
3506 * Thus instead of asking for a read lock here we need to ask
3507 * for a write lock. JRA.
3508 * Note that the requested lock size is unaffected by max_send.
3511 br_lck = do_lock(req->sconn->msg_ctx,
3513 (uint64_t)req->smbpid,
3514 (uint64_t)numtoread,
3518 False, /* Non-blocking lock. */
3522 TALLOC_FREE(br_lck);
3524 if (NT_STATUS_V(status)) {
3525 reply_nterror(req, status);
3526 END_PROFILE(SMBlockread);
3531 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3533 maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3535 if (numtoread > maxtoread) {
3536 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3537 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3538 (unsigned int)numtoread, (unsigned int)maxtoread,
3539 (unsigned int)sconn->smb1.sessions.max_send));
3540 numtoread = maxtoread;
3543 reply_outbuf(req, 5, numtoread + 3);
3545 data = smb_buf(req->outbuf) + 3;
3547 nread = read_file(fsp,data,startpos,numtoread);
3550 reply_nterror(req, map_nt_error_from_unix(errno));
3551 END_PROFILE(SMBlockread);
3555 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3557 SSVAL(req->outbuf,smb_vwv0,nread);
3558 SSVAL(req->outbuf,smb_vwv5,nread+3);
3559 p = smb_buf(req->outbuf);
3560 SCVAL(p,0,0); /* pad byte. */
3563 DEBUG(3,("lockread %s num=%d nread=%d\n",
3564 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3566 END_PROFILE(SMBlockread);
3571 #define DBGC_CLASS DBGC_ALL
3573 /****************************************************************************
3575 ****************************************************************************/
3577 void reply_read(struct smb_request *req)
3579 connection_struct *conn = req->conn;
3586 struct lock_struct lock;
3587 struct smbd_server_connection *sconn = req->sconn;
3589 START_PROFILE(SMBread);
3592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3593 END_PROFILE(SMBread);
3597 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3599 if (!check_fsp(conn, req, fsp)) {
3600 END_PROFILE(SMBread);
3604 if (!CHECK_READ(fsp,req)) {
3605 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3606 END_PROFILE(SMBread);
3610 numtoread = SVAL(req->vwv+1, 0);
3611 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3613 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3616 * The requested read size cannot be greater than max_recv. JRA.
3618 if (numtoread > sconn->smb1.negprot.max_recv) {
3619 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3620 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3621 (unsigned int)numtoread,
3622 (unsigned int)sconn->smb1.negprot.max_recv));
3623 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3626 reply_outbuf(req, 5, numtoread+3);
3628 data = smb_buf(req->outbuf) + 3;
3630 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3631 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3634 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3635 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3636 END_PROFILE(SMBread);
3641 nread = read_file(fsp,data,startpos,numtoread);
3644 reply_nterror(req, map_nt_error_from_unix(errno));
3648 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3650 SSVAL(req->outbuf,smb_vwv0,nread);
3651 SSVAL(req->outbuf,smb_vwv5,nread+3);
3652 SCVAL(smb_buf(req->outbuf),0,1);
3653 SSVAL(smb_buf(req->outbuf),1,nread);
3655 DEBUG(3, ("read %s num=%d nread=%d\n",
3656 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3659 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3661 END_PROFILE(SMBread);
3665 /****************************************************************************
3667 ****************************************************************************/
3669 static int setup_readX_header(struct smb_request *req, char *outbuf,
3674 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3676 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3678 SCVAL(outbuf,smb_vwv0,0xFF);
3679 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3680 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3681 SSVAL(outbuf,smb_vwv6,
3682 (smb_wct - 4) /* offset from smb header to wct */
3683 + 1 /* the wct field */
3684 + 12 * sizeof(uint16_t) /* vwv */
3685 + 2); /* the buflen field */
3686 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3687 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3688 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3689 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3693 /****************************************************************************
3694 Reply to a read and X - possibly using sendfile.
3695 ****************************************************************************/
3697 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3698 files_struct *fsp, off_t startpos,
3702 struct lock_struct lock;
3703 int saved_errno = 0;
3705 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3706 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3709 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3710 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3715 * We can only use sendfile on a non-chained packet
3716 * but we can use on a non-oplocked file. tridge proved this
3717 * on a train in Germany :-). JRA.
3720 if (!req_is_in_chain(req) &&
3722 (fsp->base_fsp == NULL) &&
3723 (fsp->wcp == NULL) &&
3724 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3725 uint8 headerbuf[smb_size + 12 * 2];
3728 if(fsp_stat(fsp) == -1) {
3729 reply_nterror(req, map_nt_error_from_unix(errno));
3733 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3734 (startpos > fsp->fsp_name->st.st_ex_size) ||
3735 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3737 * We already know that we would do a short read, so don't
3738 * try the sendfile() path.
3740 goto nosendfile_read;
3744 * Set up the packet header before send. We
3745 * assume here the sendfile will work (get the
3746 * correct amount of data).
3749 header = data_blob_const(headerbuf, sizeof(headerbuf));
3751 construct_reply_common_req(req, (char *)headerbuf);
3752 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3754 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3755 startpos, smb_maxcnt);
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 DEBUG(0,("send_file_readX: "
3777 "fake_sendfile failed for "
3781 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3783 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3784 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3785 /* No outbuf here means successful sendfile. */
3789 DEBUG(0,("send_file_readX: sendfile failed for file "
3790 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3792 exit_server_cleanly("send_file_readX sendfile failed");
3793 } else if (nread == 0) {
3795 * Some sendfile implementations return 0 to indicate
3796 * that there was a short read, but nothing was
3797 * actually written to the socket. In this case,
3798 * fallback to the normal read path so the header gets
3799 * the correct byte count.
3801 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3802 "falling back to the normal read: %s\n",
3807 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3808 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3810 /* Deal with possible short send. */
3811 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3812 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3814 /* No outbuf here means successful sendfile. */
3815 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3816 SMB_PERFCOUNT_END(&req->pcd);
3822 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3823 uint8 headerbuf[smb_size + 2*12];
3825 construct_reply_common_req(req, (char *)headerbuf);
3826 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3828 /* Send out the header. */
3829 if (write_data(req->sconn->sock, (char *)headerbuf,
3830 sizeof(headerbuf)) != sizeof(headerbuf)) {
3832 char addr[INET6_ADDRSTRLEN];
3834 * Try and give an error message saying what
3837 DEBUG(0, ("write_data failed for client %s. "
3839 get_peer_addr(req->sconn->sock, addr,
3843 DEBUG(0,("send_file_readX: write_data failed for file "
3844 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3846 exit_server_cleanly("send_file_readX sendfile failed");
3848 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3850 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3851 "file %s (%s).\n", fsp_str_dbg(fsp),
3853 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3860 reply_outbuf(req, 12, smb_maxcnt);
3861 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3862 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3864 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3865 saved_errno = errno;
3867 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3870 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3874 setup_readX_header(req, (char *)req->outbuf, nread);
3876 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3877 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3881 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3882 TALLOC_FREE(req->outbuf);
3886 /****************************************************************************
3887 Work out how much space we have for a read return.
3888 ****************************************************************************/
3890 static size_t calc_max_read_pdu(const struct smb_request *req)
3892 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3893 return req->sconn->smb1.sessions.max_send;
3896 if (!lp_large_readwrite()) {
3897 return req->sconn->smb1.sessions.max_send;
3900 if (req_is_in_chain(req)) {
3901 return req->sconn->smb1.sessions.max_send;
3904 if (req->encrypted) {
3906 * Don't take encrypted traffic up to the
3907 * limit. There are padding considerations
3908 * that make that tricky.
3910 return req->sconn->smb1.sessions.max_send;
3913 if (srv_is_signing_active(req->sconn)) {
3917 if (!lp_unix_extensions()) {
3922 * We can do ultra-large POSIX reads.
3927 /****************************************************************************
3928 Calculate how big a read can be. Copes with all clients. It's always
3929 safe to return a short read - Windows does this.
3930 ****************************************************************************/
3932 static size_t calc_read_size(const struct smb_request *req,
3936 size_t max_pdu = calc_max_read_pdu(req);
3937 size_t total_size = 0;
3938 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3939 size_t max_len = max_pdu - hdr_len;
3942 * Windows explicitly ignores upper size of 0xFFFF.
3943 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3944 * We must do the same as these will never fit even in
3945 * an extended size NetBIOS packet.
3947 if (upper_size == 0xFFFF) {
3951 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3955 total_size = ((upper_size<<16) | lower_size);
3958 * LARGE_READX test shows it's always safe to return
3959 * a short read. Windows does so.
3961 return MIN(total_size, max_len);
3964 /****************************************************************************
3965 Reply to a read and X.
3966 ****************************************************************************/
3968 void reply_read_and_X(struct smb_request *req)
3970 connection_struct *conn = req->conn;
3975 bool big_readX = False;
3977 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3980 START_PROFILE(SMBreadX);
3982 if ((req->wct != 10) && (req->wct != 12)) {
3983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3987 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3988 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3989 smb_maxcnt = SVAL(req->vwv+5, 0);
3991 /* If it's an IPC, pass off the pipe handler. */
3993 reply_pipe_read_and_X(req);
3994 END_PROFILE(SMBreadX);
3998 if (!check_fsp(conn, req, fsp)) {
3999 END_PROFILE(SMBreadX);
4003 if (!CHECK_READ(fsp,req)) {
4004 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4005 END_PROFILE(SMBreadX);
4009 upper_size = SVAL(req->vwv+7, 0);
4010 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4011 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4013 * This is a heuristic to avoid keeping large
4014 * outgoing buffers around over long-lived aio
4020 if (req->wct == 12) {
4022 * This is a large offset (64 bit) read.
4024 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4029 NTSTATUS status = schedule_aio_read_and_X(conn,
4034 if (NT_STATUS_IS_OK(status)) {
4035 /* Read scheduled - we're done. */
4038 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4039 /* Real error - report to client. */
4040 END_PROFILE(SMBreadX);
4041 reply_nterror(req, status);
4044 /* NT_STATUS_RETRY - fall back to sync read. */
4047 smbd_lock_socket(req->sconn);
4048 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4049 smbd_unlock_socket(req->sconn);
4052 END_PROFILE(SMBreadX);
4056 /****************************************************************************
4057 Error replies to writebraw must have smb_wct == 1. Fix this up.
4058 ****************************************************************************/
4060 void error_to_writebrawerr(struct smb_request *req)
4062 uint8 *old_outbuf = req->outbuf;
4064 reply_outbuf(req, 1, 0);
4066 memcpy(req->outbuf, old_outbuf, smb_size);
4067 TALLOC_FREE(old_outbuf);
4070 /****************************************************************************
4071 Read 4 bytes of a smb packet and return the smb length of the packet.
4072 Store the result in the buffer. This version of the function will
4073 never return a session keepalive (length of zero).
4074 Timeout is in milliseconds.
4075 ****************************************************************************/
4077 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4080 uint8_t msgtype = NBSSkeepalive;
4082 while (msgtype == NBSSkeepalive) {
4085 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4087 if (!NT_STATUS_IS_OK(status)) {
4088 char addr[INET6_ADDRSTRLEN];
4089 /* Try and give an error message
4090 * saying what client failed. */
4091 DEBUG(0, ("read_fd_with_timeout failed for "
4092 "client %s read error = %s.\n",
4093 get_peer_addr(fd,addr,sizeof(addr)),
4094 nt_errstr(status)));
4098 msgtype = CVAL(inbuf, 0);
4101 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4102 (unsigned long)len));
4104 return NT_STATUS_OK;
4107 /****************************************************************************
4108 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4109 ****************************************************************************/
4111 void reply_writebraw(struct smb_request *req)
4113 connection_struct *conn = req->conn;
4116 ssize_t total_written=0;
4117 size_t numtowrite=0;
4120 const char *data=NULL;
4123 struct lock_struct lock;
4126 START_PROFILE(SMBwritebraw);
4129 * If we ever reply with an error, it must have the SMB command
4130 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4133 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4135 if (srv_is_signing_active(req->sconn)) {
4136 END_PROFILE(SMBwritebraw);
4137 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4138 "raw reads/writes are disallowed.");
4141 if (req->wct < 12) {
4142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4143 error_to_writebrawerr(req);
4144 END_PROFILE(SMBwritebraw);
4148 if (req->sconn->smb1.echo_handler.trusted_fde) {
4149 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4150 "'async smb echo handler = yes'\n"));
4151 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4152 error_to_writebrawerr(req);
4153 END_PROFILE(SMBwritebraw);
4157 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4158 if (!check_fsp(conn, req, fsp)) {
4159 error_to_writebrawerr(req);
4160 END_PROFILE(SMBwritebraw);
4164 if (!CHECK_WRITE(fsp)) {
4165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4166 error_to_writebrawerr(req);
4167 END_PROFILE(SMBwritebraw);
4171 tcount = IVAL(req->vwv+1, 0);
4172 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4173 write_through = BITSETW(req->vwv+7,0);
4175 /* We have to deal with slightly different formats depending
4176 on whether we are using the core+ or lanman1.0 protocol */
4178 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4179 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4180 data = smb_buf_const(req->inbuf);
4182 numtowrite = SVAL(req->vwv+10, 0);
4183 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4186 /* Ensure we don't write bytes past the end of this packet. */
4187 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4189 error_to_writebrawerr(req);
4190 END_PROFILE(SMBwritebraw);
4194 if (!fsp->print_file) {
4195 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4196 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4199 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4200 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4201 error_to_writebrawerr(req);
4202 END_PROFILE(SMBwritebraw);
4208 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4211 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4212 "wrote=%d sync=%d\n",
4213 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4214 (int)nwritten, (int)write_through));
4216 if (nwritten < (ssize_t)numtowrite) {
4217 reply_nterror(req, NT_STATUS_DISK_FULL);
4218 error_to_writebrawerr(req);
4222 total_written = nwritten;
4224 /* Allocate a buffer of 64k + length. */
4225 buf = talloc_array(NULL, char, 65540);
4227 reply_nterror(req, NT_STATUS_NO_MEMORY);
4228 error_to_writebrawerr(req);
4232 /* Return a SMBwritebraw message to the redirector to tell
4233 * it to send more bytes */
4235 memcpy(buf, req->inbuf, smb_size);
4236 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4237 SCVAL(buf,smb_com,SMBwritebraw);
4238 SSVALS(buf,smb_vwv0,0xFFFF);
4240 if (!srv_send_smb(req->sconn,
4242 false, 0, /* no signing */
4243 IS_CONN_ENCRYPTED(conn),
4245 exit_server_cleanly("reply_writebraw: srv_send_smb "
4249 /* Now read the raw data into the buffer and write it */
4250 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4252 if (!NT_STATUS_IS_OK(status)) {
4253 exit_server_cleanly("secondary writebraw failed");
4256 /* Set up outbuf to return the correct size */
4257 reply_outbuf(req, 1, 0);
4259 if (numtowrite != 0) {
4261 if (numtowrite > 0xFFFF) {
4262 DEBUG(0,("reply_writebraw: Oversize secondary write "
4263 "raw requested (%u). Terminating\n",
4264 (unsigned int)numtowrite ));
4265 exit_server_cleanly("secondary writebraw failed");
4268 if (tcount > nwritten+numtowrite) {
4269 DEBUG(3,("reply_writebraw: Client overestimated the "
4271 (int)tcount,(int)nwritten,(int)numtowrite));
4274 status = read_data(req->sconn->sock, buf+4, numtowrite);
4276 if (!NT_STATUS_IS_OK(status)) {
4277 char addr[INET6_ADDRSTRLEN];
4278 /* Try and give an error message
4279 * saying what client failed. */
4280 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4281 "raw read failed (%s) for client %s. "
4282 "Terminating\n", nt_errstr(status),
4283 get_peer_addr(req->sconn->sock, addr,
4285 exit_server_cleanly("secondary writebraw failed");
4288 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4289 if (nwritten == -1) {
4291 reply_nterror(req, map_nt_error_from_unix(errno));
4292 error_to_writebrawerr(req);
4296 if (nwritten < (ssize_t)numtowrite) {
4297 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4298 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4302 total_written += nwritten;
4307 SSVAL(req->outbuf,smb_vwv0,total_written);
4309 status = sync_file(conn, fsp, write_through);
4310 if (!NT_STATUS_IS_OK(status)) {
4311 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4312 fsp_str_dbg(fsp), nt_errstr(status)));
4313 reply_nterror(req, status);
4314 error_to_writebrawerr(req);
4318 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4320 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4321 (int)total_written));
4323 if (!fsp->print_file) {
4324 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4327 /* We won't return a status if write through is not selected - this
4328 * follows what WfWg does */
4329 END_PROFILE(SMBwritebraw);
4331 if (!write_through && total_written==tcount) {
4333 #if RABBIT_PELLET_FIX
4335 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4336 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4339 if (!send_keepalive(req->sconn->sock)) {
4340 exit_server_cleanly("reply_writebraw: send of "
4341 "keepalive failed");
4344 TALLOC_FREE(req->outbuf);
4349 if (!fsp->print_file) {
4350 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4353 END_PROFILE(SMBwritebraw);
4358 #define DBGC_CLASS DBGC_LOCKING
4360 /****************************************************************************
4361 Reply to a writeunlock (core+).
4362 ****************************************************************************/
4364 void reply_writeunlock(struct smb_request *req)
4366 connection_struct *conn = req->conn;
4367 ssize_t nwritten = -1;
4371 NTSTATUS status = NT_STATUS_OK;
4373 struct lock_struct lock;
4374 int saved_errno = 0;
4376 START_PROFILE(SMBwriteunlock);
4379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4380 END_PROFILE(SMBwriteunlock);
4384 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4386 if (!check_fsp(conn, req, fsp)) {
4387 END_PROFILE(SMBwriteunlock);
4391 if (!CHECK_WRITE(fsp)) {
4392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4393 END_PROFILE(SMBwriteunlock);
4397 numtowrite = SVAL(req->vwv+1, 0);
4398 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4399 data = (const char *)req->buf + 3;
4401 if (!fsp->print_file && numtowrite > 0) {
4402 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4403 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4406 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4407 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4408 END_PROFILE(SMBwriteunlock);
4413 /* The special X/Open SMB protocol handling of
4414 zero length writes is *NOT* done for
4416 if(numtowrite == 0) {
4419 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4420 saved_errno = errno;
4423 status = sync_file(conn, fsp, False /* write through */);
4424 if (!NT_STATUS_IS_OK(status)) {
4425 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4426 fsp_str_dbg(fsp), nt_errstr(status)));
4427 reply_nterror(req, status);
4432 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4436 if((nwritten < numtowrite) && (numtowrite != 0)) {
4437 reply_nterror(req, NT_STATUS_DISK_FULL);
4441 if (numtowrite && !fsp->print_file) {
4442 status = do_unlock(req->sconn->msg_ctx,
4444 (uint64_t)req->smbpid,
4445 (uint64_t)numtowrite,
4449 if (NT_STATUS_V(status)) {
4450 reply_nterror(req, status);
4455 reply_outbuf(req, 1, 0);
4457 SSVAL(req->outbuf,smb_vwv0,nwritten);
4459 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4460 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4463 if (numtowrite && !fsp->print_file) {
4464 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4467 END_PROFILE(SMBwriteunlock);
4472 #define DBGC_CLASS DBGC_ALL
4474 /****************************************************************************
4476 ****************************************************************************/
4478 void reply_write(struct smb_request *req)
4480 connection_struct *conn = req->conn;
4482 ssize_t nwritten = -1;
4486 struct lock_struct lock;
4488 int saved_errno = 0;
4490 START_PROFILE(SMBwrite);
4493 END_PROFILE(SMBwrite);
4494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4498 /* If it's an IPC, pass off the pipe handler. */
4500 reply_pipe_write(req);
4501 END_PROFILE(SMBwrite);
4505 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4507 if (!check_fsp(conn, req, fsp)) {
4508 END_PROFILE(SMBwrite);
4512 if (!CHECK_WRITE(fsp)) {
4513 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4514 END_PROFILE(SMBwrite);
4518 numtowrite = SVAL(req->vwv+1, 0);
4519 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4520 data = (const char *)req->buf + 3;
4522 if (!fsp->print_file) {
4523 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4524 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4527 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4528 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4529 END_PROFILE(SMBwrite);
4535 * X/Open SMB protocol says that if smb_vwv1 is
4536 * zero then the file size should be extended or
4537 * truncated to the size given in smb_vwv[2-3].
4540 if(numtowrite == 0) {
4542 * This is actually an allocate call, and set EOF. JRA.
4544 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4546 reply_nterror(req, NT_STATUS_DISK_FULL);
4549 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4551 reply_nterror(req, NT_STATUS_DISK_FULL);
4554 trigger_write_time_update_immediate(fsp);
4556 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4559 status = sync_file(conn, fsp, False);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4562 fsp_str_dbg(fsp), nt_errstr(status)));
4563 reply_nterror(req, status);
4568 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4572 if((nwritten == 0) && (numtowrite != 0)) {
4573 reply_nterror(req, NT_STATUS_DISK_FULL);
4577 reply_outbuf(req, 1, 0);
4579 SSVAL(req->outbuf,smb_vwv0,nwritten);
4581 if (nwritten < (ssize_t)numtowrite) {
4582 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4583 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4586 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4589 if (!fsp->print_file) {
4590 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4593 END_PROFILE(SMBwrite);
4597 /****************************************************************************
4598 Ensure a buffer is a valid writeX for recvfile purposes.
4599 ****************************************************************************/
4601 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4602 (2*14) + /* word count (including bcc) */ \
4605 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4606 const uint8_t *inbuf)
4609 connection_struct *conn = NULL;
4610 unsigned int doff = 0;
4611 size_t len = smb_len_large(inbuf);
4612 struct smbXsrv_tcon *tcon;
4616 if (is_encrypted_packet(sconn, inbuf)) {
4617 /* Can't do this on encrypted
4622 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4626 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4627 CVAL(inbuf,smb_wct) != 14) {
4628 DEBUG(10,("is_valid_writeX_buffer: chained or "
4629 "invalid word length.\n"));
4633 status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
4635 if (!NT_STATUS_IS_OK(status)) {
4636 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4639 conn = tcon->compat;
4642 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4645 if (IS_PRINT(conn)) {
4646 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4649 doff = SVAL(inbuf,smb_vwv11);
4651 numtowrite = SVAL(inbuf,smb_vwv10);
4653 if (len > doff && len - doff > 0xFFFF) {
4654 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4657 if (numtowrite == 0) {
4658 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4662 /* Ensure the sizes match up. */
4663 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4664 /* no pad byte...old smbclient :-( */
4665 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4667 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4671 if (len - doff != numtowrite) {
4672 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4673 "len = %u, doff = %u, numtowrite = %u\n",
4676 (unsigned int)numtowrite ));
4680 DEBUG(10,("is_valid_writeX_buffer: true "
4681 "len = %u, doff = %u, numtowrite = %u\n",
4684 (unsigned int)numtowrite ));
4689 /****************************************************************************
4690 Reply to a write and X.
4691 ****************************************************************************/
4693 void reply_write_and_X(struct smb_request *req)
4695 connection_struct *conn = req->conn;
4697 struct lock_struct lock;
4702 unsigned int smb_doff;
4703 unsigned int smblen;
4706 int saved_errno = 0;
4708 START_PROFILE(SMBwriteX);
4710 if ((req->wct != 12) && (req->wct != 14)) {
4711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4715 numtowrite = SVAL(req->vwv+10, 0);
4716 smb_doff = SVAL(req->vwv+11, 0);
4717 smblen = smb_len(req->inbuf);
4719 if (req->unread_bytes > 0xFFFF ||
4720 (smblen > smb_doff &&
4721 smblen - smb_doff > 0xFFFF)) {
4722 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4725 if (req->unread_bytes) {
4726 /* Can't do a recvfile write on IPC$ */
4728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4731 if (numtowrite != req->unread_bytes) {
4732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4736 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4737 smb_doff + numtowrite > smblen) {
4738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4743 /* If it's an IPC, pass off the pipe handler. */
4745 if (req->unread_bytes) {
4746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4749 reply_pipe_write_and_X(req);
4753 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4754 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4755 write_through = BITSETW(req->vwv+7,0);
4757 if (!check_fsp(conn, req, fsp)) {
4761 if (!CHECK_WRITE(fsp)) {
4762 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4766 data = smb_base(req->inbuf) + smb_doff;
4768 if(req->wct == 14) {
4770 * This is a large offset (64 bit) write.
4772 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4776 /* X/Open SMB protocol says that, unlike SMBwrite
4777 if the length is zero then NO truncation is
4778 done, just a write of zero. To truncate a file,
4781 if(numtowrite == 0) {
4784 if (req->unread_bytes == 0) {
4785 status = schedule_aio_write_and_X(conn,
4792 if (NT_STATUS_IS_OK(status)) {
4793 /* write scheduled - we're done. */
4796 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4797 /* Real error - report to client. */
4798 reply_nterror(req, status);
4801 /* NT_STATUS_RETRY - fall through to sync write. */
4804 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4805 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4808 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4809 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4813 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4814 saved_errno = errno;
4816 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4820 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4824 if((nwritten == 0) && (numtowrite != 0)) {
4825 reply_nterror(req, NT_STATUS_DISK_FULL);
4829 reply_outbuf(req, 6, 0);
4830 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4831 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4832 SSVAL(req->outbuf,smb_vwv2,nwritten);
4833 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4835 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4836 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4838 status = sync_file(conn, fsp, write_through);
4839 if (!NT_STATUS_IS_OK(status)) {
4840 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4841 fsp_str_dbg(fsp), nt_errstr(status)));
4842 reply_nterror(req, status);
4846 END_PROFILE(SMBwriteX);
4850 if (req->unread_bytes) {
4851 /* writeX failed. drain socket. */
4852 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4853 req->unread_bytes) {
4854 smb_panic("failed to drain pending bytes");
4856 req->unread_bytes = 0;
4859 END_PROFILE(SMBwriteX);
4863 /****************************************************************************
4865 ****************************************************************************/
4867 void reply_lseek(struct smb_request *req)
4869 connection_struct *conn = req->conn;
4875 START_PROFILE(SMBlseek);
4878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4879 END_PROFILE(SMBlseek);
4883 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4885 if (!check_fsp(conn, req, fsp)) {
4889 flush_write_cache(fsp, SEEK_FLUSH);
4891 mode = SVAL(req->vwv+1, 0) & 3;
4892 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4893 startpos = (off_t)IVALS(req->vwv+2, 0);
4902 res = fsp->fh->pos + startpos;
4913 if (umode == SEEK_END) {
4914 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4915 if(errno == EINVAL) {
4916 off_t current_pos = startpos;
4918 if(fsp_stat(fsp) == -1) {
4920 map_nt_error_from_unix(errno));
4921 END_PROFILE(SMBlseek);
4925 current_pos += fsp->fsp_name->st.st_ex_size;
4927 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4932 reply_nterror(req, map_nt_error_from_unix(errno));
4933 END_PROFILE(SMBlseek);
4940 reply_outbuf(req, 2, 0);
4941 SIVAL(req->outbuf,smb_vwv0,res);
4943 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4944 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4946 END_PROFILE(SMBlseek);
4950 /****************************************************************************
4952 ****************************************************************************/
4954 void reply_flush(struct smb_request *req)
4956 connection_struct *conn = req->conn;
4960 START_PROFILE(SMBflush);
4963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4967 fnum = SVAL(req->vwv+0, 0);
4968 fsp = file_fsp(req, fnum);
4970 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4975 file_sync_all(conn);
4977 NTSTATUS status = sync_file(conn, fsp, True);
4978 if (!NT_STATUS_IS_OK(status)) {
4979 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4980 fsp_str_dbg(fsp), nt_errstr(status)));
4981 reply_nterror(req, status);
4982 END_PROFILE(SMBflush);
4987 reply_outbuf(req, 0, 0);
4989 DEBUG(3,("flush\n"));
4990 END_PROFILE(SMBflush);
4994 /****************************************************************************
4996 conn POINTER CAN BE NULL HERE !
4997 ****************************************************************************/
4999 void reply_exit(struct smb_request *req)
5001 START_PROFILE(SMBexit);
5003 file_close_pid(req->sconn, req->smbpid, req->vuid);
5005 reply_outbuf(req, 0, 0);
5007 DEBUG(3,("exit\n"));
5009 END_PROFILE(SMBexit);
5013 struct reply_close_state {
5015 struct smb_request *smbreq;
5018 static void do_smb1_close(struct tevent_req *req);
5020 void reply_close(struct smb_request *req)
5022 connection_struct *conn = req->conn;
5023 NTSTATUS status = NT_STATUS_OK;
5024 files_struct *fsp = NULL;
5025 START_PROFILE(SMBclose);
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5029 END_PROFILE(SMBclose);
5033 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5036 * We can only use check_fsp if we know it's not a directory.
5039 if (!check_fsp_open(conn, req, fsp)) {
5040 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5041 END_PROFILE(SMBclose);
5045 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5046 fsp->is_directory ? "directory" : "file",
5047 fsp->fh->fd, fsp_fnum_dbg(fsp),
5048 conn->num_files_open));
5050 if (!fsp->is_directory) {
5054 * Take care of any time sent in the close.
5057 t = srv_make_unix_date3(req->vwv+1);
5058 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5061 if (fsp->num_aio_requests != 0) {
5063 struct reply_close_state *state;
5065 DEBUG(10, ("closing with aio %u requests pending\n",
5066 fsp->num_aio_requests));
5069 * We depend on the aio_extra destructor to take care of this
5070 * close request once fsp->num_aio_request drops to 0.
5073 fsp->deferred_close = tevent_wait_send(
5074 fsp, fsp->conn->sconn->ev_ctx);
5075 if (fsp->deferred_close == NULL) {
5076 status = NT_STATUS_NO_MEMORY;
5080 state = talloc(fsp, struct reply_close_state);
5081 if (state == NULL) {
5082 TALLOC_FREE(fsp->deferred_close);
5083 status = NT_STATUS_NO_MEMORY;
5087 state->smbreq = talloc_move(fsp, &req);
5088 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5090 END_PROFILE(SMBclose);
5095 * close_file() returns the unix errno if an error was detected on
5096 * close - normally this is due to a disk full error. If not then it
5097 * was probably an I/O error.
5100 status = close_file(req, fsp, NORMAL_CLOSE);
5102 if (!NT_STATUS_IS_OK(status)) {
5103 reply_nterror(req, status);
5104 END_PROFILE(SMBclose);
5108 reply_outbuf(req, 0, 0);
5109 END_PROFILE(SMBclose);
5113 static void do_smb1_close(struct tevent_req *req)
5115 struct reply_close_state *state = tevent_req_callback_data(
5116 req, struct reply_close_state);
5117 struct smb_request *smbreq;
5121 ret = tevent_wait_recv(req);
5124 DEBUG(10, ("tevent_wait_recv returned %s\n",
5127 * Continue anyway, this should never happen
5132 * fsp->smb2_close_request right now is a talloc grandchild of
5133 * fsp. When we close_file(fsp), it would go with it. No chance to
5136 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5138 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5139 if (NT_STATUS_IS_OK(status)) {
5140 reply_outbuf(smbreq, 0, 0);
5142 reply_nterror(smbreq, status);
5144 if (!srv_send_smb(smbreq->sconn,
5145 (char *)smbreq->outbuf,
5148 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5150 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5153 TALLOC_FREE(smbreq);
5156 /****************************************************************************
5157 Reply to a writeclose (Core+ protocol).
5158 ****************************************************************************/
5160 void reply_writeclose(struct smb_request *req)
5162 connection_struct *conn = req->conn;
5164 ssize_t nwritten = -1;
5165 NTSTATUS close_status = NT_STATUS_OK;
5168 struct timespec mtime;
5170 struct lock_struct lock;
5172 START_PROFILE(SMBwriteclose);
5175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5176 END_PROFILE(SMBwriteclose);
5180 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5182 if (!check_fsp(conn, req, fsp)) {
5183 END_PROFILE(SMBwriteclose);
5186 if (!CHECK_WRITE(fsp)) {
5187 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5188 END_PROFILE(SMBwriteclose);
5192 numtowrite = SVAL(req->vwv+1, 0);
5193 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5194 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5195 data = (const char *)req->buf + 1;
5197 if (!fsp->print_file) {
5198 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5199 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5202 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5203 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5204 END_PROFILE(SMBwriteclose);
5209 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5211 set_close_write_time(fsp, mtime);
5214 * More insanity. W2K only closes the file if writelen > 0.
5219 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5220 "file %s\n", fsp_str_dbg(fsp)));
5221 close_status = close_file(req, fsp, NORMAL_CLOSE);
5224 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5225 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5226 conn->num_files_open));
5228 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5229 reply_nterror(req, NT_STATUS_DISK_FULL);
5233 if(!NT_STATUS_IS_OK(close_status)) {
5234 reply_nterror(req, close_status);
5238 reply_outbuf(req, 1, 0);
5240 SSVAL(req->outbuf,smb_vwv0,nwritten);
5243 if (numtowrite && !fsp->print_file) {
5244 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5247 END_PROFILE(SMBwriteclose);
5252 #define DBGC_CLASS DBGC_LOCKING
5254 /****************************************************************************
5256 ****************************************************************************/
5258 void reply_lock(struct smb_request *req)
5260 connection_struct *conn = req->conn;
5261 uint64_t count,offset;
5264 struct byte_range_lock *br_lck = NULL;
5266 START_PROFILE(SMBlock);
5269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5270 END_PROFILE(SMBlock);
5274 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5276 if (!check_fsp(conn, req, fsp)) {
5277 END_PROFILE(SMBlock);
5281 count = (uint64_t)IVAL(req->vwv+1, 0);
5282 offset = (uint64_t)IVAL(req->vwv+3, 0);
5284 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5285 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5287 br_lck = do_lock(req->sconn->msg_ctx,
5289 (uint64_t)req->smbpid,
5294 False, /* Non-blocking lock. */
5299 TALLOC_FREE(br_lck);
5301 if (NT_STATUS_V(status)) {
5302 reply_nterror(req, status);
5303 END_PROFILE(SMBlock);
5307 reply_outbuf(req, 0, 0);
5309 END_PROFILE(SMBlock);
5313 /****************************************************************************
5315 ****************************************************************************/
5317 void reply_unlock(struct smb_request *req)
5319 connection_struct *conn = req->conn;
5320 uint64_t count,offset;
5324 START_PROFILE(SMBunlock);
5327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5328 END_PROFILE(SMBunlock);
5332 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5334 if (!check_fsp(conn, req, fsp)) {
5335 END_PROFILE(SMBunlock);
5339 count = (uint64_t)IVAL(req->vwv+1, 0);
5340 offset = (uint64_t)IVAL(req->vwv+3, 0);
5342 status = do_unlock(req->sconn->msg_ctx,
5344 (uint64_t)req->smbpid,
5349 if (NT_STATUS_V(status)) {
5350 reply_nterror(req, status);
5351 END_PROFILE(SMBunlock);
5355 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5356 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5358 reply_outbuf(req, 0, 0);
5360 END_PROFILE(SMBunlock);
5365 #define DBGC_CLASS DBGC_ALL
5367 /****************************************************************************
5369 conn POINTER CAN BE NULL HERE !
5370 ****************************************************************************/
5372 void reply_tdis(struct smb_request *req)
5375 connection_struct *conn = req->conn;
5376 struct smbXsrv_tcon *tcon;
5378 START_PROFILE(SMBtdis);
5381 DEBUG(4,("Invalid connection in tdis\n"));
5382 reply_force_doserror(req, ERRSRV, ERRinvnid);
5383 END_PROFILE(SMBtdis);
5391 * TODO: cancel all outstanding requests on the tcon
5393 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 DEBUG(0, ("reply_tdis: "
5396 "smbXsrv_tcon_disconnect() failed: %s\n",
5397 nt_errstr(status)));
5399 * If we hit this case, there is something completely
5400 * wrong, so we better disconnect the transport connection.
5402 END_PROFILE(SMBtdis);
5403 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5409 reply_outbuf(req, 0, 0);
5410 END_PROFILE(SMBtdis);
5414 /****************************************************************************
5416 conn POINTER CAN BE NULL HERE !
5417 ****************************************************************************/
5419 void reply_echo(struct smb_request *req)
5421 connection_struct *conn = req->conn;
5422 struct smb_perfcount_data local_pcd;
5423 struct smb_perfcount_data *cur_pcd;
5427 START_PROFILE(SMBecho);
5429 smb_init_perfcount_data(&local_pcd);
5432 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5433 END_PROFILE(SMBecho);
5437 smb_reverb = SVAL(req->vwv+0, 0);
5439 reply_outbuf(req, 1, req->buflen);
5441 /* copy any incoming data back out */
5442 if (req->buflen > 0) {
5443 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5446 if (smb_reverb > 100) {
5447 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5451 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5453 /* this makes sure we catch the request pcd */
5454 if (seq_num == smb_reverb) {
5455 cur_pcd = &req->pcd;
5457 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5458 cur_pcd = &local_pcd;
5461 SSVAL(req->outbuf,smb_vwv0,seq_num);
5463 show_msg((char *)req->outbuf);
5464 if (!srv_send_smb(req->sconn,
5465 (char *)req->outbuf,
5466 true, req->seqnum+1,
5467 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5469 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5472 DEBUG(3,("echo %d times\n", smb_reverb));
5474 TALLOC_FREE(req->outbuf);
5476 END_PROFILE(SMBecho);
5480 /****************************************************************************
5481 Reply to a printopen.
5482 ****************************************************************************/
5484 void reply_printopen(struct smb_request *req)
5486 connection_struct *conn = req->conn;
5490 START_PROFILE(SMBsplopen);
5493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5494 END_PROFILE(SMBsplopen);
5498 if (!CAN_PRINT(conn)) {
5499 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5500 END_PROFILE(SMBsplopen);
5504 status = file_new(req, conn, &fsp);
5505 if(!NT_STATUS_IS_OK(status)) {
5506 reply_nterror(req, status);
5507 END_PROFILE(SMBsplopen);
5511 /* Open for exclusive use, write only. */
5512 status = print_spool_open(fsp, NULL, req->vuid);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 file_free(req, fsp);
5516 reply_nterror(req, status);
5517 END_PROFILE(SMBsplopen);
5521 reply_outbuf(req, 1, 0);
5522 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5524 DEBUG(3,("openprint fd=%d %s\n",
5525 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5527 END_PROFILE(SMBsplopen);
5531 /****************************************************************************
5532 Reply to a printclose.
5533 ****************************************************************************/
5535 void reply_printclose(struct smb_request *req)
5537 connection_struct *conn = req->conn;
5541 START_PROFILE(SMBsplclose);
5544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5545 END_PROFILE(SMBsplclose);
5549 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5551 if (!check_fsp(conn, req, fsp)) {
5552 END_PROFILE(SMBsplclose);
5556 if (!CAN_PRINT(conn)) {
5557 reply_force_doserror(req, ERRSRV, ERRerror);
5558 END_PROFILE(SMBsplclose);
5562 DEBUG(3,("printclose fd=%d %s\n",
5563 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5565 status = close_file(req, fsp, NORMAL_CLOSE);
5567 if(!NT_STATUS_IS_OK(status)) {
5568 reply_nterror(req, status);
5569 END_PROFILE(SMBsplclose);
5573 reply_outbuf(req, 0, 0);
5575 END_PROFILE(SMBsplclose);
5579 /****************************************************************************
5580 Reply to a printqueue.
5581 ****************************************************************************/
5583 void reply_printqueue(struct smb_request *req)
5585 connection_struct *conn = req->conn;
5589 START_PROFILE(SMBsplretq);
5592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5593 END_PROFILE(SMBsplretq);
5597 max_count = SVAL(req->vwv+0, 0);
5598 start_index = SVAL(req->vwv+1, 0);
5600 /* we used to allow the client to get the cnum wrong, but that
5601 is really quite gross and only worked when there was only
5602 one printer - I think we should now only accept it if they
5603 get it right (tridge) */
5604 if (!CAN_PRINT(conn)) {
5605 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5606 END_PROFILE(SMBsplretq);
5610 reply_outbuf(req, 2, 3);
5611 SSVAL(req->outbuf,smb_vwv0,0);
5612 SSVAL(req->outbuf,smb_vwv1,0);
5613 SCVAL(smb_buf(req->outbuf),0,1);
5614 SSVAL(smb_buf(req->outbuf),1,0);
5616 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5617 start_index, max_count));
5620 TALLOC_CTX *mem_ctx = talloc_tos();
5623 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5624 struct rpc_pipe_client *cli = NULL;
5625 struct dcerpc_binding_handle *b = NULL;
5626 struct policy_handle handle;
5627 struct spoolss_DevmodeContainer devmode_ctr;
5628 union spoolss_JobInfo *info;
5630 uint32_t num_to_get;
5634 ZERO_STRUCT(handle);
5636 status = rpc_pipe_open_interface(conn,
5637 &ndr_table_spoolss.syntax_id,
5639 conn->sconn->remote_address,
5640 conn->sconn->msg_ctx,
5642 if (!NT_STATUS_IS_OK(status)) {
5643 DEBUG(0, ("reply_printqueue: "
5644 "could not connect to spoolss: %s\n",
5645 nt_errstr(status)));
5646 reply_nterror(req, status);
5649 b = cli->binding_handle;
5651 ZERO_STRUCT(devmode_ctr);
5653 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5656 SEC_FLAG_MAXIMUM_ALLOWED,
5659 if (!NT_STATUS_IS_OK(status)) {
5660 reply_nterror(req, status);
5663 if (!W_ERROR_IS_OK(werr)) {
5664 reply_nterror(req, werror_to_ntstatus(werr));
5668 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5676 if (!W_ERROR_IS_OK(werr)) {
5677 reply_nterror(req, werror_to_ntstatus(werr));
5681 if (max_count > 0) {
5682 first = start_index;
5684 first = start_index + max_count + 1;
5687 if (first >= count) {
5690 num_to_get = first + MIN(ABS(max_count), count - first);
5693 for (i = first; i < num_to_get; i++) {
5696 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5698 uint16_t qrapjobid = pjobid_to_rap(sharename,
5699 info[i].info2.job_id);
5701 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5707 srv_put_dos_date2(p, 0, qtime);
5708 SCVAL(p, 4, qstatus);
5709 SSVAL(p, 5, qrapjobid);
5710 SIVAL(p, 7, info[i].info2.size);
5712 srvstr_push(blob, req->flags2, p+12,
5713 info[i].info2.notify_name, 16, STR_ASCII);
5715 if (message_push_blob(
5718 blob, sizeof(blob))) == -1) {
5719 reply_nterror(req, NT_STATUS_NO_MEMORY);
5725 SSVAL(req->outbuf,smb_vwv0,count);
5726 SSVAL(req->outbuf,smb_vwv1,
5727 (max_count>0?first+count:first-1));
5728 SCVAL(smb_buf(req->outbuf),0,1);
5729 SSVAL(smb_buf(req->outbuf),1,28*count);
5733 DEBUG(3, ("%u entries returned in queue\n",
5737 if (b && is_valid_policy_hnd(&handle)) {
5738 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5743 END_PROFILE(SMBsplretq);
5747 /****************************************************************************
5748 Reply to a printwrite.
5749 ****************************************************************************/
5751 void reply_printwrite(struct smb_request *req)
5753 connection_struct *conn = req->conn;
5758 START_PROFILE(SMBsplwr);
5761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5762 END_PROFILE(SMBsplwr);
5766 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5768 if (!check_fsp(conn, req, fsp)) {
5769 END_PROFILE(SMBsplwr);
5773 if (!fsp->print_file) {
5774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5775 END_PROFILE(SMBsplwr);
5779 if (!CHECK_WRITE(fsp)) {
5780 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5781 END_PROFILE(SMBsplwr);
5785 numtowrite = SVAL(req->buf, 1);
5787 if (req->buflen < numtowrite + 3) {
5788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5789 END_PROFILE(SMBsplwr);
5793 data = (const char *)req->buf + 3;
5795 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5796 reply_nterror(req, map_nt_error_from_unix(errno));
5797 END_PROFILE(SMBsplwr);
5801 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5803 END_PROFILE(SMBsplwr);
5807 /****************************************************************************
5809 ****************************************************************************/
5811 void reply_mkdir(struct smb_request *req)
5813 connection_struct *conn = req->conn;
5814 struct smb_filename *smb_dname = NULL;
5815 char *directory = NULL;
5817 TALLOC_CTX *ctx = talloc_tos();
5819 START_PROFILE(SMBmkdir);
5821 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5822 STR_TERMINATE, &status);
5823 if (!NT_STATUS_IS_OK(status)) {
5824 reply_nterror(req, status);
5828 status = filename_convert(ctx, conn,
5829 req->flags2 & FLAGS2_DFS_PATHNAMES,
5831 UCF_PREP_CREATEFILE,
5834 if (!NT_STATUS_IS_OK(status)) {
5835 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5836 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5837 ERRSRV, ERRbadpath);
5840 reply_nterror(req, status);
5844 status = create_directory(conn, req, smb_dname);
5846 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5848 if (!NT_STATUS_IS_OK(status)) {
5850 if (!use_nt_status()
5851 && NT_STATUS_EQUAL(status,
5852 NT_STATUS_OBJECT_NAME_COLLISION)) {
5854 * Yes, in the DOS error code case we get a
5855 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5856 * samba4 torture test.
5858 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5861 reply_nterror(req, status);
5865 reply_outbuf(req, 0, 0);
5867 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5869 TALLOC_FREE(smb_dname);
5870 END_PROFILE(SMBmkdir);
5874 /****************************************************************************
5876 ****************************************************************************/
5878 void reply_rmdir(struct smb_request *req)
5880 connection_struct *conn = req->conn;
5881 struct smb_filename *smb_dname = NULL;
5882 char *directory = NULL;
5884 TALLOC_CTX *ctx = talloc_tos();
5885 files_struct *fsp = NULL;
5887 struct smbd_server_connection *sconn = req->sconn;
5889 START_PROFILE(SMBrmdir);
5891 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5892 STR_TERMINATE, &status);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 reply_nterror(req, status);
5898 status = filename_convert(ctx, conn,
5899 req->flags2 & FLAGS2_DFS_PATHNAMES,
5904 if (!NT_STATUS_IS_OK(status)) {
5905 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5906 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5907 ERRSRV, ERRbadpath);
5910 reply_nterror(req, status);
5914 if (is_ntfs_stream_smb_fname(smb_dname)) {
5915 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5919 status = SMB_VFS_CREATE_FILE(
5922 0, /* root_dir_fid */
5923 smb_dname, /* fname */
5924 DELETE_ACCESS, /* access_mask */
5925 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5927 FILE_OPEN, /* create_disposition*/
5928 FILE_DIRECTORY_FILE, /* create_options */
5929 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5930 0, /* oplock_request */
5931 0, /* allocation_size */
5932 0, /* private_flags */
5938 if (!NT_STATUS_IS_OK(status)) {
5939 if (open_was_deferred(req->sconn, req->mid)) {
5940 /* We have re-scheduled this call. */
5943 reply_nterror(req, status);
5947 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 close_file(req, fsp, ERROR_CLOSE);
5950 reply_nterror(req, status);
5954 if (!set_delete_on_close(fsp, true,
5955 conn->session_info->security_token,
5956 conn->session_info->unix_token)) {
5957 close_file(req, fsp, ERROR_CLOSE);
5958 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5962 status = close_file(req, fsp, NORMAL_CLOSE);
5963 if (!NT_STATUS_IS_OK(status)) {
5964 reply_nterror(req, status);
5966 reply_outbuf(req, 0, 0);
5969 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5971 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5973 TALLOC_FREE(smb_dname);
5974 END_PROFILE(SMBrmdir);
5978 /*******************************************************************
5979 Resolve wildcards in a filename rename.
5980 ********************************************************************/
5982 static bool resolve_wildcards(TALLOC_CTX *ctx,
5987 char *name2_copy = NULL;
5992 char *p,*p2, *pname1, *pname2;
5994 name2_copy = talloc_strdup(ctx, name2);
5999 pname1 = strrchr_m(name1,'/');
6000 pname2 = strrchr_m(name2_copy,'/');
6002 if (!pname1 || !pname2) {
6006 /* Truncate the copy of name2 at the last '/' */
6009 /* Now go past the '/' */
6013 root1 = talloc_strdup(ctx, pname1);
6014 root2 = talloc_strdup(ctx, pname2);
6016 if (!root1 || !root2) {
6020 p = strrchr_m(root1,'.');
6023 ext1 = talloc_strdup(ctx, p+1);
6025 ext1 = talloc_strdup(ctx, "");
6027 p = strrchr_m(root2,'.');
6030 ext2 = talloc_strdup(ctx, p+1);
6032 ext2 = talloc_strdup(ctx, "");
6035 if (!ext1 || !ext2) {
6043 /* Hmmm. Should this be mb-aware ? */
6046 } else if (*p2 == '*') {
6048 root2 = talloc_asprintf(ctx, "%s%s",
6067 /* Hmmm. Should this be mb-aware ? */
6070 } else if (*p2 == '*') {
6072 ext2 = talloc_asprintf(ctx, "%s%s",
6088 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6093 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6105 /****************************************************************************
6106 Ensure open files have their names updated. Updated to notify other smbd's
6108 ****************************************************************************/
6110 static void rename_open_files(connection_struct *conn,
6111 struct share_mode_lock *lck,
6112 uint32_t orig_name_hash,
6113 const struct smb_filename *smb_fname_dst)
6116 bool did_rename = False;
6118 uint32_t new_name_hash = 0;
6120 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
6121 fsp = file_find_di_next(fsp)) {
6122 /* fsp_name is a relative path under the fsp. To change this for other
6123 sharepaths we need to manipulate relative paths. */
6124 /* TODO - create the absolute path and manipulate the newname
6125 relative to the sharepath. */
6126 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6129 if (fsp->name_hash != orig_name_hash) {
6132 DEBUG(10, ("rename_open_files: renaming file %s "
6133 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6134 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6135 smb_fname_str_dbg(smb_fname_dst)));
6137 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6138 if (NT_STATUS_IS_OK(status)) {
6140 new_name_hash = fsp->name_hash;
6145 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6146 "for %s\n", file_id_string_tos(&lck->data->id),
6147 smb_fname_str_dbg(smb_fname_dst)));
6150 /* Send messages to all smbd's (not ourself) that the name has changed. */
6151 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
6152 orig_name_hash, new_name_hash,
6157 /****************************************************************************
6158 We need to check if the source path is a parent directory of the destination
6159 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6160 refuse the rename with a sharing violation. Under UNIX the above call can
6161 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6162 probably need to check that the client is a Windows one before disallowing
6163 this as a UNIX client (one with UNIX extensions) can know the source is a
6164 symlink and make this decision intelligently. Found by an excellent bug
6165 report from <AndyLiebman@aol.com>.
6166 ****************************************************************************/
6168 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6169 const struct smb_filename *smb_fname_dst)
6171 const char *psrc = smb_fname_src->base_name;
6172 const char *pdst = smb_fname_dst->base_name;
6175 if (psrc[0] == '.' && psrc[1] == '/') {
6178 if (pdst[0] == '.' && pdst[1] == '/') {
6181 if ((slen = strlen(psrc)) > strlen(pdst)) {
6184 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6188 * Do the notify calls from a rename
6191 static void notify_rename(connection_struct *conn, bool is_dir,
6192 const struct smb_filename *smb_fname_src,
6193 const struct smb_filename *smb_fname_dst)
6195 char *parent_dir_src = NULL;
6196 char *parent_dir_dst = NULL;
6199 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6200 : FILE_NOTIFY_CHANGE_FILE_NAME;
6202 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6203 &parent_dir_src, NULL) ||
6204 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6205 &parent_dir_dst, NULL)) {
6209 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6210 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6211 smb_fname_src->base_name);
6212 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6213 smb_fname_dst->base_name);
6216 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6217 smb_fname_src->base_name);
6218 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6219 smb_fname_dst->base_name);
6222 /* this is a strange one. w2k3 gives an additional event for
6223 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6224 files, but not directories */
6226 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6227 FILE_NOTIFY_CHANGE_ATTRIBUTES
6228 |FILE_NOTIFY_CHANGE_CREATION,
6229 smb_fname_dst->base_name);
6232 TALLOC_FREE(parent_dir_src);
6233 TALLOC_FREE(parent_dir_dst);
6236 /****************************************************************************
6237 Returns an error if the parent directory for a filename is open in an
6239 ****************************************************************************/
6241 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6242 const struct smb_filename *smb_fname_dst_in)
6244 char *parent_dir = NULL;
6245 struct smb_filename smb_fname_parent;
6247 files_struct *fsp = NULL;
6250 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6251 &parent_dir, NULL)) {
6252 return NT_STATUS_NO_MEMORY;
6254 ZERO_STRUCT(smb_fname_parent);
6255 smb_fname_parent.base_name = parent_dir;
6257 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6259 return map_nt_error_from_unix(errno);
6263 * We're only checking on this smbd here, mostly good
6264 * enough.. and will pass tests.
6267 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6268 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6269 fsp = file_find_di_next(fsp)) {
6270 if (fsp->access_mask & DELETE_ACCESS) {
6271 return NT_STATUS_SHARING_VIOLATION;
6274 return NT_STATUS_OK;
6277 /****************************************************************************
6278 Rename an open file - given an fsp.
6279 ****************************************************************************/
6281 NTSTATUS rename_internals_fsp(connection_struct *conn,
6283 const struct smb_filename *smb_fname_dst_in,
6285 bool replace_if_exists)
6287 TALLOC_CTX *ctx = talloc_tos();
6288 struct smb_filename *smb_fname_dst = NULL;
6289 NTSTATUS status = NT_STATUS_OK;
6290 struct share_mode_lock *lck = NULL;
6291 bool dst_exists, old_is_stream, new_is_stream;
6293 status = check_name(conn, smb_fname_dst_in->base_name);
6294 if (!NT_STATUS_IS_OK(status)) {
6298 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6299 if (!NT_STATUS_IS_OK(status)) {
6303 /* Make a copy of the dst smb_fname structs */
6305 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6306 if (!NT_STATUS_IS_OK(status)) {
6311 * Check for special case with case preserving and not
6312 * case sensitive. If the old last component differs from the original
6313 * last component only by case, then we should allow
6314 * the rename (user is trying to change the case of the
6317 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6318 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6319 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6321 char *fname_dst_lcomp_base_mod = NULL;
6322 struct smb_filename *smb_fname_orig_lcomp = NULL;
6325 * Get the last component of the destination name.
6327 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6329 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6331 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6333 if (!fname_dst_lcomp_base_mod) {
6334 status = NT_STATUS_NO_MEMORY;
6339 * Create an smb_filename struct using the original last
6340 * component of the destination.
6342 status = create_synthetic_smb_fname_split(ctx,
6343 smb_fname_dst->original_lcomp, NULL,
6344 &smb_fname_orig_lcomp);
6345 if (!NT_STATUS_IS_OK(status)) {
6346 TALLOC_FREE(fname_dst_lcomp_base_mod);
6350 /* If the base names only differ by case, use original. */
6351 if(!strcsequal(fname_dst_lcomp_base_mod,
6352 smb_fname_orig_lcomp->base_name)) {
6355 * Replace the modified last component with the
6359 *last_slash = '\0'; /* Truncate at the '/' */
6360 tmp = talloc_asprintf(smb_fname_dst,
6362 smb_fname_dst->base_name,
6363 smb_fname_orig_lcomp->base_name);
6365 tmp = talloc_asprintf(smb_fname_dst,
6367 smb_fname_orig_lcomp->base_name);
6370 status = NT_STATUS_NO_MEMORY;
6371 TALLOC_FREE(fname_dst_lcomp_base_mod);
6372 TALLOC_FREE(smb_fname_orig_lcomp);
6375 TALLOC_FREE(smb_fname_dst->base_name);
6376 smb_fname_dst->base_name = tmp;
6379 /* If the stream_names only differ by case, use original. */
6380 if(!strcsequal(smb_fname_dst->stream_name,
6381 smb_fname_orig_lcomp->stream_name)) {
6383 /* Use the original stream. */
6384 tmp = talloc_strdup(smb_fname_dst,
6385 smb_fname_orig_lcomp->stream_name);
6387 status = NT_STATUS_NO_MEMORY;
6388 TALLOC_FREE(fname_dst_lcomp_base_mod);
6389 TALLOC_FREE(smb_fname_orig_lcomp);
6392 TALLOC_FREE(smb_fname_dst->stream_name);
6393 smb_fname_dst->stream_name = tmp;
6395 TALLOC_FREE(fname_dst_lcomp_base_mod);
6396 TALLOC_FREE(smb_fname_orig_lcomp);
6400 * If the src and dest names are identical - including case,
6401 * don't do the rename, just return success.
6404 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6405 strcsequal(fsp->fsp_name->stream_name,
6406 smb_fname_dst->stream_name)) {
6407 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6408 "- returning success\n",
6409 smb_fname_str_dbg(smb_fname_dst)));
6410 status = NT_STATUS_OK;
6414 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6415 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6417 /* Return the correct error code if both names aren't streams. */
6418 if (!old_is_stream && new_is_stream) {
6419 status = NT_STATUS_OBJECT_NAME_INVALID;
6423 if (old_is_stream && !new_is_stream) {
6424 status = NT_STATUS_INVALID_PARAMETER;
6428 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6430 if(!replace_if_exists && dst_exists) {
6431 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6432 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6433 smb_fname_str_dbg(smb_fname_dst)));
6434 status = NT_STATUS_OBJECT_NAME_COLLISION;
6439 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6440 &smb_fname_dst->st);
6441 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6443 /* The file can be open when renaming a stream */
6444 if (dst_fsp && !new_is_stream) {
6445 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6446 status = NT_STATUS_ACCESS_DENIED;
6451 /* Ensure we have a valid stat struct for the source. */
6452 status = vfs_stat_fsp(fsp);
6453 if (!NT_STATUS_IS_OK(status)) {
6457 status = can_rename(conn, fsp, attrs);
6459 if (!NT_STATUS_IS_OK(status)) {
6460 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6461 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6462 smb_fname_str_dbg(smb_fname_dst)));
6463 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6464 status = NT_STATUS_ACCESS_DENIED;
6468 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6469 status = NT_STATUS_ACCESS_DENIED;
6472 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6475 * We have the file open ourselves, so not being able to get the
6476 * corresponding share mode lock is a fatal error.
6479 SMB_ASSERT(lck != NULL);
6481 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6482 uint32 create_options = fsp->fh->private_options;
6484 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6485 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6486 smb_fname_str_dbg(smb_fname_dst)));
6488 if (!fsp->is_directory &&
6489 !lp_posix_pathnames() &&
6490 (lp_map_archive(SNUM(conn)) ||
6491 lp_store_dos_attributes(SNUM(conn)))) {
6492 /* We must set the archive bit on the newly
6494 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6495 uint32_t old_dosmode = dos_mode(conn,
6497 file_set_dosmode(conn,
6499 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6505 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6508 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6511 * A rename acts as a new file create w.r.t. allowing an initial delete
6512 * on close, probably because in Windows there is a new handle to the
6513 * new file. If initial delete on close was requested but not
6514 * originally set, we need to set it here. This is probably not 100% correct,
6515 * but will work for the CIFSFS client which in non-posix mode
6516 * depends on these semantics. JRA.
6519 if (create_options & FILE_DELETE_ON_CLOSE) {
6520 status = can_set_delete_on_close(fsp, 0);
6522 if (NT_STATUS_IS_OK(status)) {
6523 /* Note that here we set the *inital* delete on close flag,
6524 * not the regular one. The magic gets handled in close. */
6525 fsp->initial_delete_on_close = True;
6529 status = NT_STATUS_OK;
6535 if (errno == ENOTDIR || errno == EISDIR) {
6536 status = NT_STATUS_OBJECT_NAME_COLLISION;
6538 status = map_nt_error_from_unix(errno);
6541 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6542 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6543 smb_fname_str_dbg(smb_fname_dst)));
6546 TALLOC_FREE(smb_fname_dst);
6551 /****************************************************************************
6552 The guts of the rename command, split out so it may be called by the NT SMB
6554 ****************************************************************************/
6556 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6557 connection_struct *conn,
6558 struct smb_request *req,
6559 struct smb_filename *smb_fname_src,
6560 struct smb_filename *smb_fname_dst,
6562 bool replace_if_exists,
6565 uint32_t access_mask)
6567 char *fname_src_dir = NULL;
6568 char *fname_src_mask = NULL;
6570 NTSTATUS status = NT_STATUS_OK;
6571 struct smb_Dir *dir_hnd = NULL;
6572 const char *dname = NULL;
6573 char *talloced = NULL;
6575 int create_options = 0;
6576 bool posix_pathnames = lp_posix_pathnames();
6579 * Split the old name into directory and last component
6580 * strings. Note that unix_convert may have stripped off a
6581 * leading ./ from both name and newname if the rename is
6582 * at the root of the share. We need to make sure either both
6583 * name and newname contain a / character or neither of them do
6584 * as this is checked in resolve_wildcards().
6587 /* Split up the directory from the filename/mask. */
6588 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6589 &fname_src_dir, &fname_src_mask);
6590 if (!NT_STATUS_IS_OK(status)) {
6591 status = NT_STATUS_NO_MEMORY;
6596 * We should only check the mangled cache
6597 * here if unix_convert failed. This means
6598 * that the path in 'mask' doesn't exist
6599 * on the file system and so we need to look
6600 * for a possible mangle. This patch from
6601 * Tine Smukavec <valentin.smukavec@hermes.si>.
6604 if (!VALID_STAT(smb_fname_src->st) &&
6605 mangle_is_mangled(fname_src_mask, conn->params)) {
6606 char *new_mask = NULL;
6607 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6610 TALLOC_FREE(fname_src_mask);
6611 fname_src_mask = new_mask;
6615 if (!src_has_wild) {
6619 * Only one file needs to be renamed. Append the mask back
6620 * onto the directory.
6622 TALLOC_FREE(smb_fname_src->base_name);
6623 if (ISDOT(fname_src_dir)) {
6624 /* Ensure we use canonical names on open. */
6625 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6629 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6634 if (!smb_fname_src->base_name) {
6635 status = NT_STATUS_NO_MEMORY;
6639 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6640 "case_preserve = %d, short case preserve = %d, "
6641 "directory = %s, newname = %s, "
6642 "last_component_dest = %s\n",
6643 conn->case_sensitive, conn->case_preserve,
6644 conn->short_case_preserve,
6645 smb_fname_str_dbg(smb_fname_src),
6646 smb_fname_str_dbg(smb_fname_dst),
6647 smb_fname_dst->original_lcomp));
6649 /* The dest name still may have wildcards. */
6650 if (dest_has_wild) {
6651 char *fname_dst_mod = NULL;
6652 if (!resolve_wildcards(smb_fname_dst,
6653 smb_fname_src->base_name,
6654 smb_fname_dst->base_name,
6656 DEBUG(6, ("rename_internals: resolve_wildcards "
6658 smb_fname_src->base_name,
6659 smb_fname_dst->base_name));
6660 status = NT_STATUS_NO_MEMORY;
6663 TALLOC_FREE(smb_fname_dst->base_name);
6664 smb_fname_dst->base_name = fname_dst_mod;
6667 ZERO_STRUCT(smb_fname_src->st);
6668 if (posix_pathnames) {
6669 SMB_VFS_LSTAT(conn, smb_fname_src);
6671 SMB_VFS_STAT(conn, smb_fname_src);
6674 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6675 create_options |= FILE_DIRECTORY_FILE;
6678 status = SMB_VFS_CREATE_FILE(
6681 0, /* root_dir_fid */
6682 smb_fname_src, /* fname */
6683 access_mask, /* access_mask */
6684 (FILE_SHARE_READ | /* share_access */
6686 FILE_OPEN, /* create_disposition*/
6687 create_options, /* create_options */
6688 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6689 0, /* oplock_request */
6690 0, /* allocation_size */
6691 0, /* private_flags */
6697 if (!NT_STATUS_IS_OK(status)) {
6698 DEBUG(3, ("Could not open rename source %s: %s\n",
6699 smb_fname_str_dbg(smb_fname_src),
6700 nt_errstr(status)));
6704 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6705 attrs, replace_if_exists);
6707 close_file(req, fsp, NORMAL_CLOSE);
6709 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6710 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6711 smb_fname_str_dbg(smb_fname_dst)));
6717 * Wildcards - process each file that matches.
6719 if (strequal(fname_src_mask, "????????.???")) {
6720 TALLOC_FREE(fname_src_mask);
6721 fname_src_mask = talloc_strdup(ctx, "*");
6722 if (!fname_src_mask) {
6723 status = NT_STATUS_NO_MEMORY;
6728 status = check_name(conn, fname_src_dir);
6729 if (!NT_STATUS_IS_OK(status)) {
6733 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6735 if (dir_hnd == NULL) {
6736 status = map_nt_error_from_unix(errno);
6740 status = NT_STATUS_NO_SUCH_FILE;
6742 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6743 * - gentest fix. JRA
6746 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6748 files_struct *fsp = NULL;
6749 char *destname = NULL;
6750 bool sysdir_entry = False;
6752 /* Quick check for "." and ".." */
6753 if (ISDOT(dname) || ISDOTDOT(dname)) {
6754 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6755 sysdir_entry = True;
6757 TALLOC_FREE(talloced);
6762 if (!is_visible_file(conn, fname_src_dir, dname,
6763 &smb_fname_src->st, false)) {
6764 TALLOC_FREE(talloced);
6768 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6769 TALLOC_FREE(talloced);
6774 status = NT_STATUS_OBJECT_NAME_INVALID;
6778 TALLOC_FREE(smb_fname_src->base_name);
6779 if (ISDOT(fname_src_dir)) {
6780 /* Ensure we use canonical names on open. */
6781 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6785 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6790 if (!smb_fname_src->base_name) {
6791 status = NT_STATUS_NO_MEMORY;
6795 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6796 smb_fname_dst->base_name,
6798 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6799 smb_fname_src->base_name, destname));
6800 TALLOC_FREE(talloced);
6804 status = NT_STATUS_NO_MEMORY;
6808 TALLOC_FREE(smb_fname_dst->base_name);
6809 smb_fname_dst->base_name = destname;
6811 ZERO_STRUCT(smb_fname_src->st);
6812 if (posix_pathnames) {
6813 SMB_VFS_LSTAT(conn, smb_fname_src);
6815 SMB_VFS_STAT(conn, smb_fname_src);
6820 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6821 create_options |= FILE_DIRECTORY_FILE;
6824 status = SMB_VFS_CREATE_FILE(
6827 0, /* root_dir_fid */
6828 smb_fname_src, /* fname */
6829 access_mask, /* access_mask */
6830 (FILE_SHARE_READ | /* share_access */
6832 FILE_OPEN, /* create_disposition*/
6833 create_options, /* create_options */
6834 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6835 0, /* oplock_request */
6836 0, /* allocation_size */
6837 0, /* private_flags */
6843 if (!NT_STATUS_IS_OK(status)) {
6844 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6845 "returned %s rename %s -> %s\n",
6847 smb_fname_str_dbg(smb_fname_src),
6848 smb_fname_str_dbg(smb_fname_dst)));
6852 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6854 if (!smb_fname_dst->original_lcomp) {
6855 status = NT_STATUS_NO_MEMORY;
6859 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6860 attrs, replace_if_exists);
6862 close_file(req, fsp, NORMAL_CLOSE);
6864 if (!NT_STATUS_IS_OK(status)) {
6865 DEBUG(3, ("rename_internals_fsp returned %s for "
6866 "rename %s -> %s\n", nt_errstr(status),
6867 smb_fname_str_dbg(smb_fname_src),
6868 smb_fname_str_dbg(smb_fname_dst)));
6874 DEBUG(3,("rename_internals: doing rename on %s -> "
6875 "%s\n", smb_fname_str_dbg(smb_fname_src),
6876 smb_fname_str_dbg(smb_fname_src)));
6877 TALLOC_FREE(talloced);
6879 TALLOC_FREE(dir_hnd);
6881 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6882 status = map_nt_error_from_unix(errno);
6886 TALLOC_FREE(talloced);
6887 TALLOC_FREE(fname_src_dir);
6888 TALLOC_FREE(fname_src_mask);
6892 /****************************************************************************
6894 ****************************************************************************/
6896 void reply_mv(struct smb_request *req)
6898 connection_struct *conn = req->conn;
6900 char *newname = NULL;
6904 bool src_has_wcard = False;
6905 bool dest_has_wcard = False;
6906 TALLOC_CTX *ctx = talloc_tos();
6907 struct smb_filename *smb_fname_src = NULL;
6908 struct smb_filename *smb_fname_dst = NULL;
6909 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6910 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6911 bool stream_rename = false;
6913 START_PROFILE(SMBmv);
6916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6920 attrs = SVAL(req->vwv+0, 0);
6922 p = (const char *)req->buf + 1;
6923 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6924 &status, &src_has_wcard);
6925 if (!NT_STATUS_IS_OK(status)) {
6926 reply_nterror(req, status);
6930 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6931 &status, &dest_has_wcard);
6932 if (!NT_STATUS_IS_OK(status)) {
6933 reply_nterror(req, status);
6937 if (!lp_posix_pathnames()) {
6938 /* The newname must begin with a ':' if the
6939 name contains a ':'. */
6940 if (strchr_m(name, ':')) {
6941 if (newname[0] != ':') {
6942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6945 stream_rename = true;
6949 status = filename_convert(ctx,
6951 req->flags2 & FLAGS2_DFS_PATHNAMES,
6957 if (!NT_STATUS_IS_OK(status)) {
6958 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6959 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6960 ERRSRV, ERRbadpath);
6963 reply_nterror(req, status);
6967 status = filename_convert(ctx,
6969 req->flags2 & FLAGS2_DFS_PATHNAMES,
6975 if (!NT_STATUS_IS_OK(status)) {
6976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6977 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6978 ERRSRV, ERRbadpath);
6981 reply_nterror(req, status);
6985 if (stream_rename) {
6986 /* smb_fname_dst->base_name must be the same as
6987 smb_fname_src->base_name. */
6988 TALLOC_FREE(smb_fname_dst->base_name);
6989 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6990 smb_fname_src->base_name);
6991 if (!smb_fname_dst->base_name) {
6992 reply_nterror(req, NT_STATUS_NO_MEMORY);
6997 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6998 smb_fname_str_dbg(smb_fname_dst)));
7000 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7001 attrs, False, src_has_wcard, dest_has_wcard,
7003 if (!NT_STATUS_IS_OK(status)) {
7004 if (open_was_deferred(req->sconn, req->mid)) {
7005 /* We have re-scheduled this call. */
7008 reply_nterror(req, status);
7012 reply_outbuf(req, 0, 0);
7014 TALLOC_FREE(smb_fname_src);
7015 TALLOC_FREE(smb_fname_dst);
7020 /*******************************************************************
7021 Copy a file as part of a reply_copy.
7022 ******************************************************************/
7025 * TODO: check error codes on all callers
7028 NTSTATUS copy_file(TALLOC_CTX *ctx,
7029 connection_struct *conn,
7030 struct smb_filename *smb_fname_src,
7031 struct smb_filename *smb_fname_dst,
7034 bool target_is_directory)
7036 struct smb_filename *smb_fname_dst_tmp = NULL;
7038 files_struct *fsp1,*fsp2;
7040 uint32 new_create_disposition;
7044 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
7045 if (!NT_STATUS_IS_OK(status)) {
7050 * If the target is a directory, extract the last component from the
7051 * src filename and append it to the dst filename
7053 if (target_is_directory) {
7056 /* dest/target can't be a stream if it's a directory. */
7057 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7059 p = strrchr_m(smb_fname_src->base_name,'/');
7063 p = smb_fname_src->base_name;
7065 smb_fname_dst_tmp->base_name =
7066 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7068 if (!smb_fname_dst_tmp->base_name) {
7069 status = NT_STATUS_NO_MEMORY;
7074 status = vfs_file_exist(conn, smb_fname_src);
7075 if (!NT_STATUS_IS_OK(status)) {
7079 if (!target_is_directory && count) {
7080 new_create_disposition = FILE_OPEN;
7082 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7085 &new_create_disposition,
7088 status = NT_STATUS_INVALID_PARAMETER;
7093 /* Open the src file for reading. */
7094 status = SMB_VFS_CREATE_FILE(
7097 0, /* root_dir_fid */
7098 smb_fname_src, /* fname */
7099 FILE_GENERIC_READ, /* access_mask */
7100 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7101 FILE_OPEN, /* create_disposition*/
7102 0, /* create_options */
7103 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7104 INTERNAL_OPEN_ONLY, /* oplock_request */
7105 0, /* allocation_size */
7106 0, /* private_flags */
7112 if (!NT_STATUS_IS_OK(status)) {
7116 dosattrs = dos_mode(conn, smb_fname_src);
7118 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7119 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7122 /* Open the dst file for writing. */
7123 status = SMB_VFS_CREATE_FILE(
7126 0, /* root_dir_fid */
7127 smb_fname_dst, /* fname */
7128 FILE_GENERIC_WRITE, /* access_mask */
7129 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7130 new_create_disposition, /* create_disposition*/
7131 0, /* create_options */
7132 dosattrs, /* file_attributes */
7133 INTERNAL_OPEN_ONLY, /* oplock_request */
7134 0, /* allocation_size */
7135 0, /* private_flags */
7141 if (!NT_STATUS_IS_OK(status)) {
7142 close_file(NULL, fsp1, ERROR_CLOSE);
7146 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7147 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7149 DEBUG(0, ("error - vfs lseek returned error %s\n",
7151 status = map_nt_error_from_unix(errno);
7152 close_file(NULL, fsp1, ERROR_CLOSE);
7153 close_file(NULL, fsp2, ERROR_CLOSE);
7158 /* Do the actual copy. */
7159 if (smb_fname_src->st.st_ex_size) {
7160 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7165 close_file(NULL, fsp1, NORMAL_CLOSE);
7167 /* Ensure the modtime is set correctly on the destination file. */
7168 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7171 * As we are opening fsp1 read-only we only expect
7172 * an error on close on fsp2 if we are out of space.
7173 * Thus we don't look at the error return from the
7176 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7178 if (!NT_STATUS_IS_OK(status)) {
7182 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7183 status = NT_STATUS_DISK_FULL;
7187 status = NT_STATUS_OK;
7190 TALLOC_FREE(smb_fname_dst_tmp);
7194 /****************************************************************************
7195 Reply to a file copy.
7196 ****************************************************************************/
7198 void reply_copy(struct smb_request *req)
7200 connection_struct *conn = req->conn;
7201 struct smb_filename *smb_fname_src = NULL;
7202 struct smb_filename *smb_fname_dst = NULL;
7203 char *fname_src = NULL;
7204 char *fname_dst = NULL;
7205 char *fname_src_mask = NULL;
7206 char *fname_src_dir = NULL;
7209 int error = ERRnoaccess;
7213 bool target_is_directory=False;
7214 bool source_has_wild = False;
7215 bool dest_has_wild = False;
7217 TALLOC_CTX *ctx = talloc_tos();
7219 START_PROFILE(SMBcopy);
7222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7226 tid2 = SVAL(req->vwv+0, 0);
7227 ofun = SVAL(req->vwv+1, 0);
7228 flags = SVAL(req->vwv+2, 0);
7230 p = (const char *)req->buf;
7231 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7232 &status, &source_has_wild);
7233 if (!NT_STATUS_IS_OK(status)) {
7234 reply_nterror(req, status);
7237 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7238 &status, &dest_has_wild);
7239 if (!NT_STATUS_IS_OK(status)) {
7240 reply_nterror(req, status);
7244 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7246 if (tid2 != conn->cnum) {
7247 /* can't currently handle inter share copies XXXX */
7248 DEBUG(3,("Rejecting inter-share copy\n"));
7249 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7253 status = filename_convert(ctx, conn,
7254 req->flags2 & FLAGS2_DFS_PATHNAMES,
7256 UCF_COND_ALLOW_WCARD_LCOMP,
7259 if (!NT_STATUS_IS_OK(status)) {
7260 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7261 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7262 ERRSRV, ERRbadpath);
7265 reply_nterror(req, status);
7269 status = filename_convert(ctx, conn,
7270 req->flags2 & FLAGS2_DFS_PATHNAMES,
7272 UCF_COND_ALLOW_WCARD_LCOMP,
7275 if (!NT_STATUS_IS_OK(status)) {
7276 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7277 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7278 ERRSRV, ERRbadpath);
7281 reply_nterror(req, status);
7285 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7287 if ((flags&1) && target_is_directory) {
7288 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7292 if ((flags&2) && !target_is_directory) {
7293 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7297 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7298 /* wants a tree copy! XXXX */
7299 DEBUG(3,("Rejecting tree copy\n"));
7300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7304 /* Split up the directory from the filename/mask. */
7305 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7306 &fname_src_dir, &fname_src_mask);
7307 if (!NT_STATUS_IS_OK(status)) {
7308 reply_nterror(req, NT_STATUS_NO_MEMORY);
7313 * We should only check the mangled cache
7314 * here if unix_convert failed. This means
7315 * that the path in 'mask' doesn't exist
7316 * on the file system and so we need to look
7317 * for a possible mangle. This patch from
7318 * Tine Smukavec <valentin.smukavec@hermes.si>.
7320 if (!VALID_STAT(smb_fname_src->st) &&
7321 mangle_is_mangled(fname_src_mask, conn->params)) {
7322 char *new_mask = NULL;
7323 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7324 &new_mask, conn->params);
7326 /* Use demangled name if one was successfully found. */
7328 TALLOC_FREE(fname_src_mask);
7329 fname_src_mask = new_mask;
7333 if (!source_has_wild) {
7336 * Only one file needs to be copied. Append the mask back onto
7339 TALLOC_FREE(smb_fname_src->base_name);
7340 if (ISDOT(fname_src_dir)) {
7341 /* Ensure we use canonical names on open. */
7342 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7346 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7351 if (!smb_fname_src->base_name) {
7352 reply_nterror(req, NT_STATUS_NO_MEMORY);
7356 if (dest_has_wild) {
7357 char *fname_dst_mod = NULL;
7358 if (!resolve_wildcards(smb_fname_dst,
7359 smb_fname_src->base_name,
7360 smb_fname_dst->base_name,
7362 reply_nterror(req, NT_STATUS_NO_MEMORY);
7365 TALLOC_FREE(smb_fname_dst->base_name);
7366 smb_fname_dst->base_name = fname_dst_mod;
7369 status = check_name(conn, smb_fname_src->base_name);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 reply_nterror(req, status);
7375 status = check_name(conn, smb_fname_dst->base_name);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 reply_nterror(req, status);
7381 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7382 ofun, count, target_is_directory);
7384 if(!NT_STATUS_IS_OK(status)) {
7385 reply_nterror(req, status);
7391 struct smb_Dir *dir_hnd = NULL;
7392 const char *dname = NULL;
7393 char *talloced = NULL;
7397 * There is a wildcard that requires us to actually read the
7398 * src dir and copy each file matching the mask to the dst.
7399 * Right now streams won't be copied, but this could
7400 * presumably be added with a nested loop for reach dir entry.
7402 SMB_ASSERT(!smb_fname_src->stream_name);
7403 SMB_ASSERT(!smb_fname_dst->stream_name);
7405 smb_fname_src->stream_name = NULL;
7406 smb_fname_dst->stream_name = NULL;
7408 if (strequal(fname_src_mask,"????????.???")) {
7409 TALLOC_FREE(fname_src_mask);
7410 fname_src_mask = talloc_strdup(ctx, "*");
7411 if (!fname_src_mask) {
7412 reply_nterror(req, NT_STATUS_NO_MEMORY);
7417 status = check_name(conn, fname_src_dir);
7418 if (!NT_STATUS_IS_OK(status)) {
7419 reply_nterror(req, status);
7423 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7424 if (dir_hnd == NULL) {
7425 status = map_nt_error_from_unix(errno);
7426 reply_nterror(req, status);
7432 /* Iterate over the src dir copying each entry to the dst. */
7433 while ((dname = ReadDirName(dir_hnd, &offset,
7434 &smb_fname_src->st, &talloced))) {
7435 char *destname = NULL;
7437 if (ISDOT(dname) || ISDOTDOT(dname)) {
7438 TALLOC_FREE(talloced);
7442 if (!is_visible_file(conn, fname_src_dir, dname,
7443 &smb_fname_src->st, false)) {
7444 TALLOC_FREE(talloced);
7448 if(!mask_match(dname, fname_src_mask,
7449 conn->case_sensitive)) {
7450 TALLOC_FREE(talloced);
7454 error = ERRnoaccess;
7456 /* Get the src smb_fname struct setup. */
7457 TALLOC_FREE(smb_fname_src->base_name);
7458 if (ISDOT(fname_src_dir)) {
7459 /* Ensure we use canonical names on open. */
7460 smb_fname_src->base_name =
7461 talloc_asprintf(smb_fname_src, "%s",
7464 smb_fname_src->base_name =
7465 talloc_asprintf(smb_fname_src, "%s/%s",
7466 fname_src_dir, dname);
7469 if (!smb_fname_src->base_name) {
7470 TALLOC_FREE(dir_hnd);
7471 TALLOC_FREE(talloced);
7472 reply_nterror(req, NT_STATUS_NO_MEMORY);
7476 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7477 smb_fname_dst->base_name,
7479 TALLOC_FREE(talloced);
7483 TALLOC_FREE(dir_hnd);
7484 TALLOC_FREE(talloced);
7485 reply_nterror(req, NT_STATUS_NO_MEMORY);
7489 TALLOC_FREE(smb_fname_dst->base_name);
7490 smb_fname_dst->base_name = destname;
7492 status = check_name(conn, smb_fname_src->base_name);
7493 if (!NT_STATUS_IS_OK(status)) {
7494 TALLOC_FREE(dir_hnd);
7495 TALLOC_FREE(talloced);
7496 reply_nterror(req, status);
7500 status = check_name(conn, smb_fname_dst->base_name);
7501 if (!NT_STATUS_IS_OK(status)) {
7502 TALLOC_FREE(dir_hnd);
7503 TALLOC_FREE(talloced);
7504 reply_nterror(req, status);
7508 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7509 smb_fname_src->base_name,
7510 smb_fname_dst->base_name));
7512 status = copy_file(ctx, conn, smb_fname_src,
7513 smb_fname_dst, ofun, count,
7514 target_is_directory);
7515 if (NT_STATUS_IS_OK(status)) {
7519 TALLOC_FREE(talloced);
7521 TALLOC_FREE(dir_hnd);
7525 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7529 reply_outbuf(req, 1, 0);
7530 SSVAL(req->outbuf,smb_vwv0,count);
7532 TALLOC_FREE(smb_fname_src);
7533 TALLOC_FREE(smb_fname_dst);
7534 TALLOC_FREE(fname_src);
7535 TALLOC_FREE(fname_dst);
7536 TALLOC_FREE(fname_src_mask);
7537 TALLOC_FREE(fname_src_dir);
7539 END_PROFILE(SMBcopy);
7544 #define DBGC_CLASS DBGC_LOCKING
7546 /****************************************************************************
7547 Get a lock pid, dealing with large count requests.
7548 ****************************************************************************/
7550 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7551 bool large_file_format)
7553 if(!large_file_format)
7554 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7556 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7559 /****************************************************************************
7560 Get a lock count, dealing with large count requests.
7561 ****************************************************************************/
7563 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7564 bool large_file_format)
7568 if(!large_file_format) {
7569 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7572 #if defined(HAVE_LONGLONG)
7573 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7574 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7575 #else /* HAVE_LONGLONG */
7578 * NT4.x seems to be broken in that it sends large file (64 bit)
7579 * lockingX calls even if the CAP_LARGE_FILES was *not*
7580 * negotiated. For boxes without large unsigned ints truncate the
7581 * lock count by dropping the top 32 bits.
7584 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7585 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7586 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7587 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7588 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7591 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7592 #endif /* HAVE_LONGLONG */
7598 #if !defined(HAVE_LONGLONG)
7599 /****************************************************************************
7600 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7601 ****************************************************************************/
7603 static uint32 map_lock_offset(uint32 high, uint32 low)
7607 uint32 highcopy = high;
7610 * Try and find out how many significant bits there are in high.
7613 for(i = 0; highcopy; i++)
7617 * We use 31 bits not 32 here as POSIX
7618 * lock offsets may not be negative.
7621 mask = (~0) << (31 - i);
7624 return 0; /* Fail. */
7630 #endif /* !defined(HAVE_LONGLONG) */
7632 /****************************************************************************
7633 Get a lock offset, dealing with large offset requests.
7634 ****************************************************************************/
7636 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7637 bool large_file_format, bool *err)
7639 uint64_t offset = 0;
7643 if(!large_file_format) {
7644 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7647 #if defined(HAVE_LONGLONG)
7648 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7649 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7650 #else /* HAVE_LONGLONG */
7653 * NT4.x seems to be broken in that it sends large file (64 bit)
7654 * lockingX calls even if the CAP_LARGE_FILES was *not*
7655 * negotiated. For boxes without large unsigned ints mangle the
7656 * lock offset by mapping the top 32 bits onto the lower 32.
7659 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7660 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7661 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7664 if((new_low = map_lock_offset(high, low)) == 0) {
7666 return (uint64_t)-1;
7669 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7670 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7671 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7672 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7675 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7676 #endif /* HAVE_LONGLONG */
7682 NTSTATUS smbd_do_locking(struct smb_request *req,
7686 uint16_t num_ulocks,
7687 struct smbd_lock_element *ulocks,
7689 struct smbd_lock_element *locks,
7692 connection_struct *conn = req->conn;
7694 NTSTATUS status = NT_STATUS_OK;
7698 /* Data now points at the beginning of the list
7699 of smb_unlkrng structs */
7700 for(i = 0; i < (int)num_ulocks; i++) {
7701 struct smbd_lock_element *e = &ulocks[i];
7703 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7704 "pid %u, file %s\n",
7707 (unsigned int)e->smblctx,
7710 if (e->brltype != UNLOCK_LOCK) {
7711 /* this can only happen with SMB2 */
7712 return NT_STATUS_INVALID_PARAMETER;
7715 status = do_unlock(req->sconn->msg_ctx,
7722 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7723 nt_errstr(status)));
7725 if (!NT_STATUS_IS_OK(status)) {
7730 /* Setup the timeout in seconds. */
7732 if (!lp_blocking_locks(SNUM(conn))) {
7736 /* Data now points at the beginning of the list
7737 of smb_lkrng structs */
7739 for(i = 0; i < (int)num_locks; i++) {
7740 struct smbd_lock_element *e = &locks[i];
7742 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7743 "%llu, file %s timeout = %d\n",
7746 (unsigned long long)e->smblctx,
7750 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7751 struct blocking_lock_record *blr = NULL;
7753 if (num_locks > 1) {
7755 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7756 * if the lock vector contains one entry. When given mutliple cancel
7757 * requests in a single PDU we expect the server to return an
7758 * error. Windows servers seem to accept the request but only
7759 * cancel the first lock.
7760 * JRA - Do what Windows does (tm) :-).
7764 /* MS-CIFS (2.2.4.32.1) behavior. */
7765 return NT_STATUS_DOS(ERRDOS,
7766 ERRcancelviolation);
7768 /* Windows behavior. */
7770 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7771 "cancel request\n"));
7777 if (lp_blocking_locks(SNUM(conn))) {
7779 /* Schedule a message to ourselves to
7780 remove the blocking lock record and
7781 return the right error. */
7783 blr = blocking_lock_cancel_smb1(fsp,
7789 NT_STATUS_FILE_LOCK_CONFLICT);
7791 return NT_STATUS_DOS(
7793 ERRcancelviolation);
7796 /* Remove a matching pending lock. */
7797 status = do_lock_cancel(fsp,
7804 bool blocking_lock = timeout ? true : false;
7805 bool defer_lock = false;
7806 struct byte_range_lock *br_lck;
7807 uint64_t block_smblctx;
7809 br_lck = do_lock(req->sconn->msg_ctx,
7821 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7822 /* Windows internal resolution for blocking locks seems
7823 to be about 200ms... Don't wait for less than that. JRA. */
7824 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7825 timeout = lp_lock_spin_time();
7830 /* If a lock sent with timeout of zero would fail, and
7831 * this lock has been requested multiple times,
7832 * according to brl_lock_failed() we convert this
7833 * request to a blocking lock with a timeout of between
7834 * 150 - 300 milliseconds.
7836 * If lp_lock_spin_time() has been set to 0, we skip
7837 * this blocking retry and fail immediately.
7839 * Replacement for do_lock_spin(). JRA. */
7841 if (!req->sconn->using_smb2 &&
7842 br_lck && lp_blocking_locks(SNUM(conn)) &&
7843 lp_lock_spin_time() && !blocking_lock &&
7844 NT_STATUS_EQUAL((status),
7845 NT_STATUS_FILE_LOCK_CONFLICT))
7848 timeout = lp_lock_spin_time();
7851 if (br_lck && defer_lock) {
7853 * A blocking lock was requested. Package up
7854 * this smb into a queued request and push it
7855 * onto the blocking lock queue.
7857 if(push_blocking_lock_request(br_lck,
7868 TALLOC_FREE(br_lck);
7870 return NT_STATUS_OK;
7874 TALLOC_FREE(br_lck);
7877 if (!NT_STATUS_IS_OK(status)) {
7882 /* If any of the above locks failed, then we must unlock
7883 all of the previous locks (X/Open spec). */
7885 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7887 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7888 i = -1; /* we want to skip the for loop */
7892 * Ensure we don't do a remove on the lock that just failed,
7893 * as under POSIX rules, if we have a lock already there, we
7894 * will delete it (and we shouldn't) .....
7896 for(i--; i >= 0; i--) {
7897 struct smbd_lock_element *e = &locks[i];
7899 do_unlock(req->sconn->msg_ctx,
7909 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7910 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
7912 return NT_STATUS_OK;
7915 /****************************************************************************
7916 Reply to a lockingX request.
7917 ****************************************************************************/
7919 void reply_lockingX(struct smb_request *req)
7921 connection_struct *conn = req->conn;
7923 unsigned char locktype;
7924 unsigned char oplocklevel;
7929 const uint8_t *data;
7930 bool large_file_format;
7932 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7933 struct smbd_lock_element *ulocks;
7934 struct smbd_lock_element *locks;
7937 START_PROFILE(SMBlockingX);
7940 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7941 END_PROFILE(SMBlockingX);
7945 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7946 locktype = CVAL(req->vwv+3, 0);
7947 oplocklevel = CVAL(req->vwv+3, 1);
7948 num_ulocks = SVAL(req->vwv+6, 0);
7949 num_locks = SVAL(req->vwv+7, 0);
7950 lock_timeout = IVAL(req->vwv+4, 0);
7951 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7953 if (!check_fsp(conn, req, fsp)) {
7954 END_PROFILE(SMBlockingX);
7960 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7961 /* we don't support these - and CANCEL_LOCK makes w2k
7962 and XP reboot so I don't really want to be
7963 compatible! (tridge) */
7964 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7965 END_PROFILE(SMBlockingX);
7969 /* Check if this is an oplock break on a file
7970 we have granted an oplock on.
7972 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7973 /* Client can insist on breaking to none. */
7974 bool break_to_none = (oplocklevel == 0);
7977 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7978 "for %s\n", (unsigned int)oplocklevel,
7979 fsp_fnum_dbg(fsp)));
7982 * Make sure we have granted an exclusive or batch oplock on
7986 if (fsp->oplock_type == 0) {
7988 /* The Samba4 nbench simulator doesn't understand
7989 the difference between break to level2 and break
7990 to none from level2 - it sends oplock break
7991 replies in both cases. Don't keep logging an error
7992 message here - just ignore it. JRA. */
7994 DEBUG(5,("reply_lockingX: Error : oplock break from "
7995 "client for %s (oplock=%d) and no "
7996 "oplock granted on this file (%s).\n",
7997 fsp_fnum_dbg(fsp), fsp->oplock_type,
8000 /* if this is a pure oplock break request then don't
8002 if (num_locks == 0 && num_ulocks == 0) {
8003 END_PROFILE(SMBlockingX);
8006 END_PROFILE(SMBlockingX);
8007 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8012 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8014 result = remove_oplock(fsp);
8016 result = downgrade_oplock(fsp);
8020 DEBUG(0, ("reply_lockingX: error in removing "
8021 "oplock on file %s\n", fsp_str_dbg(fsp)));
8022 /* Hmmm. Is this panic justified? */
8023 smb_panic("internal tdb error");
8026 reply_to_oplock_break_requests(fsp);
8028 /* if this is a pure oplock break request then don't send a
8030 if (num_locks == 0 && num_ulocks == 0) {
8031 /* Sanity check - ensure a pure oplock break is not a
8033 if(CVAL(req->vwv+0, 0) != 0xff)
8034 DEBUG(0,("reply_lockingX: Error : pure oplock "
8035 "break is a chained %d request !\n",
8036 (unsigned int)CVAL(req->vwv+0, 0)));
8037 END_PROFILE(SMBlockingX);
8043 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8045 END_PROFILE(SMBlockingX);
8049 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8050 if (ulocks == NULL) {
8051 reply_nterror(req, NT_STATUS_NO_MEMORY);
8052 END_PROFILE(SMBlockingX);
8056 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8057 if (locks == NULL) {
8058 reply_nterror(req, NT_STATUS_NO_MEMORY);
8059 END_PROFILE(SMBlockingX);
8063 /* Data now points at the beginning of the list
8064 of smb_unlkrng structs */
8065 for(i = 0; i < (int)num_ulocks; i++) {
8066 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8067 ulocks[i].count = get_lock_count(data, i, large_file_format);
8068 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
8069 ulocks[i].brltype = UNLOCK_LOCK;
8072 * There is no error code marked "stupid client bug".... :-).
8075 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8076 END_PROFILE(SMBlockingX);
8081 /* Now do any requested locks */
8082 data += ((large_file_format ? 20 : 10)*num_ulocks);
8084 /* Data now points at the beginning of the list
8085 of smb_lkrng structs */
8087 for(i = 0; i < (int)num_locks; i++) {
8088 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8089 locks[i].count = get_lock_count(data, i, large_file_format);
8090 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
8092 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8093 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8094 locks[i].brltype = PENDING_READ_LOCK;
8096 locks[i].brltype = READ_LOCK;
8099 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8100 locks[i].brltype = PENDING_WRITE_LOCK;
8102 locks[i].brltype = WRITE_LOCK;
8107 * There is no error code marked "stupid client bug".... :-).
8110 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8111 END_PROFILE(SMBlockingX);
8116 status = smbd_do_locking(req, fsp,
8117 locktype, lock_timeout,
8121 if (!NT_STATUS_IS_OK(status)) {
8122 END_PROFILE(SMBlockingX);
8123 reply_nterror(req, status);
8127 END_PROFILE(SMBlockingX);
8131 reply_outbuf(req, 2, 0);
8132 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8133 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8135 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8136 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8138 END_PROFILE(SMBlockingX);
8142 #define DBGC_CLASS DBGC_ALL
8144 /****************************************************************************
8145 Reply to a SMBreadbmpx (read block multiplex) request.
8146 Always reply with an error, if someone has a platform really needs this,
8147 please contact vl@samba.org
8148 ****************************************************************************/
8150 void reply_readbmpx(struct smb_request *req)
8152 START_PROFILE(SMBreadBmpx);
8153 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8154 END_PROFILE(SMBreadBmpx);
8158 /****************************************************************************
8159 Reply to a SMBreadbs (read block multiplex secondary) request.
8160 Always reply with an error, if someone has a platform really needs this,
8161 please contact vl@samba.org
8162 ****************************************************************************/
8164 void reply_readbs(struct smb_request *req)
8166 START_PROFILE(SMBreadBs);
8167 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8168 END_PROFILE(SMBreadBs);
8172 /****************************************************************************
8173 Reply to a SMBsetattrE.
8174 ****************************************************************************/
8176 void reply_setattrE(struct smb_request *req)
8178 connection_struct *conn = req->conn;
8179 struct smb_file_time ft;
8183 START_PROFILE(SMBsetattrE);
8187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8191 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8193 if(!fsp || (fsp->conn != conn)) {
8194 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8199 * Convert the DOS times into unix times.
8202 ft.atime = convert_time_t_to_timespec(
8203 srv_make_unix_date2(req->vwv+3));
8204 ft.mtime = convert_time_t_to_timespec(
8205 srv_make_unix_date2(req->vwv+5));
8206 ft.create_time = convert_time_t_to_timespec(
8207 srv_make_unix_date2(req->vwv+1));
8209 reply_outbuf(req, 0, 0);
8212 * Patch from Ray Frush <frush@engr.colostate.edu>
8213 * Sometimes times are sent as zero - ignore them.
8216 /* Ensure we have a valid stat struct for the source. */
8217 status = vfs_stat_fsp(fsp);
8218 if (!NT_STATUS_IS_OK(status)) {
8219 reply_nterror(req, status);
8223 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8228 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8229 if (!NT_STATUS_IS_OK(status)) {
8230 reply_nterror(req, status);
8234 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8237 (unsigned int)ft.atime.tv_sec,
8238 (unsigned int)ft.mtime.tv_sec,
8239 (unsigned int)ft.create_time.tv_sec
8242 END_PROFILE(SMBsetattrE);
8247 /* Back from the dead for OS/2..... JRA. */
8249 /****************************************************************************
8250 Reply to a SMBwritebmpx (write block multiplex primary) request.
8251 Always reply with an error, if someone has a platform really needs this,
8252 please contact vl@samba.org
8253 ****************************************************************************/
8255 void reply_writebmpx(struct smb_request *req)
8257 START_PROFILE(SMBwriteBmpx);
8258 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8259 END_PROFILE(SMBwriteBmpx);
8263 /****************************************************************************
8264 Reply to a SMBwritebs (write block multiplex secondary) request.
8265 Always reply with an error, if someone has a platform really needs this,
8266 please contact vl@samba.org
8267 ****************************************************************************/
8269 void reply_writebs(struct smb_request *req)
8271 START_PROFILE(SMBwriteBs);
8272 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8273 END_PROFILE(SMBwriteBs);
8277 /****************************************************************************
8278 Reply to a SMBgetattrE.
8279 ****************************************************************************/
8281 void reply_getattrE(struct smb_request *req)
8283 connection_struct *conn = req->conn;
8286 struct timespec create_ts;
8288 START_PROFILE(SMBgetattrE);
8291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8292 END_PROFILE(SMBgetattrE);
8296 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8298 if(!fsp || (fsp->conn != conn)) {
8299 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8300 END_PROFILE(SMBgetattrE);
8304 /* Do an fstat on this file */
8306 reply_nterror(req, map_nt_error_from_unix(errno));
8307 END_PROFILE(SMBgetattrE);
8311 mode = dos_mode(conn, fsp->fsp_name);
8314 * Convert the times into dos times. Set create
8315 * date to be last modify date as UNIX doesn't save
8319 reply_outbuf(req, 11, 0);
8321 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8322 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8323 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8324 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8325 /* Should we check pending modtime here ? JRA */
8326 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8327 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8329 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8330 SIVAL(req->outbuf, smb_vwv6, 0);
8331 SIVAL(req->outbuf, smb_vwv8, 0);
8333 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8334 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8335 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8337 SSVAL(req->outbuf,smb_vwv10, mode);
8339 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8341 END_PROFILE(SMBgetattrE);