2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS check_path_syntax_internal(char *path,
60 bool *p_last_component_contains_wcard)
64 NTSTATUS ret = NT_STATUS_OK;
65 bool start_of_name_component = True;
66 bool stream_started = false;
68 *p_last_component_contains_wcard = False;
75 return NT_STATUS_OBJECT_NAME_INVALID;
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 if (strchr_m(&s[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
87 if ((*s == ':') && !posix_path && !stream_started) {
88 if (*p_last_component_contains_wcard) {
89 return NT_STATUS_OBJECT_NAME_INVALID;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started = true;
98 start_of_name_component = false;
102 return NT_STATUS_OBJECT_NAME_INVALID;
106 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s,posix_path)) {
115 if ((d != path) && (*s != '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component = True;
122 *p_last_component_contains_wcard = False;
126 if (start_of_name_component) {
127 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d > path) && (*(d-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d--; d > path; d--) {
153 s += 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
169 if (*s <= 0x1f || *s == '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID;
178 *p_last_component_contains_wcard = True;
187 /* Get the size of the next MB character. */
188 next_codepoint(s,&siz);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER;
211 start_of_name_component = False;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax(char *path)
227 return check_path_syntax_internal(path, False, &ignore);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 return check_path_syntax_internal(path, False, p_contains_wcard);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS check_path_syntax_posix(char *path)
250 return check_path_syntax_internal(path, True, &ignore);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
258 const char *base_ptr,
265 bool *contains_wcard)
271 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275 *err = NT_STATUS_INVALID_PARAMETER;
279 *contains_wcard = False;
281 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err = check_path_syntax_posix(*pp_dest);
293 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX *ctx,
304 const char *base_ptr,
313 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
314 src_len, flags, err, &ignore);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
319 NTSTATUS *err, bool *contains_wcard)
321 ssize_t bufrem = smbreq_bufrem(req, src);
324 *err = NT_STATUS_INVALID_PARAMETER;
328 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
329 req->flags2, pp_dest, src, bufrem, flags,
330 err, contains_wcard);
333 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
334 char **pp_dest, const char *src, int flags,
338 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
339 flags, err, &ignore);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
348 char **dest, const uint8_t *src, int flags)
350 ssize_t bufrem = smbreq_bufrem(req, src);
356 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
367 if ((fsp == NULL) || (conn == NULL)) {
368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
371 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct *conn, struct smb_request *req,
385 if (!check_fsp_open(conn, req, fsp)) {
388 if (fsp->is_directory) {
389 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
392 if (fsp->fh->fd == -1) {
393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
396 fsp->num_smb_operations++;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
408 if (!check_fsp_open(conn, req, fsp)) {
412 if (fsp->is_directory) {
416 if (fsp->fake_file_handle == NULL) {
420 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
424 if (fsp->fake_file_handle->private_data == NULL) {
431 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
432 const char *name, int name_type)
434 struct smbd_server_connection *sconn = xconn->sconn;
436 char *trim_name_type;
437 const char *retarget_parm;
440 int retarget_type = 0x20;
441 int retarget_port = NBT_SMB_PORT;
442 struct sockaddr_storage retarget_addr;
443 struct sockaddr_in *in_addr;
447 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
451 trim_name = talloc_strdup(talloc_tos(), name);
452 if (trim_name == NULL) {
455 trim_char(trim_name, ' ', ' ');
457 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
459 if (trim_name_type == NULL) {
463 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
464 trim_name_type, NULL);
465 if (retarget_parm == NULL) {
466 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
469 if (retarget_parm == NULL) {
473 retarget = talloc_strdup(trim_name, retarget_parm);
474 if (retarget == NULL) {
478 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
480 p = strchr(retarget, ':');
483 retarget_port = atoi(p);
486 p = strchr_m(retarget, '#');
489 if (sscanf(p, "%x", &retarget_type) != 1) {
494 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
496 DEBUG(10, ("could not resolve %s\n", retarget));
500 if (retarget_addr.ss_family != AF_INET) {
501 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
505 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
507 _smb_setlen(outbuf, 6);
508 SCVAL(outbuf, 0, 0x84);
509 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
510 *(uint16_t *)(outbuf+8) = htons(retarget_port);
512 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
514 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
520 TALLOC_FREE(trim_name);
524 static void reply_called_name_not_present(char *outbuf)
526 smb_setlen(outbuf, 1);
527 SCVAL(outbuf, 0, 0x83);
528 SCVAL(outbuf, 4, 0x82);
531 /****************************************************************************
532 Reply to a (netbios-level) special message.
533 ****************************************************************************/
535 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
537 struct smbd_server_connection *sconn = xconn->sconn;
538 int msg_type = CVAL(inbuf,0);
539 int msg_flags = CVAL(inbuf,1);
541 * We only really use 4 bytes of the outbuf, but for the smb_setlen
542 * calculation & friends (srv_send_smb uses that) we need the full smb
545 char outbuf[smb_size];
547 memset(outbuf, '\0', sizeof(outbuf));
549 smb_setlen(outbuf,0);
552 case NBSSrequest: /* session request */
554 /* inbuf_size is guarenteed to be at least 4. */
556 int name_type1, name_type2;
557 int name_len1, name_len2;
561 if (xconn->transport.nbt.got_session) {
562 exit_server_cleanly("multiple session request not permitted");
565 SCVAL(outbuf,0,NBSSpositive);
568 /* inbuf_size is guaranteed to be at least 4. */
569 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
570 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
571 DEBUG(0,("Invalid name length in session request\n"));
572 reply_called_name_not_present(outbuf);
575 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
576 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
577 DEBUG(0,("Invalid name length in session request\n"));
578 reply_called_name_not_present(outbuf);
582 name_type1 = name_extract((unsigned char *)inbuf,
583 inbuf_size,(unsigned int)4,name1);
584 name_type2 = name_extract((unsigned char *)inbuf,
585 inbuf_size,(unsigned int)(4 + name_len1),name2);
587 if (name_type1 == -1 || name_type2 == -1) {
588 DEBUG(0,("Invalid name type in session request\n"));
589 reply_called_name_not_present(outbuf);
593 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
594 name1, name_type1, name2, name_type2));
596 if (netbios_session_retarget(xconn, name1, name_type1)) {
597 exit_server_cleanly("retargeted client");
601 * Windows NT/2k uses "*SMBSERVER" and XP uses
602 * "*SMBSERV" arrggg!!!
604 if (strequal(name1, "*SMBSERVER ")
605 || strequal(name1, "*SMBSERV ")) {
608 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
611 exit_server_cleanly("could not allocate raddr");
614 fstrcpy(name1, raddr);
617 set_local_machine_name(name1, True);
618 set_remote_machine_name(name2, True);
620 if (is_ipaddress(sconn->remote_hostname)) {
621 char *p = discard_const_p(char, sconn->remote_hostname);
625 sconn->remote_hostname = talloc_strdup(sconn,
626 get_remote_machine_name());
627 if (sconn->remote_hostname == NULL) {
628 exit_server_cleanly("could not copy remote name");
630 xconn->remote_hostname = sconn->remote_hostname;
633 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
634 get_local_machine_name(), get_remote_machine_name(),
637 if (name_type2 == 'R') {
638 /* We are being asked for a pathworks session ---
640 reply_called_name_not_present(outbuf);
644 reload_services(sconn, conn_snum_used, true);
647 xconn->transport.nbt.got_session = true;
651 case 0x89: /* session keepalive request
652 (some old clients produce this?) */
653 SCVAL(outbuf,0,NBSSkeepalive);
657 case NBSSpositive: /* positive session response */
658 case NBSSnegative: /* negative session response */
659 case NBSSretarget: /* retarget session response */
660 DEBUG(0,("Unexpected session response\n"));
663 case NBSSkeepalive: /* session keepalive */
668 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
669 msg_type, msg_flags));
671 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
673 if (CVAL(outbuf, 0) != 0x82) {
674 exit_server_cleanly("invalid netbios session");
679 /****************************************************************************
681 conn POINTER CAN BE NULL HERE !
682 ****************************************************************************/
684 void reply_tcon(struct smb_request *req)
686 connection_struct *conn = req->conn;
688 char *service_buf = NULL;
689 char *password = NULL;
695 TALLOC_CTX *ctx = talloc_tos();
696 struct smbd_server_connection *sconn = req->sconn;
697 struct smbXsrv_connection *xconn = sconn->conn;
698 NTTIME now = timeval_to_nttime(&req->request_time);
700 START_PROFILE(SMBtcon);
702 if (req->buflen < 4) {
703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
704 END_PROFILE(SMBtcon);
709 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
711 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
713 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
716 if (service_buf == NULL || password == NULL || dev == NULL) {
717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
718 END_PROFILE(SMBtcon);
721 p2 = strrchr_m(service_buf,'\\');
725 service = service_buf;
728 conn = make_connection(sconn, now, service, dev,
729 req->vuid,&nt_status);
733 reply_nterror(req, nt_status);
734 END_PROFILE(SMBtcon);
738 reply_outbuf(req, 2, 0);
739 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
740 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
741 SSVAL(req->outbuf,smb_tid,conn->cnum);
743 DEBUG(3,("tcon service=%s cnum=%d\n",
744 service, conn->cnum));
746 END_PROFILE(SMBtcon);
750 /****************************************************************************
751 Reply to a tcon and X.
752 conn POINTER CAN BE NULL HERE !
753 ****************************************************************************/
755 void reply_tcon_and_X(struct smb_request *req)
757 connection_struct *conn = req->conn;
758 const char *service = NULL;
759 TALLOC_CTX *ctx = talloc_tos();
760 /* what the cleint thinks the device is */
761 char *client_devicetype = NULL;
762 /* what the server tells the client the share represents */
763 const char *server_devicetype;
770 struct smbXsrv_session *session = NULL;
771 NTTIME now = timeval_to_nttime(&req->request_time);
772 bool session_key_updated = false;
773 uint16_t optional_support = 0;
774 struct smbd_server_connection *sconn = req->sconn;
775 struct smbXsrv_connection *xconn = sconn->conn;
777 START_PROFILE(SMBtconX);
780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
781 END_PROFILE(SMBtconX);
785 passlen = SVAL(req->vwv+3, 0);
786 tcon_flags = SVAL(req->vwv+2, 0);
788 /* we might have to close an old one */
789 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
790 struct smbXsrv_tcon *tcon;
798 * TODO: cancel all outstanding requests on the tcon
800 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
801 if (!NT_STATUS_IS_OK(status)) {
802 DEBUG(0, ("reply_tcon_and_X: "
803 "smbXsrv_tcon_disconnect() failed: %s\n",
806 * If we hit this case, there is something completely
807 * wrong, so we better disconnect the transport connection.
809 END_PROFILE(SMBtconX);
810 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
817 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
818 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
819 END_PROFILE(SMBtconX);
823 if (xconn->smb1.negprot.encrypted_passwords) {
824 p = req->buf + passlen;
826 p = req->buf + passlen + 1;
829 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 END_PROFILE(SMBtconX);
838 * the service name can be either: \\server\share
839 * or share directly like on the DELL PowerVault 705
842 q = strchr_m(path+2,'\\');
844 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
845 END_PROFILE(SMBtconX);
853 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
854 &client_devicetype, p,
855 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
857 if (client_devicetype == NULL) {
858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
859 END_PROFILE(SMBtconX);
863 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
865 nt_status = smb1srv_session_lookup(req->sconn->conn,
866 req->vuid, now, &session);
867 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
868 reply_force_doserror(req, ERRSRV, ERRbaduid);
869 END_PROFILE(SMBtconX);
872 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
873 reply_nterror(req, nt_status);
874 END_PROFILE(SMBtconX);
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
879 END_PROFILE(SMBtconX);
883 if (session->global->auth_session_info == NULL) {
884 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
885 END_PROFILE(SMBtconX);
890 * If there is no application key defined yet
893 * This means we setup the application key on the
894 * first tcon that happens via the given session.
896 * Once the application key is defined, it does not
899 if (session->global->application_key.length == 0 &&
900 session->global->signing_key.length > 0)
902 struct smbXsrv_session *x = session;
903 struct auth_session_info *session_info =
904 session->global->auth_session_info;
905 uint8_t session_key[16];
907 ZERO_STRUCT(session_key);
908 memcpy(session_key, x->global->signing_key.data,
909 MIN(x->global->signing_key.length, sizeof(session_key)));
912 * The application key is truncated/padded to 16 bytes
914 x->global->application_key = data_blob_talloc(x->global,
916 sizeof(session_key));
917 ZERO_STRUCT(session_key);
918 if (x->global->application_key.data == NULL) {
919 reply_nterror(req, NT_STATUS_NO_MEMORY);
920 END_PROFILE(SMBtconX);
924 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
925 smb_key_derivation(x->global->application_key.data,
926 x->global->application_key.length,
927 x->global->application_key.data);
928 optional_support |= SMB_EXTENDED_SIGNATURES;
932 * Place the application key into the session_info
934 data_blob_clear_free(&session_info->session_key);
935 session_info->session_key = data_blob_dup_talloc(session_info,
936 x->global->application_key);
937 if (session_info->session_key.data == NULL) {
938 data_blob_clear_free(&x->global->application_key);
939 reply_nterror(req, NT_STATUS_NO_MEMORY);
940 END_PROFILE(SMBtconX);
943 session_key_updated = true;
946 conn = make_connection(sconn, now, service, client_devicetype,
947 req->vuid, &nt_status);
951 if (session_key_updated) {
952 struct smbXsrv_session *x = session;
953 struct auth_session_info *session_info =
954 session->global->auth_session_info;
955 data_blob_clear_free(&x->global->application_key);
956 data_blob_clear_free(&session_info->session_key);
958 reply_nterror(req, nt_status);
959 END_PROFILE(SMBtconX);
964 server_devicetype = "IPC";
965 else if ( IS_PRINT(conn) )
966 server_devicetype = "LPT1:";
968 server_devicetype = "A:";
970 if (get_Protocol() < PROTOCOL_NT1) {
971 reply_outbuf(req, 2, 0);
972 if (message_push_string(&req->outbuf, server_devicetype,
973 STR_TERMINATE|STR_ASCII) == -1) {
974 reply_nterror(req, NT_STATUS_NO_MEMORY);
975 END_PROFILE(SMBtconX);
979 /* NT sets the fstype of IPC$ to the null string */
980 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
982 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
983 /* Return permissions. */
987 reply_outbuf(req, 7, 0);
990 perm1 = FILE_ALL_ACCESS;
991 perm2 = FILE_ALL_ACCESS;
993 perm1 = conn->share_access;
996 SIVAL(req->outbuf, smb_vwv3, perm1);
997 SIVAL(req->outbuf, smb_vwv5, perm2);
999 reply_outbuf(req, 3, 0);
1002 if ((message_push_string(&req->outbuf, server_devicetype,
1003 STR_TERMINATE|STR_ASCII) == -1)
1004 || (message_push_string(&req->outbuf, fstype,
1005 STR_TERMINATE) == -1)) {
1006 reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 END_PROFILE(SMBtconX);
1011 /* what does setting this bit do? It is set by NT4 and
1012 may affect the ability to autorun mounted cdroms */
1013 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1015 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1017 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1018 DEBUG(2,("Serving %s as a Dfs root\n",
1019 lp_servicename(ctx, SNUM(conn)) ));
1020 optional_support |= SMB_SHARE_IN_DFS;
1023 SSVAL(req->outbuf, smb_vwv2, optional_support);
1026 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1027 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1029 DEBUG(3,("tconX service=%s \n",
1032 /* set the incoming and outgoing tid to the just created one */
1033 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1034 SSVAL(req->outbuf,smb_tid,conn->cnum);
1036 END_PROFILE(SMBtconX);
1038 req->tid = conn->cnum;
1041 /****************************************************************************
1042 Reply to an unknown type.
1043 ****************************************************************************/
1045 void reply_unknown_new(struct smb_request *req, uint8 type)
1047 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1048 smb_fn_name(type), type, type));
1049 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1053 /****************************************************************************
1055 conn POINTER CAN BE NULL HERE !
1056 ****************************************************************************/
1058 void reply_ioctl(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1067 START_PROFILE(SMBioctl);
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 END_PROFILE(SMBioctl);
1075 device = SVAL(req->vwv+1, 0);
1076 function = SVAL(req->vwv+2, 0);
1077 ioctl_code = (device << 16) + function;
1079 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1081 switch (ioctl_code) {
1082 case IOCTL_QUERY_JOB_INFO:
1086 reply_force_doserror(req, ERRSRV, ERRnosupport);
1087 END_PROFILE(SMBioctl);
1091 reply_outbuf(req, 8, replysize+1);
1092 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1093 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1094 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1095 p = smb_buf(req->outbuf);
1096 memset(p, '\0', replysize+1); /* valgrind-safe. */
1097 p += 1; /* Allow for alignment */
1099 switch (ioctl_code) {
1100 case IOCTL_QUERY_JOB_INFO:
1102 files_struct *fsp = file_fsp(
1103 req, SVAL(req->vwv+0, 0));
1105 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1106 END_PROFILE(SMBioctl);
1110 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1112 srvstr_push((char *)req->outbuf, req->flags2, p+2,
1113 lp_netbios_name(), 15,
1114 STR_TERMINATE|STR_ASCII);
1116 srvstr_push((char *)req->outbuf, req->flags2,
1118 lp_servicename(talloc_tos(),
1120 13, STR_TERMINATE|STR_ASCII);
1122 memset(p+18, 0, 13);
1128 END_PROFILE(SMBioctl);
1132 /****************************************************************************
1133 Strange checkpath NTSTATUS mapping.
1134 ****************************************************************************/
1136 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1138 /* Strange DOS error code semantics only for checkpath... */
1139 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1140 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1141 /* We need to map to ERRbadpath */
1142 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1148 /****************************************************************************
1149 Reply to a checkpath.
1150 ****************************************************************************/
1152 void reply_checkpath(struct smb_request *req)
1154 connection_struct *conn = req->conn;
1155 struct smb_filename *smb_fname = NULL;
1158 TALLOC_CTX *ctx = talloc_tos();
1160 START_PROFILE(SMBcheckpath);
1162 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1163 STR_TERMINATE, &status);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 status = map_checkpath_error(req->flags2, status);
1167 reply_nterror(req, status);
1168 END_PROFILE(SMBcheckpath);
1172 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1174 status = filename_convert(ctx,
1176 req->flags2 & FLAGS2_DFS_PATHNAMES,
1182 if (!NT_STATUS_IS_OK(status)) {
1183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1184 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1185 ERRSRV, ERRbadpath);
1186 END_PROFILE(SMBcheckpath);
1192 if (!VALID_STAT(smb_fname->st) &&
1193 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1194 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1195 smb_fname_str_dbg(smb_fname), strerror(errno)));
1196 status = map_nt_error_from_unix(errno);
1200 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1201 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1202 ERRDOS, ERRbadpath);
1206 reply_outbuf(req, 0, 0);
1209 /* We special case this - as when a Windows machine
1210 is parsing a path is steps through the components
1211 one at a time - if a component fails it expects
1212 ERRbadpath, not ERRbadfile.
1214 status = map_checkpath_error(req->flags2, status);
1215 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1217 * Windows returns different error codes if
1218 * the parent directory is valid but not the
1219 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1220 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1221 * if the path is invalid.
1223 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1224 ERRDOS, ERRbadpath);
1228 reply_nterror(req, status);
1231 TALLOC_FREE(smb_fname);
1232 END_PROFILE(SMBcheckpath);
1236 /****************************************************************************
1238 ****************************************************************************/
1240 void reply_getatr(struct smb_request *req)
1242 connection_struct *conn = req->conn;
1243 struct smb_filename *smb_fname = NULL;
1250 TALLOC_CTX *ctx = talloc_tos();
1251 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1253 START_PROFILE(SMBgetatr);
1255 p = (const char *)req->buf + 1;
1256 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 reply_nterror(req, status);
1262 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1263 under WfWg - weird! */
1264 if (*fname == '\0') {
1265 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1266 if (!CAN_WRITE(conn)) {
1267 mode |= FILE_ATTRIBUTE_READONLY;
1272 status = filename_convert(ctx,
1274 req->flags2 & FLAGS2_DFS_PATHNAMES,
1279 if (!NT_STATUS_IS_OK(status)) {
1280 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1281 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1282 ERRSRV, ERRbadpath);
1285 reply_nterror(req, status);
1288 if (!VALID_STAT(smb_fname->st) &&
1289 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1290 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1291 smb_fname_str_dbg(smb_fname),
1293 reply_nterror(req, map_nt_error_from_unix(errno));
1297 mode = dos_mode(conn, smb_fname);
1298 size = smb_fname->st.st_ex_size;
1300 if (ask_sharemode) {
1301 struct timespec write_time_ts;
1302 struct file_id fileid;
1304 ZERO_STRUCT(write_time_ts);
1305 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1306 get_file_infos(fileid, 0, NULL, &write_time_ts);
1307 if (!null_timespec(write_time_ts)) {
1308 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1312 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1313 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1318 reply_outbuf(req, 10, 0);
1320 SSVAL(req->outbuf,smb_vwv0,mode);
1321 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1322 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1324 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1326 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1328 if (get_Protocol() >= PROTOCOL_NT1) {
1329 SSVAL(req->outbuf, smb_flg2,
1330 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1333 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1334 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1337 TALLOC_FREE(smb_fname);
1339 END_PROFILE(SMBgetatr);
1343 /****************************************************************************
1345 ****************************************************************************/
1347 void reply_setatr(struct smb_request *req)
1349 struct smb_file_time ft;
1350 connection_struct *conn = req->conn;
1351 struct smb_filename *smb_fname = NULL;
1357 TALLOC_CTX *ctx = talloc_tos();
1359 START_PROFILE(SMBsetatr);
1364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1368 p = (const char *)req->buf + 1;
1369 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1370 if (!NT_STATUS_IS_OK(status)) {
1371 reply_nterror(req, status);
1375 status = filename_convert(ctx,
1377 req->flags2 & FLAGS2_DFS_PATHNAMES,
1382 if (!NT_STATUS_IS_OK(status)) {
1383 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1384 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1385 ERRSRV, ERRbadpath);
1388 reply_nterror(req, status);
1392 if (smb_fname->base_name[0] == '.' &&
1393 smb_fname->base_name[1] == '\0') {
1395 * Not sure here is the right place to catch this
1396 * condition. Might be moved to somewhere else later -- vl
1398 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1402 mode = SVAL(req->vwv+0, 0);
1403 mtime = srv_make_unix_date3(req->vwv+1);
1405 if (mode != FILE_ATTRIBUTE_NORMAL) {
1406 if (VALID_STAT_OF_DIR(smb_fname->st))
1407 mode |= FILE_ATTRIBUTE_DIRECTORY;
1409 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1411 status = check_access(conn, NULL, smb_fname,
1412 FILE_WRITE_ATTRIBUTES);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 reply_nterror(req, status);
1418 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1420 reply_nterror(req, map_nt_error_from_unix(errno));
1425 ft.mtime = convert_time_t_to_timespec(mtime);
1426 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1427 if (!NT_STATUS_IS_OK(status)) {
1428 reply_nterror(req, status);
1432 reply_outbuf(req, 0, 0);
1434 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1437 TALLOC_FREE(smb_fname);
1438 END_PROFILE(SMBsetatr);
1442 /****************************************************************************
1444 ****************************************************************************/
1446 void reply_dskattr(struct smb_request *req)
1448 connection_struct *conn = req->conn;
1449 uint64_t dfree,dsize,bsize;
1450 START_PROFILE(SMBdskattr);
1452 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1453 reply_nterror(req, map_nt_error_from_unix(errno));
1454 END_PROFILE(SMBdskattr);
1458 reply_outbuf(req, 5, 0);
1460 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1461 double total_space, free_space;
1462 /* we need to scale this to a number that DOS6 can handle. We
1463 use floating point so we can handle large drives on systems
1464 that don't have 64 bit integers
1466 we end up displaying a maximum of 2G to DOS systems
1468 total_space = dsize * (double)bsize;
1469 free_space = dfree * (double)bsize;
1471 dsize = (uint64_t)((total_space+63*512) / (64*512));
1472 dfree = (uint64_t)((free_space+63*512) / (64*512));
1474 if (dsize > 0xFFFF) dsize = 0xFFFF;
1475 if (dfree > 0xFFFF) dfree = 0xFFFF;
1477 SSVAL(req->outbuf,smb_vwv0,dsize);
1478 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1479 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1480 SSVAL(req->outbuf,smb_vwv3,dfree);
1482 SSVAL(req->outbuf,smb_vwv0,dsize);
1483 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1484 SSVAL(req->outbuf,smb_vwv2,512);
1485 SSVAL(req->outbuf,smb_vwv3,dfree);
1488 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1490 END_PROFILE(SMBdskattr);
1495 * Utility function to split the filename from the directory.
1497 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1498 char **fname_dir_out,
1499 char **fname_mask_out)
1501 const char *p = NULL;
1502 char *fname_dir = NULL;
1503 char *fname_mask = NULL;
1505 p = strrchr_m(fname_in, '/');
1507 fname_dir = talloc_strdup(ctx, ".");
1508 fname_mask = talloc_strdup(ctx, fname_in);
1510 fname_dir = talloc_strndup(ctx, fname_in,
1511 PTR_DIFF(p, fname_in));
1512 fname_mask = talloc_strdup(ctx, p+1);
1515 if (!fname_dir || !fname_mask) {
1516 TALLOC_FREE(fname_dir);
1517 TALLOC_FREE(fname_mask);
1518 return NT_STATUS_NO_MEMORY;
1521 *fname_dir_out = fname_dir;
1522 *fname_mask_out = fname_mask;
1523 return NT_STATUS_OK;
1526 /****************************************************************************
1528 Can be called from SMBsearch, SMBffirst or SMBfunique.
1529 ****************************************************************************/
1531 void reply_search(struct smb_request *req)
1533 connection_struct *conn = req->conn;
1535 const char *mask = NULL;
1536 char *directory = NULL;
1537 struct smb_filename *smb_fname = NULL;
1541 struct timespec date;
1543 unsigned int numentries = 0;
1544 unsigned int maxentries = 0;
1545 bool finished = False;
1550 bool check_descend = False;
1551 bool expect_close = False;
1553 bool mask_contains_wcard = False;
1554 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1555 TALLOC_CTX *ctx = talloc_tos();
1556 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1557 struct dptr_struct *dirptr = NULL;
1558 struct smbd_server_connection *sconn = req->sconn;
1559 struct smbXsrv_connection *xconn = sconn->conn;
1561 START_PROFILE(SMBsearch);
1564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1568 if (lp_posix_pathnames()) {
1569 reply_unknown_new(req, req->cmd);
1573 /* If we were called as SMBffirst then we must expect close. */
1574 if(req->cmd == SMBffirst) {
1575 expect_close = True;
1578 reply_outbuf(req, 1, 3);
1579 maxentries = SVAL(req->vwv+0, 0);
1580 dirtype = SVAL(req->vwv+1, 0);
1581 p = (const char *)req->buf + 1;
1582 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1583 &nt_status, &mask_contains_wcard);
1584 if (!NT_STATUS_IS_OK(nt_status)) {
1585 reply_nterror(req, nt_status);
1590 status_len = SVAL(p, 0);
1593 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1595 if (status_len == 0) {
1596 nt_status = filename_convert(ctx, conn,
1597 req->flags2 & FLAGS2_DFS_PATHNAMES,
1599 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1600 &mask_contains_wcard,
1602 if (!NT_STATUS_IS_OK(nt_status)) {
1603 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1604 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1605 ERRSRV, ERRbadpath);
1608 reply_nterror(req, nt_status);
1612 directory = smb_fname->base_name;
1614 p = strrchr_m(directory,'/');
1615 if ((p != NULL) && (*directory != '/')) {
1617 directory = talloc_strndup(ctx, directory,
1618 PTR_DIFF(p, directory));
1621 directory = talloc_strdup(ctx,".");
1625 reply_nterror(req, NT_STATUS_NO_MEMORY);
1629 memset((char *)status,'\0',21);
1630 SCVAL(status,0,(dirtype & 0x1F));
1632 nt_status = dptr_create(conn,
1640 mask_contains_wcard,
1643 if (!NT_STATUS_IS_OK(nt_status)) {
1644 reply_nterror(req, nt_status);
1647 dptr_num = dptr_dnum(dirptr);
1650 const char *dirpath;
1652 memcpy(status,p,21);
1653 status_dirtype = CVAL(status,0) & 0x1F;
1654 if (status_dirtype != (dirtype & 0x1F)) {
1655 dirtype = status_dirtype;
1658 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1662 dirpath = dptr_path(sconn, dptr_num);
1663 directory = talloc_strdup(ctx, dirpath);
1665 reply_nterror(req, NT_STATUS_NO_MEMORY);
1669 mask = dptr_wcard(sconn, dptr_num);
1674 * For a 'continue' search we have no string. So
1675 * check from the initial saved string.
1677 mask_contains_wcard = ms_has_wild(mask);
1678 dirtype = dptr_attr(sconn, dptr_num);
1681 DEBUG(4,("dptr_num is %d\n",dptr_num));
1683 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1684 dptr_init_search_op(dirptr);
1686 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1687 char buf[DIR_STRUCT_SIZE];
1688 memcpy(buf,status,21);
1689 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1690 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1691 reply_nterror(req, NT_STATUS_NO_MEMORY);
1694 dptr_fill(sconn, buf+12,dptr_num);
1695 if (dptr_zero(buf+12) && (status_len==0)) {
1700 if (message_push_blob(&req->outbuf,
1701 data_blob_const(buf, sizeof(buf)))
1703 reply_nterror(req, NT_STATUS_NO_MEMORY);
1708 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1709 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1711 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1713 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1714 directory,lp_dont_descend(ctx, SNUM(conn))));
1715 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1716 check_descend = True;
1719 for (i=numentries;(i<maxentries) && !finished;i++) {
1720 finished = !get_dir_entry(ctx,
1731 char buf[DIR_STRUCT_SIZE];
1732 memcpy(buf,status,21);
1733 if (!make_dir_struct(ctx,
1739 convert_timespec_to_time_t(date),
1740 !allow_long_path_components)) {
1741 reply_nterror(req, NT_STATUS_NO_MEMORY);
1744 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1747 if (message_push_blob(&req->outbuf,
1748 data_blob_const(buf, sizeof(buf)))
1750 reply_nterror(req, NT_STATUS_NO_MEMORY);
1760 /* If we were called as SMBffirst with smb_search_id == NULL
1761 and no entries were found then return error and close dirptr
1764 if (numentries == 0) {
1765 dptr_close(sconn, &dptr_num);
1766 } else if(expect_close && status_len == 0) {
1767 /* Close the dptr - we know it's gone */
1768 dptr_close(sconn, &dptr_num);
1771 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1772 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1773 dptr_close(sconn, &dptr_num);
1776 if ((numentries == 0) && !mask_contains_wcard) {
1777 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1781 SSVAL(req->outbuf,smb_vwv0,numentries);
1782 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1783 SCVAL(smb_buf(req->outbuf),0,5);
1784 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1786 /* The replies here are never long name. */
1787 SSVAL(req->outbuf, smb_flg2,
1788 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1789 if (!allow_long_path_components) {
1790 SSVAL(req->outbuf, smb_flg2,
1791 SVAL(req->outbuf, smb_flg2)
1792 & (~FLAGS2_LONG_PATH_COMPONENTS));
1795 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1796 SSVAL(req->outbuf, smb_flg2,
1797 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1799 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1800 smb_fn_name(req->cmd),
1807 TALLOC_FREE(directory);
1808 TALLOC_FREE(smb_fname);
1809 END_PROFILE(SMBsearch);
1813 /****************************************************************************
1814 Reply to a fclose (stop directory search).
1815 ****************************************************************************/
1817 void reply_fclose(struct smb_request *req)
1825 bool path_contains_wcard = False;
1826 TALLOC_CTX *ctx = talloc_tos();
1827 struct smbd_server_connection *sconn = req->sconn;
1829 START_PROFILE(SMBfclose);
1831 if (lp_posix_pathnames()) {
1832 reply_unknown_new(req, req->cmd);
1833 END_PROFILE(SMBfclose);
1837 p = (const char *)req->buf + 1;
1838 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1839 &err, &path_contains_wcard);
1840 if (!NT_STATUS_IS_OK(err)) {
1841 reply_nterror(req, err);
1842 END_PROFILE(SMBfclose);
1846 status_len = SVAL(p,0);
1849 if (status_len == 0) {
1850 reply_force_doserror(req, ERRSRV, ERRsrverror);
1851 END_PROFILE(SMBfclose);
1855 memcpy(status,p,21);
1857 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1858 /* Close the dptr - we know it's gone */
1859 dptr_close(sconn, &dptr_num);
1862 reply_outbuf(req, 1, 0);
1863 SSVAL(req->outbuf,smb_vwv0,0);
1865 DEBUG(3,("search close\n"));
1867 END_PROFILE(SMBfclose);
1871 /****************************************************************************
1873 ****************************************************************************/
1875 void reply_open(struct smb_request *req)
1877 connection_struct *conn = req->conn;
1878 struct smb_filename *smb_fname = NULL;
1890 uint32 create_disposition;
1891 uint32 create_options = 0;
1892 uint32_t private_flags = 0;
1894 TALLOC_CTX *ctx = talloc_tos();
1896 START_PROFILE(SMBopen);
1899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1903 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1904 deny_mode = SVAL(req->vwv+0, 0);
1905 dos_attr = SVAL(req->vwv+1, 0);
1907 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1908 STR_TERMINATE, &status);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 reply_nterror(req, status);
1914 if (!map_open_params_to_ntcreate(fname, deny_mode,
1915 OPENX_FILE_EXISTS_OPEN, &access_mask,
1916 &share_mode, &create_disposition,
1917 &create_options, &private_flags)) {
1918 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1922 status = filename_convert(ctx,
1924 req->flags2 & FLAGS2_DFS_PATHNAMES,
1926 UCF_PREP_CREATEFILE,
1929 if (!NT_STATUS_IS_OK(status)) {
1930 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1931 reply_botherror(req,
1932 NT_STATUS_PATH_NOT_COVERED,
1933 ERRSRV, ERRbadpath);
1936 reply_nterror(req, status);
1940 status = SMB_VFS_CREATE_FILE(
1943 0, /* root_dir_fid */
1944 smb_fname, /* fname */
1945 access_mask, /* access_mask */
1946 share_mode, /* share_access */
1947 create_disposition, /* create_disposition*/
1948 create_options, /* create_options */
1949 dos_attr, /* file_attributes */
1950 oplock_request, /* oplock_request */
1951 0, /* allocation_size */
1958 if (!NT_STATUS_IS_OK(status)) {
1959 if (open_was_deferred(req->sconn, req->mid)) {
1960 /* We have re-scheduled this call. */
1963 reply_openerror(req, status);
1967 /* Ensure we're pointing at the correct stat struct. */
1968 TALLOC_FREE(smb_fname);
1969 smb_fname = fsp->fsp_name;
1971 size = smb_fname->st.st_ex_size;
1972 fattr = dos_mode(conn, smb_fname);
1974 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1976 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1977 DEBUG(3,("attempt to open a directory %s\n",
1979 close_file(req, fsp, ERROR_CLOSE);
1980 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1981 ERRDOS, ERRnoaccess);
1985 reply_outbuf(req, 7, 0);
1986 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1987 SSVAL(req->outbuf,smb_vwv1,fattr);
1988 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1989 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1991 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1993 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1994 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1996 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1997 SCVAL(req->outbuf,smb_flg,
1998 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2001 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2002 SCVAL(req->outbuf,smb_flg,
2003 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2006 END_PROFILE(SMBopen);
2010 /****************************************************************************
2011 Reply to an open and X.
2012 ****************************************************************************/
2014 void reply_open_and_X(struct smb_request *req)
2016 connection_struct *conn = req->conn;
2017 struct smb_filename *smb_fname = NULL;
2022 /* Breakout the oplock request bits so we can set the
2023 reply bits separately. */
2024 int ex_oplock_request;
2025 int core_oplock_request;
2028 int smb_sattr = SVAL(req->vwv+4, 0);
2029 uint32 smb_time = make_unix_date3(req->vwv+6);
2037 uint64_t allocation_size;
2038 ssize_t retval = -1;
2041 uint32 create_disposition;
2042 uint32 create_options = 0;
2043 uint32_t private_flags = 0;
2044 TALLOC_CTX *ctx = talloc_tos();
2046 START_PROFILE(SMBopenX);
2048 if (req->wct < 15) {
2049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2053 open_flags = SVAL(req->vwv+2, 0);
2054 deny_mode = SVAL(req->vwv+3, 0);
2055 smb_attr = SVAL(req->vwv+5, 0);
2056 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2057 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2058 oplock_request = ex_oplock_request | core_oplock_request;
2059 smb_ofun = SVAL(req->vwv+8, 0);
2060 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2062 /* If it's an IPC, pass off the pipe handler. */
2064 if (lp_nt_pipe_support()) {
2065 reply_open_pipe_and_X(conn, req);
2067 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2072 /* XXXX we need to handle passed times, sattr and flags */
2073 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2074 STR_TERMINATE, &status);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 reply_nterror(req, status);
2080 if (!map_open_params_to_ntcreate(fname, deny_mode,
2082 &access_mask, &share_mode,
2083 &create_disposition,
2086 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2090 status = filename_convert(ctx,
2092 req->flags2 & FLAGS2_DFS_PATHNAMES,
2094 UCF_PREP_CREATEFILE,
2097 if (!NT_STATUS_IS_OK(status)) {
2098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2099 reply_botherror(req,
2100 NT_STATUS_PATH_NOT_COVERED,
2101 ERRSRV, ERRbadpath);
2104 reply_nterror(req, status);
2108 status = SMB_VFS_CREATE_FILE(
2111 0, /* root_dir_fid */
2112 smb_fname, /* fname */
2113 access_mask, /* access_mask */
2114 share_mode, /* share_access */
2115 create_disposition, /* create_disposition*/
2116 create_options, /* create_options */
2117 smb_attr, /* file_attributes */
2118 oplock_request, /* oplock_request */
2119 0, /* allocation_size */
2124 &smb_action); /* pinfo */
2126 if (!NT_STATUS_IS_OK(status)) {
2127 if (open_was_deferred(req->sconn, req->mid)) {
2128 /* We have re-scheduled this call. */
2131 reply_openerror(req, status);
2135 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2136 if the file is truncated or created. */
2137 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2138 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2139 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2140 close_file(req, fsp, ERROR_CLOSE);
2141 reply_nterror(req, NT_STATUS_DISK_FULL);
2144 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2146 close_file(req, fsp, ERROR_CLOSE);
2147 reply_nterror(req, NT_STATUS_DISK_FULL);
2150 status = vfs_stat_fsp(fsp);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 close_file(req, fsp, ERROR_CLOSE);
2153 reply_nterror(req, status);
2158 fattr = dos_mode(conn, fsp->fsp_name);
2159 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2160 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2161 close_file(req, fsp, ERROR_CLOSE);
2162 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2166 /* If the caller set the extended oplock request bit
2167 and we granted one (by whatever means) - set the
2168 correct bit for extended oplock reply.
2171 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2172 smb_action |= EXTENDED_OPLOCK_GRANTED;
2175 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2176 smb_action |= EXTENDED_OPLOCK_GRANTED;
2179 /* If the caller set the core oplock request bit
2180 and we granted one (by whatever means) - set the
2181 correct bit for core oplock reply.
2184 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2185 reply_outbuf(req, 19, 0);
2187 reply_outbuf(req, 15, 0);
2190 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2191 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2193 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2194 SCVAL(req->outbuf, smb_flg,
2195 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2198 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2199 SCVAL(req->outbuf, smb_flg,
2200 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2203 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2204 SSVAL(req->outbuf,smb_vwv3,fattr);
2205 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2206 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2208 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2210 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2211 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2212 SSVAL(req->outbuf,smb_vwv11,smb_action);
2214 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2215 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2219 TALLOC_FREE(smb_fname);
2220 END_PROFILE(SMBopenX);
2224 /****************************************************************************
2225 Reply to a SMBulogoffX.
2226 ****************************************************************************/
2228 void reply_ulogoffX(struct smb_request *req)
2230 struct smbd_server_connection *sconn = req->sconn;
2231 struct user_struct *vuser;
2232 struct smbXsrv_session *session = NULL;
2235 START_PROFILE(SMBulogoffX);
2237 vuser = get_valid_user_struct(sconn, req->vuid);
2240 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2241 (unsigned long long)req->vuid));
2243 req->vuid = UID_FIELD_INVALID;
2244 reply_force_doserror(req, ERRSRV, ERRbaduid);
2245 END_PROFILE(SMBulogoffX);
2249 session = vuser->session;
2253 * TODO: cancel all outstanding requests on the session
2255 status = smbXsrv_session_logoff(session);
2256 if (!NT_STATUS_IS_OK(status)) {
2257 DEBUG(0, ("reply_ulogoff: "
2258 "smbXsrv_session_logoff() failed: %s\n",
2259 nt_errstr(status)));
2261 * If we hit this case, there is something completely
2262 * wrong, so we better disconnect the transport connection.
2264 END_PROFILE(SMBulogoffX);
2265 exit_server(__location__ ": smbXsrv_session_logoff failed");
2269 TALLOC_FREE(session);
2271 reply_outbuf(req, 2, 0);
2272 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2273 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2275 DEBUG(3, ("ulogoffX vuid=%llu\n",
2276 (unsigned long long)req->vuid));
2278 END_PROFILE(SMBulogoffX);
2279 req->vuid = UID_FIELD_INVALID;
2282 /****************************************************************************
2283 Reply to a mknew or a create.
2284 ****************************************************************************/
2286 void reply_mknew(struct smb_request *req)
2288 connection_struct *conn = req->conn;
2289 struct smb_filename *smb_fname = NULL;
2292 struct smb_file_time ft;
2294 int oplock_request = 0;
2296 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2297 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2298 uint32 create_disposition;
2299 uint32 create_options = 0;
2300 TALLOC_CTX *ctx = talloc_tos();
2302 START_PROFILE(SMBcreate);
2306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2310 fattr = SVAL(req->vwv+0, 0);
2311 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2314 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2316 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2317 STR_TERMINATE, &status);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 reply_nterror(req, status);
2323 status = filename_convert(ctx,
2325 req->flags2 & FLAGS2_DFS_PATHNAMES,
2327 UCF_PREP_CREATEFILE,
2330 if (!NT_STATUS_IS_OK(status)) {
2331 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2332 reply_botherror(req,
2333 NT_STATUS_PATH_NOT_COVERED,
2334 ERRSRV, ERRbadpath);
2337 reply_nterror(req, status);
2341 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2342 DEBUG(0,("Attempt to create file (%s) with volid set - "
2343 "please report this\n",
2344 smb_fname_str_dbg(smb_fname)));
2347 if(req->cmd == SMBmknew) {
2348 /* We should fail if file exists. */
2349 create_disposition = FILE_CREATE;
2351 /* Create if file doesn't exist, truncate if it does. */
2352 create_disposition = FILE_OVERWRITE_IF;
2355 status = SMB_VFS_CREATE_FILE(
2358 0, /* root_dir_fid */
2359 smb_fname, /* fname */
2360 access_mask, /* access_mask */
2361 share_mode, /* share_access */
2362 create_disposition, /* create_disposition*/
2363 create_options, /* create_options */
2364 fattr, /* file_attributes */
2365 oplock_request, /* oplock_request */
2366 0, /* allocation_size */
2367 0, /* private_flags */
2373 if (!NT_STATUS_IS_OK(status)) {
2374 if (open_was_deferred(req->sconn, req->mid)) {
2375 /* We have re-scheduled this call. */
2378 reply_openerror(req, status);
2382 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2383 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 END_PROFILE(SMBcreate);
2389 reply_outbuf(req, 1, 0);
2390 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2392 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2393 SCVAL(req->outbuf,smb_flg,
2394 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2397 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2398 SCVAL(req->outbuf,smb_flg,
2399 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2402 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2403 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2404 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2405 (unsigned int)fattr));
2408 TALLOC_FREE(smb_fname);
2409 END_PROFILE(SMBcreate);
2413 /****************************************************************************
2414 Reply to a create temporary file.
2415 ****************************************************************************/
2417 void reply_ctemp(struct smb_request *req)
2419 connection_struct *conn = req->conn;
2420 struct smb_filename *smb_fname = NULL;
2421 char *wire_name = NULL;
2429 TALLOC_CTX *ctx = talloc_tos();
2431 START_PROFILE(SMBctemp);
2434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2438 fattr = SVAL(req->vwv+0, 0);
2439 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2441 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2442 STR_TERMINATE, &status);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 reply_nterror(req, status);
2448 for (i = 0; i < 10; i++) {
2450 fname = talloc_asprintf(ctx,
2453 generate_random_str_list(ctx, 5, "0123456789"));
2455 fname = talloc_asprintf(ctx,
2457 generate_random_str_list(ctx, 5, "0123456789"));
2461 reply_nterror(req, NT_STATUS_NO_MEMORY);
2465 status = filename_convert(ctx, conn,
2466 req->flags2 & FLAGS2_DFS_PATHNAMES,
2468 UCF_PREP_CREATEFILE,
2471 if (!NT_STATUS_IS_OK(status)) {
2472 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2473 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2474 ERRSRV, ERRbadpath);
2477 reply_nterror(req, status);
2481 /* Create the file. */
2482 status = SMB_VFS_CREATE_FILE(
2485 0, /* root_dir_fid */
2486 smb_fname, /* fname */
2487 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2488 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2489 FILE_CREATE, /* create_disposition*/
2490 0, /* create_options */
2491 fattr, /* file_attributes */
2492 oplock_request, /* oplock_request */
2493 0, /* allocation_size */
2494 0, /* private_flags */
2500 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2502 TALLOC_FREE(smb_fname);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 if (open_was_deferred(req->sconn, req->mid)) {
2508 /* We have re-scheduled this call. */
2511 reply_openerror(req, status);
2519 /* Collision after 10 times... */
2520 reply_nterror(req, status);
2524 reply_outbuf(req, 1, 0);
2525 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2527 /* the returned filename is relative to the directory */
2528 s = strrchr_m(fsp->fsp_name->base_name, '/');
2530 s = fsp->fsp_name->base_name;
2536 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2537 thing in the byte section. JRA */
2538 SSVALS(p, 0, -1); /* what is this? not in spec */
2540 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2542 reply_nterror(req, NT_STATUS_NO_MEMORY);
2546 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2547 SCVAL(req->outbuf, smb_flg,
2548 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2551 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2552 SCVAL(req->outbuf, smb_flg,
2553 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2556 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2557 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2558 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2560 TALLOC_FREE(smb_fname);
2561 TALLOC_FREE(wire_name);
2562 END_PROFILE(SMBctemp);
2566 /*******************************************************************
2567 Check if a user is allowed to rename a file.
2568 ********************************************************************/
2570 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2573 if (!CAN_WRITE(conn)) {
2574 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2577 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2578 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2579 /* Only bother to read the DOS attribute if we might deny the
2580 rename on the grounds of attribute missmatch. */
2581 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2582 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2583 return NT_STATUS_NO_SUCH_FILE;
2587 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2588 if (fsp->posix_open) {
2589 return NT_STATUS_OK;
2592 /* If no pathnames are open below this
2593 directory, allow the rename. */
2595 if (file_find_subpath(fsp)) {
2596 return NT_STATUS_ACCESS_DENIED;
2598 return NT_STATUS_OK;
2601 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2602 return NT_STATUS_OK;
2605 return NT_STATUS_ACCESS_DENIED;
2608 /*******************************************************************
2609 * unlink a file with all relevant access checks
2610 *******************************************************************/
2612 static NTSTATUS do_unlink(connection_struct *conn,
2613 struct smb_request *req,
2614 struct smb_filename *smb_fname,
2619 uint32 dirtype_orig = dirtype;
2622 bool posix_paths = lp_posix_pathnames();
2624 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2625 smb_fname_str_dbg(smb_fname),
2628 if (!CAN_WRITE(conn)) {
2629 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2633 ret = SMB_VFS_LSTAT(conn, smb_fname);
2635 ret = SMB_VFS_STAT(conn, smb_fname);
2638 return map_nt_error_from_unix(errno);
2641 fattr = dos_mode(conn, smb_fname);
2643 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2644 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2647 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2649 return NT_STATUS_NO_SUCH_FILE;
2652 if (!dir_check_ftype(fattr, dirtype)) {
2653 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2654 return NT_STATUS_FILE_IS_A_DIRECTORY;
2656 return NT_STATUS_NO_SUCH_FILE;
2659 if (dirtype_orig & 0x8000) {
2660 /* These will never be set for POSIX. */
2661 return NT_STATUS_NO_SUCH_FILE;
2665 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2666 return NT_STATUS_FILE_IS_A_DIRECTORY;
2669 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2670 return NT_STATUS_NO_SUCH_FILE;
2673 if (dirtype & 0xFF00) {
2674 /* These will never be set for POSIX. */
2675 return NT_STATUS_NO_SUCH_FILE;
2680 return NT_STATUS_NO_SUCH_FILE;
2683 /* Can't delete a directory. */
2684 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2685 return NT_STATUS_FILE_IS_A_DIRECTORY;
2690 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2691 return NT_STATUS_OBJECT_NAME_INVALID;
2692 #endif /* JRATEST */
2694 /* On open checks the open itself will check the share mode, so
2695 don't do it here as we'll get it wrong. */
2697 status = SMB_VFS_CREATE_FILE
2700 0, /* root_dir_fid */
2701 smb_fname, /* fname */
2702 DELETE_ACCESS, /* access_mask */
2703 FILE_SHARE_NONE, /* share_access */
2704 FILE_OPEN, /* create_disposition*/
2705 FILE_NON_DIRECTORY_FILE, /* create_options */
2706 /* file_attributes */
2707 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2708 FILE_ATTRIBUTE_NORMAL,
2709 0, /* oplock_request */
2710 0, /* allocation_size */
2711 0, /* private_flags */
2717 if (!NT_STATUS_IS_OK(status)) {
2718 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2719 nt_errstr(status)));
2723 status = can_set_delete_on_close(fsp, fattr);
2724 if (!NT_STATUS_IS_OK(status)) {
2725 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2727 smb_fname_str_dbg(smb_fname),
2728 nt_errstr(status)));
2729 close_file(req, fsp, NORMAL_CLOSE);
2733 /* The set is across all open files on this dev/inode pair. */
2734 if (!set_delete_on_close(fsp, True,
2735 conn->session_info->security_token,
2736 conn->session_info->unix_token)) {
2737 close_file(req, fsp, NORMAL_CLOSE);
2738 return NT_STATUS_ACCESS_DENIED;
2741 return close_file(req, fsp, NORMAL_CLOSE);
2744 /****************************************************************************
2745 The guts of the unlink command, split out so it may be called by the NT SMB
2747 ****************************************************************************/
2749 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2750 uint32 dirtype, struct smb_filename *smb_fname,
2753 char *fname_dir = NULL;
2754 char *fname_mask = NULL;
2756 NTSTATUS status = NT_STATUS_OK;
2757 TALLOC_CTX *ctx = talloc_tos();
2759 /* Split up the directory from the filename/mask. */
2760 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2761 &fname_dir, &fname_mask);
2762 if (!NT_STATUS_IS_OK(status)) {
2767 * We should only check the mangled cache
2768 * here if unix_convert failed. This means
2769 * that the path in 'mask' doesn't exist
2770 * on the file system and so we need to look
2771 * for a possible mangle. This patch from
2772 * Tine Smukavec <valentin.smukavec@hermes.si>.
2775 if (!VALID_STAT(smb_fname->st) &&
2776 mangle_is_mangled(fname_mask, conn->params)) {
2777 char *new_mask = NULL;
2778 mangle_lookup_name_from_8_3(ctx, fname_mask,
2779 &new_mask, conn->params);
2781 TALLOC_FREE(fname_mask);
2782 fname_mask = new_mask;
2789 * Only one file needs to be unlinked. Append the mask back
2790 * onto the directory.
2792 TALLOC_FREE(smb_fname->base_name);
2793 if (ISDOT(fname_dir)) {
2794 /* Ensure we use canonical names on open. */
2795 smb_fname->base_name = talloc_asprintf(smb_fname,
2799 smb_fname->base_name = talloc_asprintf(smb_fname,
2804 if (!smb_fname->base_name) {
2805 status = NT_STATUS_NO_MEMORY;
2809 dirtype = FILE_ATTRIBUTE_NORMAL;
2812 status = check_name(conn, smb_fname->base_name);
2813 if (!NT_STATUS_IS_OK(status)) {
2817 status = do_unlink(conn, req, smb_fname, dirtype);
2818 if (!NT_STATUS_IS_OK(status)) {
2824 struct smb_Dir *dir_hnd = NULL;
2826 const char *dname = NULL;
2827 char *talloced = NULL;
2829 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2830 status = NT_STATUS_OBJECT_NAME_INVALID;
2834 if (strequal(fname_mask,"????????.???")) {
2835 TALLOC_FREE(fname_mask);
2836 fname_mask = talloc_strdup(ctx, "*");
2838 status = NT_STATUS_NO_MEMORY;
2843 status = check_name(conn, fname_dir);
2844 if (!NT_STATUS_IS_OK(status)) {
2848 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2850 if (dir_hnd == NULL) {
2851 status = map_nt_error_from_unix(errno);
2855 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2856 the pattern matches against the long name, otherwise the short name
2857 We don't implement this yet XXXX
2860 status = NT_STATUS_NO_SUCH_FILE;
2862 while ((dname = ReadDirName(dir_hnd, &offset,
2863 &smb_fname->st, &talloced))) {
2864 TALLOC_CTX *frame = talloc_stackframe();
2866 if (!is_visible_file(conn, fname_dir, dname,
2867 &smb_fname->st, true)) {
2869 TALLOC_FREE(talloced);
2873 /* Quick check for "." and ".." */
2874 if (ISDOT(dname) || ISDOTDOT(dname)) {
2876 TALLOC_FREE(talloced);
2880 if(!mask_match(dname, fname_mask,
2881 conn->case_sensitive)) {
2883 TALLOC_FREE(talloced);
2887 TALLOC_FREE(smb_fname->base_name);
2888 if (ISDOT(fname_dir)) {
2889 /* Ensure we use canonical names on open. */
2890 smb_fname->base_name =
2891 talloc_asprintf(smb_fname, "%s",
2894 smb_fname->base_name =
2895 talloc_asprintf(smb_fname, "%s/%s",
2899 if (!smb_fname->base_name) {
2900 TALLOC_FREE(dir_hnd);
2901 status = NT_STATUS_NO_MEMORY;
2903 TALLOC_FREE(talloced);
2907 status = check_name(conn, smb_fname->base_name);
2908 if (!NT_STATUS_IS_OK(status)) {
2909 TALLOC_FREE(dir_hnd);
2911 TALLOC_FREE(talloced);
2915 status = do_unlink(conn, req, smb_fname, dirtype);
2916 if (!NT_STATUS_IS_OK(status)) {
2917 TALLOC_FREE(dir_hnd);
2919 TALLOC_FREE(talloced);
2924 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2925 smb_fname->base_name));
2928 TALLOC_FREE(talloced);
2930 TALLOC_FREE(dir_hnd);
2933 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2934 status = map_nt_error_from_unix(errno);
2938 TALLOC_FREE(fname_dir);
2939 TALLOC_FREE(fname_mask);
2943 /****************************************************************************
2945 ****************************************************************************/
2947 void reply_unlink(struct smb_request *req)
2949 connection_struct *conn = req->conn;
2951 struct smb_filename *smb_fname = NULL;
2954 bool path_contains_wcard = False;
2955 TALLOC_CTX *ctx = talloc_tos();
2957 START_PROFILE(SMBunlink);
2960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2964 dirtype = SVAL(req->vwv+0, 0);
2966 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2967 STR_TERMINATE, &status,
2968 &path_contains_wcard);
2969 if (!NT_STATUS_IS_OK(status)) {
2970 reply_nterror(req, status);
2974 status = filename_convert(ctx, conn,
2975 req->flags2 & FLAGS2_DFS_PATHNAMES,
2977 UCF_COND_ALLOW_WCARD_LCOMP,
2978 &path_contains_wcard,
2980 if (!NT_STATUS_IS_OK(status)) {
2981 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2982 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2983 ERRSRV, ERRbadpath);
2986 reply_nterror(req, status);
2990 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2992 status = unlink_internals(conn, req, dirtype, smb_fname,
2993 path_contains_wcard);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 if (open_was_deferred(req->sconn, req->mid)) {
2996 /* We have re-scheduled this call. */
2999 reply_nterror(req, status);
3003 reply_outbuf(req, 0, 0);
3005 TALLOC_FREE(smb_fname);
3006 END_PROFILE(SMBunlink);
3010 /****************************************************************************
3012 ****************************************************************************/
3014 static void fail_readraw(void)
3016 const char *errstr = talloc_asprintf(talloc_tos(),
3017 "FAIL ! reply_readbraw: socket write fail (%s)",
3022 exit_server_cleanly(errstr);
3025 /****************************************************************************
3026 Fake (read/write) sendfile. Returns -1 on read or write fail.
3027 ****************************************************************************/
3029 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
3031 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3033 size_t tosend = nread;
3040 bufsize = MIN(nread, 65536);
3042 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3046 while (tosend > 0) {
3050 if (tosend > bufsize) {
3055 ret = read_file(fsp,buf,startpos,cur_read);
3061 /* If we had a short read, fill with zeros. */
3062 if (ret < cur_read) {
3063 memset(buf + ret, '\0', cur_read - ret);
3066 ret = write_data(xconn->transport.sock, buf, cur_read);
3067 if (ret != cur_read) {
3068 int saved_errno = errno;
3070 * Try and give an error message saying what
3073 DEBUG(0, ("write_data failed for client %s. "
3075 smbXsrv_connection_dbg(xconn),
3076 strerror(saved_errno)));
3078 errno = saved_errno;
3082 startpos += cur_read;
3086 return (ssize_t)nread;
3089 /****************************************************************************
3090 Deal with the case of sendfile reading less bytes from the file than
3091 requested. Fill with zeros (all we can do).
3092 ****************************************************************************/
3094 void sendfile_short_send(files_struct *fsp,
3099 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3101 #define SHORT_SEND_BUFSIZE 1024
3102 if (nread < headersize) {
3103 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3104 "header for file %s (%s). Terminating\n",
3105 fsp_str_dbg(fsp), strerror(errno)));
3106 exit_server_cleanly("sendfile_short_send failed");
3109 nread -= headersize;
3111 if (nread < smb_maxcnt) {
3112 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3114 exit_server_cleanly("sendfile_short_send: "
3118 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3119 "with zeros !\n", fsp_str_dbg(fsp)));
3121 while (nread < smb_maxcnt) {
3123 * We asked for the real file size and told sendfile
3124 * to not go beyond the end of the file. But it can
3125 * happen that in between our fstat call and the
3126 * sendfile call the file was truncated. This is very
3127 * bad because we have already announced the larger
3128 * number of bytes to the client.
3130 * The best we can do now is to send 0-bytes, just as
3131 * a read from a hole in a sparse file would do.
3133 * This should happen rarely enough that I don't care
3134 * about efficiency here :-)
3139 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3140 ret = write_data(xconn->transport.sock, buf, to_write);
3141 if (ret != to_write) {
3142 int saved_errno = errno;
3144 * Try and give an error message saying what
3147 DEBUG(0, ("write_data failed for client %s. "
3149 smbXsrv_connection_dbg(xconn),
3150 strerror(saved_errno)));
3151 errno = saved_errno;
3152 exit_server_cleanly("sendfile_short_send: "
3153 "write_data failed");
3161 /****************************************************************************
3162 Return a readbraw error (4 bytes of zero).
3163 ****************************************************************************/
3165 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3167 struct smbd_server_connection *sconn = xconn->sconn;
3172 smbd_lock_socket(sconn);
3173 if (write_data(xconn->transport.sock,header,4) != 4) {
3174 int saved_errno = errno;
3176 * Try and give an error message saying what
3179 DEBUG(0, ("write_data failed for client %s. "
3181 smbXsrv_connection_dbg(xconn),
3182 strerror(saved_errno)));
3183 errno = saved_errno;
3187 smbd_unlock_socket(sconn);
3190 /****************************************************************************
3191 Use sendfile in readbraw.
3192 ****************************************************************************/
3194 static void send_file_readbraw(connection_struct *conn,
3195 struct smb_request *req,
3201 struct smbXsrv_connection *xconn = req->xconn;
3202 char *outbuf = NULL;
3206 * We can only use sendfile on a non-chained packet
3207 * but we can use on a non-oplocked file. tridge proved this
3208 * on a train in Germany :-). JRA.
3209 * reply_readbraw has already checked the length.
3212 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3213 (fsp->wcp == NULL) &&
3214 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3215 ssize_t sendfile_read = -1;
3217 DATA_BLOB header_blob;
3219 _smb_setlen(header,nread);
3220 header_blob = data_blob_const(header, 4);
3222 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3223 &header_blob, startpos,
3225 if (sendfile_read == -1) {
3226 /* Returning ENOSYS means no data at all was sent.
3227 * Do this as a normal read. */
3228 if (errno == ENOSYS) {
3229 goto normal_readbraw;
3233 * Special hack for broken Linux with no working sendfile. If we
3234 * return EINTR we sent the header but not the rest of the data.
3235 * Fake this up by doing read/write calls.
3237 if (errno == EINTR) {
3238 /* Ensure we don't do this again. */
3239 set_use_sendfile(SNUM(conn), False);
3240 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242 if (fake_sendfile(fsp, startpos, nread) == -1) {
3243 DEBUG(0,("send_file_readbraw: "
3244 "fake_sendfile failed for "
3248 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3253 DEBUG(0,("send_file_readbraw: sendfile failed for "
3254 "file %s (%s). Terminating\n",
3255 fsp_str_dbg(fsp), strerror(errno)));
3256 exit_server_cleanly("send_file_readbraw sendfile failed");
3257 } else if (sendfile_read == 0) {
3259 * Some sendfile implementations return 0 to indicate
3260 * that there was a short read, but nothing was
3261 * actually written to the socket. In this case,
3262 * fallback to the normal read path so the header gets
3263 * the correct byte count.
3265 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3266 "bytes falling back to the normal read: "
3267 "%s\n", fsp_str_dbg(fsp)));
3268 goto normal_readbraw;
3271 /* Deal with possible short send. */
3272 if (sendfile_read != 4+nread) {
3273 sendfile_short_send(fsp, sendfile_read, 4, nread);
3280 outbuf = talloc_array(NULL, char, nread+4);
3282 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3283 (unsigned)(nread+4)));
3284 reply_readbraw_error(xconn);
3289 ret = read_file(fsp,outbuf+4,startpos,nread);
3290 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3299 _smb_setlen(outbuf,ret);
3300 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3301 int saved_errno = errno;
3303 * Try and give an error message saying what
3306 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3307 smbXsrv_connection_dbg(xconn),
3308 strerror(saved_errno)));
3309 errno = saved_errno;
3314 TALLOC_FREE(outbuf);
3317 /****************************************************************************
3318 Reply to a readbraw (core+ protocol).
3319 ****************************************************************************/
3321 void reply_readbraw(struct smb_request *req)
3323 connection_struct *conn = req->conn;
3324 struct smbXsrv_connection *xconn = req->xconn;
3325 ssize_t maxcount,mincount;
3329 struct lock_struct lock;
3332 START_PROFILE(SMBreadbraw);
3334 if (srv_is_signing_active(xconn) || req->encrypted) {
3335 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3336 "raw reads/writes are disallowed.");
3340 reply_readbraw_error(xconn);
3341 END_PROFILE(SMBreadbraw);
3345 if (xconn->smb1.echo_handler.trusted_fde) {
3346 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3347 "'async smb echo handler = yes'\n"));
3348 reply_readbraw_error(xconn);
3349 END_PROFILE(SMBreadbraw);
3354 * Special check if an oplock break has been issued
3355 * and the readraw request croses on the wire, we must
3356 * return a zero length response here.
3359 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3362 * We have to do a check_fsp by hand here, as
3363 * we must always return 4 zero bytes on error,
3367 if (!fsp || !conn || conn != fsp->conn ||
3368 req->vuid != fsp->vuid ||
3369 fsp->is_directory || fsp->fh->fd == -1) {
3371 * fsp could be NULL here so use the value from the packet. JRA.
3373 DEBUG(3,("reply_readbraw: fnum %d not valid "
3375 (int)SVAL(req->vwv+0, 0)));
3376 reply_readbraw_error(xconn);
3377 END_PROFILE(SMBreadbraw);
3381 /* Do a "by hand" version of CHECK_READ. */
3382 if (!(fsp->can_read ||
3383 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3384 (fsp->access_mask & FILE_EXECUTE)))) {
3385 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3386 (int)SVAL(req->vwv+0, 0)));
3387 reply_readbraw_error(xconn);
3388 END_PROFILE(SMBreadbraw);
3392 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3394 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3395 if(req->wct == 10) {
3397 * This is a large offset (64 bit) read.
3400 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3403 DEBUG(0,("reply_readbraw: negative 64 bit "
3404 "readraw offset (%.0f) !\n",
3405 (double)startpos ));
3406 reply_readbraw_error(xconn);
3407 END_PROFILE(SMBreadbraw);
3412 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3413 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3415 /* ensure we don't overrun the packet size */
3416 maxcount = MIN(65535,maxcount);
3418 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3419 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3422 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3423 reply_readbraw_error(xconn);
3424 END_PROFILE(SMBreadbraw);
3428 if (fsp_stat(fsp) == 0) {
3429 size = fsp->fsp_name->st.st_ex_size;
3432 if (startpos >= size) {
3435 nread = MIN(maxcount,(size - startpos));
3438 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3439 if (nread < mincount)
3443 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3444 "min=%lu nread=%lu\n",
3445 fsp_fnum_dbg(fsp), (double)startpos,
3446 (unsigned long)maxcount,
3447 (unsigned long)mincount,
3448 (unsigned long)nread ) );
3450 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3452 DEBUG(5,("reply_readbraw finished\n"));
3454 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3456 END_PROFILE(SMBreadbraw);
3461 #define DBGC_CLASS DBGC_LOCKING
3463 /****************************************************************************
3464 Reply to a lockread (core+ protocol).
3465 ****************************************************************************/
3467 void reply_lockread(struct smb_request *req)
3469 connection_struct *conn = req->conn;
3477 struct byte_range_lock *br_lck = NULL;
3479 struct smbd_server_connection *sconn = req->sconn;
3480 struct smbXsrv_connection *xconn = sconn->conn;
3482 START_PROFILE(SMBlockread);
3485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3486 END_PROFILE(SMBlockread);
3490 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3492 if (!check_fsp(conn, req, fsp)) {
3493 END_PROFILE(SMBlockread);
3497 if (!CHECK_READ(fsp,req)) {
3498 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3499 END_PROFILE(SMBlockread);
3503 numtoread = SVAL(req->vwv+1, 0);
3504 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3507 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3508 * protocol request that predates the read/write lock concept.
3509 * Thus instead of asking for a read lock here we need to ask
3510 * for a write lock. JRA.
3511 * Note that the requested lock size is unaffected by max_send.
3514 br_lck = do_lock(req->sconn->msg_ctx,
3516 (uint64_t)req->smbpid,
3517 (uint64_t)numtoread,
3521 False, /* Non-blocking lock. */
3524 TALLOC_FREE(br_lck);
3526 if (NT_STATUS_V(status)) {
3527 reply_nterror(req, status);
3528 END_PROFILE(SMBlockread);
3533 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3535 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3537 if (numtoread > maxtoread) {
3538 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3539 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3540 (unsigned int)numtoread, (unsigned int)maxtoread,
3541 (unsigned int)xconn->smb1.sessions.max_send));
3542 numtoread = maxtoread;
3545 reply_outbuf(req, 5, numtoread + 3);
3547 data = smb_buf(req->outbuf) + 3;
3549 nread = read_file(fsp,data,startpos,numtoread);
3552 reply_nterror(req, map_nt_error_from_unix(errno));
3553 END_PROFILE(SMBlockread);
3557 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3559 SSVAL(req->outbuf,smb_vwv0,nread);
3560 SSVAL(req->outbuf,smb_vwv5,nread+3);
3561 p = smb_buf(req->outbuf);
3562 SCVAL(p,0,0); /* pad byte. */
3565 DEBUG(3,("lockread %s num=%d nread=%d\n",
3566 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3568 END_PROFILE(SMBlockread);
3573 #define DBGC_CLASS DBGC_ALL
3575 /****************************************************************************
3577 ****************************************************************************/
3579 void reply_read(struct smb_request *req)
3581 connection_struct *conn = req->conn;
3588 struct lock_struct lock;
3589 struct smbd_server_connection *sconn = req->sconn;
3590 struct smbXsrv_connection *xconn = sconn->conn;
3592 START_PROFILE(SMBread);
3595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3596 END_PROFILE(SMBread);
3600 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3602 if (!check_fsp(conn, req, fsp)) {
3603 END_PROFILE(SMBread);
3607 if (!CHECK_READ(fsp,req)) {
3608 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3609 END_PROFILE(SMBread);
3613 numtoread = SVAL(req->vwv+1, 0);
3614 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3617 * The requested read size cannot be greater than max_send. JRA.
3619 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3621 if (numtoread > maxtoread) {
3622 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3623 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3624 (unsigned int)numtoread, (unsigned int)maxtoread,
3625 (unsigned int)xconn->smb1.sessions.max_send));
3626 numtoread = maxtoread;
3629 reply_outbuf(req, 5, numtoread+3);
3631 data = smb_buf(req->outbuf) + 3;
3633 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3634 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3637 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3638 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3639 END_PROFILE(SMBread);
3644 nread = read_file(fsp,data,startpos,numtoread);
3647 reply_nterror(req, map_nt_error_from_unix(errno));
3651 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3653 SSVAL(req->outbuf,smb_vwv0,nread);
3654 SSVAL(req->outbuf,smb_vwv5,nread+3);
3655 SCVAL(smb_buf(req->outbuf),0,1);
3656 SSVAL(smb_buf(req->outbuf),1,nread);
3658 DEBUG(3, ("read %s num=%d nread=%d\n",
3659 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3662 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3664 END_PROFILE(SMBread);
3668 /****************************************************************************
3670 ****************************************************************************/
3672 static int setup_readX_header(struct smb_request *req, char *outbuf,
3677 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3679 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3681 SCVAL(outbuf,smb_vwv0,0xFF);
3682 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3683 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3684 SSVAL(outbuf,smb_vwv6,
3685 (smb_wct - 4) /* offset from smb header to wct */
3686 + 1 /* the wct field */
3687 + 12 * sizeof(uint16_t) /* vwv */
3688 + 2); /* the buflen field */
3689 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3690 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3691 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3692 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3696 /****************************************************************************
3697 Reply to a read and X - possibly using sendfile.
3698 ****************************************************************************/
3700 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3701 files_struct *fsp, off_t startpos,
3704 struct smbXsrv_connection *xconn = req->sconn->conn;
3706 struct lock_struct lock;
3707 int saved_errno = 0;
3709 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3710 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3713 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3714 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3719 * We can only use sendfile on a non-chained packet
3720 * but we can use on a non-oplocked file. tridge proved this
3721 * on a train in Germany :-). JRA.
3724 if (!req_is_in_chain(req) &&
3726 (fsp->base_fsp == NULL) &&
3727 (fsp->wcp == NULL) &&
3728 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3729 uint8 headerbuf[smb_size + 12 * 2];
3732 if(fsp_stat(fsp) == -1) {
3733 reply_nterror(req, map_nt_error_from_unix(errno));
3737 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3738 (startpos > fsp->fsp_name->st.st_ex_size) ||
3739 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3741 * We already know that we would do a short read, so don't
3742 * try the sendfile() path.
3744 goto nosendfile_read;
3748 * Set up the packet header before send. We
3749 * assume here the sendfile will work (get the
3750 * correct amount of data).
3753 header = data_blob_const(headerbuf, sizeof(headerbuf));
3755 construct_reply_common_req(req, (char *)headerbuf);
3756 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3758 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3759 startpos, smb_maxcnt);
3761 saved_errno = errno;
3763 /* Returning ENOSYS means no data at all was sent.
3764 Do this as a normal read. */
3765 if (errno == ENOSYS) {
3770 * Special hack for broken Linux with no working sendfile. If we
3771 * return EINTR we sent the header but not the rest of the data.
3772 * Fake this up by doing read/write calls.
3775 if (errno == EINTR) {
3776 /* Ensure we don't do this again. */
3777 set_use_sendfile(SNUM(conn), False);
3778 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3779 nread = fake_sendfile(fsp, startpos,
3782 saved_errno = errno;
3783 DEBUG(0,("send_file_readX: "
3784 "fake_sendfile failed for "
3785 "file %s (%s) for client %s. "
3788 smbXsrv_connection_dbg(xconn),
3789 strerror(saved_errno)));
3790 errno = saved_errno;
3791 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3793 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3794 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3795 /* No outbuf here means successful sendfile. */
3799 DEBUG(0,("send_file_readX: sendfile failed for file "
3800 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3802 exit_server_cleanly("send_file_readX sendfile failed");
3803 } else if (nread == 0) {
3805 * Some sendfile implementations return 0 to indicate
3806 * that there was a short read, but nothing was
3807 * actually written to the socket. In this case,
3808 * fallback to the normal read path so the header gets
3809 * the correct byte count.
3811 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3812 "falling back to the normal read: %s\n",
3817 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3818 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3820 /* Deal with possible short send. */
3821 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3822 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3824 /* No outbuf here means successful sendfile. */
3825 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3826 SMB_PERFCOUNT_END(&req->pcd);
3832 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3833 uint8 headerbuf[smb_size + 2*12];
3836 construct_reply_common_req(req, (char *)headerbuf);
3837 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3839 /* Send out the header. */
3840 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3842 if (ret != sizeof(headerbuf)) {
3843 saved_errno = errno;
3845 * Try and give an error message saying what
3848 DEBUG(0,("send_file_readX: write_data failed for file "
3849 "%s (%s) for client %s. Terminating\n",
3851 smbXsrv_connection_dbg(xconn),
3852 strerror(saved_errno)));
3853 errno = saved_errno;
3854 exit_server_cleanly("send_file_readX sendfile failed");
3856 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3858 saved_errno = errno;
3859 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3860 "%s (%s) for client %s. Terminating\n",
3862 smbXsrv_connection_dbg(xconn),
3863 strerror(saved_errno)));
3864 errno = saved_errno;
3865 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3872 reply_outbuf(req, 12, smb_maxcnt);
3873 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3874 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3876 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3877 saved_errno = errno;
3879 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3882 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3886 setup_readX_header(req, (char *)req->outbuf, nread);
3888 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3889 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3893 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3894 TALLOC_FREE(req->outbuf);
3898 /****************************************************************************
3899 Work out how much space we have for a read return.
3900 ****************************************************************************/
3902 static size_t calc_max_read_pdu(const struct smb_request *req)
3904 struct smbXsrv_connection *xconn = req->sconn->conn;
3906 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3907 return xconn->smb1.sessions.max_send;
3910 if (!lp_large_readwrite()) {
3911 return xconn->smb1.sessions.max_send;
3914 if (req_is_in_chain(req)) {
3915 return xconn->smb1.sessions.max_send;
3918 if (req->encrypted) {
3920 * Don't take encrypted traffic up to the
3921 * limit. There are padding considerations
3922 * that make that tricky.
3924 return xconn->smb1.sessions.max_send;
3927 if (srv_is_signing_active(xconn)) {
3931 if (!lp_unix_extensions()) {
3936 * We can do ultra-large POSIX reads.
3941 /****************************************************************************
3942 Calculate how big a read can be. Copes with all clients. It's always
3943 safe to return a short read - Windows does this.
3944 ****************************************************************************/
3946 static size_t calc_read_size(const struct smb_request *req,
3950 size_t max_pdu = calc_max_read_pdu(req);
3951 size_t total_size = 0;
3952 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3953 size_t max_len = max_pdu - hdr_len;
3956 * Windows explicitly ignores upper size of 0xFFFF.
3957 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3958 * We must do the same as these will never fit even in
3959 * an extended size NetBIOS packet.
3961 if (upper_size == 0xFFFF) {
3965 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3969 total_size = ((upper_size<<16) | lower_size);
3972 * LARGE_READX test shows it's always safe to return
3973 * a short read. Windows does so.
3975 return MIN(total_size, max_len);
3978 /****************************************************************************
3979 Reply to a read and X.
3980 ****************************************************************************/
3982 void reply_read_and_X(struct smb_request *req)
3984 connection_struct *conn = req->conn;
3989 bool big_readX = False;
3991 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3994 START_PROFILE(SMBreadX);
3996 if ((req->wct != 10) && (req->wct != 12)) {
3997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4001 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4002 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4003 smb_maxcnt = SVAL(req->vwv+5, 0);
4005 /* If it's an IPC, pass off the pipe handler. */
4007 reply_pipe_read_and_X(req);
4008 END_PROFILE(SMBreadX);
4012 if (!check_fsp(conn, req, fsp)) {
4013 END_PROFILE(SMBreadX);
4017 if (!CHECK_READ(fsp,req)) {
4018 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4019 END_PROFILE(SMBreadX);
4023 upper_size = SVAL(req->vwv+7, 0);
4024 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4025 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4027 * This is a heuristic to avoid keeping large
4028 * outgoing buffers around over long-lived aio
4034 if (req->wct == 12) {
4036 * This is a large offset (64 bit) read.
4038 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4043 NTSTATUS status = schedule_aio_read_and_X(conn,
4048 if (NT_STATUS_IS_OK(status)) {
4049 /* Read scheduled - we're done. */
4052 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4053 /* Real error - report to client. */
4054 END_PROFILE(SMBreadX);
4055 reply_nterror(req, status);
4058 /* NT_STATUS_RETRY - fall back to sync read. */
4061 smbd_lock_socket(req->sconn);
4062 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4063 smbd_unlock_socket(req->sconn);
4066 END_PROFILE(SMBreadX);
4070 /****************************************************************************
4071 Error replies to writebraw must have smb_wct == 1. Fix this up.
4072 ****************************************************************************/
4074 void error_to_writebrawerr(struct smb_request *req)
4076 uint8 *old_outbuf = req->outbuf;
4078 reply_outbuf(req, 1, 0);
4080 memcpy(req->outbuf, old_outbuf, smb_size);
4081 TALLOC_FREE(old_outbuf);
4084 /****************************************************************************
4085 Read 4 bytes of a smb packet and return the smb length of the packet.
4086 Store the result in the buffer. This version of the function will
4087 never return a session keepalive (length of zero).
4088 Timeout is in milliseconds.
4089 ****************************************************************************/
4091 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4094 uint8_t msgtype = NBSSkeepalive;
4096 while (msgtype == NBSSkeepalive) {
4099 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4101 if (!NT_STATUS_IS_OK(status)) {
4102 char addr[INET6_ADDRSTRLEN];
4103 /* Try and give an error message
4104 * saying what client failed. */
4105 DEBUG(0, ("read_fd_with_timeout failed for "
4106 "client %s read error = %s.\n",
4107 get_peer_addr(fd,addr,sizeof(addr)),
4108 nt_errstr(status)));
4112 msgtype = CVAL(inbuf, 0);
4115 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4116 (unsigned long)len));
4118 return NT_STATUS_OK;
4121 /****************************************************************************
4122 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4123 ****************************************************************************/
4125 void reply_writebraw(struct smb_request *req)
4127 connection_struct *conn = req->conn;
4128 struct smbXsrv_connection *xconn = req->sconn->conn;
4131 ssize_t total_written=0;
4132 size_t numtowrite=0;
4135 const char *data=NULL;
4138 struct lock_struct lock;
4141 START_PROFILE(SMBwritebraw);
4144 * If we ever reply with an error, it must have the SMB command
4145 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4148 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4150 if (srv_is_signing_active(xconn)) {
4151 END_PROFILE(SMBwritebraw);
4152 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4153 "raw reads/writes are disallowed.");
4156 if (req->wct < 12) {
4157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4158 error_to_writebrawerr(req);
4159 END_PROFILE(SMBwritebraw);
4163 if (xconn->smb1.echo_handler.trusted_fde) {
4164 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4165 "'async smb echo handler = yes'\n"));
4166 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4167 error_to_writebrawerr(req);
4168 END_PROFILE(SMBwritebraw);
4172 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4173 if (!check_fsp(conn, req, fsp)) {
4174 error_to_writebrawerr(req);
4175 END_PROFILE(SMBwritebraw);
4179 if (!CHECK_WRITE(fsp)) {
4180 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4181 error_to_writebrawerr(req);
4182 END_PROFILE(SMBwritebraw);
4186 tcount = IVAL(req->vwv+1, 0);
4187 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4188 write_through = BITSETW(req->vwv+7,0);
4190 /* We have to deal with slightly different formats depending
4191 on whether we are using the core+ or lanman1.0 protocol */
4193 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4194 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4195 data = smb_buf_const(req->inbuf);
4197 numtowrite = SVAL(req->vwv+10, 0);
4198 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4201 /* Ensure we don't write bytes past the end of this packet. */
4202 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4204 error_to_writebrawerr(req);
4205 END_PROFILE(SMBwritebraw);
4209 if (!fsp->print_file) {
4210 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4211 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4214 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4215 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4216 error_to_writebrawerr(req);
4217 END_PROFILE(SMBwritebraw);
4223 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4226 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4227 "wrote=%d sync=%d\n",
4228 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4229 (int)nwritten, (int)write_through));
4231 if (nwritten < (ssize_t)numtowrite) {
4232 reply_nterror(req, NT_STATUS_DISK_FULL);
4233 error_to_writebrawerr(req);
4237 total_written = nwritten;
4239 /* Allocate a buffer of 64k + length. */
4240 buf = talloc_array(NULL, char, 65540);
4242 reply_nterror(req, NT_STATUS_NO_MEMORY);
4243 error_to_writebrawerr(req);
4247 /* Return a SMBwritebraw message to the redirector to tell
4248 * it to send more bytes */
4250 memcpy(buf, req->inbuf, smb_size);
4251 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4252 SCVAL(buf,smb_com,SMBwritebraw);
4253 SSVALS(buf,smb_vwv0,0xFFFF);
4255 if (!srv_send_smb(req->sconn,
4257 false, 0, /* no signing */
4258 IS_CONN_ENCRYPTED(conn),
4260 exit_server_cleanly("reply_writebraw: srv_send_smb "
4264 /* Now read the raw data into the buffer and write it */
4265 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4267 if (!NT_STATUS_IS_OK(status)) {
4268 exit_server_cleanly("secondary writebraw failed");
4271 /* Set up outbuf to return the correct size */
4272 reply_outbuf(req, 1, 0);
4274 if (numtowrite != 0) {
4276 if (numtowrite > 0xFFFF) {
4277 DEBUG(0,("reply_writebraw: Oversize secondary write "
4278 "raw requested (%u). Terminating\n",
4279 (unsigned int)numtowrite ));
4280 exit_server_cleanly("secondary writebraw failed");
4283 if (tcount > nwritten+numtowrite) {
4284 DEBUG(3,("reply_writebraw: Client overestimated the "
4286 (int)tcount,(int)nwritten,(int)numtowrite));
4289 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4291 if (!NT_STATUS_IS_OK(status)) {
4292 /* Try and give an error message
4293 * saying what client failed. */
4294 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4295 "raw read failed (%s) for client %s. "
4296 "Terminating\n", nt_errstr(status),
4297 smbXsrv_connection_dbg(xconn)));
4298 exit_server_cleanly("secondary writebraw failed");
4301 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4302 if (nwritten == -1) {
4304 reply_nterror(req, map_nt_error_from_unix(errno));
4305 error_to_writebrawerr(req);
4309 if (nwritten < (ssize_t)numtowrite) {
4310 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4311 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4315 total_written += nwritten;
4320 SSVAL(req->outbuf,smb_vwv0,total_written);
4322 status = sync_file(conn, fsp, write_through);
4323 if (!NT_STATUS_IS_OK(status)) {
4324 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4325 fsp_str_dbg(fsp), nt_errstr(status)));
4326 reply_nterror(req, status);
4327 error_to_writebrawerr(req);
4331 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4333 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4334 (int)total_written));
4336 if (!fsp->print_file) {
4337 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4340 /* We won't return a status if write through is not selected - this
4341 * follows what WfWg does */
4342 END_PROFILE(SMBwritebraw);
4344 if (!write_through && total_written==tcount) {
4346 #if RABBIT_PELLET_FIX
4348 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4349 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4352 if (!send_keepalive(xconn->transport.sock)) {
4353 exit_server_cleanly("reply_writebraw: send of "
4354 "keepalive failed");
4357 TALLOC_FREE(req->outbuf);
4362 if (!fsp->print_file) {
4363 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4366 END_PROFILE(SMBwritebraw);
4371 #define DBGC_CLASS DBGC_LOCKING
4373 /****************************************************************************
4374 Reply to a writeunlock (core+).
4375 ****************************************************************************/
4377 void reply_writeunlock(struct smb_request *req)
4379 connection_struct *conn = req->conn;
4380 ssize_t nwritten = -1;
4384 NTSTATUS status = NT_STATUS_OK;
4386 struct lock_struct lock;
4387 int saved_errno = 0;
4389 START_PROFILE(SMBwriteunlock);
4392 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4393 END_PROFILE(SMBwriteunlock);
4397 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4399 if (!check_fsp(conn, req, fsp)) {
4400 END_PROFILE(SMBwriteunlock);
4404 if (!CHECK_WRITE(fsp)) {
4405 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4406 END_PROFILE(SMBwriteunlock);
4410 numtowrite = SVAL(req->vwv+1, 0);
4411 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4412 data = (const char *)req->buf + 3;
4414 if (!fsp->print_file && numtowrite > 0) {
4415 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4416 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4419 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4420 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4421 END_PROFILE(SMBwriteunlock);
4426 /* The special X/Open SMB protocol handling of
4427 zero length writes is *NOT* done for
4429 if(numtowrite == 0) {
4432 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4433 saved_errno = errno;
4436 status = sync_file(conn, fsp, False /* write through */);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4439 fsp_str_dbg(fsp), nt_errstr(status)));
4440 reply_nterror(req, status);
4445 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4449 if((nwritten < numtowrite) && (numtowrite != 0)) {
4450 reply_nterror(req, NT_STATUS_DISK_FULL);
4454 if (numtowrite && !fsp->print_file) {
4455 status = do_unlock(req->sconn->msg_ctx,
4457 (uint64_t)req->smbpid,
4458 (uint64_t)numtowrite,
4462 if (NT_STATUS_V(status)) {
4463 reply_nterror(req, status);
4468 reply_outbuf(req, 1, 0);
4470 SSVAL(req->outbuf,smb_vwv0,nwritten);
4472 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4473 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4476 if (numtowrite && !fsp->print_file) {
4477 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4480 END_PROFILE(SMBwriteunlock);
4485 #define DBGC_CLASS DBGC_ALL
4487 /****************************************************************************
4489 ****************************************************************************/
4491 void reply_write(struct smb_request *req)
4493 connection_struct *conn = req->conn;
4495 ssize_t nwritten = -1;
4499 struct lock_struct lock;
4501 int saved_errno = 0;
4503 START_PROFILE(SMBwrite);
4506 END_PROFILE(SMBwrite);
4507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4511 /* If it's an IPC, pass off the pipe handler. */
4513 reply_pipe_write(req);
4514 END_PROFILE(SMBwrite);
4518 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4520 if (!check_fsp(conn, req, fsp)) {
4521 END_PROFILE(SMBwrite);
4525 if (!CHECK_WRITE(fsp)) {
4526 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4527 END_PROFILE(SMBwrite);
4531 numtowrite = SVAL(req->vwv+1, 0);
4532 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4533 data = (const char *)req->buf + 3;
4535 if (!fsp->print_file) {
4536 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4537 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4540 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4541 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4542 END_PROFILE(SMBwrite);
4548 * X/Open SMB protocol says that if smb_vwv1 is
4549 * zero then the file size should be extended or
4550 * truncated to the size given in smb_vwv[2-3].
4553 if(numtowrite == 0) {
4555 * This is actually an allocate call, and set EOF. JRA.
4557 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4559 reply_nterror(req, NT_STATUS_DISK_FULL);
4562 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4564 reply_nterror(req, NT_STATUS_DISK_FULL);
4567 trigger_write_time_update_immediate(fsp);
4569 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4572 status = sync_file(conn, fsp, False);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4575 fsp_str_dbg(fsp), nt_errstr(status)));
4576 reply_nterror(req, status);
4581 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4585 if((nwritten == 0) && (numtowrite != 0)) {
4586 reply_nterror(req, NT_STATUS_DISK_FULL);
4590 reply_outbuf(req, 1, 0);
4592 SSVAL(req->outbuf,smb_vwv0,nwritten);
4594 if (nwritten < (ssize_t)numtowrite) {
4595 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4596 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4599 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4602 if (!fsp->print_file) {
4603 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4606 END_PROFILE(SMBwrite);
4610 /****************************************************************************
4611 Ensure a buffer is a valid writeX for recvfile purposes.
4612 ****************************************************************************/
4614 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4615 (2*14) + /* word count (including bcc) */ \
4618 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4619 const uint8_t *inbuf)
4622 unsigned int doff = 0;
4623 size_t len = smb_len_large(inbuf);
4625 struct smbXsrv_open *op = NULL;
4626 struct files_struct *fsp = NULL;
4629 if (is_encrypted_packet(inbuf)) {
4630 /* Can't do this on encrypted
4635 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4639 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4640 CVAL(inbuf,smb_wct) != 14) {
4641 DEBUG(10,("is_valid_writeX_buffer: chained or "
4642 "invalid word length.\n"));
4646 fnum = SVAL(inbuf, smb_vwv2);
4647 status = smb1srv_open_lookup(xconn,
4651 if (!NT_STATUS_IS_OK(status)) {
4652 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4657 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4660 if (fsp->conn == NULL) {
4661 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4665 if (IS_IPC(fsp->conn)) {
4666 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4669 if (IS_PRINT(fsp->conn)) {
4670 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4673 doff = SVAL(inbuf,smb_vwv11);
4675 numtowrite = SVAL(inbuf,smb_vwv10);
4677 if (len > doff && len - doff > 0xFFFF) {
4678 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4681 if (numtowrite == 0) {
4682 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4686 /* Ensure the sizes match up. */
4687 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4688 /* no pad byte...old smbclient :-( */
4689 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4691 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4695 if (len - doff != numtowrite) {
4696 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4697 "len = %u, doff = %u, numtowrite = %u\n",
4700 (unsigned int)numtowrite ));
4704 DEBUG(10,("is_valid_writeX_buffer: true "
4705 "len = %u, doff = %u, numtowrite = %u\n",
4708 (unsigned int)numtowrite ));
4713 /****************************************************************************
4714 Reply to a write and X.
4715 ****************************************************************************/
4717 void reply_write_and_X(struct smb_request *req)
4719 connection_struct *conn = req->conn;
4720 struct smbXsrv_connection *xconn = req->sconn->conn;
4722 struct lock_struct lock;
4727 unsigned int smb_doff;
4728 unsigned int smblen;
4731 int saved_errno = 0;
4733 START_PROFILE(SMBwriteX);
4735 if ((req->wct != 12) && (req->wct != 14)) {
4736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740 numtowrite = SVAL(req->vwv+10, 0);
4741 smb_doff = SVAL(req->vwv+11, 0);
4742 smblen = smb_len(req->inbuf);
4744 if (req->unread_bytes > 0xFFFF ||
4745 (smblen > smb_doff &&
4746 smblen - smb_doff > 0xFFFF)) {
4747 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4750 if (req->unread_bytes) {
4751 /* Can't do a recvfile write on IPC$ */
4753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4756 if (numtowrite != req->unread_bytes) {
4757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4761 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4762 smb_doff + numtowrite > smblen) {
4763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768 /* If it's an IPC, pass off the pipe handler. */
4770 if (req->unread_bytes) {
4771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4774 reply_pipe_write_and_X(req);
4778 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4779 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4780 write_through = BITSETW(req->vwv+7,0);
4782 if (!check_fsp(conn, req, fsp)) {
4786 if (!CHECK_WRITE(fsp)) {
4787 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4791 data = smb_base(req->inbuf) + smb_doff;
4793 if(req->wct == 14) {
4795 * This is a large offset (64 bit) write.
4797 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4801 /* X/Open SMB protocol says that, unlike SMBwrite
4802 if the length is zero then NO truncation is
4803 done, just a write of zero. To truncate a file,
4806 if(numtowrite == 0) {
4809 if (req->unread_bytes == 0) {
4810 status = schedule_aio_write_and_X(conn,
4817 if (NT_STATUS_IS_OK(status)) {
4818 /* write scheduled - we're done. */
4821 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4822 /* Real error - report to client. */
4823 reply_nterror(req, status);
4826 /* NT_STATUS_RETRY - fall through to sync write. */
4829 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4830 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4833 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4834 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4838 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4839 saved_errno = errno;
4841 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4845 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4849 if((nwritten == 0) && (numtowrite != 0)) {
4850 reply_nterror(req, NT_STATUS_DISK_FULL);
4854 reply_outbuf(req, 6, 0);
4855 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4856 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4857 SSVAL(req->outbuf,smb_vwv2,nwritten);
4858 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4860 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4861 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4863 status = sync_file(conn, fsp, write_through);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4866 fsp_str_dbg(fsp), nt_errstr(status)));
4867 reply_nterror(req, status);
4871 END_PROFILE(SMBwriteX);
4875 if (req->unread_bytes) {
4876 /* writeX failed. drain socket. */
4877 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4878 req->unread_bytes) {
4879 smb_panic("failed to drain pending bytes");
4881 req->unread_bytes = 0;
4884 END_PROFILE(SMBwriteX);
4888 /****************************************************************************
4890 ****************************************************************************/
4892 void reply_lseek(struct smb_request *req)
4894 connection_struct *conn = req->conn;
4900 START_PROFILE(SMBlseek);
4903 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4904 END_PROFILE(SMBlseek);
4908 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4910 if (!check_fsp(conn, req, fsp)) {
4914 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4916 mode = SVAL(req->vwv+1, 0) & 3;
4917 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4918 startpos = (off_t)IVALS(req->vwv+2, 0);
4927 res = fsp->fh->pos + startpos;
4938 if (umode == SEEK_END) {
4939 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4940 if(errno == EINVAL) {
4941 off_t current_pos = startpos;
4943 if(fsp_stat(fsp) == -1) {
4945 map_nt_error_from_unix(errno));
4946 END_PROFILE(SMBlseek);
4950 current_pos += fsp->fsp_name->st.st_ex_size;
4952 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4957 reply_nterror(req, map_nt_error_from_unix(errno));
4958 END_PROFILE(SMBlseek);
4965 reply_outbuf(req, 2, 0);
4966 SIVAL(req->outbuf,smb_vwv0,res);
4968 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4969 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4971 END_PROFILE(SMBlseek);
4975 /****************************************************************************
4977 ****************************************************************************/
4979 void reply_flush(struct smb_request *req)
4981 connection_struct *conn = req->conn;
4985 START_PROFILE(SMBflush);
4988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4992 fnum = SVAL(req->vwv+0, 0);
4993 fsp = file_fsp(req, fnum);
4995 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5000 file_sync_all(conn);
5002 NTSTATUS status = sync_file(conn, fsp, True);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5005 fsp_str_dbg(fsp), nt_errstr(status)));
5006 reply_nterror(req, status);
5007 END_PROFILE(SMBflush);
5012 reply_outbuf(req, 0, 0);
5014 DEBUG(3,("flush\n"));
5015 END_PROFILE(SMBflush);
5019 /****************************************************************************
5021 conn POINTER CAN BE NULL HERE !
5022 ****************************************************************************/
5024 void reply_exit(struct smb_request *req)
5026 START_PROFILE(SMBexit);
5028 file_close_pid(req->sconn, req->smbpid, req->vuid);
5030 reply_outbuf(req, 0, 0);
5032 DEBUG(3,("exit\n"));
5034 END_PROFILE(SMBexit);
5038 struct reply_close_state {
5040 struct smb_request *smbreq;
5043 static void do_smb1_close(struct tevent_req *req);
5045 void reply_close(struct smb_request *req)
5047 connection_struct *conn = req->conn;
5048 NTSTATUS status = NT_STATUS_OK;
5049 files_struct *fsp = NULL;
5050 START_PROFILE(SMBclose);
5053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5054 END_PROFILE(SMBclose);
5058 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5061 * We can only use check_fsp if we know it's not a directory.
5064 if (!check_fsp_open(conn, req, fsp)) {
5065 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5066 END_PROFILE(SMBclose);
5070 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5071 fsp->is_directory ? "directory" : "file",
5072 fsp->fh->fd, fsp_fnum_dbg(fsp),
5073 conn->num_files_open));
5075 if (!fsp->is_directory) {
5079 * Take care of any time sent in the close.
5082 t = srv_make_unix_date3(req->vwv+1);
5083 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5086 if (fsp->num_aio_requests != 0) {
5088 struct reply_close_state *state;
5090 DEBUG(10, ("closing with aio %u requests pending\n",
5091 fsp->num_aio_requests));
5094 * We depend on the aio_extra destructor to take care of this
5095 * close request once fsp->num_aio_request drops to 0.
5098 fsp->deferred_close = tevent_wait_send(
5099 fsp, fsp->conn->sconn->ev_ctx);
5100 if (fsp->deferred_close == NULL) {
5101 status = NT_STATUS_NO_MEMORY;
5105 state = talloc(fsp, struct reply_close_state);
5106 if (state == NULL) {
5107 TALLOC_FREE(fsp->deferred_close);
5108 status = NT_STATUS_NO_MEMORY;
5112 state->smbreq = talloc_move(fsp, &req);
5113 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5115 END_PROFILE(SMBclose);
5120 * close_file() returns the unix errno if an error was detected on
5121 * close - normally this is due to a disk full error. If not then it
5122 * was probably an I/O error.
5125 status = close_file(req, fsp, NORMAL_CLOSE);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 reply_nterror(req, status);
5129 END_PROFILE(SMBclose);
5133 reply_outbuf(req, 0, 0);
5134 END_PROFILE(SMBclose);
5138 static void do_smb1_close(struct tevent_req *req)
5140 struct reply_close_state *state = tevent_req_callback_data(
5141 req, struct reply_close_state);
5142 struct smb_request *smbreq;
5146 ret = tevent_wait_recv(req);
5149 DEBUG(10, ("tevent_wait_recv returned %s\n",
5152 * Continue anyway, this should never happen
5157 * fsp->smb2_close_request right now is a talloc grandchild of
5158 * fsp. When we close_file(fsp), it would go with it. No chance to
5161 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5163 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5164 if (NT_STATUS_IS_OK(status)) {
5165 reply_outbuf(smbreq, 0, 0);
5167 reply_nterror(smbreq, status);
5169 if (!srv_send_smb(smbreq->sconn,
5170 (char *)smbreq->outbuf,
5173 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5175 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5178 TALLOC_FREE(smbreq);
5181 /****************************************************************************
5182 Reply to a writeclose (Core+ protocol).
5183 ****************************************************************************/
5185 void reply_writeclose(struct smb_request *req)
5187 connection_struct *conn = req->conn;
5189 ssize_t nwritten = -1;
5190 NTSTATUS close_status = NT_STATUS_OK;
5193 struct timespec mtime;
5195 struct lock_struct lock;
5197 START_PROFILE(SMBwriteclose);
5200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5201 END_PROFILE(SMBwriteclose);
5205 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5207 if (!check_fsp(conn, req, fsp)) {
5208 END_PROFILE(SMBwriteclose);
5211 if (!CHECK_WRITE(fsp)) {
5212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5213 END_PROFILE(SMBwriteclose);
5217 numtowrite = SVAL(req->vwv+1, 0);
5218 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5219 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5220 data = (const char *)req->buf + 1;
5222 if (fsp->print_file == NULL) {
5223 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5224 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5227 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5228 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5229 END_PROFILE(SMBwriteclose);
5234 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5236 if (fsp->print_file == NULL) {
5237 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5240 set_close_write_time(fsp, mtime);
5243 * More insanity. W2K only closes the file if writelen > 0.
5247 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5248 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5249 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5252 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5253 "file %s\n", fsp_str_dbg(fsp)));
5254 close_status = close_file(req, fsp, NORMAL_CLOSE);
5258 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5259 reply_nterror(req, NT_STATUS_DISK_FULL);
5263 if(!NT_STATUS_IS_OK(close_status)) {
5264 reply_nterror(req, close_status);
5268 reply_outbuf(req, 1, 0);
5270 SSVAL(req->outbuf,smb_vwv0,nwritten);
5274 END_PROFILE(SMBwriteclose);
5279 #define DBGC_CLASS DBGC_LOCKING
5281 /****************************************************************************
5283 ****************************************************************************/
5285 void reply_lock(struct smb_request *req)
5287 connection_struct *conn = req->conn;
5288 uint64_t count,offset;
5291 struct byte_range_lock *br_lck = NULL;
5293 START_PROFILE(SMBlock);
5296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5297 END_PROFILE(SMBlock);
5301 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5303 if (!check_fsp(conn, req, fsp)) {
5304 END_PROFILE(SMBlock);
5308 count = (uint64_t)IVAL(req->vwv+1, 0);
5309 offset = (uint64_t)IVAL(req->vwv+3, 0);
5311 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5312 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5314 br_lck = do_lock(req->sconn->msg_ctx,
5316 (uint64_t)req->smbpid,
5321 False, /* Non-blocking lock. */
5325 TALLOC_FREE(br_lck);
5327 if (NT_STATUS_V(status)) {
5328 reply_nterror(req, status);
5329 END_PROFILE(SMBlock);
5333 reply_outbuf(req, 0, 0);
5335 END_PROFILE(SMBlock);
5339 /****************************************************************************
5341 ****************************************************************************/
5343 void reply_unlock(struct smb_request *req)
5345 connection_struct *conn = req->conn;
5346 uint64_t count,offset;
5350 START_PROFILE(SMBunlock);
5353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5354 END_PROFILE(SMBunlock);
5358 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5360 if (!check_fsp(conn, req, fsp)) {
5361 END_PROFILE(SMBunlock);
5365 count = (uint64_t)IVAL(req->vwv+1, 0);
5366 offset = (uint64_t)IVAL(req->vwv+3, 0);
5368 status = do_unlock(req->sconn->msg_ctx,
5370 (uint64_t)req->smbpid,
5375 if (NT_STATUS_V(status)) {
5376 reply_nterror(req, status);
5377 END_PROFILE(SMBunlock);
5381 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5382 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5384 reply_outbuf(req, 0, 0);
5386 END_PROFILE(SMBunlock);
5391 #define DBGC_CLASS DBGC_ALL
5393 /****************************************************************************
5395 conn POINTER CAN BE NULL HERE !
5396 ****************************************************************************/
5398 void reply_tdis(struct smb_request *req)
5401 connection_struct *conn = req->conn;
5402 struct smbXsrv_tcon *tcon;
5404 START_PROFILE(SMBtdis);
5407 DEBUG(4,("Invalid connection in tdis\n"));
5408 reply_force_doserror(req, ERRSRV, ERRinvnid);
5409 END_PROFILE(SMBtdis);
5417 * TODO: cancel all outstanding requests on the tcon
5419 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 DEBUG(0, ("reply_tdis: "
5422 "smbXsrv_tcon_disconnect() failed: %s\n",
5423 nt_errstr(status)));
5425 * If we hit this case, there is something completely
5426 * wrong, so we better disconnect the transport connection.
5428 END_PROFILE(SMBtdis);
5429 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5435 reply_outbuf(req, 0, 0);
5436 END_PROFILE(SMBtdis);
5440 /****************************************************************************
5442 conn POINTER CAN BE NULL HERE !
5443 ****************************************************************************/
5445 void reply_echo(struct smb_request *req)
5447 connection_struct *conn = req->conn;
5448 struct smb_perfcount_data local_pcd;
5449 struct smb_perfcount_data *cur_pcd;
5453 START_PROFILE(SMBecho);
5455 smb_init_perfcount_data(&local_pcd);
5458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5459 END_PROFILE(SMBecho);
5463 smb_reverb = SVAL(req->vwv+0, 0);
5465 reply_outbuf(req, 1, req->buflen);
5467 /* copy any incoming data back out */
5468 if (req->buflen > 0) {
5469 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5472 if (smb_reverb > 100) {
5473 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5477 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5479 /* this makes sure we catch the request pcd */
5480 if (seq_num == smb_reverb) {
5481 cur_pcd = &req->pcd;
5483 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5484 cur_pcd = &local_pcd;
5487 SSVAL(req->outbuf,smb_vwv0,seq_num);
5489 show_msg((char *)req->outbuf);
5490 if (!srv_send_smb(req->sconn,
5491 (char *)req->outbuf,
5492 true, req->seqnum+1,
5493 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5495 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5498 DEBUG(3,("echo %d times\n", smb_reverb));
5500 TALLOC_FREE(req->outbuf);
5502 END_PROFILE(SMBecho);
5506 /****************************************************************************
5507 Reply to a printopen.
5508 ****************************************************************************/
5510 void reply_printopen(struct smb_request *req)
5512 connection_struct *conn = req->conn;
5516 START_PROFILE(SMBsplopen);
5519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5520 END_PROFILE(SMBsplopen);
5524 if (!CAN_PRINT(conn)) {
5525 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5526 END_PROFILE(SMBsplopen);
5530 status = file_new(req, conn, &fsp);
5531 if(!NT_STATUS_IS_OK(status)) {
5532 reply_nterror(req, status);
5533 END_PROFILE(SMBsplopen);
5537 /* Open for exclusive use, write only. */
5538 status = print_spool_open(fsp, NULL, req->vuid);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 file_free(req, fsp);
5542 reply_nterror(req, status);
5543 END_PROFILE(SMBsplopen);
5547 reply_outbuf(req, 1, 0);
5548 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5550 DEBUG(3,("openprint fd=%d %s\n",
5551 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5553 END_PROFILE(SMBsplopen);
5557 /****************************************************************************
5558 Reply to a printclose.
5559 ****************************************************************************/
5561 void reply_printclose(struct smb_request *req)
5563 connection_struct *conn = req->conn;
5567 START_PROFILE(SMBsplclose);
5570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5571 END_PROFILE(SMBsplclose);
5575 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5577 if (!check_fsp(conn, req, fsp)) {
5578 END_PROFILE(SMBsplclose);
5582 if (!CAN_PRINT(conn)) {
5583 reply_force_doserror(req, ERRSRV, ERRerror);
5584 END_PROFILE(SMBsplclose);
5588 DEBUG(3,("printclose fd=%d %s\n",
5589 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5591 status = close_file(req, fsp, NORMAL_CLOSE);
5593 if(!NT_STATUS_IS_OK(status)) {
5594 reply_nterror(req, status);
5595 END_PROFILE(SMBsplclose);
5599 reply_outbuf(req, 0, 0);
5601 END_PROFILE(SMBsplclose);
5605 /****************************************************************************
5606 Reply to a printqueue.
5607 ****************************************************************************/
5609 void reply_printqueue(struct smb_request *req)
5611 connection_struct *conn = req->conn;
5615 START_PROFILE(SMBsplretq);
5618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5619 END_PROFILE(SMBsplretq);
5623 max_count = SVAL(req->vwv+0, 0);
5624 start_index = SVAL(req->vwv+1, 0);
5626 /* we used to allow the client to get the cnum wrong, but that
5627 is really quite gross and only worked when there was only
5628 one printer - I think we should now only accept it if they
5629 get it right (tridge) */
5630 if (!CAN_PRINT(conn)) {
5631 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5632 END_PROFILE(SMBsplretq);
5636 reply_outbuf(req, 2, 3);
5637 SSVAL(req->outbuf,smb_vwv0,0);
5638 SSVAL(req->outbuf,smb_vwv1,0);
5639 SCVAL(smb_buf(req->outbuf),0,1);
5640 SSVAL(smb_buf(req->outbuf),1,0);
5642 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5643 start_index, max_count));
5646 TALLOC_CTX *mem_ctx = talloc_tos();
5649 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5650 struct rpc_pipe_client *cli = NULL;
5651 struct dcerpc_binding_handle *b = NULL;
5652 struct policy_handle handle;
5653 struct spoolss_DevmodeContainer devmode_ctr;
5654 union spoolss_JobInfo *info;
5656 uint32_t num_to_get;
5660 ZERO_STRUCT(handle);
5662 status = rpc_pipe_open_interface(conn,
5665 conn->sconn->remote_address,
5666 conn->sconn->msg_ctx,
5668 if (!NT_STATUS_IS_OK(status)) {
5669 DEBUG(0, ("reply_printqueue: "
5670 "could not connect to spoolss: %s\n",
5671 nt_errstr(status)));
5672 reply_nterror(req, status);
5675 b = cli->binding_handle;
5677 ZERO_STRUCT(devmode_ctr);
5679 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5682 SEC_FLAG_MAXIMUM_ALLOWED,
5685 if (!NT_STATUS_IS_OK(status)) {
5686 reply_nterror(req, status);
5689 if (!W_ERROR_IS_OK(werr)) {
5690 reply_nterror(req, werror_to_ntstatus(werr));
5694 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5702 if (!W_ERROR_IS_OK(werr)) {
5703 reply_nterror(req, werror_to_ntstatus(werr));
5707 if (max_count > 0) {
5708 first = start_index;
5710 first = start_index + max_count + 1;
5713 if (first >= count) {
5716 num_to_get = first + MIN(ABS(max_count), count - first);
5719 for (i = first; i < num_to_get; i++) {
5722 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5724 uint16_t qrapjobid = pjobid_to_rap(sharename,
5725 info[i].info2.job_id);
5727 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5733 srv_put_dos_date2(p, 0, qtime);
5734 SCVAL(p, 4, qstatus);
5735 SSVAL(p, 5, qrapjobid);
5736 SIVAL(p, 7, info[i].info2.size);
5738 srvstr_push(blob, req->flags2, p+12,
5739 info[i].info2.notify_name, 16, STR_ASCII);
5741 if (message_push_blob(
5744 blob, sizeof(blob))) == -1) {
5745 reply_nterror(req, NT_STATUS_NO_MEMORY);
5751 SSVAL(req->outbuf,smb_vwv0,count);
5752 SSVAL(req->outbuf,smb_vwv1,
5753 (max_count>0?first+count:first-1));
5754 SCVAL(smb_buf(req->outbuf),0,1);
5755 SSVAL(smb_buf(req->outbuf),1,28*count);
5759 DEBUG(3, ("%u entries returned in queue\n",
5763 if (b && is_valid_policy_hnd(&handle)) {
5764 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5769 END_PROFILE(SMBsplretq);
5773 /****************************************************************************
5774 Reply to a printwrite.
5775 ****************************************************************************/
5777 void reply_printwrite(struct smb_request *req)
5779 connection_struct *conn = req->conn;
5784 START_PROFILE(SMBsplwr);
5787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5788 END_PROFILE(SMBsplwr);
5792 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5794 if (!check_fsp(conn, req, fsp)) {
5795 END_PROFILE(SMBsplwr);
5799 if (!fsp->print_file) {
5800 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5801 END_PROFILE(SMBsplwr);
5805 if (!CHECK_WRITE(fsp)) {
5806 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5807 END_PROFILE(SMBsplwr);
5811 numtowrite = SVAL(req->buf, 1);
5813 if (req->buflen < numtowrite + 3) {
5814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5815 END_PROFILE(SMBsplwr);
5819 data = (const char *)req->buf + 3;
5821 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5822 reply_nterror(req, map_nt_error_from_unix(errno));
5823 END_PROFILE(SMBsplwr);
5827 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5829 END_PROFILE(SMBsplwr);
5833 /****************************************************************************
5835 ****************************************************************************/
5837 void reply_mkdir(struct smb_request *req)
5839 connection_struct *conn = req->conn;
5840 struct smb_filename *smb_dname = NULL;
5841 char *directory = NULL;
5843 TALLOC_CTX *ctx = talloc_tos();
5845 START_PROFILE(SMBmkdir);
5847 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5848 STR_TERMINATE, &status);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 reply_nterror(req, status);
5854 status = filename_convert(ctx, conn,
5855 req->flags2 & FLAGS2_DFS_PATHNAMES,
5857 UCF_PREP_CREATEFILE,
5860 if (!NT_STATUS_IS_OK(status)) {
5861 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5862 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5863 ERRSRV, ERRbadpath);
5866 reply_nterror(req, status);
5870 status = create_directory(conn, req, smb_dname);
5872 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5874 if (!NT_STATUS_IS_OK(status)) {
5876 if (!use_nt_status()
5877 && NT_STATUS_EQUAL(status,
5878 NT_STATUS_OBJECT_NAME_COLLISION)) {
5880 * Yes, in the DOS error code case we get a
5881 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5882 * samba4 torture test.
5884 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5887 reply_nterror(req, status);
5891 reply_outbuf(req, 0, 0);
5893 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5895 TALLOC_FREE(smb_dname);
5896 END_PROFILE(SMBmkdir);
5900 /****************************************************************************
5902 ****************************************************************************/
5904 void reply_rmdir(struct smb_request *req)
5906 connection_struct *conn = req->conn;
5907 struct smb_filename *smb_dname = NULL;
5908 char *directory = NULL;
5910 TALLOC_CTX *ctx = talloc_tos();
5911 files_struct *fsp = NULL;
5913 struct smbd_server_connection *sconn = req->sconn;
5915 START_PROFILE(SMBrmdir);
5917 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5918 STR_TERMINATE, &status);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 reply_nterror(req, status);
5924 status = filename_convert(ctx, conn,
5925 req->flags2 & FLAGS2_DFS_PATHNAMES,
5930 if (!NT_STATUS_IS_OK(status)) {
5931 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5932 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5933 ERRSRV, ERRbadpath);
5936 reply_nterror(req, status);
5940 if (is_ntfs_stream_smb_fname(smb_dname)) {
5941 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5945 status = SMB_VFS_CREATE_FILE(
5948 0, /* root_dir_fid */
5949 smb_dname, /* fname */
5950 DELETE_ACCESS, /* access_mask */
5951 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5953 FILE_OPEN, /* create_disposition*/
5954 FILE_DIRECTORY_FILE, /* create_options */
5955 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5956 0, /* oplock_request */
5957 0, /* allocation_size */
5958 0, /* private_flags */
5964 if (!NT_STATUS_IS_OK(status)) {
5965 if (open_was_deferred(req->sconn, req->mid)) {
5966 /* We have re-scheduled this call. */
5969 reply_nterror(req, status);
5973 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 close_file(req, fsp, ERROR_CLOSE);
5976 reply_nterror(req, status);
5980 if (!set_delete_on_close(fsp, true,
5981 conn->session_info->security_token,
5982 conn->session_info->unix_token)) {
5983 close_file(req, fsp, ERROR_CLOSE);
5984 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5988 status = close_file(req, fsp, NORMAL_CLOSE);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 reply_nterror(req, status);
5992 reply_outbuf(req, 0, 0);
5995 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5997 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5999 TALLOC_FREE(smb_dname);
6000 END_PROFILE(SMBrmdir);
6004 /*******************************************************************
6005 Resolve wildcards in a filename rename.
6006 ********************************************************************/
6008 static bool resolve_wildcards(TALLOC_CTX *ctx,
6013 char *name2_copy = NULL;
6018 char *p,*p2, *pname1, *pname2;
6020 name2_copy = talloc_strdup(ctx, name2);
6025 pname1 = strrchr_m(name1,'/');
6026 pname2 = strrchr_m(name2_copy,'/');
6028 if (!pname1 || !pname2) {
6032 /* Truncate the copy of name2 at the last '/' */
6035 /* Now go past the '/' */
6039 root1 = talloc_strdup(ctx, pname1);
6040 root2 = talloc_strdup(ctx, pname2);
6042 if (!root1 || !root2) {
6046 p = strrchr_m(root1,'.');
6049 ext1 = talloc_strdup(ctx, p+1);
6051 ext1 = talloc_strdup(ctx, "");
6053 p = strrchr_m(root2,'.');
6056 ext2 = talloc_strdup(ctx, p+1);
6058 ext2 = talloc_strdup(ctx, "");
6061 if (!ext1 || !ext2) {
6069 /* Hmmm. Should this be mb-aware ? */
6072 } else if (*p2 == '*') {
6074 root2 = talloc_asprintf(ctx, "%s%s",
6093 /* Hmmm. Should this be mb-aware ? */
6096 } else if (*p2 == '*') {
6098 ext2 = talloc_asprintf(ctx, "%s%s",
6114 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6119 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6131 /****************************************************************************
6132 Ensure open files have their names updated. Updated to notify other smbd's
6134 ****************************************************************************/
6136 static void rename_open_files(connection_struct *conn,
6137 struct share_mode_lock *lck,
6139 uint32_t orig_name_hash,
6140 const struct smb_filename *smb_fname_dst)
6143 bool did_rename = False;
6145 uint32_t new_name_hash = 0;
6147 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6148 fsp = file_find_di_next(fsp)) {
6149 /* fsp_name is a relative path under the fsp. To change this for other
6150 sharepaths we need to manipulate relative paths. */
6151 /* TODO - create the absolute path and manipulate the newname
6152 relative to the sharepath. */
6153 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6156 if (fsp->name_hash != orig_name_hash) {
6159 DEBUG(10, ("rename_open_files: renaming file %s "
6160 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6161 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6162 smb_fname_str_dbg(smb_fname_dst)));
6164 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6165 if (NT_STATUS_IS_OK(status)) {
6167 new_name_hash = fsp->name_hash;
6172 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6173 "for %s\n", file_id_string_tos(&id),
6174 smb_fname_str_dbg(smb_fname_dst)));
6177 /* Send messages to all smbd's (not ourself) that the name has changed. */
6178 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6179 orig_name_hash, new_name_hash,
6184 /****************************************************************************
6185 We need to check if the source path is a parent directory of the destination
6186 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6187 refuse the rename with a sharing violation. Under UNIX the above call can
6188 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6189 probably need to check that the client is a Windows one before disallowing
6190 this as a UNIX client (one with UNIX extensions) can know the source is a
6191 symlink and make this decision intelligently. Found by an excellent bug
6192 report from <AndyLiebman@aol.com>.
6193 ****************************************************************************/
6195 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6196 const struct smb_filename *smb_fname_dst)
6198 const char *psrc = smb_fname_src->base_name;
6199 const char *pdst = smb_fname_dst->base_name;
6202 if (psrc[0] == '.' && psrc[1] == '/') {
6205 if (pdst[0] == '.' && pdst[1] == '/') {
6208 if ((slen = strlen(psrc)) > strlen(pdst)) {
6211 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6215 * Do the notify calls from a rename
6218 static void notify_rename(connection_struct *conn, bool is_dir,
6219 const struct smb_filename *smb_fname_src,
6220 const struct smb_filename *smb_fname_dst)
6222 char *parent_dir_src = NULL;
6223 char *parent_dir_dst = NULL;
6226 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6227 : FILE_NOTIFY_CHANGE_FILE_NAME;
6229 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6230 &parent_dir_src, NULL) ||
6231 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6232 &parent_dir_dst, NULL)) {
6236 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6237 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6238 smb_fname_src->base_name);
6239 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6240 smb_fname_dst->base_name);
6243 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6244 smb_fname_src->base_name);
6245 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6246 smb_fname_dst->base_name);
6249 /* this is a strange one. w2k3 gives an additional event for
6250 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6251 files, but not directories */
6253 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6254 FILE_NOTIFY_CHANGE_ATTRIBUTES
6255 |FILE_NOTIFY_CHANGE_CREATION,
6256 smb_fname_dst->base_name);
6259 TALLOC_FREE(parent_dir_src);
6260 TALLOC_FREE(parent_dir_dst);
6263 /****************************************************************************
6264 Returns an error if the parent directory for a filename is open in an
6266 ****************************************************************************/
6268 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6269 const struct smb_filename *smb_fname_dst_in)
6271 char *parent_dir = NULL;
6272 struct smb_filename smb_fname_parent;
6274 files_struct *fsp = NULL;
6277 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6278 &parent_dir, NULL)) {
6279 return NT_STATUS_NO_MEMORY;
6281 ZERO_STRUCT(smb_fname_parent);
6282 smb_fname_parent.base_name = parent_dir;
6284 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6286 return map_nt_error_from_unix(errno);
6290 * We're only checking on this smbd here, mostly good
6291 * enough.. and will pass tests.
6294 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6295 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6296 fsp = file_find_di_next(fsp)) {
6297 if (fsp->access_mask & DELETE_ACCESS) {
6298 return NT_STATUS_SHARING_VIOLATION;
6301 return NT_STATUS_OK;
6304 /****************************************************************************
6305 Rename an open file - given an fsp.
6306 ****************************************************************************/
6308 NTSTATUS rename_internals_fsp(connection_struct *conn,
6310 const struct smb_filename *smb_fname_dst_in,
6312 bool replace_if_exists)
6314 TALLOC_CTX *ctx = talloc_tos();
6315 struct smb_filename *smb_fname_dst = NULL;
6316 NTSTATUS status = NT_STATUS_OK;
6317 struct share_mode_lock *lck = NULL;
6318 bool dst_exists, old_is_stream, new_is_stream;
6320 status = check_name(conn, smb_fname_dst_in->base_name);
6321 if (!NT_STATUS_IS_OK(status)) {
6325 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6326 if (!NT_STATUS_IS_OK(status)) {
6330 /* Make a copy of the dst smb_fname structs */
6332 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6333 if (smb_fname_dst == NULL) {
6334 status = NT_STATUS_NO_MEMORY;
6339 * Check for special case with case preserving and not
6340 * case sensitive. If the old last component differs from the original
6341 * last component only by case, then we should allow
6342 * the rename (user is trying to change the case of the
6345 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6346 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6347 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6349 char *fname_dst_lcomp_base_mod = NULL;
6350 struct smb_filename *smb_fname_orig_lcomp = NULL;
6353 * Get the last component of the destination name.
6355 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6357 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6359 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6361 if (!fname_dst_lcomp_base_mod) {
6362 status = NT_STATUS_NO_MEMORY;
6367 * Create an smb_filename struct using the original last
6368 * component of the destination.
6370 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6371 ctx, smb_fname_dst->original_lcomp, NULL);
6372 if (smb_fname_orig_lcomp == NULL) {
6373 status = NT_STATUS_NO_MEMORY;
6374 TALLOC_FREE(fname_dst_lcomp_base_mod);
6378 /* If the base names only differ by case, use original. */
6379 if(!strcsequal(fname_dst_lcomp_base_mod,
6380 smb_fname_orig_lcomp->base_name)) {
6383 * Replace the modified last component with the
6387 *last_slash = '\0'; /* Truncate at the '/' */
6388 tmp = talloc_asprintf(smb_fname_dst,
6390 smb_fname_dst->base_name,
6391 smb_fname_orig_lcomp->base_name);
6393 tmp = talloc_asprintf(smb_fname_dst,
6395 smb_fname_orig_lcomp->base_name);
6398 status = NT_STATUS_NO_MEMORY;
6399 TALLOC_FREE(fname_dst_lcomp_base_mod);
6400 TALLOC_FREE(smb_fname_orig_lcomp);
6403 TALLOC_FREE(smb_fname_dst->base_name);
6404 smb_fname_dst->base_name = tmp;
6407 /* If the stream_names only differ by case, use original. */
6408 if(!strcsequal(smb_fname_dst->stream_name,
6409 smb_fname_orig_lcomp->stream_name)) {
6411 /* Use the original stream. */
6412 tmp = talloc_strdup(smb_fname_dst,
6413 smb_fname_orig_lcomp->stream_name);
6415 status = NT_STATUS_NO_MEMORY;
6416 TALLOC_FREE(fname_dst_lcomp_base_mod);
6417 TALLOC_FREE(smb_fname_orig_lcomp);
6420 TALLOC_FREE(smb_fname_dst->stream_name);
6421 smb_fname_dst->stream_name = tmp;
6423 TALLOC_FREE(fname_dst_lcomp_base_mod);
6424 TALLOC_FREE(smb_fname_orig_lcomp);
6428 * If the src and dest names are identical - including case,
6429 * don't do the rename, just return success.
6432 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6433 strcsequal(fsp->fsp_name->stream_name,
6434 smb_fname_dst->stream_name)) {
6435 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6436 "- returning success\n",
6437 smb_fname_str_dbg(smb_fname_dst)));
6438 status = NT_STATUS_OK;
6442 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6443 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6445 /* Return the correct error code if both names aren't streams. */
6446 if (!old_is_stream && new_is_stream) {
6447 status = NT_STATUS_OBJECT_NAME_INVALID;
6451 if (old_is_stream && !new_is_stream) {
6452 status = NT_STATUS_INVALID_PARAMETER;
6456 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6458 if(!replace_if_exists && dst_exists) {
6459 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6460 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6461 smb_fname_str_dbg(smb_fname_dst)));
6462 status = NT_STATUS_OBJECT_NAME_COLLISION;
6467 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6468 &smb_fname_dst->st);
6469 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6471 /* The file can be open when renaming a stream */
6472 if (dst_fsp && !new_is_stream) {
6473 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6474 status = NT_STATUS_ACCESS_DENIED;
6479 /* Ensure we have a valid stat struct for the source. */
6480 status = vfs_stat_fsp(fsp);
6481 if (!NT_STATUS_IS_OK(status)) {
6485 status = can_rename(conn, fsp, attrs);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6489 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6490 smb_fname_str_dbg(smb_fname_dst)));
6491 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6492 status = NT_STATUS_ACCESS_DENIED;
6496 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6497 status = NT_STATUS_ACCESS_DENIED;
6500 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6503 * We have the file open ourselves, so not being able to get the
6504 * corresponding share mode lock is a fatal error.
6507 SMB_ASSERT(lck != NULL);
6509 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6510 uint32 create_options = fsp->fh->private_options;
6512 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6513 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6514 smb_fname_str_dbg(smb_fname_dst)));
6516 if (!fsp->is_directory &&
6517 !lp_posix_pathnames() &&
6518 (lp_map_archive(SNUM(conn)) ||
6519 lp_store_dos_attributes(SNUM(conn)))) {
6520 /* We must set the archive bit on the newly
6522 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6523 uint32_t old_dosmode = dos_mode(conn,
6525 file_set_dosmode(conn,
6527 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6533 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6536 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6540 * A rename acts as a new file create w.r.t. allowing an initial delete
6541 * on close, probably because in Windows there is a new handle to the
6542 * new file. If initial delete on close was requested but not
6543 * originally set, we need to set it here. This is probably not 100% correct,
6544 * but will work for the CIFSFS client which in non-posix mode
6545 * depends on these semantics. JRA.
6548 if (create_options & FILE_DELETE_ON_CLOSE) {
6549 status = can_set_delete_on_close(fsp, 0);
6551 if (NT_STATUS_IS_OK(status)) {
6552 /* Note that here we set the *inital* delete on close flag,
6553 * not the regular one. The magic gets handled in close. */
6554 fsp->initial_delete_on_close = True;
6558 status = NT_STATUS_OK;
6564 if (errno == ENOTDIR || errno == EISDIR) {
6565 status = NT_STATUS_OBJECT_NAME_COLLISION;
6567 status = map_nt_error_from_unix(errno);
6570 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6571 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6572 smb_fname_str_dbg(smb_fname_dst)));
6575 TALLOC_FREE(smb_fname_dst);
6580 /****************************************************************************
6581 The guts of the rename command, split out so it may be called by the NT SMB
6583 ****************************************************************************/
6585 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6586 connection_struct *conn,
6587 struct smb_request *req,
6588 struct smb_filename *smb_fname_src,
6589 struct smb_filename *smb_fname_dst,
6591 bool replace_if_exists,
6594 uint32_t access_mask)
6596 char *fname_src_dir = NULL;
6597 char *fname_src_mask = NULL;
6599 NTSTATUS status = NT_STATUS_OK;
6600 struct smb_Dir *dir_hnd = NULL;
6601 const char *dname = NULL;
6602 char *talloced = NULL;
6604 int create_options = 0;
6605 bool posix_pathnames = lp_posix_pathnames();
6609 * Split the old name into directory and last component
6610 * strings. Note that unix_convert may have stripped off a
6611 * leading ./ from both name and newname if the rename is
6612 * at the root of the share. We need to make sure either both
6613 * name and newname contain a / character or neither of them do
6614 * as this is checked in resolve_wildcards().
6617 /* Split up the directory from the filename/mask. */
6618 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6619 &fname_src_dir, &fname_src_mask);
6620 if (!NT_STATUS_IS_OK(status)) {
6621 status = NT_STATUS_NO_MEMORY;
6626 * We should only check the mangled cache
6627 * here if unix_convert failed. This means
6628 * that the path in 'mask' doesn't exist
6629 * on the file system and so we need to look
6630 * for a possible mangle. This patch from
6631 * Tine Smukavec <valentin.smukavec@hermes.si>.
6634 if (!VALID_STAT(smb_fname_src->st) &&
6635 mangle_is_mangled(fname_src_mask, conn->params)) {
6636 char *new_mask = NULL;
6637 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6640 TALLOC_FREE(fname_src_mask);
6641 fname_src_mask = new_mask;
6645 if (!src_has_wild) {
6649 * Only one file needs to be renamed. Append the mask back
6650 * onto the directory.
6652 TALLOC_FREE(smb_fname_src->base_name);
6653 if (ISDOT(fname_src_dir)) {
6654 /* Ensure we use canonical names on open. */
6655 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6659 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6664 if (!smb_fname_src->base_name) {
6665 status = NT_STATUS_NO_MEMORY;
6669 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6670 "case_preserve = %d, short case preserve = %d, "
6671 "directory = %s, newname = %s, "
6672 "last_component_dest = %s\n",
6673 conn->case_sensitive, conn->case_preserve,
6674 conn->short_case_preserve,
6675 smb_fname_str_dbg(smb_fname_src),
6676 smb_fname_str_dbg(smb_fname_dst),
6677 smb_fname_dst->original_lcomp));
6679 /* The dest name still may have wildcards. */
6680 if (dest_has_wild) {
6681 char *fname_dst_mod = NULL;
6682 if (!resolve_wildcards(smb_fname_dst,
6683 smb_fname_src->base_name,
6684 smb_fname_dst->base_name,
6686 DEBUG(6, ("rename_internals: resolve_wildcards "
6688 smb_fname_src->base_name,
6689 smb_fname_dst->base_name));
6690 status = NT_STATUS_NO_MEMORY;
6693 TALLOC_FREE(smb_fname_dst->base_name);
6694 smb_fname_dst->base_name = fname_dst_mod;
6697 ZERO_STRUCT(smb_fname_src->st);
6698 if (posix_pathnames) {
6699 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6701 rc = SMB_VFS_STAT(conn, smb_fname_src);
6704 status = map_nt_error_from_unix_common(errno);
6708 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6709 create_options |= FILE_DIRECTORY_FILE;
6712 status = SMB_VFS_CREATE_FILE(
6715 0, /* root_dir_fid */
6716 smb_fname_src, /* fname */
6717 access_mask, /* access_mask */
6718 (FILE_SHARE_READ | /* share_access */
6720 FILE_OPEN, /* create_disposition*/
6721 create_options, /* create_options */
6722 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6723 0, /* oplock_request */
6724 0, /* allocation_size */
6725 0, /* private_flags */
6731 if (!NT_STATUS_IS_OK(status)) {
6732 DEBUG(3, ("Could not open rename source %s: %s\n",
6733 smb_fname_str_dbg(smb_fname_src),
6734 nt_errstr(status)));
6738 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6739 attrs, replace_if_exists);
6741 close_file(req, fsp, NORMAL_CLOSE);
6743 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6744 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6745 smb_fname_str_dbg(smb_fname_dst)));
6751 * Wildcards - process each file that matches.
6753 if (strequal(fname_src_mask, "????????.???")) {
6754 TALLOC_FREE(fname_src_mask);
6755 fname_src_mask = talloc_strdup(ctx, "*");
6756 if (!fname_src_mask) {
6757 status = NT_STATUS_NO_MEMORY;
6762 status = check_name(conn, fname_src_dir);
6763 if (!NT_STATUS_IS_OK(status)) {
6767 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6769 if (dir_hnd == NULL) {
6770 status = map_nt_error_from_unix(errno);
6774 status = NT_STATUS_NO_SUCH_FILE;
6776 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6777 * - gentest fix. JRA
6780 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6782 files_struct *fsp = NULL;
6783 char *destname = NULL;
6784 bool sysdir_entry = False;
6786 /* Quick check for "." and ".." */
6787 if (ISDOT(dname) || ISDOTDOT(dname)) {
6788 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6789 sysdir_entry = True;
6791 TALLOC_FREE(talloced);
6796 if (!is_visible_file(conn, fname_src_dir, dname,
6797 &smb_fname_src->st, false)) {
6798 TALLOC_FREE(talloced);
6802 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6803 TALLOC_FREE(talloced);
6808 status = NT_STATUS_OBJECT_NAME_INVALID;
6812 TALLOC_FREE(smb_fname_src->base_name);
6813 if (ISDOT(fname_src_dir)) {
6814 /* Ensure we use canonical names on open. */
6815 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6819 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6824 if (!smb_fname_src->base_name) {
6825 status = NT_STATUS_NO_MEMORY;
6829 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6830 smb_fname_dst->base_name,
6832 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6833 smb_fname_src->base_name, destname));
6834 TALLOC_FREE(talloced);
6838 status = NT_STATUS_NO_MEMORY;
6842 TALLOC_FREE(smb_fname_dst->base_name);
6843 smb_fname_dst->base_name = destname;
6845 ZERO_STRUCT(smb_fname_src->st);
6846 if (posix_pathnames) {
6847 SMB_VFS_LSTAT(conn, smb_fname_src);
6849 SMB_VFS_STAT(conn, smb_fname_src);
6854 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6855 create_options |= FILE_DIRECTORY_FILE;
6858 status = SMB_VFS_CREATE_FILE(
6861 0, /* root_dir_fid */
6862 smb_fname_src, /* fname */
6863 access_mask, /* access_mask */
6864 (FILE_SHARE_READ | /* share_access */
6866 FILE_OPEN, /* create_disposition*/
6867 create_options, /* create_options */
6868 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6869 0, /* oplock_request */
6870 0, /* allocation_size */
6871 0, /* private_flags */
6877 if (!NT_STATUS_IS_OK(status)) {
6878 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6879 "returned %s rename %s -> %s\n",
6881 smb_fname_str_dbg(smb_fname_src),
6882 smb_fname_str_dbg(smb_fname_dst)));
6886 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6888 if (!smb_fname_dst->original_lcomp) {
6889 status = NT_STATUS_NO_MEMORY;
6893 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6894 attrs, replace_if_exists);
6896 close_file(req, fsp, NORMAL_CLOSE);
6898 if (!NT_STATUS_IS_OK(status)) {
6899 DEBUG(3, ("rename_internals_fsp returned %s for "
6900 "rename %s -> %s\n", nt_errstr(status),
6901 smb_fname_str_dbg(smb_fname_src),
6902 smb_fname_str_dbg(smb_fname_dst)));
6908 DEBUG(3,("rename_internals: doing rename on %s -> "
6909 "%s\n", smb_fname_str_dbg(smb_fname_src),
6910 smb_fname_str_dbg(smb_fname_src)));
6911 TALLOC_FREE(talloced);
6913 TALLOC_FREE(dir_hnd);
6915 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6916 status = map_nt_error_from_unix(errno);
6920 TALLOC_FREE(talloced);
6921 TALLOC_FREE(fname_src_dir);
6922 TALLOC_FREE(fname_src_mask);
6926 /****************************************************************************
6928 ****************************************************************************/
6930 void reply_mv(struct smb_request *req)
6932 connection_struct *conn = req->conn;
6934 char *newname = NULL;
6938 bool src_has_wcard = False;
6939 bool dest_has_wcard = False;
6940 TALLOC_CTX *ctx = talloc_tos();
6941 struct smb_filename *smb_fname_src = NULL;
6942 struct smb_filename *smb_fname_dst = NULL;
6943 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6944 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6945 bool stream_rename = false;
6947 START_PROFILE(SMBmv);
6950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6954 attrs = SVAL(req->vwv+0, 0);
6956 p = (const char *)req->buf + 1;
6957 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6958 &status, &src_has_wcard);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 reply_nterror(req, status);
6964 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6965 &status, &dest_has_wcard);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 reply_nterror(req, status);
6971 if (!lp_posix_pathnames()) {
6972 /* The newname must begin with a ':' if the
6973 name contains a ':'. */
6974 if (strchr_m(name, ':')) {
6975 if (newname[0] != ':') {
6976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6979 stream_rename = true;
6983 status = filename_convert(ctx,
6985 req->flags2 & FLAGS2_DFS_PATHNAMES,
6991 if (!NT_STATUS_IS_OK(status)) {
6992 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6993 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6994 ERRSRV, ERRbadpath);
6997 reply_nterror(req, status);
7001 status = filename_convert(ctx,
7003 req->flags2 & FLAGS2_DFS_PATHNAMES,
7009 if (!NT_STATUS_IS_OK(status)) {
7010 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7011 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7012 ERRSRV, ERRbadpath);
7015 reply_nterror(req, status);
7019 if (stream_rename) {
7020 /* smb_fname_dst->base_name must be the same as
7021 smb_fname_src->base_name. */
7022 TALLOC_FREE(smb_fname_dst->base_name);
7023 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7024 smb_fname_src->base_name);
7025 if (!smb_fname_dst->base_name) {
7026 reply_nterror(req, NT_STATUS_NO_MEMORY);
7031 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7032 smb_fname_str_dbg(smb_fname_dst)));
7034 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7035 attrs, False, src_has_wcard, dest_has_wcard,
7037 if (!NT_STATUS_IS_OK(status)) {
7038 if (open_was_deferred(req->sconn, req->mid)) {
7039 /* We have re-scheduled this call. */
7042 reply_nterror(req, status);
7046 reply_outbuf(req, 0, 0);
7048 TALLOC_FREE(smb_fname_src);
7049 TALLOC_FREE(smb_fname_dst);
7054 /*******************************************************************
7055 Copy a file as part of a reply_copy.
7056 ******************************************************************/
7059 * TODO: check error codes on all callers
7062 NTSTATUS copy_file(TALLOC_CTX *ctx,
7063 connection_struct *conn,
7064 struct smb_filename *smb_fname_src,
7065 struct smb_filename *smb_fname_dst,
7068 bool target_is_directory)
7070 struct smb_filename *smb_fname_dst_tmp = NULL;
7072 files_struct *fsp1,*fsp2;
7074 uint32 new_create_disposition;
7078 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7079 if (smb_fname_dst_tmp == NULL) {
7080 return NT_STATUS_NO_MEMORY;
7084 * If the target is a directory, extract the last component from the
7085 * src filename and append it to the dst filename
7087 if (target_is_directory) {
7090 /* dest/target can't be a stream if it's a directory. */
7091 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7093 p = strrchr_m(smb_fname_src->base_name,'/');
7097 p = smb_fname_src->base_name;
7099 smb_fname_dst_tmp->base_name =
7100 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7102 if (!smb_fname_dst_tmp->base_name) {
7103 status = NT_STATUS_NO_MEMORY;
7108 status = vfs_file_exist(conn, smb_fname_src);
7109 if (!NT_STATUS_IS_OK(status)) {
7113 if (!target_is_directory && count) {
7114 new_create_disposition = FILE_OPEN;
7116 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7119 &new_create_disposition,
7122 status = NT_STATUS_INVALID_PARAMETER;
7127 /* Open the src file for reading. */
7128 status = SMB_VFS_CREATE_FILE(
7131 0, /* root_dir_fid */
7132 smb_fname_src, /* fname */
7133 FILE_GENERIC_READ, /* access_mask */
7134 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7135 FILE_OPEN, /* create_disposition*/
7136 0, /* create_options */
7137 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7138 INTERNAL_OPEN_ONLY, /* oplock_request */
7139 0, /* allocation_size */
7140 0, /* private_flags */
7146 if (!NT_STATUS_IS_OK(status)) {
7150 dosattrs = dos_mode(conn, smb_fname_src);
7152 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7153 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7156 /* Open the dst file for writing. */
7157 status = SMB_VFS_CREATE_FILE(
7160 0, /* root_dir_fid */
7161 smb_fname_dst, /* fname */
7162 FILE_GENERIC_WRITE, /* access_mask */
7163 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7164 new_create_disposition, /* create_disposition*/
7165 0, /* create_options */
7166 dosattrs, /* file_attributes */
7167 INTERNAL_OPEN_ONLY, /* oplock_request */
7168 0, /* allocation_size */
7169 0, /* private_flags */
7175 if (!NT_STATUS_IS_OK(status)) {
7176 close_file(NULL, fsp1, ERROR_CLOSE);
7180 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7181 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7183 DEBUG(0, ("error - vfs lseek returned error %s\n",
7185 status = map_nt_error_from_unix(errno);
7186 close_file(NULL, fsp1, ERROR_CLOSE);
7187 close_file(NULL, fsp2, ERROR_CLOSE);
7192 /* Do the actual copy. */
7193 if (smb_fname_src->st.st_ex_size) {
7194 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7199 close_file(NULL, fsp1, NORMAL_CLOSE);
7201 /* Ensure the modtime is set correctly on the destination file. */
7202 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7205 * As we are opening fsp1 read-only we only expect
7206 * an error on close on fsp2 if we are out of space.
7207 * Thus we don't look at the error return from the
7210 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7212 if (!NT_STATUS_IS_OK(status)) {
7216 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7217 status = NT_STATUS_DISK_FULL;
7221 status = NT_STATUS_OK;
7224 TALLOC_FREE(smb_fname_dst_tmp);
7228 /****************************************************************************
7229 Reply to a file copy.
7230 ****************************************************************************/
7232 void reply_copy(struct smb_request *req)
7234 connection_struct *conn = req->conn;
7235 struct smb_filename *smb_fname_src = NULL;
7236 struct smb_filename *smb_fname_dst = NULL;
7237 char *fname_src = NULL;
7238 char *fname_dst = NULL;
7239 char *fname_src_mask = NULL;
7240 char *fname_src_dir = NULL;
7243 int error = ERRnoaccess;
7247 bool target_is_directory=False;
7248 bool source_has_wild = False;
7249 bool dest_has_wild = False;
7251 TALLOC_CTX *ctx = talloc_tos();
7253 START_PROFILE(SMBcopy);
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7260 tid2 = SVAL(req->vwv+0, 0);
7261 ofun = SVAL(req->vwv+1, 0);
7262 flags = SVAL(req->vwv+2, 0);
7264 p = (const char *)req->buf;
7265 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7266 &status, &source_has_wild);
7267 if (!NT_STATUS_IS_OK(status)) {
7268 reply_nterror(req, status);
7271 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7272 &status, &dest_has_wild);
7273 if (!NT_STATUS_IS_OK(status)) {
7274 reply_nterror(req, status);
7278 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7280 if (tid2 != conn->cnum) {
7281 /* can't currently handle inter share copies XXXX */
7282 DEBUG(3,("Rejecting inter-share copy\n"));
7283 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7287 status = filename_convert(ctx, conn,
7288 req->flags2 & FLAGS2_DFS_PATHNAMES,
7290 UCF_COND_ALLOW_WCARD_LCOMP,
7293 if (!NT_STATUS_IS_OK(status)) {
7294 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7295 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7296 ERRSRV, ERRbadpath);
7299 reply_nterror(req, status);
7303 status = filename_convert(ctx, conn,
7304 req->flags2 & FLAGS2_DFS_PATHNAMES,
7306 UCF_COND_ALLOW_WCARD_LCOMP,
7309 if (!NT_STATUS_IS_OK(status)) {
7310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7311 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7312 ERRSRV, ERRbadpath);
7315 reply_nterror(req, status);
7319 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7321 if ((flags&1) && target_is_directory) {
7322 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7326 if ((flags&2) && !target_is_directory) {
7327 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7331 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7332 /* wants a tree copy! XXXX */
7333 DEBUG(3,("Rejecting tree copy\n"));
7334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7338 /* Split up the directory from the filename/mask. */
7339 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7340 &fname_src_dir, &fname_src_mask);
7341 if (!NT_STATUS_IS_OK(status)) {
7342 reply_nterror(req, NT_STATUS_NO_MEMORY);
7347 * We should only check the mangled cache
7348 * here if unix_convert failed. This means
7349 * that the path in 'mask' doesn't exist
7350 * on the file system and so we need to look
7351 * for a possible mangle. This patch from
7352 * Tine Smukavec <valentin.smukavec@hermes.si>.
7354 if (!VALID_STAT(smb_fname_src->st) &&
7355 mangle_is_mangled(fname_src_mask, conn->params)) {
7356 char *new_mask = NULL;
7357 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7358 &new_mask, conn->params);
7360 /* Use demangled name if one was successfully found. */
7362 TALLOC_FREE(fname_src_mask);
7363 fname_src_mask = new_mask;
7367 if (!source_has_wild) {
7370 * Only one file needs to be copied. Append the mask back onto
7373 TALLOC_FREE(smb_fname_src->base_name);
7374 if (ISDOT(fname_src_dir)) {
7375 /* Ensure we use canonical names on open. */
7376 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7380 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7385 if (!smb_fname_src->base_name) {
7386 reply_nterror(req, NT_STATUS_NO_MEMORY);
7390 if (dest_has_wild) {
7391 char *fname_dst_mod = NULL;
7392 if (!resolve_wildcards(smb_fname_dst,
7393 smb_fname_src->base_name,
7394 smb_fname_dst->base_name,
7396 reply_nterror(req, NT_STATUS_NO_MEMORY);
7399 TALLOC_FREE(smb_fname_dst->base_name);
7400 smb_fname_dst->base_name = fname_dst_mod;
7403 status = check_name(conn, smb_fname_src->base_name);
7404 if (!NT_STATUS_IS_OK(status)) {
7405 reply_nterror(req, status);
7409 status = check_name(conn, smb_fname_dst->base_name);
7410 if (!NT_STATUS_IS_OK(status)) {
7411 reply_nterror(req, status);
7415 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7416 ofun, count, target_is_directory);
7418 if(!NT_STATUS_IS_OK(status)) {
7419 reply_nterror(req, status);
7425 struct smb_Dir *dir_hnd = NULL;
7426 const char *dname = NULL;
7427 char *talloced = NULL;
7431 * There is a wildcard that requires us to actually read the
7432 * src dir and copy each file matching the mask to the dst.
7433 * Right now streams won't be copied, but this could
7434 * presumably be added with a nested loop for reach dir entry.
7436 SMB_ASSERT(!smb_fname_src->stream_name);
7437 SMB_ASSERT(!smb_fname_dst->stream_name);
7439 smb_fname_src->stream_name = NULL;
7440 smb_fname_dst->stream_name = NULL;
7442 if (strequal(fname_src_mask,"????????.???")) {
7443 TALLOC_FREE(fname_src_mask);
7444 fname_src_mask = talloc_strdup(ctx, "*");
7445 if (!fname_src_mask) {
7446 reply_nterror(req, NT_STATUS_NO_MEMORY);
7451 status = check_name(conn, fname_src_dir);
7452 if (!NT_STATUS_IS_OK(status)) {
7453 reply_nterror(req, status);
7457 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7458 if (dir_hnd == NULL) {
7459 status = map_nt_error_from_unix(errno);
7460 reply_nterror(req, status);
7466 /* Iterate over the src dir copying each entry to the dst. */
7467 while ((dname = ReadDirName(dir_hnd, &offset,
7468 &smb_fname_src->st, &talloced))) {
7469 char *destname = NULL;
7471 if (ISDOT(dname) || ISDOTDOT(dname)) {
7472 TALLOC_FREE(talloced);
7476 if (!is_visible_file(conn, fname_src_dir, dname,
7477 &smb_fname_src->st, false)) {
7478 TALLOC_FREE(talloced);
7482 if(!mask_match(dname, fname_src_mask,
7483 conn->case_sensitive)) {
7484 TALLOC_FREE(talloced);
7488 error = ERRnoaccess;
7490 /* Get the src smb_fname struct setup. */
7491 TALLOC_FREE(smb_fname_src->base_name);
7492 if (ISDOT(fname_src_dir)) {
7493 /* Ensure we use canonical names on open. */
7494 smb_fname_src->base_name =
7495 talloc_asprintf(smb_fname_src, "%s",
7498 smb_fname_src->base_name =
7499 talloc_asprintf(smb_fname_src, "%s/%s",
7500 fname_src_dir, dname);
7503 if (!smb_fname_src->base_name) {
7504 TALLOC_FREE(dir_hnd);
7505 TALLOC_FREE(talloced);
7506 reply_nterror(req, NT_STATUS_NO_MEMORY);
7510 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7511 smb_fname_dst->base_name,
7513 TALLOC_FREE(talloced);
7517 TALLOC_FREE(dir_hnd);
7518 TALLOC_FREE(talloced);
7519 reply_nterror(req, NT_STATUS_NO_MEMORY);
7523 TALLOC_FREE(smb_fname_dst->base_name);
7524 smb_fname_dst->base_name = destname;
7526 status = check_name(conn, smb_fname_src->base_name);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 TALLOC_FREE(dir_hnd);
7529 TALLOC_FREE(talloced);
7530 reply_nterror(req, status);
7534 status = check_name(conn, smb_fname_dst->base_name);
7535 if (!NT_STATUS_IS_OK(status)) {
7536 TALLOC_FREE(dir_hnd);
7537 TALLOC_FREE(talloced);
7538 reply_nterror(req, status);
7542 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7543 smb_fname_src->base_name,
7544 smb_fname_dst->base_name));
7546 status = copy_file(ctx, conn, smb_fname_src,
7547 smb_fname_dst, ofun, count,
7548 target_is_directory);
7549 if (NT_STATUS_IS_OK(status)) {
7553 TALLOC_FREE(talloced);
7555 TALLOC_FREE(dir_hnd);
7559 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7563 reply_outbuf(req, 1, 0);
7564 SSVAL(req->outbuf,smb_vwv0,count);
7566 TALLOC_FREE(smb_fname_src);
7567 TALLOC_FREE(smb_fname_dst);
7568 TALLOC_FREE(fname_src);
7569 TALLOC_FREE(fname_dst);
7570 TALLOC_FREE(fname_src_mask);
7571 TALLOC_FREE(fname_src_dir);
7573 END_PROFILE(SMBcopy);
7578 #define DBGC_CLASS DBGC_LOCKING
7580 /****************************************************************************
7581 Get a lock pid, dealing with large count requests.
7582 ****************************************************************************/
7584 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7585 bool large_file_format)
7587 if(!large_file_format)
7588 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7590 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7593 /****************************************************************************
7594 Get a lock count, dealing with large count requests.
7595 ****************************************************************************/
7597 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7598 bool large_file_format)
7602 if(!large_file_format) {
7603 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7606 * No BVAL, this is reversed!
7608 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7609 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7615 /****************************************************************************
7616 Get a lock offset, dealing with large offset requests.
7617 ****************************************************************************/
7619 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7620 bool large_file_format)
7622 uint64_t offset = 0;
7624 if(!large_file_format) {
7625 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7628 * No BVAL, this is reversed!
7630 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7631 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7637 NTSTATUS smbd_do_locking(struct smb_request *req,
7642 struct smbd_lock_element *locks,
7645 connection_struct *conn = req->conn;
7647 NTSTATUS status = NT_STATUS_OK;
7651 /* Setup the timeout in seconds. */
7653 if (!lp_blocking_locks(SNUM(conn))) {
7657 for(i = 0; i < (int)num_locks; i++) {
7658 struct smbd_lock_element *e = &locks[i];
7660 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7661 "%llu, file %s timeout = %d\n",
7664 (unsigned long long)e->smblctx,
7668 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7669 struct blocking_lock_record *blr = NULL;
7671 if (num_locks > 1) {
7673 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7674 * if the lock vector contains one entry. When given multiple cancel
7675 * requests in a single PDU we expect the server to return an
7676 * error. Windows servers seem to accept the request but only
7677 * cancel the first lock.
7678 * JRA - Do what Windows does (tm) :-).
7682 /* MS-CIFS (2.2.4.32.1) behavior. */
7683 return NT_STATUS_DOS(ERRDOS,
7684 ERRcancelviolation);
7686 /* Windows behavior. */
7688 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7689 "cancel request\n"));
7695 if (lp_blocking_locks(SNUM(conn))) {
7697 /* Schedule a message to ourselves to
7698 remove the blocking lock record and
7699 return the right error. */
7701 blr = blocking_lock_cancel_smb1(fsp,
7707 NT_STATUS_FILE_LOCK_CONFLICT);
7709 return NT_STATUS_DOS(
7711 ERRcancelviolation);
7714 /* Remove a matching pending lock. */
7715 status = do_lock_cancel(fsp,
7721 bool blocking_lock = timeout ? true : false;
7722 bool defer_lock = false;
7723 struct byte_range_lock *br_lck;
7724 uint64_t block_smblctx;
7726 br_lck = do_lock(req->sconn->msg_ctx,
7737 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7738 /* Windows internal resolution for blocking locks seems
7739 to be about 200ms... Don't wait for less than that. JRA. */
7740 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7741 timeout = lp_lock_spin_time();
7746 /* If a lock sent with timeout of zero would fail, and
7747 * this lock has been requested multiple times,
7748 * according to brl_lock_failed() we convert this
7749 * request to a blocking lock with a timeout of between
7750 * 150 - 300 milliseconds.
7752 * If lp_lock_spin_time() has been set to 0, we skip
7753 * this blocking retry and fail immediately.
7755 * Replacement for do_lock_spin(). JRA. */
7757 if (!req->sconn->using_smb2 &&
7758 br_lck && lp_blocking_locks(SNUM(conn)) &&
7759 lp_lock_spin_time() && !blocking_lock &&
7760 NT_STATUS_EQUAL((status),
7761 NT_STATUS_FILE_LOCK_CONFLICT))
7764 timeout = lp_lock_spin_time();
7767 if (br_lck && defer_lock) {
7769 * A blocking lock was requested. Package up
7770 * this smb into a queued request and push it
7771 * onto the blocking lock queue.
7773 if(push_blocking_lock_request(br_lck,
7784 TALLOC_FREE(br_lck);
7786 return NT_STATUS_OK;
7790 TALLOC_FREE(br_lck);
7793 if (!NT_STATUS_IS_OK(status)) {
7798 /* If any of the above locks failed, then we must unlock
7799 all of the previous locks (X/Open spec). */
7801 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7803 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7804 i = -1; /* we want to skip the for loop */
7808 * Ensure we don't do a remove on the lock that just failed,
7809 * as under POSIX rules, if we have a lock already there, we
7810 * will delete it (and we shouldn't) .....
7812 for(i--; i >= 0; i--) {
7813 struct smbd_lock_element *e = &locks[i];
7815 do_unlock(req->sconn->msg_ctx,
7825 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7826 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7828 return NT_STATUS_OK;
7831 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7833 uint16_t num_ulocks,
7834 struct smbd_lock_element *ulocks)
7838 for(i = 0; i < (int)num_ulocks; i++) {
7839 struct smbd_lock_element *e = &ulocks[i];
7842 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7843 "pid %u, file %s\n", __func__,
7846 (unsigned int)e->smblctx,
7849 if (e->brltype != UNLOCK_LOCK) {
7850 /* this can only happen with SMB2 */
7851 return NT_STATUS_INVALID_PARAMETER;
7854 status = do_unlock(req->sconn->msg_ctx,
7861 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7862 nt_errstr(status)));
7864 if (!NT_STATUS_IS_OK(status)) {
7869 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7872 return NT_STATUS_OK;
7875 /****************************************************************************
7876 Reply to a lockingX request.
7877 ****************************************************************************/
7879 void reply_lockingX(struct smb_request *req)
7881 connection_struct *conn = req->conn;
7883 unsigned char locktype;
7884 unsigned char oplocklevel;
7889 const uint8_t *data;
7890 bool large_file_format;
7891 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7892 struct smbd_lock_element *ulocks;
7893 struct smbd_lock_element *locks;
7896 START_PROFILE(SMBlockingX);
7899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7900 END_PROFILE(SMBlockingX);
7904 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7905 locktype = CVAL(req->vwv+3, 0);
7906 oplocklevel = CVAL(req->vwv+3, 1);
7907 num_ulocks = SVAL(req->vwv+6, 0);
7908 num_locks = SVAL(req->vwv+7, 0);
7909 lock_timeout = IVAL(req->vwv+4, 0);
7910 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7912 if (!check_fsp(conn, req, fsp)) {
7913 END_PROFILE(SMBlockingX);
7919 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7920 /* we don't support these - and CANCEL_LOCK makes w2k
7921 and XP reboot so I don't really want to be
7922 compatible! (tridge) */
7923 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7924 END_PROFILE(SMBlockingX);
7928 /* Check if this is an oplock break on a file
7929 we have granted an oplock on.
7931 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7932 /* Client can insist on breaking to none. */
7933 bool break_to_none = (oplocklevel == 0);
7936 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7937 "for %s\n", (unsigned int)oplocklevel,
7938 fsp_fnum_dbg(fsp)));
7941 * Make sure we have granted an exclusive or batch oplock on
7945 if (fsp->oplock_type == 0) {
7947 /* The Samba4 nbench simulator doesn't understand
7948 the difference between break to level2 and break
7949 to none from level2 - it sends oplock break
7950 replies in both cases. Don't keep logging an error
7951 message here - just ignore it. JRA. */
7953 DEBUG(5,("reply_lockingX: Error : oplock break from "
7954 "client for %s (oplock=%d) and no "
7955 "oplock granted on this file (%s).\n",
7956 fsp_fnum_dbg(fsp), fsp->oplock_type,
7959 /* if this is a pure oplock break request then don't
7961 if (num_locks == 0 && num_ulocks == 0) {
7962 END_PROFILE(SMBlockingX);
7965 END_PROFILE(SMBlockingX);
7966 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7971 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7973 result = remove_oplock(fsp);
7975 result = downgrade_oplock(fsp);
7979 DEBUG(0, ("reply_lockingX: error in removing "
7980 "oplock on file %s\n", fsp_str_dbg(fsp)));
7981 /* Hmmm. Is this panic justified? */
7982 smb_panic("internal tdb error");
7985 /* if this is a pure oplock break request then don't send a
7987 if (num_locks == 0 && num_ulocks == 0) {
7988 /* Sanity check - ensure a pure oplock break is not a
7990 if (CVAL(req->vwv+0, 0) != 0xff) {
7991 DEBUG(0,("reply_lockingX: Error : pure oplock "
7992 "break is a chained %d request !\n",
7993 (unsigned int)CVAL(req->vwv+0, 0)));
7995 END_PROFILE(SMBlockingX);
8001 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8003 END_PROFILE(SMBlockingX);
8007 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8008 if (ulocks == NULL) {
8009 reply_nterror(req, NT_STATUS_NO_MEMORY);
8010 END_PROFILE(SMBlockingX);
8014 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8015 if (locks == NULL) {
8016 reply_nterror(req, NT_STATUS_NO_MEMORY);
8017 END_PROFILE(SMBlockingX);
8021 /* Data now points at the beginning of the list
8022 of smb_unlkrng structs */
8023 for(i = 0; i < (int)num_ulocks; i++) {
8024 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8025 ulocks[i].count = get_lock_count(data, i, large_file_format);
8026 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8027 ulocks[i].brltype = UNLOCK_LOCK;
8030 /* Now do any requested locks */
8031 data += ((large_file_format ? 20 : 10)*num_ulocks);
8033 /* Data now points at the beginning of the list
8034 of smb_lkrng structs */
8036 for(i = 0; i < (int)num_locks; i++) {
8037 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8038 locks[i].count = get_lock_count(data, i, large_file_format);
8039 locks[i].offset = get_lock_offset(data, i, large_file_format);
8041 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8042 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8043 locks[i].brltype = PENDING_READ_LOCK;
8045 locks[i].brltype = READ_LOCK;
8048 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8049 locks[i].brltype = PENDING_WRITE_LOCK;
8051 locks[i].brltype = WRITE_LOCK;
8056 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8057 if (!NT_STATUS_IS_OK(status)) {
8058 END_PROFILE(SMBlockingX);
8059 reply_nterror(req, status);
8063 status = smbd_do_locking(req, fsp,
8064 locktype, lock_timeout,
8067 if (!NT_STATUS_IS_OK(status)) {
8068 END_PROFILE(SMBlockingX);
8069 reply_nterror(req, status);
8073 END_PROFILE(SMBlockingX);
8077 reply_outbuf(req, 2, 0);
8078 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8079 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8081 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8082 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8084 END_PROFILE(SMBlockingX);
8088 #define DBGC_CLASS DBGC_ALL
8090 /****************************************************************************
8091 Reply to a SMBreadbmpx (read block multiplex) request.
8092 Always reply with an error, if someone has a platform really needs this,
8093 please contact vl@samba.org
8094 ****************************************************************************/
8096 void reply_readbmpx(struct smb_request *req)
8098 START_PROFILE(SMBreadBmpx);
8099 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8100 END_PROFILE(SMBreadBmpx);
8104 /****************************************************************************
8105 Reply to a SMBreadbs (read block multiplex secondary) request.
8106 Always reply with an error, if someone has a platform really needs this,
8107 please contact vl@samba.org
8108 ****************************************************************************/
8110 void reply_readbs(struct smb_request *req)
8112 START_PROFILE(SMBreadBs);
8113 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8114 END_PROFILE(SMBreadBs);
8118 /****************************************************************************
8119 Reply to a SMBsetattrE.
8120 ****************************************************************************/
8122 void reply_setattrE(struct smb_request *req)
8124 connection_struct *conn = req->conn;
8125 struct smb_file_time ft;
8129 START_PROFILE(SMBsetattrE);
8133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8137 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8139 if(!fsp || (fsp->conn != conn)) {
8140 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8145 * Convert the DOS times into unix times.
8148 ft.atime = convert_time_t_to_timespec(
8149 srv_make_unix_date2(req->vwv+3));
8150 ft.mtime = convert_time_t_to_timespec(
8151 srv_make_unix_date2(req->vwv+5));
8152 ft.create_time = convert_time_t_to_timespec(
8153 srv_make_unix_date2(req->vwv+1));
8155 reply_outbuf(req, 0, 0);
8158 * Patch from Ray Frush <frush@engr.colostate.edu>
8159 * Sometimes times are sent as zero - ignore them.
8162 /* Ensure we have a valid stat struct for the source. */
8163 status = vfs_stat_fsp(fsp);
8164 if (!NT_STATUS_IS_OK(status)) {
8165 reply_nterror(req, status);
8169 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8170 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8174 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8175 if (!NT_STATUS_IS_OK(status)) {
8176 reply_nterror(req, status);
8180 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8183 (unsigned int)ft.atime.tv_sec,
8184 (unsigned int)ft.mtime.tv_sec,
8185 (unsigned int)ft.create_time.tv_sec
8188 END_PROFILE(SMBsetattrE);
8193 /* Back from the dead for OS/2..... JRA. */
8195 /****************************************************************************
8196 Reply to a SMBwritebmpx (write block multiplex primary) request.
8197 Always reply with an error, if someone has a platform really needs this,
8198 please contact vl@samba.org
8199 ****************************************************************************/
8201 void reply_writebmpx(struct smb_request *req)
8203 START_PROFILE(SMBwriteBmpx);
8204 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8205 END_PROFILE(SMBwriteBmpx);
8209 /****************************************************************************
8210 Reply to a SMBwritebs (write block multiplex secondary) request.
8211 Always reply with an error, if someone has a platform really needs this,
8212 please contact vl@samba.org
8213 ****************************************************************************/
8215 void reply_writebs(struct smb_request *req)
8217 START_PROFILE(SMBwriteBs);
8218 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8219 END_PROFILE(SMBwriteBs);
8223 /****************************************************************************
8224 Reply to a SMBgetattrE.
8225 ****************************************************************************/
8227 void reply_getattrE(struct smb_request *req)
8229 connection_struct *conn = req->conn;
8232 struct timespec create_ts;
8234 START_PROFILE(SMBgetattrE);
8237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8238 END_PROFILE(SMBgetattrE);
8242 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8244 if(!fsp || (fsp->conn != conn)) {
8245 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8246 END_PROFILE(SMBgetattrE);
8250 /* Do an fstat on this file */
8252 reply_nterror(req, map_nt_error_from_unix(errno));
8253 END_PROFILE(SMBgetattrE);
8257 mode = dos_mode(conn, fsp->fsp_name);
8260 * Convert the times into dos times. Set create
8261 * date to be last modify date as UNIX doesn't save
8265 reply_outbuf(req, 11, 0);
8267 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8268 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8269 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8270 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8271 /* Should we check pending modtime here ? JRA */
8272 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8273 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8275 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8276 SIVAL(req->outbuf, smb_vwv6, 0);
8277 SIVAL(req->outbuf, smb_vwv8, 0);
8279 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8280 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8281 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8283 SSVAL(req->outbuf,smb_vwv10, mode);
8285 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8287 END_PROFILE(SMBgetattrE);