build: Move uid_wrapper to third_party
[Samba.git] / source3 / smbd / reply.c
blob623f83b1250e787b4d363cd4382abe72f836913b
1 /*
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
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.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"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 set.
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
60 bool posix_path,
61 bool *p_last_component_contains_wcard)
63 char *d = path;
64 const char *s = path;
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
71 while (*s) {
72 if (stream_started) {
73 switch (*s) {
74 case '/':
75 case '\\':
76 return NT_STATUS_OBJECT_NAME_INVALID;
77 case ':':
78 if (s[1] == '\0') {
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
84 break;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
96 JRA.
98 stream_started = true;
99 start_of_name_component = false;
100 posix_path = true;
102 if (s[1] == '\0') {
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
114 s++;
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
118 *d++ = '/';
121 start_of_name_component = True;
122 /* New component. */
123 *p_last_component_contains_wcard = False;
124 continue;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
137 *(d-1) = '\0';
138 d--;
141 /* Are we at the start ? Can't go back further if so. */
142 if (d <= path) {
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
144 break;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
151 if (*d == '/')
152 break;
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
156 continue;
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
159 if (posix_path) {
160 /* Eat the '.' */
161 s++;
162 continue;
168 if (!(*s & 0x80)) {
169 if (!posix_path) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
173 switch (*s) {
174 case '*':
175 case '?':
176 case '<':
177 case '>':
178 case '"':
179 *p_last_component_contains_wcard = True;
180 break;
181 default:
182 break;
185 *d++ = *s++;
186 } else {
187 size_t siz;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
190 switch(siz) {
191 case 5:
192 *d++ = *s++;
193 /*fall through*/
194 case 4:
195 *d++ = *s++;
196 /*fall through*/
197 case 3:
198 *d++ = *s++;
199 /*fall through*/
200 case 2:
201 *d++ = *s++;
202 /*fall through*/
203 case 1:
204 *d++ = *s++;
205 break;
206 default:
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 *d = '\0';
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
215 *d = '\0';
217 return ret;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
227 bool ignore;
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 a wildcard.
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
250 bool ignore;
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257 ****************************************************************************/
259 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
261 uint16_t smb_flags2,
262 char **pp_dest,
263 const char *src,
264 size_t src_len,
265 int flags,
266 bool posix_pathnames,
267 NTSTATUS *err,
268 bool *contains_wcard)
270 size_t ret;
272 *pp_dest = NULL;
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275 src_len, flags);
277 if (!*pp_dest) {
278 *err = NT_STATUS_INVALID_PARAMETER;
279 return ret;
282 *contains_wcard = False;
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
289 *err = NT_STATUS_OK;
290 return ret;
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
295 } else {
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
299 return ret;
302 /****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304 ****************************************************************************/
306 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
308 uint16_t smb_flags2,
309 char **pp_dest,
310 const char *src,
311 size_t src_len,
312 int flags,
313 NTSTATUS *err,
314 bool *contains_wcard)
316 return srvstr_get_path_wcard_internal(ctx,
317 base_ptr,
318 smb_flags2,
319 pp_dest,
320 src,
321 src_len,
322 flags,
323 false,
324 err,
325 contains_wcard);
328 /****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331 ****************************************************************************/
333 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
335 uint16_t smb_flags2,
336 char **pp_dest,
337 const char *src,
338 size_t src_len,
339 int flags,
340 NTSTATUS *err,
341 bool *contains_wcard)
343 return srvstr_get_path_wcard_internal(ctx,
344 base_ptr,
345 smb_flags2,
346 pp_dest,
347 src,
348 src_len,
349 flags,
350 true,
351 err,
352 contains_wcard);
355 /****************************************************************************
356 Pull a string and check the path - provide for error return.
357 ****************************************************************************/
359 size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
361 uint16_t smb_flags2,
362 char **pp_dest,
363 const char *src,
364 size_t src_len,
365 int flags,
366 NTSTATUS *err)
368 bool ignore;
369 return srvstr_get_path_wcard_internal(ctx,
370 base_ptr,
371 smb_flags2,
372 pp_dest,
373 src,
374 src_len,
375 flags,
376 false,
377 err,
378 &ignore);
381 /****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384 ****************************************************************************/
386 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
388 uint16_t smb_flags2,
389 char **pp_dest,
390 const char *src,
391 size_t src_len,
392 int flags,
393 NTSTATUS *err)
395 bool ignore;
396 return srvstr_get_path_wcard_internal(ctx,
397 base_ptr,
398 smb_flags2,
399 pp_dest,
400 src,
401 src_len,
402 flags,
403 true,
404 err,
405 &ignore);
409 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
413 ssize_t bufrem = smbreq_bufrem(req, src);
415 if (bufrem < 0) {
416 *err = NT_STATUS_INVALID_PARAMETER;
417 return 0;
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
423 req->flags2,
424 pp_dest,
425 src,
426 bufrem,
427 flags,
428 true,
429 err,
430 contains_wcard);
431 } else {
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
434 req->flags2,
435 pp_dest,
436 src,
437 bufrem,
438 flags,
439 false,
440 err,
441 contains_wcard);
445 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
447 NTSTATUS *err)
449 bool ignore;
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
459 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
462 ssize_t bufrem = smbreq_bufrem(req, src);
464 if (bufrem < 0) {
465 return 0;
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
469 bufrem, flags);
472 /****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474 ****************************************************************************/
476 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
477 files_struct *fsp)
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
481 return False;
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
485 return False;
487 return True;
490 /****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492 ****************************************************************************/
494 bool check_fsp(connection_struct *conn, struct smb_request *req,
495 files_struct *fsp)
497 if (!check_fsp_open(conn, req, fsp)) {
498 return False;
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
502 return False;
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
506 return False;
508 fsp->num_smb_operations++;
509 return True;
512 /****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515 ****************************************************************************/
517 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
518 files_struct *fsp)
520 if (!check_fsp_open(conn, req, fsp)) {
521 return false;
524 if (fsp->is_directory) {
525 return false;
528 if (fsp->fake_file_handle == NULL) {
529 return false;
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
533 return false;
536 if (fsp->fake_file_handle->private_data == NULL) {
537 return false;
540 return true;
543 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
546 char *trim_name;
547 char *trim_name_type;
548 const char *retarget_parm;
549 char *retarget;
550 char *p;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
555 bool ret = false;
556 uint8_t outbuf[10];
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
559 return false;
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
564 goto fail;
566 trim_char(trim_name, ' ', ' ');
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
569 name_type);
570 if (trim_name_type == NULL) {
571 goto fail;
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 trim_name, NULL);
580 if (retarget_parm == NULL) {
581 goto fail;
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
586 goto fail;
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
591 p = strchr(retarget, ':');
592 if (p != NULL) {
593 *p++ = '\0';
594 retarget_port = atoi(p);
597 p = strchr_m(retarget, '#');
598 if (p != NULL) {
599 *p++ = '\0';
600 if (sscanf(p, "%x", &retarget_type) != 1) {
601 goto fail;
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
606 if (!ret) {
607 DEBUG(10, ("could not resolve %s\n", retarget));
608 goto fail;
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
613 goto fail;
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
624 NULL)) {
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
626 "failed.");
629 ret = true;
630 fail:
631 TALLOC_FREE(trim_name);
632 return ret;
635 static void reply_called_name_not_present(char *outbuf)
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
642 /****************************************************************************
643 Reply to a (netbios-level) special message.
644 ****************************************************************************/
646 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
654 * header.
656 char outbuf[smb_size];
658 memset(outbuf, '\0', sizeof(outbuf));
660 smb_setlen(outbuf,0);
662 switch (msg_type) {
663 case NBSSrequest: /* session request */
665 /* inbuf_size is guarenteed to be at least 4. */
666 fstring name1,name2;
667 int name_type1, name_type2;
668 int name_len1, name_len2;
670 *name1 = *name2 = 0;
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
676 SCVAL(outbuf,0,NBSSpositive);
677 SCVAL(outbuf,3,0);
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
684 break;
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
690 break;
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
701 break;
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
717 char *raddr;
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
720 talloc_tos());
721 if (raddr == NULL) {
722 exit_server_cleanly("could not allocate raddr");
725 fstrcpy(name1, raddr);
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
734 talloc_free(p);
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
741 xconn->remote_hostname = sconn->remote_hostname;
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
746 name_type2));
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
750 no thanks! */
751 reply_called_name_not_present(outbuf);
752 break;
755 reload_services(sconn, conn_snum_used, true);
756 reopen_logs();
758 xconn->transport.nbt.got_session = true;
759 break;
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
765 SCVAL(outbuf,3,0);
766 break;
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
772 break;
774 case NBSSkeepalive: /* session keepalive */
775 default:
776 return;
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
782 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
783 exit_server_cleanly("reply_special: srv_send_smb failed.");
786 if (CVAL(outbuf, 0) != 0x82) {
787 exit_server_cleanly("invalid netbios session");
789 return;
792 /****************************************************************************
793 Reply to a tcon.
794 conn POINTER CAN BE NULL HERE !
795 ****************************************************************************/
797 void reply_tcon(struct smb_request *req)
799 connection_struct *conn = req->conn;
800 const char *service;
801 char *service_buf = NULL;
802 char *password = NULL;
803 char *dev = NULL;
804 int pwlen=0;
805 NTSTATUS nt_status;
806 const uint8_t *p;
807 const char *p2;
808 TALLOC_CTX *ctx = talloc_tos();
809 struct smbXsrv_connection *xconn = req->xconn;
810 NTTIME now = timeval_to_nttime(&req->request_time);
812 START_PROFILE(SMBtcon);
814 if (req->buflen < 4) {
815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
816 END_PROFILE(SMBtcon);
817 return;
820 p = req->buf + 1;
821 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
822 p += 1;
823 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
824 p += pwlen+1;
825 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
826 p += 1;
828 if (service_buf == NULL || password == NULL || dev == NULL) {
829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830 END_PROFILE(SMBtcon);
831 return;
833 p2 = strrchr_m(service_buf,'\\');
834 if (p2) {
835 service = p2+1;
836 } else {
837 service = service_buf;
840 conn = make_connection(req, now, service, dev,
841 req->vuid,&nt_status);
842 req->conn = conn;
844 if (!conn) {
845 reply_nterror(req, nt_status);
846 END_PROFILE(SMBtcon);
847 return;
850 reply_outbuf(req, 2, 0);
851 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
852 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
853 SSVAL(req->outbuf,smb_tid,conn->cnum);
855 DEBUG(3,("tcon service=%s cnum=%d\n",
856 service, conn->cnum));
858 END_PROFILE(SMBtcon);
859 return;
862 /****************************************************************************
863 Reply to a tcon and X.
864 conn POINTER CAN BE NULL HERE !
865 ****************************************************************************/
867 void reply_tcon_and_X(struct smb_request *req)
869 connection_struct *conn = req->conn;
870 const char *service = NULL;
871 TALLOC_CTX *ctx = talloc_tos();
872 /* what the client thinks the device is */
873 char *client_devicetype = NULL;
874 /* what the server tells the client the share represents */
875 const char *server_devicetype;
876 NTSTATUS nt_status;
877 int passlen;
878 char *path = NULL;
879 const uint8_t *p;
880 const char *q;
881 uint16_t tcon_flags;
882 struct smbXsrv_session *session = NULL;
883 NTTIME now = timeval_to_nttime(&req->request_time);
884 bool session_key_updated = false;
885 uint16_t optional_support = 0;
886 struct smbXsrv_connection *xconn = req->xconn;
888 START_PROFILE(SMBtconX);
890 if (req->wct < 4) {
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 END_PROFILE(SMBtconX);
893 return;
896 passlen = SVAL(req->vwv+3, 0);
897 tcon_flags = SVAL(req->vwv+2, 0);
899 /* we might have to close an old one */
900 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
901 struct smbXsrv_tcon *tcon;
902 NTSTATUS status;
904 tcon = conn->tcon;
905 req->conn = NULL;
906 conn = NULL;
909 * TODO: cancel all outstanding requests on the tcon
911 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
912 if (!NT_STATUS_IS_OK(status)) {
913 DEBUG(0, ("reply_tcon_and_X: "
914 "smbXsrv_tcon_disconnect() failed: %s\n",
915 nt_errstr(status)));
917 * If we hit this case, there is something completely
918 * wrong, so we better disconnect the transport connection.
920 END_PROFILE(SMBtconX);
921 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
922 return;
925 TALLOC_FREE(tcon);
927 * This tree id is gone. Make sure we can't re-use it
928 * by accident.
930 req->tid = 0;
933 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
934 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
935 END_PROFILE(SMBtconX);
936 return;
939 if (xconn->smb1.negprot.encrypted_passwords) {
940 p = req->buf + passlen;
941 } else {
942 p = req->buf + passlen + 1;
945 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
947 if (path == NULL) {
948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
949 END_PROFILE(SMBtconX);
950 return;
954 * the service name can be either: \\server\share
955 * or share directly like on the DELL PowerVault 705
957 if (*path=='\\') {
958 q = strchr_m(path+2,'\\');
959 if (!q) {
960 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
961 END_PROFILE(SMBtconX);
962 return;
964 service = q+1;
965 } else {
966 service = path;
969 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
970 &client_devicetype, p,
971 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
973 if (client_devicetype == NULL) {
974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
975 END_PROFILE(SMBtconX);
976 return;
979 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
981 nt_status = smb1srv_session_lookup(xconn,
982 req->vuid, now, &session);
983 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
984 reply_force_doserror(req, ERRSRV, ERRbaduid);
985 END_PROFILE(SMBtconX);
986 return;
988 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
989 reply_nterror(req, nt_status);
990 END_PROFILE(SMBtconX);
991 return;
993 if (!NT_STATUS_IS_OK(nt_status)) {
994 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
995 END_PROFILE(SMBtconX);
996 return;
999 if (session->global->auth_session_info == NULL) {
1000 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1001 END_PROFILE(SMBtconX);
1002 return;
1006 * If there is no application key defined yet
1007 * we create one.
1009 * This means we setup the application key on the
1010 * first tcon that happens via the given session.
1012 * Once the application key is defined, it does not
1013 * change any more.
1015 if (session->global->application_key.length == 0 &&
1016 session->global->signing_key.length > 0)
1018 struct smbXsrv_session *x = session;
1019 struct auth_session_info *session_info =
1020 session->global->auth_session_info;
1021 uint8_t session_key[16];
1023 ZERO_STRUCT(session_key);
1024 memcpy(session_key, x->global->signing_key.data,
1025 MIN(x->global->signing_key.length, sizeof(session_key)));
1028 * The application key is truncated/padded to 16 bytes
1030 x->global->application_key = data_blob_talloc(x->global,
1031 session_key,
1032 sizeof(session_key));
1033 ZERO_STRUCT(session_key);
1034 if (x->global->application_key.data == NULL) {
1035 reply_nterror(req, NT_STATUS_NO_MEMORY);
1036 END_PROFILE(SMBtconX);
1037 return;
1040 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1041 smb_key_derivation(x->global->application_key.data,
1042 x->global->application_key.length,
1043 x->global->application_key.data);
1044 optional_support |= SMB_EXTENDED_SIGNATURES;
1048 * Place the application key into the session_info
1050 data_blob_clear_free(&session_info->session_key);
1051 session_info->session_key = data_blob_dup_talloc(session_info,
1052 x->global->application_key);
1053 if (session_info->session_key.data == NULL) {
1054 data_blob_clear_free(&x->global->application_key);
1055 reply_nterror(req, NT_STATUS_NO_MEMORY);
1056 END_PROFILE(SMBtconX);
1057 return;
1059 session_key_updated = true;
1062 conn = make_connection(req, now, service, client_devicetype,
1063 req->vuid, &nt_status);
1064 req->conn =conn;
1066 if (!conn) {
1067 if (session_key_updated) {
1068 struct smbXsrv_session *x = session;
1069 struct auth_session_info *session_info =
1070 session->global->auth_session_info;
1071 data_blob_clear_free(&x->global->application_key);
1072 data_blob_clear_free(&session_info->session_key);
1074 reply_nterror(req, nt_status);
1075 END_PROFILE(SMBtconX);
1076 return;
1079 if ( IS_IPC(conn) )
1080 server_devicetype = "IPC";
1081 else if ( IS_PRINT(conn) )
1082 server_devicetype = "LPT1:";
1083 else
1084 server_devicetype = "A:";
1086 if (get_Protocol() < PROTOCOL_NT1) {
1087 reply_outbuf(req, 2, 0);
1088 if (message_push_string(&req->outbuf, server_devicetype,
1089 STR_TERMINATE|STR_ASCII) == -1) {
1090 reply_nterror(req, NT_STATUS_NO_MEMORY);
1091 END_PROFILE(SMBtconX);
1092 return;
1094 } else {
1095 /* NT sets the fstype of IPC$ to the null string */
1096 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1098 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1099 /* Return permissions. */
1100 uint32_t perm1 = 0;
1101 uint32_t perm2 = 0;
1103 reply_outbuf(req, 7, 0);
1105 if (IS_IPC(conn)) {
1106 perm1 = FILE_ALL_ACCESS;
1107 perm2 = FILE_ALL_ACCESS;
1108 } else {
1109 perm1 = conn->share_access;
1112 SIVAL(req->outbuf, smb_vwv3, perm1);
1113 SIVAL(req->outbuf, smb_vwv5, perm2);
1114 } else {
1115 reply_outbuf(req, 3, 0);
1118 if ((message_push_string(&req->outbuf, server_devicetype,
1119 STR_TERMINATE|STR_ASCII) == -1)
1120 || (message_push_string(&req->outbuf, fstype,
1121 STR_TERMINATE) == -1)) {
1122 reply_nterror(req, NT_STATUS_NO_MEMORY);
1123 END_PROFILE(SMBtconX);
1124 return;
1127 /* what does setting this bit do? It is set by NT4 and
1128 may affect the ability to autorun mounted cdroms */
1129 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1130 optional_support |=
1131 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1133 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1134 DEBUG(2,("Serving %s as a Dfs root\n",
1135 lp_servicename(ctx, SNUM(conn)) ));
1136 optional_support |= SMB_SHARE_IN_DFS;
1139 SSVAL(req->outbuf, smb_vwv2, optional_support);
1142 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1143 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1145 DEBUG(3,("tconX service=%s \n",
1146 service));
1148 /* set the incoming and outgoing tid to the just created one */
1149 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1150 SSVAL(req->outbuf,smb_tid,conn->cnum);
1152 END_PROFILE(SMBtconX);
1154 req->tid = conn->cnum;
1157 /****************************************************************************
1158 Reply to an unknown type.
1159 ****************************************************************************/
1161 void reply_unknown_new(struct smb_request *req, uint8_t type)
1163 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1164 smb_fn_name(type), type, type));
1165 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1166 return;
1169 /****************************************************************************
1170 Reply to an ioctl.
1171 conn POINTER CAN BE NULL HERE !
1172 ****************************************************************************/
1174 void reply_ioctl(struct smb_request *req)
1176 connection_struct *conn = req->conn;
1177 uint16_t device;
1178 uint16_t function;
1179 uint32_t ioctl_code;
1180 int replysize;
1181 char *p;
1183 START_PROFILE(SMBioctl);
1185 if (req->wct < 3) {
1186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1187 END_PROFILE(SMBioctl);
1188 return;
1191 device = SVAL(req->vwv+1, 0);
1192 function = SVAL(req->vwv+2, 0);
1193 ioctl_code = (device << 16) + function;
1195 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1197 switch (ioctl_code) {
1198 case IOCTL_QUERY_JOB_INFO:
1199 replysize = 32;
1200 break;
1201 default:
1202 reply_force_doserror(req, ERRSRV, ERRnosupport);
1203 END_PROFILE(SMBioctl);
1204 return;
1207 reply_outbuf(req, 8, replysize+1);
1208 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1209 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1210 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1211 p = smb_buf(req->outbuf);
1212 memset(p, '\0', replysize+1); /* valgrind-safe. */
1213 p += 1; /* Allow for alignment */
1215 switch (ioctl_code) {
1216 case IOCTL_QUERY_JOB_INFO:
1218 NTSTATUS status;
1219 size_t len = 0;
1220 files_struct *fsp = file_fsp(
1221 req, SVAL(req->vwv+0, 0));
1222 if (!fsp) {
1223 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1224 END_PROFILE(SMBioctl);
1225 return;
1227 /* Job number */
1228 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1230 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1231 lp_netbios_name(), 15,
1232 STR_TERMINATE|STR_ASCII, &len);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 reply_nterror(req, status);
1235 END_PROFILE(SMBioctl);
1236 return;
1238 if (conn) {
1239 status = srvstr_push((char *)req->outbuf, req->flags2,
1240 p+18,
1241 lp_servicename(talloc_tos(),
1242 SNUM(conn)),
1243 13, STR_TERMINATE|STR_ASCII, &len);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 reply_nterror(req, status);
1246 END_PROFILE(SMBioctl);
1247 return;
1249 } else {
1250 memset(p+18, 0, 13);
1252 break;
1256 END_PROFILE(SMBioctl);
1257 return;
1260 /****************************************************************************
1261 Strange checkpath NTSTATUS mapping.
1262 ****************************************************************************/
1264 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1266 /* Strange DOS error code semantics only for checkpath... */
1267 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1268 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1269 /* We need to map to ERRbadpath */
1270 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1273 return status;
1276 /****************************************************************************
1277 Reply to a checkpath.
1278 ****************************************************************************/
1280 void reply_checkpath(struct smb_request *req)
1282 connection_struct *conn = req->conn;
1283 struct smb_filename *smb_fname = NULL;
1284 char *name = NULL;
1285 NTSTATUS status;
1286 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1287 TALLOC_CTX *ctx = talloc_tos();
1289 START_PROFILE(SMBcheckpath);
1291 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1292 STR_TERMINATE, &status);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 status = map_checkpath_error(req->flags2, status);
1296 reply_nterror(req, status);
1297 END_PROFILE(SMBcheckpath);
1298 return;
1301 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1303 status = filename_convert(ctx,
1304 conn,
1305 name,
1306 ucf_flags,
1307 NULL,
1308 &smb_fname);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1312 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1313 ERRSRV, ERRbadpath);
1314 END_PROFILE(SMBcheckpath);
1315 return;
1317 goto path_err;
1320 if (!VALID_STAT(smb_fname->st) &&
1321 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1322 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1323 smb_fname_str_dbg(smb_fname), strerror(errno)));
1324 status = map_nt_error_from_unix(errno);
1325 goto path_err;
1328 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1329 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1330 ERRDOS, ERRbadpath);
1331 goto out;
1334 reply_outbuf(req, 0, 0);
1336 path_err:
1337 /* We special case this - as when a Windows machine
1338 is parsing a path is steps through the components
1339 one at a time - if a component fails it expects
1340 ERRbadpath, not ERRbadfile.
1342 status = map_checkpath_error(req->flags2, status);
1343 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1345 * Windows returns different error codes if
1346 * the parent directory is valid but not the
1347 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1348 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1349 * if the path is invalid.
1351 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1352 ERRDOS, ERRbadpath);
1353 goto out;
1356 reply_nterror(req, status);
1358 out:
1359 TALLOC_FREE(smb_fname);
1360 END_PROFILE(SMBcheckpath);
1361 return;
1364 /****************************************************************************
1365 Reply to a getatr.
1366 ****************************************************************************/
1368 void reply_getatr(struct smb_request *req)
1370 connection_struct *conn = req->conn;
1371 struct smb_filename *smb_fname = NULL;
1372 char *fname = NULL;
1373 int mode=0;
1374 off_t size=0;
1375 time_t mtime=0;
1376 const char *p;
1377 NTSTATUS status;
1378 TALLOC_CTX *ctx = talloc_tos();
1379 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1381 START_PROFILE(SMBgetatr);
1383 p = (const char *)req->buf + 1;
1384 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 reply_nterror(req, status);
1387 goto out;
1390 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1391 under WfWg - weird! */
1392 if (*fname == '\0') {
1393 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1394 if (!CAN_WRITE(conn)) {
1395 mode |= FILE_ATTRIBUTE_READONLY;
1397 size = 0;
1398 mtime = 0;
1399 } else {
1400 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1401 status = filename_convert(ctx,
1402 conn,
1403 fname,
1404 ucf_flags,
1405 NULL,
1406 &smb_fname);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1409 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1410 ERRSRV, ERRbadpath);
1411 goto out;
1413 reply_nterror(req, status);
1414 goto out;
1416 if (!VALID_STAT(smb_fname->st) &&
1417 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1418 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1419 smb_fname_str_dbg(smb_fname),
1420 strerror(errno)));
1421 reply_nterror(req, map_nt_error_from_unix(errno));
1422 goto out;
1425 mode = dos_mode(conn, smb_fname);
1426 size = smb_fname->st.st_ex_size;
1428 if (ask_sharemode) {
1429 struct timespec write_time_ts;
1430 struct file_id fileid;
1432 ZERO_STRUCT(write_time_ts);
1433 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1434 get_file_infos(fileid, 0, NULL, &write_time_ts);
1435 if (!null_timespec(write_time_ts)) {
1436 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1440 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1441 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1442 size = 0;
1446 reply_outbuf(req, 10, 0);
1448 SSVAL(req->outbuf,smb_vwv0,mode);
1449 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1450 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1451 } else {
1452 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1454 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1456 if (get_Protocol() >= PROTOCOL_NT1) {
1457 SSVAL(req->outbuf, smb_flg2,
1458 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1461 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1462 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1464 out:
1465 TALLOC_FREE(smb_fname);
1466 TALLOC_FREE(fname);
1467 END_PROFILE(SMBgetatr);
1468 return;
1471 /****************************************************************************
1472 Reply to a setatr.
1473 ****************************************************************************/
1475 void reply_setatr(struct smb_request *req)
1477 struct smb_file_time ft;
1478 connection_struct *conn = req->conn;
1479 struct smb_filename *smb_fname = NULL;
1480 char *fname = NULL;
1481 int mode;
1482 time_t mtime;
1483 const char *p;
1484 NTSTATUS status;
1485 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1486 TALLOC_CTX *ctx = talloc_tos();
1488 START_PROFILE(SMBsetatr);
1490 ZERO_STRUCT(ft);
1492 if (req->wct < 2) {
1493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1494 goto out;
1497 p = (const char *)req->buf + 1;
1498 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 reply_nterror(req, status);
1501 goto out;
1504 status = filename_convert(ctx,
1505 conn,
1506 fname,
1507 ucf_flags,
1508 NULL,
1509 &smb_fname);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1512 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1513 ERRSRV, ERRbadpath);
1514 goto out;
1516 reply_nterror(req, status);
1517 goto out;
1520 if (smb_fname->base_name[0] == '.' &&
1521 smb_fname->base_name[1] == '\0') {
1523 * Not sure here is the right place to catch this
1524 * condition. Might be moved to somewhere else later -- vl
1526 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1527 goto out;
1530 mode = SVAL(req->vwv+0, 0);
1531 mtime = srv_make_unix_date3(req->vwv+1);
1533 if (mode != FILE_ATTRIBUTE_NORMAL) {
1534 if (VALID_STAT_OF_DIR(smb_fname->st))
1535 mode |= FILE_ATTRIBUTE_DIRECTORY;
1536 else
1537 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1539 status = check_access(conn, NULL, smb_fname,
1540 FILE_WRITE_ATTRIBUTES);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 reply_nterror(req, status);
1543 goto out;
1546 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1547 false) != 0) {
1548 reply_nterror(req, map_nt_error_from_unix(errno));
1549 goto out;
1553 ft.mtime = convert_time_t_to_timespec(mtime);
1554 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 reply_nterror(req, status);
1557 goto out;
1560 reply_outbuf(req, 0, 0);
1562 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1563 mode));
1564 out:
1565 TALLOC_FREE(smb_fname);
1566 END_PROFILE(SMBsetatr);
1567 return;
1570 /****************************************************************************
1571 Reply to a dskattr.
1572 ****************************************************************************/
1574 void reply_dskattr(struct smb_request *req)
1576 connection_struct *conn = req->conn;
1577 uint64_t ret;
1578 uint64_t dfree,dsize,bsize;
1579 struct smb_filename smb_fname;
1580 START_PROFILE(SMBdskattr);
1582 ZERO_STRUCT(smb_fname);
1583 smb_fname.base_name = discard_const_p(char, ".");
1585 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1586 reply_nterror(req, map_nt_error_from_unix(errno));
1587 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1588 END_PROFILE(SMBdskattr);
1589 return;
1592 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1593 if (ret == (uint64_t)-1) {
1594 reply_nterror(req, map_nt_error_from_unix(errno));
1595 END_PROFILE(SMBdskattr);
1596 return;
1600 * Force max to fit in 16 bit fields.
1602 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1603 dfree /= 2;
1604 dsize /= 2;
1605 bsize *= 2;
1606 if (bsize > (WORDMAX*512)) {
1607 bsize = (WORDMAX*512);
1608 if (dsize > WORDMAX)
1609 dsize = WORDMAX;
1610 if (dfree > WORDMAX)
1611 dfree = WORDMAX;
1612 break;
1616 reply_outbuf(req, 5, 0);
1618 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1619 double total_space, free_space;
1620 /* we need to scale this to a number that DOS6 can handle. We
1621 use floating point so we can handle large drives on systems
1622 that don't have 64 bit integers
1624 we end up displaying a maximum of 2G to DOS systems
1626 total_space = dsize * (double)bsize;
1627 free_space = dfree * (double)bsize;
1629 dsize = (uint64_t)((total_space+63*512) / (64*512));
1630 dfree = (uint64_t)((free_space+63*512) / (64*512));
1632 if (dsize > 0xFFFF) dsize = 0xFFFF;
1633 if (dfree > 0xFFFF) dfree = 0xFFFF;
1635 SSVAL(req->outbuf,smb_vwv0,dsize);
1636 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1637 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1638 SSVAL(req->outbuf,smb_vwv3,dfree);
1639 } else {
1640 SSVAL(req->outbuf,smb_vwv0,dsize);
1641 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1642 SSVAL(req->outbuf,smb_vwv2,512);
1643 SSVAL(req->outbuf,smb_vwv3,dfree);
1646 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1648 END_PROFILE(SMBdskattr);
1649 return;
1653 * Utility function to split the filename from the directory.
1655 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1656 char **fname_dir_out,
1657 char **fname_mask_out)
1659 const char *p = NULL;
1660 char *fname_dir = NULL;
1661 char *fname_mask = NULL;
1663 p = strrchr_m(fname_in, '/');
1664 if (!p) {
1665 fname_dir = talloc_strdup(ctx, ".");
1666 fname_mask = talloc_strdup(ctx, fname_in);
1667 } else {
1668 fname_dir = talloc_strndup(ctx, fname_in,
1669 PTR_DIFF(p, fname_in));
1670 fname_mask = talloc_strdup(ctx, p+1);
1673 if (!fname_dir || !fname_mask) {
1674 TALLOC_FREE(fname_dir);
1675 TALLOC_FREE(fname_mask);
1676 return NT_STATUS_NO_MEMORY;
1679 *fname_dir_out = fname_dir;
1680 *fname_mask_out = fname_mask;
1681 return NT_STATUS_OK;
1684 /****************************************************************************
1685 Make a dir struct.
1686 ****************************************************************************/
1688 static bool make_dir_struct(TALLOC_CTX *ctx,
1689 char *buf,
1690 const char *mask,
1691 const char *fname,
1692 off_t size,
1693 uint32_t mode,
1694 time_t date,
1695 bool uc)
1697 char *p;
1698 char *mask2 = talloc_strdup(ctx, mask);
1700 if (!mask2) {
1701 return False;
1704 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1705 size = 0;
1708 memset(buf+1,' ',11);
1709 if ((p = strchr_m(mask2,'.')) != NULL) {
1710 *p = 0;
1711 push_ascii(buf+1,mask2,8, 0);
1712 push_ascii(buf+9,p+1,3, 0);
1713 *p = '.';
1714 } else {
1715 push_ascii(buf+1,mask2,11, 0);
1718 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1719 SCVAL(buf,21,mode);
1720 srv_put_dos_date(buf,22,date);
1721 SSVAL(buf,26,size & 0xFFFF);
1722 SSVAL(buf,28,(size >> 16)&0xFFFF);
1723 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1724 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1725 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1726 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1727 return True;
1730 /****************************************************************************
1731 Reply to a search.
1732 Can be called from SMBsearch, SMBffirst or SMBfunique.
1733 ****************************************************************************/
1735 void reply_search(struct smb_request *req)
1737 connection_struct *conn = req->conn;
1738 char *path = NULL;
1739 char *mask = NULL;
1740 char *directory = NULL;
1741 struct smb_filename *smb_fname = NULL;
1742 char *fname = NULL;
1743 off_t size;
1744 uint32_t mode;
1745 struct timespec date;
1746 uint32_t dirtype;
1747 unsigned int numentries = 0;
1748 unsigned int maxentries = 0;
1749 bool finished = False;
1750 const char *p;
1751 int status_len;
1752 char status[21];
1753 int dptr_num= -1;
1754 bool check_descend = False;
1755 bool expect_close = False;
1756 NTSTATUS nt_status;
1757 bool mask_contains_wcard = False;
1758 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1759 TALLOC_CTX *ctx = talloc_tos();
1760 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1761 struct dptr_struct *dirptr = NULL;
1762 struct smbXsrv_connection *xconn = req->xconn;
1763 struct smbd_server_connection *sconn = req->sconn;
1765 START_PROFILE(SMBsearch);
1767 if (req->wct < 2) {
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1769 goto out;
1772 if (req->posix_pathnames) {
1773 reply_unknown_new(req, req->cmd);
1774 goto out;
1777 /* If we were called as SMBffirst then we must expect close. */
1778 if(req->cmd == SMBffirst) {
1779 expect_close = True;
1782 reply_outbuf(req, 1, 3);
1783 maxentries = SVAL(req->vwv+0, 0);
1784 dirtype = SVAL(req->vwv+1, 0);
1785 p = (const char *)req->buf + 1;
1786 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1787 &nt_status, &mask_contains_wcard);
1788 if (!NT_STATUS_IS_OK(nt_status)) {
1789 reply_nterror(req, nt_status);
1790 goto out;
1793 p++;
1794 status_len = SVAL(p, 0);
1795 p += 2;
1797 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1799 if (status_len == 0) {
1800 struct smb_filename *smb_dname = NULL;
1801 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1802 ucf_flags_from_smb_request(req);
1803 nt_status = filename_convert(ctx, conn,
1804 path,
1805 ucf_flags,
1806 &mask_contains_wcard,
1807 &smb_fname);
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1810 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1811 ERRSRV, ERRbadpath);
1812 goto out;
1814 reply_nterror(req, nt_status);
1815 goto out;
1818 directory = smb_fname->base_name;
1820 p = strrchr_m(directory,'/');
1821 if ((p != NULL) && (*directory != '/')) {
1822 mask = talloc_strdup(ctx, p + 1);
1823 directory = talloc_strndup(ctx, directory,
1824 PTR_DIFF(p, directory));
1825 } else {
1826 mask = talloc_strdup(ctx, directory);
1827 directory = talloc_strdup(ctx,".");
1830 if (!directory) {
1831 reply_nterror(req, NT_STATUS_NO_MEMORY);
1832 goto out;
1835 memset((char *)status,'\0',21);
1836 SCVAL(status,0,(dirtype & 0x1F));
1838 smb_dname = synthetic_smb_fname(talloc_tos(),
1839 directory,
1840 NULL,
1841 NULL,
1842 smb_fname->flags);
1843 if (smb_dname == NULL) {
1844 reply_nterror(req, NT_STATUS_NO_MEMORY);
1845 goto out;
1848 nt_status = dptr_create(conn,
1849 NULL, /* req */
1850 NULL, /* fsp */
1851 smb_dname,
1852 True,
1853 expect_close,
1854 req->smbpid,
1855 mask,
1856 mask_contains_wcard,
1857 dirtype,
1858 &dirptr);
1860 TALLOC_FREE(smb_dname);
1862 if (!NT_STATUS_IS_OK(nt_status)) {
1863 reply_nterror(req, nt_status);
1864 goto out;
1866 dptr_num = dptr_dnum(dirptr);
1867 } else {
1868 int status_dirtype;
1869 const char *dirpath;
1871 memcpy(status,p,21);
1872 status_dirtype = CVAL(status,0) & 0x1F;
1873 if (status_dirtype != (dirtype & 0x1F)) {
1874 dirtype = status_dirtype;
1877 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1878 if (!dirptr) {
1879 goto SearchEmpty;
1881 dirpath = dptr_path(sconn, dptr_num);
1882 directory = talloc_strdup(ctx, dirpath);
1883 if (!directory) {
1884 reply_nterror(req, NT_STATUS_NO_MEMORY);
1885 goto out;
1888 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1889 if (!mask) {
1890 goto SearchEmpty;
1893 * For a 'continue' search we have no string. So
1894 * check from the initial saved string.
1896 if (!req->posix_pathnames) {
1897 mask_contains_wcard = ms_has_wild(mask);
1899 dirtype = dptr_attr(sconn, dptr_num);
1902 DEBUG(4,("dptr_num is %d\n",dptr_num));
1904 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1905 char buf[DIR_STRUCT_SIZE];
1906 memcpy(buf,status,21);
1907 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1908 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1909 reply_nterror(req, NT_STATUS_NO_MEMORY);
1910 goto out;
1912 dptr_fill(sconn, buf+12,dptr_num);
1913 if (dptr_zero(buf+12) && (status_len==0)) {
1914 numentries = 1;
1915 } else {
1916 numentries = 0;
1918 if (message_push_blob(&req->outbuf,
1919 data_blob_const(buf, sizeof(buf)))
1920 == -1) {
1921 reply_nterror(req, NT_STATUS_NO_MEMORY);
1922 goto out;
1924 } else {
1925 unsigned int i;
1926 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1927 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1929 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1931 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1932 directory,lp_dont_descend(ctx, SNUM(conn))));
1933 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1934 check_descend = True;
1937 for (i=numentries;(i<maxentries) && !finished;i++) {
1938 finished = !get_dir_entry(ctx,
1939 dirptr,
1940 mask,
1941 dirtype,
1942 &fname,
1943 &size,
1944 &mode,
1945 &date,
1946 check_descend,
1947 ask_sharemode);
1948 if (!finished) {
1949 char buf[DIR_STRUCT_SIZE];
1950 memcpy(buf,status,21);
1951 if (!make_dir_struct(ctx,
1952 buf,
1953 mask,
1954 fname,
1955 size,
1956 mode,
1957 convert_timespec_to_time_t(date),
1958 !allow_long_path_components)) {
1959 reply_nterror(req, NT_STATUS_NO_MEMORY);
1960 goto out;
1962 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1963 break;
1965 if (message_push_blob(&req->outbuf,
1966 data_blob_const(buf, sizeof(buf)))
1967 == -1) {
1968 reply_nterror(req, NT_STATUS_NO_MEMORY);
1969 goto out;
1971 numentries++;
1976 SearchEmpty:
1978 /* If we were called as SMBffirst with smb_search_id == NULL
1979 and no entries were found then return error and close dirptr
1980 (X/Open spec) */
1982 if (numentries == 0) {
1983 dptr_close(sconn, &dptr_num);
1984 } else if(expect_close && status_len == 0) {
1985 /* Close the dptr - we know it's gone */
1986 dptr_close(sconn, &dptr_num);
1989 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1990 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1991 dptr_close(sconn, &dptr_num);
1994 if ((numentries == 0) && !mask_contains_wcard) {
1995 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1996 goto out;
1999 SSVAL(req->outbuf,smb_vwv0,numentries);
2000 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2001 SCVAL(smb_buf(req->outbuf),0,5);
2002 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2004 /* The replies here are never long name. */
2005 SSVAL(req->outbuf, smb_flg2,
2006 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2007 if (!allow_long_path_components) {
2008 SSVAL(req->outbuf, smb_flg2,
2009 SVAL(req->outbuf, smb_flg2)
2010 & (~FLAGS2_LONG_PATH_COMPONENTS));
2013 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2014 SSVAL(req->outbuf, smb_flg2,
2015 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2017 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2018 smb_fn_name(req->cmd),
2019 mask,
2020 directory,
2021 dirtype,
2022 numentries,
2023 maxentries ));
2024 out:
2025 TALLOC_FREE(directory);
2026 TALLOC_FREE(mask);
2027 TALLOC_FREE(smb_fname);
2028 END_PROFILE(SMBsearch);
2029 return;
2032 /****************************************************************************
2033 Reply to a fclose (stop directory search).
2034 ****************************************************************************/
2036 void reply_fclose(struct smb_request *req)
2038 int status_len;
2039 char status[21];
2040 int dptr_num= -2;
2041 const char *p;
2042 char *path = NULL;
2043 NTSTATUS err;
2044 bool path_contains_wcard = False;
2045 TALLOC_CTX *ctx = talloc_tos();
2046 struct smbd_server_connection *sconn = req->sconn;
2048 START_PROFILE(SMBfclose);
2050 if (req->posix_pathnames) {
2051 reply_unknown_new(req, req->cmd);
2052 END_PROFILE(SMBfclose);
2053 return;
2056 p = (const char *)req->buf + 1;
2057 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2058 &err, &path_contains_wcard);
2059 if (!NT_STATUS_IS_OK(err)) {
2060 reply_nterror(req, err);
2061 END_PROFILE(SMBfclose);
2062 return;
2064 p++;
2065 status_len = SVAL(p,0);
2066 p += 2;
2068 if (status_len == 0) {
2069 reply_force_doserror(req, ERRSRV, ERRsrverror);
2070 END_PROFILE(SMBfclose);
2071 return;
2074 memcpy(status,p,21);
2076 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2077 /* Close the dptr - we know it's gone */
2078 dptr_close(sconn, &dptr_num);
2081 reply_outbuf(req, 1, 0);
2082 SSVAL(req->outbuf,smb_vwv0,0);
2084 DEBUG(3,("search close\n"));
2086 END_PROFILE(SMBfclose);
2087 return;
2090 /****************************************************************************
2091 Reply to an open.
2092 ****************************************************************************/
2094 void reply_open(struct smb_request *req)
2096 connection_struct *conn = req->conn;
2097 struct smb_filename *smb_fname = NULL;
2098 char *fname = NULL;
2099 uint32_t fattr=0;
2100 off_t size = 0;
2101 time_t mtime=0;
2102 int info;
2103 files_struct *fsp;
2104 int oplock_request;
2105 int deny_mode;
2106 uint32_t dos_attr;
2107 uint32_t access_mask;
2108 uint32_t share_mode;
2109 uint32_t create_disposition;
2110 uint32_t create_options = 0;
2111 uint32_t private_flags = 0;
2112 NTSTATUS status;
2113 uint32_t ucf_flags;
2114 TALLOC_CTX *ctx = talloc_tos();
2116 START_PROFILE(SMBopen);
2118 if (req->wct < 2) {
2119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2120 goto out;
2123 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2124 deny_mode = SVAL(req->vwv+0, 0);
2125 dos_attr = SVAL(req->vwv+1, 0);
2127 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2128 STR_TERMINATE, &status);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 reply_nterror(req, status);
2131 goto out;
2134 if (!map_open_params_to_ntcreate(fname, deny_mode,
2135 OPENX_FILE_EXISTS_OPEN, &access_mask,
2136 &share_mode, &create_disposition,
2137 &create_options, &private_flags)) {
2138 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2139 goto out;
2142 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2144 status = filename_convert(ctx,
2145 conn,
2146 fname,
2147 ucf_flags,
2148 NULL,
2149 &smb_fname);
2150 if (!NT_STATUS_IS_OK(status)) {
2151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2152 reply_botherror(req,
2153 NT_STATUS_PATH_NOT_COVERED,
2154 ERRSRV, ERRbadpath);
2155 goto out;
2157 reply_nterror(req, status);
2158 goto out;
2161 status = SMB_VFS_CREATE_FILE(
2162 conn, /* conn */
2163 req, /* req */
2164 0, /* root_dir_fid */
2165 smb_fname, /* fname */
2166 access_mask, /* access_mask */
2167 share_mode, /* share_access */
2168 create_disposition, /* create_disposition*/
2169 create_options, /* create_options */
2170 dos_attr, /* file_attributes */
2171 oplock_request, /* oplock_request */
2172 NULL, /* lease */
2173 0, /* allocation_size */
2174 private_flags,
2175 NULL, /* sd */
2176 NULL, /* ea_list */
2177 &fsp, /* result */
2178 &info, /* pinfo */
2179 NULL, NULL); /* create context */
2181 if (!NT_STATUS_IS_OK(status)) {
2182 if (open_was_deferred(req->xconn, req->mid)) {
2183 /* We have re-scheduled this call. */
2184 goto out;
2186 reply_openerror(req, status);
2187 goto out;
2190 /* Ensure we're pointing at the correct stat struct. */
2191 TALLOC_FREE(smb_fname);
2192 smb_fname = fsp->fsp_name;
2194 size = smb_fname->st.st_ex_size;
2195 fattr = dos_mode(conn, smb_fname);
2197 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2199 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2200 DEBUG(3,("attempt to open a directory %s\n",
2201 fsp_str_dbg(fsp)));
2202 close_file(req, fsp, ERROR_CLOSE);
2203 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2204 ERRDOS, ERRnoaccess);
2205 goto out;
2208 reply_outbuf(req, 7, 0);
2209 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2210 SSVAL(req->outbuf,smb_vwv1,fattr);
2211 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2212 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2213 } else {
2214 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2216 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2217 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2219 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2220 SCVAL(req->outbuf,smb_flg,
2221 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2224 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2225 SCVAL(req->outbuf,smb_flg,
2226 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 out:
2229 END_PROFILE(SMBopen);
2230 return;
2233 /****************************************************************************
2234 Reply to an open and X.
2235 ****************************************************************************/
2237 void reply_open_and_X(struct smb_request *req)
2239 connection_struct *conn = req->conn;
2240 struct smb_filename *smb_fname = NULL;
2241 char *fname = NULL;
2242 uint16_t open_flags;
2243 int deny_mode;
2244 uint32_t smb_attr;
2245 /* Breakout the oplock request bits so we can set the
2246 reply bits separately. */
2247 int ex_oplock_request;
2248 int core_oplock_request;
2249 int oplock_request;
2250 #if 0
2251 int smb_sattr = SVAL(req->vwv+4, 0);
2252 uint32_t smb_time = make_unix_date3(req->vwv+6);
2253 #endif
2254 int smb_ofun;
2255 uint32_t fattr=0;
2256 int mtime=0;
2257 int smb_action = 0;
2258 files_struct *fsp;
2259 NTSTATUS status;
2260 uint64_t allocation_size;
2261 ssize_t retval = -1;
2262 uint32_t access_mask;
2263 uint32_t share_mode;
2264 uint32_t create_disposition;
2265 uint32_t create_options = 0;
2266 uint32_t private_flags = 0;
2267 uint32_t ucf_flags;
2268 TALLOC_CTX *ctx = talloc_tos();
2270 START_PROFILE(SMBopenX);
2272 if (req->wct < 15) {
2273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2274 goto out;
2277 open_flags = SVAL(req->vwv+2, 0);
2278 deny_mode = SVAL(req->vwv+3, 0);
2279 smb_attr = SVAL(req->vwv+5, 0);
2280 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2281 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2282 oplock_request = ex_oplock_request | core_oplock_request;
2283 smb_ofun = SVAL(req->vwv+8, 0);
2284 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2286 /* If it's an IPC, pass off the pipe handler. */
2287 if (IS_IPC(conn)) {
2288 if (lp_nt_pipe_support()) {
2289 reply_open_pipe_and_X(conn, req);
2290 } else {
2291 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2293 goto out;
2296 /* XXXX we need to handle passed times, sattr and flags */
2297 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2298 STR_TERMINATE, &status);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 reply_nterror(req, status);
2301 goto out;
2304 if (!map_open_params_to_ntcreate(fname, deny_mode,
2305 smb_ofun,
2306 &access_mask, &share_mode,
2307 &create_disposition,
2308 &create_options,
2309 &private_flags)) {
2310 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2311 goto out;
2314 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2316 status = filename_convert(ctx,
2317 conn,
2318 fname,
2319 ucf_flags,
2320 NULL,
2321 &smb_fname);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2324 reply_botherror(req,
2325 NT_STATUS_PATH_NOT_COVERED,
2326 ERRSRV, ERRbadpath);
2327 goto out;
2329 reply_nterror(req, status);
2330 goto out;
2333 status = SMB_VFS_CREATE_FILE(
2334 conn, /* conn */
2335 req, /* req */
2336 0, /* root_dir_fid */
2337 smb_fname, /* fname */
2338 access_mask, /* access_mask */
2339 share_mode, /* share_access */
2340 create_disposition, /* create_disposition*/
2341 create_options, /* create_options */
2342 smb_attr, /* file_attributes */
2343 oplock_request, /* oplock_request */
2344 NULL, /* lease */
2345 0, /* allocation_size */
2346 private_flags,
2347 NULL, /* sd */
2348 NULL, /* ea_list */
2349 &fsp, /* result */
2350 &smb_action, /* pinfo */
2351 NULL, NULL); /* create context */
2353 if (!NT_STATUS_IS_OK(status)) {
2354 if (open_was_deferred(req->xconn, req->mid)) {
2355 /* We have re-scheduled this call. */
2356 goto out;
2358 reply_openerror(req, status);
2359 goto out;
2362 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2363 if the file is truncated or created. */
2364 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2365 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2366 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2367 close_file(req, fsp, ERROR_CLOSE);
2368 reply_nterror(req, NT_STATUS_DISK_FULL);
2369 goto out;
2371 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2372 if (retval < 0) {
2373 close_file(req, fsp, ERROR_CLOSE);
2374 reply_nterror(req, NT_STATUS_DISK_FULL);
2375 goto out;
2377 status = vfs_stat_fsp(fsp);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 close_file(req, fsp, ERROR_CLOSE);
2380 reply_nterror(req, status);
2381 goto out;
2385 fattr = dos_mode(conn, fsp->fsp_name);
2386 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2387 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2388 close_file(req, fsp, ERROR_CLOSE);
2389 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2390 goto out;
2393 /* If the caller set the extended oplock request bit
2394 and we granted one (by whatever means) - set the
2395 correct bit for extended oplock reply.
2398 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2399 smb_action |= EXTENDED_OPLOCK_GRANTED;
2402 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2403 smb_action |= EXTENDED_OPLOCK_GRANTED;
2406 /* If the caller set the core oplock request bit
2407 and we granted one (by whatever means) - set the
2408 correct bit for core oplock reply.
2411 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2412 reply_outbuf(req, 19, 0);
2413 } else {
2414 reply_outbuf(req, 15, 0);
2417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2420 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2421 SCVAL(req->outbuf, smb_flg,
2422 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2425 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2426 SCVAL(req->outbuf, smb_flg,
2427 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2430 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2431 SSVAL(req->outbuf,smb_vwv3,fattr);
2432 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2433 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2434 } else {
2435 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2437 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2438 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2439 SSVAL(req->outbuf,smb_vwv11,smb_action);
2441 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2442 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2445 out:
2446 TALLOC_FREE(smb_fname);
2447 END_PROFILE(SMBopenX);
2448 return;
2451 /****************************************************************************
2452 Reply to a SMBulogoffX.
2453 ****************************************************************************/
2455 void reply_ulogoffX(struct smb_request *req)
2457 struct smbd_server_connection *sconn = req->sconn;
2458 struct user_struct *vuser;
2459 struct smbXsrv_session *session = NULL;
2460 NTSTATUS status;
2462 START_PROFILE(SMBulogoffX);
2464 vuser = get_valid_user_struct(sconn, req->vuid);
2466 if(vuser == NULL) {
2467 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2468 (unsigned long long)req->vuid));
2470 req->vuid = UID_FIELD_INVALID;
2471 reply_force_doserror(req, ERRSRV, ERRbaduid);
2472 END_PROFILE(SMBulogoffX);
2473 return;
2476 session = vuser->session;
2477 vuser = NULL;
2480 * TODO: cancel all outstanding requests on the session
2482 status = smbXsrv_session_logoff(session);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 DEBUG(0, ("reply_ulogoff: "
2485 "smbXsrv_session_logoff() failed: %s\n",
2486 nt_errstr(status)));
2488 * If we hit this case, there is something completely
2489 * wrong, so we better disconnect the transport connection.
2491 END_PROFILE(SMBulogoffX);
2492 exit_server(__location__ ": smbXsrv_session_logoff failed");
2493 return;
2496 TALLOC_FREE(session);
2498 reply_outbuf(req, 2, 0);
2499 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2500 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2502 DEBUG(3, ("ulogoffX vuid=%llu\n",
2503 (unsigned long long)req->vuid));
2505 END_PROFILE(SMBulogoffX);
2506 req->vuid = UID_FIELD_INVALID;
2509 /****************************************************************************
2510 Reply to a mknew or a create.
2511 ****************************************************************************/
2513 void reply_mknew(struct smb_request *req)
2515 connection_struct *conn = req->conn;
2516 struct smb_filename *smb_fname = NULL;
2517 char *fname = NULL;
2518 uint32_t fattr = 0;
2519 struct smb_file_time ft;
2520 files_struct *fsp;
2521 int oplock_request = 0;
2522 NTSTATUS status;
2523 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2524 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2525 uint32_t create_disposition;
2526 uint32_t create_options = 0;
2527 uint32_t ucf_flags;
2528 TALLOC_CTX *ctx = talloc_tos();
2530 START_PROFILE(SMBcreate);
2531 ZERO_STRUCT(ft);
2533 if (req->wct < 3) {
2534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2535 goto out;
2538 fattr = SVAL(req->vwv+0, 0);
2539 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2541 if (req->cmd == SMBmknew) {
2542 /* We should fail if file exists. */
2543 create_disposition = FILE_CREATE;
2544 } else {
2545 /* Create if file doesn't exist, truncate if it does. */
2546 create_disposition = FILE_OVERWRITE_IF;
2549 /* mtime. */
2550 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2552 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2553 STR_TERMINATE, &status);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 reply_nterror(req, status);
2556 goto out;
2559 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2560 status = filename_convert(ctx,
2561 conn,
2562 fname,
2563 ucf_flags,
2564 NULL,
2565 &smb_fname);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2568 reply_botherror(req,
2569 NT_STATUS_PATH_NOT_COVERED,
2570 ERRSRV, ERRbadpath);
2571 goto out;
2573 reply_nterror(req, status);
2574 goto out;
2577 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2578 DEBUG(0,("Attempt to create file (%s) with volid set - "
2579 "please report this\n",
2580 smb_fname_str_dbg(smb_fname)));
2583 status = SMB_VFS_CREATE_FILE(
2584 conn, /* conn */
2585 req, /* req */
2586 0, /* root_dir_fid */
2587 smb_fname, /* fname */
2588 access_mask, /* access_mask */
2589 share_mode, /* share_access */
2590 create_disposition, /* create_disposition*/
2591 create_options, /* create_options */
2592 fattr, /* file_attributes */
2593 oplock_request, /* oplock_request */
2594 NULL, /* lease */
2595 0, /* allocation_size */
2596 0, /* private_flags */
2597 NULL, /* sd */
2598 NULL, /* ea_list */
2599 &fsp, /* result */
2600 NULL, /* pinfo */
2601 NULL, NULL); /* create context */
2603 if (!NT_STATUS_IS_OK(status)) {
2604 if (open_was_deferred(req->xconn, req->mid)) {
2605 /* We have re-scheduled this call. */
2606 goto out;
2608 reply_openerror(req, status);
2609 goto out;
2612 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2613 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 END_PROFILE(SMBcreate);
2616 goto out;
2619 reply_outbuf(req, 1, 0);
2620 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2622 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2623 SCVAL(req->outbuf,smb_flg,
2624 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2627 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2628 SCVAL(req->outbuf,smb_flg,
2629 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2632 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2633 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2634 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2635 (unsigned int)fattr));
2637 out:
2638 TALLOC_FREE(smb_fname);
2639 END_PROFILE(SMBcreate);
2640 return;
2643 /****************************************************************************
2644 Reply to a create temporary file.
2645 ****************************************************************************/
2647 void reply_ctemp(struct smb_request *req)
2649 connection_struct *conn = req->conn;
2650 struct smb_filename *smb_fname = NULL;
2651 char *wire_name = NULL;
2652 char *fname = NULL;
2653 uint32_t fattr;
2654 files_struct *fsp;
2655 int oplock_request;
2656 char *s;
2657 NTSTATUS status;
2658 int i;
2659 uint32_t ucf_flags;
2660 TALLOC_CTX *ctx = talloc_tos();
2662 START_PROFILE(SMBctemp);
2664 if (req->wct < 3) {
2665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2666 goto out;
2669 fattr = SVAL(req->vwv+0, 0);
2670 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2672 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2673 STR_TERMINATE, &status);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 reply_nterror(req, status);
2676 goto out;
2679 for (i = 0; i < 10; i++) {
2680 if (*wire_name) {
2681 fname = talloc_asprintf(ctx,
2682 "%s/TMP%s",
2683 wire_name,
2684 generate_random_str_list(ctx, 5, "0123456789"));
2685 } else {
2686 fname = talloc_asprintf(ctx,
2687 "TMP%s",
2688 generate_random_str_list(ctx, 5, "0123456789"));
2691 if (!fname) {
2692 reply_nterror(req, NT_STATUS_NO_MEMORY);
2693 goto out;
2696 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2697 status = filename_convert(ctx, conn,
2698 fname,
2699 ucf_flags,
2700 NULL,
2701 &smb_fname);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2704 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2705 ERRSRV, ERRbadpath);
2706 goto out;
2708 reply_nterror(req, status);
2709 goto out;
2712 /* Create the file. */
2713 status = SMB_VFS_CREATE_FILE(
2714 conn, /* conn */
2715 req, /* req */
2716 0, /* root_dir_fid */
2717 smb_fname, /* fname */
2718 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2719 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2720 FILE_CREATE, /* create_disposition*/
2721 0, /* create_options */
2722 fattr, /* file_attributes */
2723 oplock_request, /* oplock_request */
2724 NULL, /* lease */
2725 0, /* allocation_size */
2726 0, /* private_flags */
2727 NULL, /* sd */
2728 NULL, /* ea_list */
2729 &fsp, /* result */
2730 NULL, /* pinfo */
2731 NULL, NULL); /* create context */
2733 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2734 TALLOC_FREE(fname);
2735 TALLOC_FREE(smb_fname);
2736 continue;
2739 if (!NT_STATUS_IS_OK(status)) {
2740 if (open_was_deferred(req->xconn, req->mid)) {
2741 /* We have re-scheduled this call. */
2742 goto out;
2744 reply_openerror(req, status);
2745 goto out;
2748 break;
2751 if (i == 10) {
2752 /* Collision after 10 times... */
2753 reply_nterror(req, status);
2754 goto out;
2757 reply_outbuf(req, 1, 0);
2758 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2760 /* the returned filename is relative to the directory */
2761 s = strrchr_m(fsp->fsp_name->base_name, '/');
2762 if (!s) {
2763 s = fsp->fsp_name->base_name;
2764 } else {
2765 s++;
2768 #if 0
2769 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2770 thing in the byte section. JRA */
2771 SSVALS(p, 0, -1); /* what is this? not in spec */
2772 #endif
2773 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2774 == -1) {
2775 reply_nterror(req, NT_STATUS_NO_MEMORY);
2776 goto out;
2779 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2780 SCVAL(req->outbuf, smb_flg,
2781 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2784 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2785 SCVAL(req->outbuf, smb_flg,
2786 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2789 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2790 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2791 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2792 out:
2793 TALLOC_FREE(smb_fname);
2794 TALLOC_FREE(wire_name);
2795 END_PROFILE(SMBctemp);
2796 return;
2799 /*******************************************************************
2800 Check if a user is allowed to rename a file.
2801 ********************************************************************/
2803 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2804 uint16_t dirtype)
2806 if (!CAN_WRITE(conn)) {
2807 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2810 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2811 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2812 /* Only bother to read the DOS attribute if we might deny the
2813 rename on the grounds of attribute mismatch. */
2814 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2815 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2816 return NT_STATUS_NO_SUCH_FILE;
2820 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2821 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2822 return NT_STATUS_OK;
2825 /* If no pathnames are open below this
2826 directory, allow the rename. */
2828 if (lp_strict_rename(SNUM(conn))) {
2830 * Strict rename, check open file db.
2832 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2833 return NT_STATUS_ACCESS_DENIED;
2835 } else if (file_find_subpath(fsp)) {
2837 * No strict rename, just look in local process.
2839 return NT_STATUS_ACCESS_DENIED;
2841 return NT_STATUS_OK;
2844 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2845 return NT_STATUS_OK;
2848 return NT_STATUS_ACCESS_DENIED;
2851 /*******************************************************************
2852 * unlink a file with all relevant access checks
2853 *******************************************************************/
2855 static NTSTATUS do_unlink(connection_struct *conn,
2856 struct smb_request *req,
2857 struct smb_filename *smb_fname,
2858 uint32_t dirtype)
2860 uint32_t fattr;
2861 files_struct *fsp;
2862 uint32_t dirtype_orig = dirtype;
2863 NTSTATUS status;
2864 int ret;
2865 bool posix_paths = (req != NULL && req->posix_pathnames);
2867 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2868 smb_fname_str_dbg(smb_fname),
2869 dirtype));
2871 if (!CAN_WRITE(conn)) {
2872 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2875 if (posix_paths) {
2876 ret = SMB_VFS_LSTAT(conn, smb_fname);
2877 } else {
2878 ret = SMB_VFS_STAT(conn, smb_fname);
2880 if (ret != 0) {
2881 return map_nt_error_from_unix(errno);
2884 fattr = dos_mode(conn, smb_fname);
2886 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2887 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2890 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2891 if (!dirtype) {
2892 return NT_STATUS_NO_SUCH_FILE;
2895 if (!dir_check_ftype(fattr, dirtype)) {
2896 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2897 return NT_STATUS_FILE_IS_A_DIRECTORY;
2899 return NT_STATUS_NO_SUCH_FILE;
2902 if (dirtype_orig & 0x8000) {
2903 /* These will never be set for POSIX. */
2904 return NT_STATUS_NO_SUCH_FILE;
2907 #if 0
2908 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2909 return NT_STATUS_FILE_IS_A_DIRECTORY;
2912 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2913 return NT_STATUS_NO_SUCH_FILE;
2916 if (dirtype & 0xFF00) {
2917 /* These will never be set for POSIX. */
2918 return NT_STATUS_NO_SUCH_FILE;
2921 dirtype &= 0xFF;
2922 if (!dirtype) {
2923 return NT_STATUS_NO_SUCH_FILE;
2926 /* Can't delete a directory. */
2927 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2928 return NT_STATUS_FILE_IS_A_DIRECTORY;
2930 #endif
2932 #if 0 /* JRATEST */
2933 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2934 return NT_STATUS_OBJECT_NAME_INVALID;
2935 #endif /* JRATEST */
2937 /* On open checks the open itself will check the share mode, so
2938 don't do it here as we'll get it wrong. */
2940 status = SMB_VFS_CREATE_FILE
2941 (conn, /* conn */
2942 req, /* req */
2943 0, /* root_dir_fid */
2944 smb_fname, /* fname */
2945 DELETE_ACCESS, /* access_mask */
2946 FILE_SHARE_NONE, /* share_access */
2947 FILE_OPEN, /* create_disposition*/
2948 FILE_NON_DIRECTORY_FILE, /* create_options */
2949 /* file_attributes */
2950 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2951 FILE_ATTRIBUTE_NORMAL,
2952 0, /* oplock_request */
2953 NULL, /* lease */
2954 0, /* allocation_size */
2955 0, /* private_flags */
2956 NULL, /* sd */
2957 NULL, /* ea_list */
2958 &fsp, /* result */
2959 NULL, /* pinfo */
2960 NULL, NULL); /* create context */
2962 if (!NT_STATUS_IS_OK(status)) {
2963 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2964 nt_errstr(status)));
2965 return status;
2968 status = can_set_delete_on_close(fsp, fattr);
2969 if (!NT_STATUS_IS_OK(status)) {
2970 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2971 "(%s)\n",
2972 smb_fname_str_dbg(smb_fname),
2973 nt_errstr(status)));
2974 close_file(req, fsp, NORMAL_CLOSE);
2975 return status;
2978 /* The set is across all open files on this dev/inode pair. */
2979 if (!set_delete_on_close(fsp, True,
2980 conn->session_info->security_token,
2981 conn->session_info->unix_token)) {
2982 close_file(req, fsp, NORMAL_CLOSE);
2983 return NT_STATUS_ACCESS_DENIED;
2986 return close_file(req, fsp, NORMAL_CLOSE);
2989 /****************************************************************************
2990 The guts of the unlink command, split out so it may be called by the NT SMB
2991 code.
2992 ****************************************************************************/
2994 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2995 uint32_t dirtype, struct smb_filename *smb_fname,
2996 bool has_wild)
2998 char *fname_dir = NULL;
2999 char *fname_mask = NULL;
3000 int count=0;
3001 NTSTATUS status = NT_STATUS_OK;
3002 struct smb_filename *smb_fname_dir = NULL;
3003 TALLOC_CTX *ctx = talloc_tos();
3005 /* Split up the directory from the filename/mask. */
3006 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3007 &fname_dir, &fname_mask);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 goto out;
3013 * We should only check the mangled cache
3014 * here if unix_convert failed. This means
3015 * that the path in 'mask' doesn't exist
3016 * on the file system and so we need to look
3017 * for a possible mangle. This patch from
3018 * Tine Smukavec <valentin.smukavec@hermes.si>.
3021 if (!VALID_STAT(smb_fname->st) &&
3022 mangle_is_mangled(fname_mask, conn->params)) {
3023 char *new_mask = NULL;
3024 mangle_lookup_name_from_8_3(ctx, fname_mask,
3025 &new_mask, conn->params);
3026 if (new_mask) {
3027 TALLOC_FREE(fname_mask);
3028 fname_mask = new_mask;
3032 if (!has_wild) {
3035 * Only one file needs to be unlinked. Append the mask back
3036 * onto the directory.
3038 TALLOC_FREE(smb_fname->base_name);
3039 if (ISDOT(fname_dir)) {
3040 /* Ensure we use canonical names on open. */
3041 smb_fname->base_name = talloc_asprintf(smb_fname,
3042 "%s",
3043 fname_mask);
3044 } else {
3045 smb_fname->base_name = talloc_asprintf(smb_fname,
3046 "%s/%s",
3047 fname_dir,
3048 fname_mask);
3050 if (!smb_fname->base_name) {
3051 status = NT_STATUS_NO_MEMORY;
3052 goto out;
3054 if (dirtype == 0) {
3055 dirtype = FILE_ATTRIBUTE_NORMAL;
3058 status = check_name(conn, smb_fname);
3059 if (!NT_STATUS_IS_OK(status)) {
3060 goto out;
3063 status = do_unlink(conn, req, smb_fname, dirtype);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 goto out;
3068 count++;
3069 } else {
3070 struct smb_Dir *dir_hnd = NULL;
3071 long offset = 0;
3072 const char *dname = NULL;
3073 char *talloced = NULL;
3075 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3076 status = NT_STATUS_OBJECT_NAME_INVALID;
3077 goto out;
3079 if (dirtype == 0) {
3080 dirtype = FILE_ATTRIBUTE_NORMAL;
3083 if (strequal(fname_mask,"????????.???")) {
3084 TALLOC_FREE(fname_mask);
3085 fname_mask = talloc_strdup(ctx, "*");
3086 if (!fname_mask) {
3087 status = NT_STATUS_NO_MEMORY;
3088 goto out;
3092 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3093 fname_dir,
3094 NULL,
3095 NULL,
3096 smb_fname->flags);
3097 if (smb_fname_dir == NULL) {
3098 status = NT_STATUS_NO_MEMORY;
3099 goto out;
3102 status = check_name(conn, smb_fname_dir);
3103 if (!NT_STATUS_IS_OK(status)) {
3104 goto out;
3107 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3108 dirtype);
3109 if (dir_hnd == NULL) {
3110 status = map_nt_error_from_unix(errno);
3111 goto out;
3114 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3115 the pattern matches against the long name, otherwise the short name
3116 We don't implement this yet XXXX
3119 status = NT_STATUS_NO_SUCH_FILE;
3121 while ((dname = ReadDirName(dir_hnd, &offset,
3122 &smb_fname->st, &talloced))) {
3123 TALLOC_CTX *frame = talloc_stackframe();
3125 if (!is_visible_file(conn, fname_dir, dname,
3126 &smb_fname->st, true)) {
3127 TALLOC_FREE(frame);
3128 TALLOC_FREE(talloced);
3129 continue;
3132 /* Quick check for "." and ".." */
3133 if (ISDOT(dname) || ISDOTDOT(dname)) {
3134 TALLOC_FREE(frame);
3135 TALLOC_FREE(talloced);
3136 continue;
3139 if(!mask_match(dname, fname_mask,
3140 conn->case_sensitive)) {
3141 TALLOC_FREE(frame);
3142 TALLOC_FREE(talloced);
3143 continue;
3146 TALLOC_FREE(smb_fname->base_name);
3147 if (ISDOT(fname_dir)) {
3148 /* Ensure we use canonical names on open. */
3149 smb_fname->base_name =
3150 talloc_asprintf(smb_fname, "%s",
3151 dname);
3152 } else {
3153 smb_fname->base_name =
3154 talloc_asprintf(smb_fname, "%s/%s",
3155 fname_dir, dname);
3158 if (!smb_fname->base_name) {
3159 TALLOC_FREE(dir_hnd);
3160 status = NT_STATUS_NO_MEMORY;
3161 TALLOC_FREE(frame);
3162 TALLOC_FREE(talloced);
3163 goto out;
3166 status = check_name(conn, smb_fname);
3167 if (!NT_STATUS_IS_OK(status)) {
3168 TALLOC_FREE(dir_hnd);
3169 TALLOC_FREE(frame);
3170 TALLOC_FREE(talloced);
3171 goto out;
3174 status = do_unlink(conn, req, smb_fname, dirtype);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 TALLOC_FREE(dir_hnd);
3177 TALLOC_FREE(frame);
3178 TALLOC_FREE(talloced);
3179 goto out;
3182 count++;
3183 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3184 smb_fname->base_name));
3186 TALLOC_FREE(frame);
3187 TALLOC_FREE(talloced);
3189 TALLOC_FREE(dir_hnd);
3192 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3193 status = map_nt_error_from_unix(errno);
3196 out:
3197 TALLOC_FREE(smb_fname_dir);
3198 TALLOC_FREE(fname_dir);
3199 TALLOC_FREE(fname_mask);
3200 return status;
3203 /****************************************************************************
3204 Reply to a unlink
3205 ****************************************************************************/
3207 void reply_unlink(struct smb_request *req)
3209 connection_struct *conn = req->conn;
3210 char *name = NULL;
3211 struct smb_filename *smb_fname = NULL;
3212 uint32_t dirtype;
3213 NTSTATUS status;
3214 bool path_contains_wcard = False;
3215 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3216 ucf_flags_from_smb_request(req);
3217 TALLOC_CTX *ctx = talloc_tos();
3219 START_PROFILE(SMBunlink);
3221 if (req->wct < 1) {
3222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3223 goto out;
3226 dirtype = SVAL(req->vwv+0, 0);
3228 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3229 STR_TERMINATE, &status,
3230 &path_contains_wcard);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 reply_nterror(req, status);
3233 goto out;
3236 status = filename_convert(ctx, conn,
3237 name,
3238 ucf_flags,
3239 &path_contains_wcard,
3240 &smb_fname);
3241 if (!NT_STATUS_IS_OK(status)) {
3242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3244 ERRSRV, ERRbadpath);
3245 goto out;
3247 reply_nterror(req, status);
3248 goto out;
3251 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3253 status = unlink_internals(conn, req, dirtype, smb_fname,
3254 path_contains_wcard);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 if (open_was_deferred(req->xconn, req->mid)) {
3257 /* We have re-scheduled this call. */
3258 goto out;
3260 reply_nterror(req, status);
3261 goto out;
3264 reply_outbuf(req, 0, 0);
3265 out:
3266 TALLOC_FREE(smb_fname);
3267 END_PROFILE(SMBunlink);
3268 return;
3271 /****************************************************************************
3272 Fail for readbraw.
3273 ****************************************************************************/
3275 static void fail_readraw(void)
3277 const char *errstr = talloc_asprintf(talloc_tos(),
3278 "FAIL ! reply_readbraw: socket write fail (%s)",
3279 strerror(errno));
3280 if (!errstr) {
3281 errstr = "";
3283 exit_server_cleanly(errstr);
3286 /****************************************************************************
3287 Fake (read/write) sendfile. Returns -1 on read or write fail.
3288 ****************************************************************************/
3290 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3291 off_t startpos, size_t nread)
3293 size_t bufsize;
3294 size_t tosend = nread;
3295 char *buf;
3297 if (nread == 0) {
3298 return 0;
3301 bufsize = MIN(nread, 65536);
3303 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3304 return -1;
3307 while (tosend > 0) {
3308 ssize_t ret;
3309 size_t cur_read;
3311 cur_read = MIN(tosend, bufsize);
3312 ret = read_file(fsp,buf,startpos,cur_read);
3313 if (ret == -1) {
3314 SAFE_FREE(buf);
3315 return -1;
3318 /* If we had a short read, fill with zeros. */
3319 if (ret < cur_read) {
3320 memset(buf + ret, '\0', cur_read - ret);
3323 ret = write_data(xconn->transport.sock, buf, cur_read);
3324 if (ret != cur_read) {
3325 int saved_errno = errno;
3327 * Try and give an error message saying what
3328 * client failed.
3330 DEBUG(0, ("write_data failed for client %s. "
3331 "Error %s\n",
3332 smbXsrv_connection_dbg(xconn),
3333 strerror(saved_errno)));
3334 SAFE_FREE(buf);
3335 errno = saved_errno;
3336 return -1;
3338 tosend -= cur_read;
3339 startpos += cur_read;
3342 SAFE_FREE(buf);
3343 return (ssize_t)nread;
3346 /****************************************************************************
3347 Deal with the case of sendfile reading less bytes from the file than
3348 requested. Fill with zeros (all we can do). Returns 0 on success
3349 ****************************************************************************/
3351 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3352 files_struct *fsp,
3353 ssize_t nread,
3354 size_t headersize,
3355 size_t smb_maxcnt)
3357 #define SHORT_SEND_BUFSIZE 1024
3358 if (nread < headersize) {
3359 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3360 "header for file %s (%s). Terminating\n",
3361 fsp_str_dbg(fsp), strerror(errno)));
3362 return -1;
3365 nread -= headersize;
3367 if (nread < smb_maxcnt) {
3368 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3369 if (!buf) {
3370 DEBUG(0,("sendfile_short_send: malloc failed "
3371 "for file %s (%s). Terminating\n",
3372 fsp_str_dbg(fsp), strerror(errno)));
3373 return -1;
3376 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3377 "with zeros !\n", fsp_str_dbg(fsp)));
3379 while (nread < smb_maxcnt) {
3381 * We asked for the real file size and told sendfile
3382 * to not go beyond the end of the file. But it can
3383 * happen that in between our fstat call and the
3384 * sendfile call the file was truncated. This is very
3385 * bad because we have already announced the larger
3386 * number of bytes to the client.
3388 * The best we can do now is to send 0-bytes, just as
3389 * a read from a hole in a sparse file would do.
3391 * This should happen rarely enough that I don't care
3392 * about efficiency here :-)
3394 size_t to_write;
3395 ssize_t ret;
3397 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3398 ret = write_data(xconn->transport.sock, buf, to_write);
3399 if (ret != to_write) {
3400 int saved_errno = errno;
3402 * Try and give an error message saying what
3403 * client failed.
3405 DEBUG(0, ("write_data failed for client %s. "
3406 "Error %s\n",
3407 smbXsrv_connection_dbg(xconn),
3408 strerror(saved_errno)));
3409 errno = saved_errno;
3410 return -1;
3412 nread += to_write;
3414 SAFE_FREE(buf);
3417 return 0;
3420 /****************************************************************************
3421 Return a readbraw error (4 bytes of zero).
3422 ****************************************************************************/
3424 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3426 char header[4];
3428 SIVAL(header,0,0);
3430 smbd_lock_socket(xconn);
3431 if (write_data(xconn->transport.sock,header,4) != 4) {
3432 int saved_errno = errno;
3434 * Try and give an error message saying what
3435 * client failed.
3437 DEBUG(0, ("write_data failed for client %s. "
3438 "Error %s\n",
3439 smbXsrv_connection_dbg(xconn),
3440 strerror(saved_errno)));
3441 errno = saved_errno;
3443 fail_readraw();
3445 smbd_unlock_socket(xconn);
3448 /****************************************************************************
3449 Use sendfile in readbraw.
3450 ****************************************************************************/
3452 static void send_file_readbraw(connection_struct *conn,
3453 struct smb_request *req,
3454 files_struct *fsp,
3455 off_t startpos,
3456 size_t nread,
3457 ssize_t mincount)
3459 struct smbXsrv_connection *xconn = req->xconn;
3460 char *outbuf = NULL;
3461 ssize_t ret=0;
3464 * We can only use sendfile on a non-chained packet
3465 * but we can use on a non-oplocked file. tridge proved this
3466 * on a train in Germany :-). JRA.
3467 * reply_readbraw has already checked the length.
3470 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3471 (fsp->wcp == NULL) &&
3472 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3473 ssize_t sendfile_read = -1;
3474 char header[4];
3475 DATA_BLOB header_blob;
3477 _smb_setlen(header,nread);
3478 header_blob = data_blob_const(header, 4);
3480 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3481 &header_blob, startpos,
3482 nread);
3483 if (sendfile_read == -1) {
3484 /* Returning ENOSYS means no data at all was sent.
3485 * Do this as a normal read. */
3486 if (errno == ENOSYS) {
3487 goto normal_readbraw;
3491 * Special hack for broken Linux with no working sendfile. If we
3492 * return EINTR we sent the header but not the rest of the data.
3493 * Fake this up by doing read/write calls.
3495 if (errno == EINTR) {
3496 /* Ensure we don't do this again. */
3497 set_use_sendfile(SNUM(conn), False);
3498 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3500 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3501 DEBUG(0,("send_file_readbraw: "
3502 "fake_sendfile failed for "
3503 "file %s (%s).\n",
3504 fsp_str_dbg(fsp),
3505 strerror(errno)));
3506 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3508 return;
3511 DEBUG(0,("send_file_readbraw: sendfile failed for "
3512 "file %s (%s). Terminating\n",
3513 fsp_str_dbg(fsp), strerror(errno)));
3514 exit_server_cleanly("send_file_readbraw sendfile failed");
3515 } else if (sendfile_read == 0) {
3517 * Some sendfile implementations return 0 to indicate
3518 * that there was a short read, but nothing was
3519 * actually written to the socket. In this case,
3520 * fallback to the normal read path so the header gets
3521 * the correct byte count.
3523 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3524 "bytes falling back to the normal read: "
3525 "%s\n", fsp_str_dbg(fsp)));
3526 goto normal_readbraw;
3529 /* Deal with possible short send. */
3530 if (sendfile_read != 4+nread) {
3531 ret = sendfile_short_send(xconn, fsp,
3532 sendfile_read, 4, nread);
3533 if (ret == -1) {
3534 fail_readraw();
3537 return;
3540 normal_readbraw:
3542 outbuf = talloc_array(NULL, char, nread+4);
3543 if (!outbuf) {
3544 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3545 (unsigned)(nread+4)));
3546 reply_readbraw_error(xconn);
3547 return;
3550 if (nread > 0) {
3551 ret = read_file(fsp,outbuf+4,startpos,nread);
3552 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3553 if (ret < mincount)
3554 ret = 0;
3555 #else
3556 if (ret < nread)
3557 ret = 0;
3558 #endif
3561 _smb_setlen(outbuf,ret);
3562 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3563 int saved_errno = errno;
3565 * Try and give an error message saying what
3566 * client failed.
3568 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3569 smbXsrv_connection_dbg(xconn),
3570 strerror(saved_errno)));
3571 errno = saved_errno;
3573 fail_readraw();
3576 TALLOC_FREE(outbuf);
3579 /****************************************************************************
3580 Reply to a readbraw (core+ protocol).
3581 ****************************************************************************/
3583 void reply_readbraw(struct smb_request *req)
3585 connection_struct *conn = req->conn;
3586 struct smbXsrv_connection *xconn = req->xconn;
3587 ssize_t maxcount,mincount;
3588 size_t nread = 0;
3589 off_t startpos;
3590 files_struct *fsp;
3591 struct lock_struct lock;
3592 off_t size = 0;
3594 START_PROFILE(SMBreadbraw);
3596 if (srv_is_signing_active(xconn) || req->encrypted) {
3597 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3598 "raw reads/writes are disallowed.");
3601 if (req->wct < 8) {
3602 reply_readbraw_error(xconn);
3603 END_PROFILE(SMBreadbraw);
3604 return;
3607 if (xconn->smb1.echo_handler.trusted_fde) {
3608 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3609 "'async smb echo handler = yes'\n"));
3610 reply_readbraw_error(xconn);
3611 END_PROFILE(SMBreadbraw);
3612 return;
3616 * Special check if an oplock break has been issued
3617 * and the readraw request croses on the wire, we must
3618 * return a zero length response here.
3621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3624 * We have to do a check_fsp by hand here, as
3625 * we must always return 4 zero bytes on error,
3626 * not a NTSTATUS.
3629 if (!fsp || !conn || conn != fsp->conn ||
3630 req->vuid != fsp->vuid ||
3631 fsp->is_directory || fsp->fh->fd == -1) {
3633 * fsp could be NULL here so use the value from the packet. JRA.
3635 DEBUG(3,("reply_readbraw: fnum %d not valid "
3636 "- cache prime?\n",
3637 (int)SVAL(req->vwv+0, 0)));
3638 reply_readbraw_error(xconn);
3639 END_PROFILE(SMBreadbraw);
3640 return;
3643 /* Do a "by hand" version of CHECK_READ. */
3644 if (!(fsp->can_read ||
3645 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3646 (fsp->access_mask & FILE_EXECUTE)))) {
3647 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3648 (int)SVAL(req->vwv+0, 0)));
3649 reply_readbraw_error(xconn);
3650 END_PROFILE(SMBreadbraw);
3651 return;
3654 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3656 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3657 if(req->wct == 10) {
3659 * This is a large offset (64 bit) read.
3662 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3664 if(startpos < 0) {
3665 DEBUG(0,("reply_readbraw: negative 64 bit "
3666 "readraw offset (%.0f) !\n",
3667 (double)startpos ));
3668 reply_readbraw_error(xconn);
3669 END_PROFILE(SMBreadbraw);
3670 return;
3674 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3675 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3677 /* ensure we don't overrun the packet size */
3678 maxcount = MIN(65535,maxcount);
3680 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3681 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3682 &lock);
3684 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3685 reply_readbraw_error(xconn);
3686 END_PROFILE(SMBreadbraw);
3687 return;
3690 if (fsp_stat(fsp) == 0) {
3691 size = fsp->fsp_name->st.st_ex_size;
3694 if (startpos >= size) {
3695 nread = 0;
3696 } else {
3697 nread = MIN(maxcount,(size - startpos));
3700 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3701 if (nread < mincount)
3702 nread = 0;
3703 #endif
3705 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3706 "min=%lu nread=%lu\n",
3707 fsp_fnum_dbg(fsp), (double)startpos,
3708 (unsigned long)maxcount,
3709 (unsigned long)mincount,
3710 (unsigned long)nread ) );
3712 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3714 DEBUG(5,("reply_readbraw finished\n"));
3716 END_PROFILE(SMBreadbraw);
3717 return;
3720 #undef DBGC_CLASS
3721 #define DBGC_CLASS DBGC_LOCKING
3723 /****************************************************************************
3724 Reply to a lockread (core+ protocol).
3725 ****************************************************************************/
3727 void reply_lockread(struct smb_request *req)
3729 connection_struct *conn = req->conn;
3730 ssize_t nread = -1;
3731 char *data;
3732 off_t startpos;
3733 size_t numtoread;
3734 size_t maxtoread;
3735 NTSTATUS status;
3736 files_struct *fsp;
3737 struct byte_range_lock *br_lck = NULL;
3738 char *p = NULL;
3739 struct smbXsrv_connection *xconn = req->xconn;
3741 START_PROFILE(SMBlockread);
3743 if (req->wct < 5) {
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3745 END_PROFILE(SMBlockread);
3746 return;
3749 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3751 if (!check_fsp(conn, req, fsp)) {
3752 END_PROFILE(SMBlockread);
3753 return;
3756 if (!CHECK_READ(fsp,req)) {
3757 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3758 END_PROFILE(SMBlockread);
3759 return;
3762 numtoread = SVAL(req->vwv+1, 0);
3763 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3766 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3767 * protocol request that predates the read/write lock concept.
3768 * Thus instead of asking for a read lock here we need to ask
3769 * for a write lock. JRA.
3770 * Note that the requested lock size is unaffected by max_send.
3773 br_lck = do_lock(req->sconn->msg_ctx,
3774 fsp,
3775 (uint64_t)req->smbpid,
3776 (uint64_t)numtoread,
3777 (uint64_t)startpos,
3778 WRITE_LOCK,
3779 WINDOWS_LOCK,
3780 False, /* Non-blocking lock. */
3781 &status,
3782 NULL);
3783 TALLOC_FREE(br_lck);
3785 if (NT_STATUS_V(status)) {
3786 reply_nterror(req, status);
3787 END_PROFILE(SMBlockread);
3788 return;
3792 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3794 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3796 if (numtoread > maxtoread) {
3797 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3798 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3799 (unsigned int)numtoread, (unsigned int)maxtoread,
3800 (unsigned int)xconn->smb1.sessions.max_send));
3801 numtoread = maxtoread;
3804 reply_outbuf(req, 5, numtoread + 3);
3806 data = smb_buf(req->outbuf) + 3;
3808 nread = read_file(fsp,data,startpos,numtoread);
3810 if (nread < 0) {
3811 reply_nterror(req, map_nt_error_from_unix(errno));
3812 END_PROFILE(SMBlockread);
3813 return;
3816 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3818 SSVAL(req->outbuf,smb_vwv0,nread);
3819 SSVAL(req->outbuf,smb_vwv5,nread+3);
3820 p = smb_buf(req->outbuf);
3821 SCVAL(p,0,0); /* pad byte. */
3822 SSVAL(p,1,nread);
3824 DEBUG(3,("lockread %s num=%d nread=%d\n",
3825 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3827 END_PROFILE(SMBlockread);
3828 return;
3831 #undef DBGC_CLASS
3832 #define DBGC_CLASS DBGC_ALL
3834 /****************************************************************************
3835 Reply to a read.
3836 ****************************************************************************/
3838 void reply_read(struct smb_request *req)
3840 connection_struct *conn = req->conn;
3841 size_t numtoread;
3842 size_t maxtoread;
3843 ssize_t nread = 0;
3844 char *data;
3845 off_t startpos;
3846 files_struct *fsp;
3847 struct lock_struct lock;
3848 struct smbXsrv_connection *xconn = req->xconn;
3850 START_PROFILE(SMBread);
3852 if (req->wct < 3) {
3853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3854 END_PROFILE(SMBread);
3855 return;
3858 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3860 if (!check_fsp(conn, req, fsp)) {
3861 END_PROFILE(SMBread);
3862 return;
3865 if (!CHECK_READ(fsp,req)) {
3866 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3867 END_PROFILE(SMBread);
3868 return;
3871 numtoread = SVAL(req->vwv+1, 0);
3872 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3875 * The requested read size cannot be greater than max_send. JRA.
3877 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3879 if (numtoread > maxtoread) {
3880 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3881 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3882 (unsigned int)numtoread, (unsigned int)maxtoread,
3883 (unsigned int)xconn->smb1.sessions.max_send));
3884 numtoread = maxtoread;
3887 reply_outbuf(req, 5, numtoread+3);
3889 data = smb_buf(req->outbuf) + 3;
3891 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3892 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3893 &lock);
3895 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3896 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3897 END_PROFILE(SMBread);
3898 return;
3901 if (numtoread > 0)
3902 nread = read_file(fsp,data,startpos,numtoread);
3904 if (nread < 0) {
3905 reply_nterror(req, map_nt_error_from_unix(errno));
3906 goto out;
3909 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3911 SSVAL(req->outbuf,smb_vwv0,nread);
3912 SSVAL(req->outbuf,smb_vwv5,nread+3);
3913 SCVAL(smb_buf(req->outbuf),0,1);
3914 SSVAL(smb_buf(req->outbuf),1,nread);
3916 DEBUG(3, ("read %s num=%d nread=%d\n",
3917 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3919 out:
3920 END_PROFILE(SMBread);
3921 return;
3924 /****************************************************************************
3925 Setup readX header.
3926 ****************************************************************************/
3928 int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3930 int outsize;
3932 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3933 False);
3935 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3937 SCVAL(outbuf,smb_vwv0,0xFF);
3938 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3939 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3940 SSVAL(outbuf,smb_vwv6,
3941 (smb_wct - 4) /* offset from smb header to wct */
3942 + 1 /* the wct field */
3943 + 12 * sizeof(uint16_t) /* vwv */
3944 + 2 /* the buflen field */
3945 + 1); /* padding byte */
3946 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3947 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3948 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3949 _smb_setlen_large(outbuf,
3950 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3951 return outsize;
3954 /****************************************************************************
3955 Reply to a read and X - possibly using sendfile.
3956 ****************************************************************************/
3958 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3959 files_struct *fsp, off_t startpos,
3960 size_t smb_maxcnt)
3962 struct smbXsrv_connection *xconn = req->xconn;
3963 ssize_t nread = -1;
3964 struct lock_struct lock;
3965 int saved_errno = 0;
3967 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3968 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3969 &lock);
3971 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3972 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3973 return;
3977 * We can only use sendfile on a non-chained packet
3978 * but we can use on a non-oplocked file. tridge proved this
3979 * on a train in Germany :-). JRA.
3982 if (!req_is_in_chain(req) &&
3983 !req->encrypted &&
3984 (fsp->base_fsp == NULL) &&
3985 (fsp->wcp == NULL) &&
3986 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3987 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3988 DATA_BLOB header;
3990 if(fsp_stat(fsp) == -1) {
3991 reply_nterror(req, map_nt_error_from_unix(errno));
3992 goto out;
3995 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3996 (startpos > fsp->fsp_name->st.st_ex_size) ||
3997 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3999 * We already know that we would do a short read, so don't
4000 * try the sendfile() path.
4002 goto nosendfile_read;
4006 * Set up the packet header before send. We
4007 * assume here the sendfile will work (get the
4008 * correct amount of data).
4011 header = data_blob_const(headerbuf, sizeof(headerbuf));
4013 construct_reply_common_req(req, (char *)headerbuf);
4014 setup_readX_header((char *)headerbuf, smb_maxcnt);
4016 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4017 startpos, smb_maxcnt);
4018 if (nread == -1) {
4019 saved_errno = errno;
4021 /* Returning ENOSYS means no data at all was sent.
4022 Do this as a normal read. */
4023 if (errno == ENOSYS) {
4024 goto normal_read;
4028 * Special hack for broken Linux with no working sendfile. If we
4029 * return EINTR we sent the header but not the rest of the data.
4030 * Fake this up by doing read/write calls.
4033 if (errno == EINTR) {
4034 /* Ensure we don't do this again. */
4035 set_use_sendfile(SNUM(conn), False);
4036 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4037 nread = fake_sendfile(xconn, fsp, startpos,
4038 smb_maxcnt);
4039 if (nread == -1) {
4040 saved_errno = errno;
4041 DEBUG(0,("send_file_readX: "
4042 "fake_sendfile failed for "
4043 "file %s (%s) for client %s. "
4044 "Terminating\n",
4045 fsp_str_dbg(fsp),
4046 smbXsrv_connection_dbg(xconn),
4047 strerror(saved_errno)));
4048 errno = saved_errno;
4049 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4051 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4052 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4053 /* No outbuf here means successful sendfile. */
4054 goto out;
4057 DEBUG(0,("send_file_readX: sendfile failed for file "
4058 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4059 strerror(errno)));
4060 exit_server_cleanly("send_file_readX sendfile failed");
4061 } else if (nread == 0) {
4063 * Some sendfile implementations return 0 to indicate
4064 * that there was a short read, but nothing was
4065 * actually written to the socket. In this case,
4066 * fallback to the normal read path so the header gets
4067 * the correct byte count.
4069 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4070 "falling back to the normal read: %s\n",
4071 fsp_str_dbg(fsp)));
4072 goto normal_read;
4075 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4076 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4078 /* Deal with possible short send. */
4079 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4080 ssize_t ret;
4082 ret = sendfile_short_send(xconn, fsp, nread,
4083 sizeof(headerbuf), smb_maxcnt);
4084 if (ret == -1) {
4085 const char *r;
4086 r = "send_file_readX: sendfile_short_send failed";
4087 DEBUG(0,("%s for file %s (%s).\n",
4088 r, fsp_str_dbg(fsp), strerror(errno)));
4089 exit_server_cleanly(r);
4092 /* No outbuf here means successful sendfile. */
4093 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4094 SMB_PERFCOUNT_END(&req->pcd);
4095 goto out;
4098 normal_read:
4100 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4101 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4102 ssize_t ret;
4104 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4105 (startpos > fsp->fsp_name->st.st_ex_size) ||
4106 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4108 * We already know that we would do a short
4109 * read, so don't try the sendfile() path.
4111 goto nosendfile_read;
4114 construct_reply_common_req(req, (char *)headerbuf);
4115 setup_readX_header((char *)headerbuf, smb_maxcnt);
4117 /* Send out the header. */
4118 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4119 sizeof(headerbuf));
4120 if (ret != sizeof(headerbuf)) {
4121 saved_errno = errno;
4123 * Try and give an error message saying what
4124 * client failed.
4126 DEBUG(0,("send_file_readX: write_data failed for file "
4127 "%s (%s) for client %s. Terminating\n",
4128 fsp_str_dbg(fsp),
4129 smbXsrv_connection_dbg(xconn),
4130 strerror(saved_errno)));
4131 errno = saved_errno;
4132 exit_server_cleanly("send_file_readX sendfile failed");
4134 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4135 if (nread == -1) {
4136 saved_errno = errno;
4137 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4138 "%s (%s) for client %s. Terminating\n",
4139 fsp_str_dbg(fsp),
4140 smbXsrv_connection_dbg(xconn),
4141 strerror(saved_errno)));
4142 errno = saved_errno;
4143 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4145 goto out;
4148 nosendfile_read:
4150 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4151 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4152 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4154 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4155 startpos, smb_maxcnt);
4156 saved_errno = errno;
4158 if (nread < 0) {
4159 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4160 return;
4163 setup_readX_header((char *)req->outbuf, nread);
4165 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4166 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4167 return;
4169 out:
4170 TALLOC_FREE(req->outbuf);
4171 return;
4174 /****************************************************************************
4175 Work out how much space we have for a read return.
4176 ****************************************************************************/
4178 static size_t calc_max_read_pdu(const struct smb_request *req)
4180 struct smbXsrv_connection *xconn = req->xconn;
4182 if (xconn->protocol < PROTOCOL_NT1) {
4183 return xconn->smb1.sessions.max_send;
4186 if (!lp_large_readwrite()) {
4187 return xconn->smb1.sessions.max_send;
4190 if (req_is_in_chain(req)) {
4191 return xconn->smb1.sessions.max_send;
4194 if (req->encrypted) {
4196 * Don't take encrypted traffic up to the
4197 * limit. There are padding considerations
4198 * that make that tricky.
4200 return xconn->smb1.sessions.max_send;
4203 if (srv_is_signing_active(xconn)) {
4204 return 0x1FFFF;
4207 if (!lp_unix_extensions()) {
4208 return 0x1FFFF;
4212 * We can do ultra-large POSIX reads.
4214 return 0xFFFFFF;
4217 /****************************************************************************
4218 Calculate how big a read can be. Copes with all clients. It's always
4219 safe to return a short read - Windows does this.
4220 ****************************************************************************/
4222 static size_t calc_read_size(const struct smb_request *req,
4223 size_t upper_size,
4224 size_t lower_size)
4226 struct smbXsrv_connection *xconn = req->xconn;
4227 size_t max_pdu = calc_max_read_pdu(req);
4228 size_t total_size = 0;
4229 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4230 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4233 * Windows explicitly ignores upper size of 0xFFFF.
4234 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4235 * We must do the same as these will never fit even in
4236 * an extended size NetBIOS packet.
4238 if (upper_size == 0xFFFF) {
4239 upper_size = 0;
4242 if (xconn->protocol < PROTOCOL_NT1) {
4243 upper_size = 0;
4246 total_size = ((upper_size<<16) | lower_size);
4249 * LARGE_READX test shows it's always safe to return
4250 * a short read. Windows does so.
4252 return MIN(total_size, max_len);
4255 /****************************************************************************
4256 Reply to a read and X.
4257 ****************************************************************************/
4259 void reply_read_and_X(struct smb_request *req)
4261 connection_struct *conn = req->conn;
4262 files_struct *fsp;
4263 off_t startpos;
4264 size_t smb_maxcnt;
4265 size_t upper_size;
4266 bool big_readX = False;
4267 #if 0
4268 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4269 #endif
4271 START_PROFILE(SMBreadX);
4273 if ((req->wct != 10) && (req->wct != 12)) {
4274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4275 return;
4278 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4279 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4280 smb_maxcnt = SVAL(req->vwv+5, 0);
4282 /* If it's an IPC, pass off the pipe handler. */
4283 if (IS_IPC(conn)) {
4284 reply_pipe_read_and_X(req);
4285 END_PROFILE(SMBreadX);
4286 return;
4289 if (!check_fsp(conn, req, fsp)) {
4290 END_PROFILE(SMBreadX);
4291 return;
4294 if (!CHECK_READ(fsp,req)) {
4295 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4296 END_PROFILE(SMBreadX);
4297 return;
4300 upper_size = SVAL(req->vwv+7, 0);
4301 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4302 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4304 * This is a heuristic to avoid keeping large
4305 * outgoing buffers around over long-lived aio
4306 * requests.
4308 big_readX = True;
4311 if (req->wct == 12) {
4313 * This is a large offset (64 bit) read.
4315 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4319 if (!big_readX) {
4320 NTSTATUS status = schedule_aio_read_and_X(conn,
4321 req,
4322 fsp,
4323 startpos,
4324 smb_maxcnt);
4325 if (NT_STATUS_IS_OK(status)) {
4326 /* Read scheduled - we're done. */
4327 goto out;
4329 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4330 /* Real error - report to client. */
4331 END_PROFILE(SMBreadX);
4332 reply_nterror(req, status);
4333 return;
4335 /* NT_STATUS_RETRY - fall back to sync read. */
4338 smbd_lock_socket(req->xconn);
4339 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4340 smbd_unlock_socket(req->xconn);
4342 out:
4343 END_PROFILE(SMBreadX);
4344 return;
4347 /****************************************************************************
4348 Error replies to writebraw must have smb_wct == 1. Fix this up.
4349 ****************************************************************************/
4351 void error_to_writebrawerr(struct smb_request *req)
4353 uint8_t *old_outbuf = req->outbuf;
4355 reply_outbuf(req, 1, 0);
4357 memcpy(req->outbuf, old_outbuf, smb_size);
4358 TALLOC_FREE(old_outbuf);
4361 /****************************************************************************
4362 Read 4 bytes of a smb packet and return the smb length of the packet.
4363 Store the result in the buffer. This version of the function will
4364 never return a session keepalive (length of zero).
4365 Timeout is in milliseconds.
4366 ****************************************************************************/
4368 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4369 size_t *len)
4371 uint8_t msgtype = NBSSkeepalive;
4373 while (msgtype == NBSSkeepalive) {
4374 NTSTATUS status;
4376 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4377 len);
4378 if (!NT_STATUS_IS_OK(status)) {
4379 char addr[INET6_ADDRSTRLEN];
4380 /* Try and give an error message
4381 * saying what client failed. */
4382 DEBUG(0, ("read_fd_with_timeout failed for "
4383 "client %s read error = %s.\n",
4384 get_peer_addr(fd,addr,sizeof(addr)),
4385 nt_errstr(status)));
4386 return status;
4389 msgtype = CVAL(inbuf, 0);
4392 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4393 (unsigned long)len));
4395 return NT_STATUS_OK;
4398 /****************************************************************************
4399 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4400 ****************************************************************************/
4402 void reply_writebraw(struct smb_request *req)
4404 connection_struct *conn = req->conn;
4405 struct smbXsrv_connection *xconn = req->xconn;
4406 char *buf = NULL;
4407 ssize_t nwritten=0;
4408 ssize_t total_written=0;
4409 size_t numtowrite=0;
4410 size_t tcount;
4411 off_t startpos;
4412 const char *data=NULL;
4413 bool write_through;
4414 files_struct *fsp;
4415 struct lock_struct lock;
4416 NTSTATUS status;
4418 START_PROFILE(SMBwritebraw);
4421 * If we ever reply with an error, it must have the SMB command
4422 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4423 * we're finished.
4425 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4427 if (srv_is_signing_active(xconn)) {
4428 END_PROFILE(SMBwritebraw);
4429 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4430 "raw reads/writes are disallowed.");
4433 if (req->wct < 12) {
4434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4435 error_to_writebrawerr(req);
4436 END_PROFILE(SMBwritebraw);
4437 return;
4440 if (xconn->smb1.echo_handler.trusted_fde) {
4441 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4442 "'async smb echo handler = yes'\n"));
4443 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4444 error_to_writebrawerr(req);
4445 END_PROFILE(SMBwritebraw);
4446 return;
4449 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4450 if (!check_fsp(conn, req, fsp)) {
4451 error_to_writebrawerr(req);
4452 END_PROFILE(SMBwritebraw);
4453 return;
4456 if (!CHECK_WRITE(fsp)) {
4457 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4458 error_to_writebrawerr(req);
4459 END_PROFILE(SMBwritebraw);
4460 return;
4463 tcount = IVAL(req->vwv+1, 0);
4464 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4465 write_through = BITSETW(req->vwv+7,0);
4467 /* We have to deal with slightly different formats depending
4468 on whether we are using the core+ or lanman1.0 protocol */
4470 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4471 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4472 data = smb_buf_const(req->inbuf);
4473 } else {
4474 numtowrite = SVAL(req->vwv+10, 0);
4475 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4478 /* Ensure we don't write bytes past the end of this packet. */
4480 * This already protects us against CVE-2017-12163.
4482 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4483 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4484 error_to_writebrawerr(req);
4485 END_PROFILE(SMBwritebraw);
4486 return;
4489 if (!fsp->print_file) {
4490 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4491 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4492 &lock);
4494 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4495 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4496 error_to_writebrawerr(req);
4497 END_PROFILE(SMBwritebraw);
4498 return;
4502 if (numtowrite>0) {
4503 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4506 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4507 "wrote=%d sync=%d\n",
4508 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4509 (int)nwritten, (int)write_through));
4511 if (nwritten < (ssize_t)numtowrite) {
4512 reply_nterror(req, NT_STATUS_DISK_FULL);
4513 error_to_writebrawerr(req);
4514 goto out;
4517 total_written = nwritten;
4519 /* Allocate a buffer of 64k + length. */
4520 buf = talloc_array(NULL, char, 65540);
4521 if (!buf) {
4522 reply_nterror(req, NT_STATUS_NO_MEMORY);
4523 error_to_writebrawerr(req);
4524 goto out;
4527 /* Return a SMBwritebraw message to the redirector to tell
4528 * it to send more bytes */
4530 memcpy(buf, req->inbuf, smb_size);
4531 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4532 SCVAL(buf,smb_com,SMBwritebraw);
4533 SSVALS(buf,smb_vwv0,0xFFFF);
4534 show_msg(buf);
4535 if (!srv_send_smb(req->xconn,
4536 buf,
4537 false, 0, /* no signing */
4538 IS_CONN_ENCRYPTED(conn),
4539 &req->pcd)) {
4540 exit_server_cleanly("reply_writebraw: srv_send_smb "
4541 "failed.");
4544 /* Now read the raw data into the buffer and write it */
4545 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4546 &numtowrite);
4547 if (!NT_STATUS_IS_OK(status)) {
4548 exit_server_cleanly("secondary writebraw failed");
4551 /* Set up outbuf to return the correct size */
4552 reply_outbuf(req, 1, 0);
4554 if (numtowrite != 0) {
4556 if (numtowrite > 0xFFFF) {
4557 DEBUG(0,("reply_writebraw: Oversize secondary write "
4558 "raw requested (%u). Terminating\n",
4559 (unsigned int)numtowrite ));
4560 exit_server_cleanly("secondary writebraw failed");
4563 if (tcount > nwritten+numtowrite) {
4564 DEBUG(3,("reply_writebraw: Client overestimated the "
4565 "write %d %d %d\n",
4566 (int)tcount,(int)nwritten,(int)numtowrite));
4569 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4570 numtowrite);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 /* Try and give an error message
4574 * saying what client failed. */
4575 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4576 "raw read failed (%s) for client %s. "
4577 "Terminating\n", nt_errstr(status),
4578 smbXsrv_connection_dbg(xconn)));
4579 exit_server_cleanly("secondary writebraw failed");
4583 * We are not vulnerable to CVE-2017-12163
4584 * here as we are guarenteed to have numtowrite
4585 * bytes available - we just read from the client.
4587 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4588 if (nwritten == -1) {
4589 TALLOC_FREE(buf);
4590 reply_nterror(req, map_nt_error_from_unix(errno));
4591 error_to_writebrawerr(req);
4592 goto out;
4595 if (nwritten < (ssize_t)numtowrite) {
4596 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4597 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4600 if (nwritten > 0) {
4601 total_written += nwritten;
4605 TALLOC_FREE(buf);
4606 SSVAL(req->outbuf,smb_vwv0,total_written);
4608 status = sync_file(conn, fsp, write_through);
4609 if (!NT_STATUS_IS_OK(status)) {
4610 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4611 fsp_str_dbg(fsp), nt_errstr(status)));
4612 reply_nterror(req, status);
4613 error_to_writebrawerr(req);
4614 goto out;
4617 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4618 "wrote=%d\n",
4619 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4620 (int)total_written));
4622 /* We won't return a status if write through is not selected - this
4623 * follows what WfWg does */
4624 END_PROFILE(SMBwritebraw);
4626 if (!write_through && total_written==tcount) {
4628 #if RABBIT_PELLET_FIX
4630 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4631 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4632 * JRA.
4634 if (!send_keepalive(xconn->transport.sock)) {
4635 exit_server_cleanly("reply_writebraw: send of "
4636 "keepalive failed");
4638 #endif
4639 TALLOC_FREE(req->outbuf);
4641 return;
4643 out:
4644 END_PROFILE(SMBwritebraw);
4645 return;
4648 #undef DBGC_CLASS
4649 #define DBGC_CLASS DBGC_LOCKING
4651 /****************************************************************************
4652 Reply to a writeunlock (core+).
4653 ****************************************************************************/
4655 void reply_writeunlock(struct smb_request *req)
4657 connection_struct *conn = req->conn;
4658 ssize_t nwritten = -1;
4659 size_t numtowrite;
4660 size_t remaining;
4661 off_t startpos;
4662 const char *data;
4663 NTSTATUS status = NT_STATUS_OK;
4664 files_struct *fsp;
4665 struct lock_struct lock;
4666 int saved_errno = 0;
4668 START_PROFILE(SMBwriteunlock);
4670 if (req->wct < 5) {
4671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4672 END_PROFILE(SMBwriteunlock);
4673 return;
4676 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4678 if (!check_fsp(conn, req, fsp)) {
4679 END_PROFILE(SMBwriteunlock);
4680 return;
4683 if (!CHECK_WRITE(fsp)) {
4684 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4685 END_PROFILE(SMBwriteunlock);
4686 return;
4689 numtowrite = SVAL(req->vwv+1, 0);
4690 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4691 data = (const char *)req->buf + 3;
4694 * Ensure client isn't asking us to write more than
4695 * they sent. CVE-2017-12163.
4697 remaining = smbreq_bufrem(req, data);
4698 if (numtowrite > remaining) {
4699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4700 END_PROFILE(SMBwriteunlock);
4701 return;
4704 if (!fsp->print_file && numtowrite > 0) {
4705 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4706 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4707 &lock);
4709 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4710 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4711 END_PROFILE(SMBwriteunlock);
4712 return;
4716 /* The special X/Open SMB protocol handling of
4717 zero length writes is *NOT* done for
4718 this call */
4719 if(numtowrite == 0) {
4720 nwritten = 0;
4721 } else {
4722 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4723 saved_errno = errno;
4726 status = sync_file(conn, fsp, False /* write through */);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4729 fsp_str_dbg(fsp), nt_errstr(status)));
4730 reply_nterror(req, status);
4731 goto out;
4734 if(nwritten < 0) {
4735 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4736 goto out;
4739 if((nwritten < numtowrite) && (numtowrite != 0)) {
4740 reply_nterror(req, NT_STATUS_DISK_FULL);
4741 goto out;
4744 if (numtowrite && !fsp->print_file) {
4745 status = do_unlock(req->sconn->msg_ctx,
4746 fsp,
4747 (uint64_t)req->smbpid,
4748 (uint64_t)numtowrite,
4749 (uint64_t)startpos,
4750 WINDOWS_LOCK);
4752 if (NT_STATUS_V(status)) {
4753 reply_nterror(req, status);
4754 goto out;
4758 reply_outbuf(req, 1, 0);
4760 SSVAL(req->outbuf,smb_vwv0,nwritten);
4762 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4763 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4765 out:
4766 END_PROFILE(SMBwriteunlock);
4767 return;
4770 #undef DBGC_CLASS
4771 #define DBGC_CLASS DBGC_ALL
4773 /****************************************************************************
4774 Reply to a write.
4775 ****************************************************************************/
4777 void reply_write(struct smb_request *req)
4779 connection_struct *conn = req->conn;
4780 size_t numtowrite;
4781 size_t remaining;
4782 ssize_t nwritten = -1;
4783 off_t startpos;
4784 const char *data;
4785 files_struct *fsp;
4786 struct lock_struct lock;
4787 NTSTATUS status;
4788 int saved_errno = 0;
4790 START_PROFILE(SMBwrite);
4792 if (req->wct < 5) {
4793 END_PROFILE(SMBwrite);
4794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4795 return;
4798 /* If it's an IPC, pass off the pipe handler. */
4799 if (IS_IPC(conn)) {
4800 reply_pipe_write(req);
4801 END_PROFILE(SMBwrite);
4802 return;
4805 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4807 if (!check_fsp(conn, req, fsp)) {
4808 END_PROFILE(SMBwrite);
4809 return;
4812 if (!CHECK_WRITE(fsp)) {
4813 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4814 END_PROFILE(SMBwrite);
4815 return;
4818 numtowrite = SVAL(req->vwv+1, 0);
4819 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4820 data = (const char *)req->buf + 3;
4823 * Ensure client isn't asking us to write more than
4824 * they sent. CVE-2017-12163.
4826 remaining = smbreq_bufrem(req, data);
4827 if (numtowrite > remaining) {
4828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4829 END_PROFILE(SMBwrite);
4830 return;
4833 if (!fsp->print_file) {
4834 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4835 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4836 &lock);
4838 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4839 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4840 END_PROFILE(SMBwrite);
4841 return;
4846 * X/Open SMB protocol says that if smb_vwv1 is
4847 * zero then the file size should be extended or
4848 * truncated to the size given in smb_vwv[2-3].
4851 if(numtowrite == 0) {
4853 * This is actually an allocate call, and set EOF. JRA.
4855 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4856 if (nwritten < 0) {
4857 reply_nterror(req, NT_STATUS_DISK_FULL);
4858 goto out;
4860 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4861 if (nwritten < 0) {
4862 reply_nterror(req, NT_STATUS_DISK_FULL);
4863 goto out;
4865 trigger_write_time_update_immediate(fsp);
4866 } else {
4867 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4870 status = sync_file(conn, fsp, False);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4873 fsp_str_dbg(fsp), nt_errstr(status)));
4874 reply_nterror(req, status);
4875 goto out;
4878 if(nwritten < 0) {
4879 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4880 goto out;
4883 if((nwritten == 0) && (numtowrite != 0)) {
4884 reply_nterror(req, NT_STATUS_DISK_FULL);
4885 goto out;
4888 reply_outbuf(req, 1, 0);
4890 SSVAL(req->outbuf,smb_vwv0,nwritten);
4892 if (nwritten < (ssize_t)numtowrite) {
4893 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4894 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4897 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4899 out:
4900 END_PROFILE(SMBwrite);
4901 return;
4904 /****************************************************************************
4905 Ensure a buffer is a valid writeX for recvfile purposes.
4906 ****************************************************************************/
4908 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4909 (2*14) + /* word count (including bcc) */ \
4910 1 /* pad byte */)
4912 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4913 const uint8_t *inbuf)
4915 size_t numtowrite;
4916 unsigned int doff = 0;
4917 size_t len = smb_len_large(inbuf);
4918 uint16_t fnum;
4919 struct smbXsrv_open *op = NULL;
4920 struct files_struct *fsp = NULL;
4921 NTSTATUS status;
4923 if (is_encrypted_packet(inbuf)) {
4924 /* Can't do this on encrypted
4925 * connections. */
4926 return false;
4929 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4930 return false;
4933 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4934 CVAL(inbuf,smb_wct) != 14) {
4935 DEBUG(10,("is_valid_writeX_buffer: chained or "
4936 "invalid word length.\n"));
4937 return false;
4940 fnum = SVAL(inbuf, smb_vwv2);
4941 status = smb1srv_open_lookup(xconn,
4942 fnum,
4943 0, /* now */
4944 &op);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4947 return false;
4949 fsp = op->compat;
4950 if (fsp == NULL) {
4951 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4952 return false;
4954 if (fsp->conn == NULL) {
4955 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4956 return false;
4959 if (IS_IPC(fsp->conn)) {
4960 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4961 return false;
4963 if (IS_PRINT(fsp->conn)) {
4964 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4965 return false;
4967 doff = SVAL(inbuf,smb_vwv11);
4969 numtowrite = SVAL(inbuf,smb_vwv10);
4971 if (len > doff && len - doff > 0xFFFF) {
4972 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4975 if (numtowrite == 0) {
4976 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4977 return false;
4980 /* Ensure the sizes match up. */
4981 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4982 /* no pad byte...old smbclient :-( */
4983 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4984 (unsigned int)doff,
4985 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4986 return false;
4989 if (len - doff != numtowrite) {
4990 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4991 "len = %u, doff = %u, numtowrite = %u\n",
4992 (unsigned int)len,
4993 (unsigned int)doff,
4994 (unsigned int)numtowrite ));
4995 return false;
4998 DEBUG(10,("is_valid_writeX_buffer: true "
4999 "len = %u, doff = %u, numtowrite = %u\n",
5000 (unsigned int)len,
5001 (unsigned int)doff,
5002 (unsigned int)numtowrite ));
5004 return true;
5007 /****************************************************************************
5008 Reply to a write and X.
5009 ****************************************************************************/
5011 void reply_write_and_X(struct smb_request *req)
5013 connection_struct *conn = req->conn;
5014 struct smbXsrv_connection *xconn = req->xconn;
5015 files_struct *fsp;
5016 struct lock_struct lock;
5017 off_t startpos;
5018 size_t numtowrite;
5019 bool write_through;
5020 ssize_t nwritten;
5021 unsigned int smb_doff;
5022 unsigned int smblen;
5023 const char *data;
5024 NTSTATUS status;
5025 int saved_errno = 0;
5027 START_PROFILE(SMBwriteX);
5029 if ((req->wct != 12) && (req->wct != 14)) {
5030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5031 goto out;
5034 numtowrite = SVAL(req->vwv+10, 0);
5035 smb_doff = SVAL(req->vwv+11, 0);
5036 smblen = smb_len(req->inbuf);
5038 if (req->unread_bytes > 0xFFFF ||
5039 (smblen > smb_doff &&
5040 smblen - smb_doff > 0xFFFF)) {
5041 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5044 if (req->unread_bytes) {
5045 /* Can't do a recvfile write on IPC$ */
5046 if (IS_IPC(conn)) {
5047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5048 goto out;
5050 if (numtowrite != req->unread_bytes) {
5051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5052 goto out;
5054 } else {
5056 * This already protects us against CVE-2017-12163.
5058 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5059 smb_doff + numtowrite > smblen) {
5060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5061 goto out;
5065 /* If it's an IPC, pass off the pipe handler. */
5066 if (IS_IPC(conn)) {
5067 if (req->unread_bytes) {
5068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5069 goto out;
5071 reply_pipe_write_and_X(req);
5072 goto out;
5075 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5076 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5077 write_through = BITSETW(req->vwv+7,0);
5079 if (!check_fsp(conn, req, fsp)) {
5080 goto out;
5083 if (!CHECK_WRITE(fsp)) {
5084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5085 goto out;
5088 data = smb_base(req->inbuf) + smb_doff;
5090 if(req->wct == 14) {
5092 * This is a large offset (64 bit) write.
5094 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5098 /* X/Open SMB protocol says that, unlike SMBwrite
5099 if the length is zero then NO truncation is
5100 done, just a write of zero. To truncate a file,
5101 use SMBwrite. */
5103 if(numtowrite == 0) {
5104 nwritten = 0;
5105 } else {
5106 if (req->unread_bytes == 0) {
5107 status = schedule_aio_write_and_X(conn,
5108 req,
5109 fsp,
5110 data,
5111 startpos,
5112 numtowrite);
5114 if (NT_STATUS_IS_OK(status)) {
5115 /* write scheduled - we're done. */
5116 goto out;
5118 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5119 /* Real error - report to client. */
5120 reply_nterror(req, status);
5121 goto out;
5123 /* NT_STATUS_RETRY - fall through to sync write. */
5126 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5127 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5128 &lock);
5130 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5131 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5132 goto out;
5135 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5136 saved_errno = errno;
5139 if(nwritten < 0) {
5140 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5141 goto out;
5144 if((nwritten == 0) && (numtowrite != 0)) {
5145 reply_nterror(req, NT_STATUS_DISK_FULL);
5146 goto out;
5149 reply_outbuf(req, 6, 0);
5150 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5151 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5152 SSVAL(req->outbuf,smb_vwv2,nwritten);
5153 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5155 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5156 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5158 status = sync_file(conn, fsp, write_through);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5161 fsp_str_dbg(fsp), nt_errstr(status)));
5162 reply_nterror(req, status);
5163 goto out;
5166 END_PROFILE(SMBwriteX);
5167 return;
5169 out:
5170 if (req->unread_bytes) {
5171 /* writeX failed. drain socket. */
5172 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5173 req->unread_bytes) {
5174 smb_panic("failed to drain pending bytes");
5176 req->unread_bytes = 0;
5179 END_PROFILE(SMBwriteX);
5180 return;
5183 /****************************************************************************
5184 Reply to a lseek.
5185 ****************************************************************************/
5187 void reply_lseek(struct smb_request *req)
5189 connection_struct *conn = req->conn;
5190 off_t startpos;
5191 off_t res= -1;
5192 int mode,umode;
5193 files_struct *fsp;
5195 START_PROFILE(SMBlseek);
5197 if (req->wct < 4) {
5198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5199 END_PROFILE(SMBlseek);
5200 return;
5203 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5205 if (!check_fsp(conn, req, fsp)) {
5206 return;
5209 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5211 mode = SVAL(req->vwv+1, 0) & 3;
5212 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5213 startpos = (off_t)IVALS(req->vwv+2, 0);
5215 switch (mode) {
5216 case 0:
5217 umode = SEEK_SET;
5218 res = startpos;
5219 break;
5220 case 1:
5221 umode = SEEK_CUR;
5222 res = fsp->fh->pos + startpos;
5223 break;
5224 case 2:
5225 umode = SEEK_END;
5226 break;
5227 default:
5228 umode = SEEK_SET;
5229 res = startpos;
5230 break;
5233 if (umode == SEEK_END) {
5234 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5235 if(errno == EINVAL) {
5236 off_t current_pos = startpos;
5238 if(fsp_stat(fsp) == -1) {
5239 reply_nterror(req,
5240 map_nt_error_from_unix(errno));
5241 END_PROFILE(SMBlseek);
5242 return;
5245 current_pos += fsp->fsp_name->st.st_ex_size;
5246 if(current_pos < 0)
5247 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5251 if(res == -1) {
5252 reply_nterror(req, map_nt_error_from_unix(errno));
5253 END_PROFILE(SMBlseek);
5254 return;
5258 fsp->fh->pos = res;
5260 reply_outbuf(req, 2, 0);
5261 SIVAL(req->outbuf,smb_vwv0,res);
5263 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5264 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5266 END_PROFILE(SMBlseek);
5267 return;
5270 /****************************************************************************
5271 Reply to a flush.
5272 ****************************************************************************/
5274 void reply_flush(struct smb_request *req)
5276 connection_struct *conn = req->conn;
5277 uint16_t fnum;
5278 files_struct *fsp;
5280 START_PROFILE(SMBflush);
5282 if (req->wct < 1) {
5283 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5284 return;
5287 fnum = SVAL(req->vwv+0, 0);
5288 fsp = file_fsp(req, fnum);
5290 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5291 return;
5294 if (!fsp) {
5295 file_sync_all(conn);
5296 } else {
5297 NTSTATUS status = sync_file(conn, fsp, True);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5300 fsp_str_dbg(fsp), nt_errstr(status)));
5301 reply_nterror(req, status);
5302 END_PROFILE(SMBflush);
5303 return;
5307 reply_outbuf(req, 0, 0);
5309 DEBUG(3,("flush\n"));
5310 END_PROFILE(SMBflush);
5311 return;
5314 /****************************************************************************
5315 Reply to a exit.
5316 conn POINTER CAN BE NULL HERE !
5317 ****************************************************************************/
5319 void reply_exit(struct smb_request *req)
5321 START_PROFILE(SMBexit);
5323 file_close_pid(req->sconn, req->smbpid, req->vuid);
5325 reply_outbuf(req, 0, 0);
5327 DEBUG(3,("exit\n"));
5329 END_PROFILE(SMBexit);
5330 return;
5333 struct reply_close_state {
5334 files_struct *fsp;
5335 struct smb_request *smbreq;
5338 static void do_smb1_close(struct tevent_req *req);
5340 void reply_close(struct smb_request *req)
5342 connection_struct *conn = req->conn;
5343 NTSTATUS status = NT_STATUS_OK;
5344 files_struct *fsp = NULL;
5345 START_PROFILE(SMBclose);
5347 if (req->wct < 3) {
5348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5349 END_PROFILE(SMBclose);
5350 return;
5353 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5356 * We can only use check_fsp if we know it's not a directory.
5359 if (!check_fsp_open(conn, req, fsp)) {
5360 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5361 END_PROFILE(SMBclose);
5362 return;
5365 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5366 fsp->is_directory ? "directory" : "file",
5367 fsp->fh->fd, fsp_fnum_dbg(fsp),
5368 conn->num_files_open));
5370 if (!fsp->is_directory) {
5371 time_t t;
5374 * Take care of any time sent in the close.
5377 t = srv_make_unix_date3(req->vwv+1);
5378 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5381 if (fsp->num_aio_requests != 0) {
5383 struct reply_close_state *state;
5385 DEBUG(10, ("closing with aio %u requests pending\n",
5386 fsp->num_aio_requests));
5389 * We depend on the aio_extra destructor to take care of this
5390 * close request once fsp->num_aio_request drops to 0.
5393 fsp->deferred_close = tevent_wait_send(
5394 fsp, fsp->conn->sconn->ev_ctx);
5395 if (fsp->deferred_close == NULL) {
5396 status = NT_STATUS_NO_MEMORY;
5397 goto done;
5400 state = talloc(fsp, struct reply_close_state);
5401 if (state == NULL) {
5402 TALLOC_FREE(fsp->deferred_close);
5403 status = NT_STATUS_NO_MEMORY;
5404 goto done;
5406 state->fsp = fsp;
5407 state->smbreq = talloc_move(fsp, &req);
5408 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5409 state);
5410 END_PROFILE(SMBclose);
5411 return;
5415 * close_file() returns the unix errno if an error was detected on
5416 * close - normally this is due to a disk full error. If not then it
5417 * was probably an I/O error.
5420 status = close_file(req, fsp, NORMAL_CLOSE);
5421 done:
5422 if (!NT_STATUS_IS_OK(status)) {
5423 reply_nterror(req, status);
5424 END_PROFILE(SMBclose);
5425 return;
5428 reply_outbuf(req, 0, 0);
5429 END_PROFILE(SMBclose);
5430 return;
5433 static void do_smb1_close(struct tevent_req *req)
5435 struct reply_close_state *state = tevent_req_callback_data(
5436 req, struct reply_close_state);
5437 struct smb_request *smbreq;
5438 NTSTATUS status;
5439 int ret;
5441 ret = tevent_wait_recv(req);
5442 TALLOC_FREE(req);
5443 if (ret != 0) {
5444 DEBUG(10, ("tevent_wait_recv returned %s\n",
5445 strerror(ret)));
5447 * Continue anyway, this should never happen
5452 * fsp->smb2_close_request right now is a talloc grandchild of
5453 * fsp. When we close_file(fsp), it would go with it. No chance to
5454 * reply...
5456 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5458 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5459 if (NT_STATUS_IS_OK(status)) {
5460 reply_outbuf(smbreq, 0, 0);
5461 } else {
5462 reply_nterror(smbreq, status);
5464 if (!srv_send_smb(smbreq->xconn,
5465 (char *)smbreq->outbuf,
5466 true,
5467 smbreq->seqnum+1,
5468 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5469 NULL)) {
5470 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5471 "failed.");
5473 TALLOC_FREE(smbreq);
5476 /****************************************************************************
5477 Reply to a writeclose (Core+ protocol).
5478 ****************************************************************************/
5480 void reply_writeclose(struct smb_request *req)
5482 connection_struct *conn = req->conn;
5483 size_t numtowrite;
5484 size_t remaining;
5485 ssize_t nwritten = -1;
5486 NTSTATUS close_status = NT_STATUS_OK;
5487 off_t startpos;
5488 const char *data;
5489 struct timespec mtime;
5490 files_struct *fsp;
5491 struct lock_struct lock;
5493 START_PROFILE(SMBwriteclose);
5495 if (req->wct < 6) {
5496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5497 END_PROFILE(SMBwriteclose);
5498 return;
5501 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5503 if (!check_fsp(conn, req, fsp)) {
5504 END_PROFILE(SMBwriteclose);
5505 return;
5507 if (!CHECK_WRITE(fsp)) {
5508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5509 END_PROFILE(SMBwriteclose);
5510 return;
5513 numtowrite = SVAL(req->vwv+1, 0);
5514 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5515 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5516 data = (const char *)req->buf + 1;
5519 * Ensure client isn't asking us to write more than
5520 * they sent. CVE-2017-12163.
5522 remaining = smbreq_bufrem(req, data);
5523 if (numtowrite > remaining) {
5524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5525 END_PROFILE(SMBwriteclose);
5526 return;
5529 if (fsp->print_file == NULL) {
5530 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5531 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5532 &lock);
5534 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5535 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5536 END_PROFILE(SMBwriteclose);
5537 return;
5541 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5543 set_close_write_time(fsp, mtime);
5546 * More insanity. W2K only closes the file if writelen > 0.
5547 * JRA.
5550 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5551 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5552 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5554 if (numtowrite) {
5555 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5556 "file %s\n", fsp_str_dbg(fsp)));
5557 close_status = close_file(req, fsp, NORMAL_CLOSE);
5558 fsp = NULL;
5561 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5562 reply_nterror(req, NT_STATUS_DISK_FULL);
5563 goto out;
5566 if(!NT_STATUS_IS_OK(close_status)) {
5567 reply_nterror(req, close_status);
5568 goto out;
5571 reply_outbuf(req, 1, 0);
5573 SSVAL(req->outbuf,smb_vwv0,nwritten);
5575 out:
5577 END_PROFILE(SMBwriteclose);
5578 return;
5581 #undef DBGC_CLASS
5582 #define DBGC_CLASS DBGC_LOCKING
5584 /****************************************************************************
5585 Reply to a lock.
5586 ****************************************************************************/
5588 void reply_lock(struct smb_request *req)
5590 connection_struct *conn = req->conn;
5591 uint64_t count,offset;
5592 NTSTATUS status;
5593 files_struct *fsp;
5594 struct byte_range_lock *br_lck = NULL;
5596 START_PROFILE(SMBlock);
5598 if (req->wct < 5) {
5599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5600 END_PROFILE(SMBlock);
5601 return;
5604 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5606 if (!check_fsp(conn, req, fsp)) {
5607 END_PROFILE(SMBlock);
5608 return;
5611 count = (uint64_t)IVAL(req->vwv+1, 0);
5612 offset = (uint64_t)IVAL(req->vwv+3, 0);
5614 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5615 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5617 br_lck = do_lock(req->sconn->msg_ctx,
5618 fsp,
5619 (uint64_t)req->smbpid,
5620 count,
5621 offset,
5622 WRITE_LOCK,
5623 WINDOWS_LOCK,
5624 False, /* Non-blocking lock. */
5625 &status,
5626 NULL);
5628 TALLOC_FREE(br_lck);
5630 if (NT_STATUS_V(status)) {
5631 reply_nterror(req, status);
5632 END_PROFILE(SMBlock);
5633 return;
5636 reply_outbuf(req, 0, 0);
5638 END_PROFILE(SMBlock);
5639 return;
5642 /****************************************************************************
5643 Reply to a unlock.
5644 ****************************************************************************/
5646 void reply_unlock(struct smb_request *req)
5648 connection_struct *conn = req->conn;
5649 uint64_t count,offset;
5650 NTSTATUS status;
5651 files_struct *fsp;
5653 START_PROFILE(SMBunlock);
5655 if (req->wct < 5) {
5656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5657 END_PROFILE(SMBunlock);
5658 return;
5661 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5663 if (!check_fsp(conn, req, fsp)) {
5664 END_PROFILE(SMBunlock);
5665 return;
5668 count = (uint64_t)IVAL(req->vwv+1, 0);
5669 offset = (uint64_t)IVAL(req->vwv+3, 0);
5671 status = do_unlock(req->sconn->msg_ctx,
5672 fsp,
5673 (uint64_t)req->smbpid,
5674 count,
5675 offset,
5676 WINDOWS_LOCK);
5678 if (NT_STATUS_V(status)) {
5679 reply_nterror(req, status);
5680 END_PROFILE(SMBunlock);
5681 return;
5684 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5685 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5687 reply_outbuf(req, 0, 0);
5689 END_PROFILE(SMBunlock);
5690 return;
5693 #undef DBGC_CLASS
5694 #define DBGC_CLASS DBGC_ALL
5696 /****************************************************************************
5697 Reply to a tdis.
5698 conn POINTER CAN BE NULL HERE !
5699 ****************************************************************************/
5701 void reply_tdis(struct smb_request *req)
5703 NTSTATUS status;
5704 connection_struct *conn = req->conn;
5705 struct smbXsrv_tcon *tcon;
5707 START_PROFILE(SMBtdis);
5709 if (!conn) {
5710 DEBUG(4,("Invalid connection in tdis\n"));
5711 reply_force_doserror(req, ERRSRV, ERRinvnid);
5712 END_PROFILE(SMBtdis);
5713 return;
5716 tcon = conn->tcon;
5717 req->conn = NULL;
5720 * TODO: cancel all outstanding requests on the tcon
5722 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5723 if (!NT_STATUS_IS_OK(status)) {
5724 DEBUG(0, ("reply_tdis: "
5725 "smbXsrv_tcon_disconnect() failed: %s\n",
5726 nt_errstr(status)));
5728 * If we hit this case, there is something completely
5729 * wrong, so we better disconnect the transport connection.
5731 END_PROFILE(SMBtdis);
5732 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5733 return;
5736 TALLOC_FREE(tcon);
5738 reply_outbuf(req, 0, 0);
5739 END_PROFILE(SMBtdis);
5740 return;
5743 /****************************************************************************
5744 Reply to a echo.
5745 conn POINTER CAN BE NULL HERE !
5746 ****************************************************************************/
5748 void reply_echo(struct smb_request *req)
5750 connection_struct *conn = req->conn;
5751 struct smb_perfcount_data local_pcd;
5752 struct smb_perfcount_data *cur_pcd;
5753 int smb_reverb;
5754 int seq_num;
5756 START_PROFILE(SMBecho);
5758 smb_init_perfcount_data(&local_pcd);
5760 if (req->wct < 1) {
5761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5762 END_PROFILE(SMBecho);
5763 return;
5766 smb_reverb = SVAL(req->vwv+0, 0);
5768 reply_outbuf(req, 1, req->buflen);
5770 /* copy any incoming data back out */
5771 if (req->buflen > 0) {
5772 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5775 if (smb_reverb > 100) {
5776 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5777 smb_reverb = 100;
5780 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5782 /* this makes sure we catch the request pcd */
5783 if (seq_num == smb_reverb) {
5784 cur_pcd = &req->pcd;
5785 } else {
5786 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5787 cur_pcd = &local_pcd;
5790 SSVAL(req->outbuf,smb_vwv0,seq_num);
5792 show_msg((char *)req->outbuf);
5793 if (!srv_send_smb(req->xconn,
5794 (char *)req->outbuf,
5795 true, req->seqnum+1,
5796 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5797 cur_pcd))
5798 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5801 DEBUG(3,("echo %d times\n", smb_reverb));
5803 TALLOC_FREE(req->outbuf);
5805 END_PROFILE(SMBecho);
5806 return;
5809 /****************************************************************************
5810 Reply to a printopen.
5811 ****************************************************************************/
5813 void reply_printopen(struct smb_request *req)
5815 connection_struct *conn = req->conn;
5816 files_struct *fsp;
5817 NTSTATUS status;
5819 START_PROFILE(SMBsplopen);
5821 if (req->wct < 2) {
5822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5823 END_PROFILE(SMBsplopen);
5824 return;
5827 if (!CAN_PRINT(conn)) {
5828 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5829 END_PROFILE(SMBsplopen);
5830 return;
5833 status = file_new(req, conn, &fsp);
5834 if(!NT_STATUS_IS_OK(status)) {
5835 reply_nterror(req, status);
5836 END_PROFILE(SMBsplopen);
5837 return;
5840 /* Open for exclusive use, write only. */
5841 status = print_spool_open(fsp, NULL, req->vuid);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 file_free(req, fsp);
5845 reply_nterror(req, status);
5846 END_PROFILE(SMBsplopen);
5847 return;
5850 reply_outbuf(req, 1, 0);
5851 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5853 DEBUG(3,("openprint fd=%d %s\n",
5854 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5856 END_PROFILE(SMBsplopen);
5857 return;
5860 /****************************************************************************
5861 Reply to a printclose.
5862 ****************************************************************************/
5864 void reply_printclose(struct smb_request *req)
5866 connection_struct *conn = req->conn;
5867 files_struct *fsp;
5868 NTSTATUS status;
5870 START_PROFILE(SMBsplclose);
5872 if (req->wct < 1) {
5873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5874 END_PROFILE(SMBsplclose);
5875 return;
5878 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5880 if (!check_fsp(conn, req, fsp)) {
5881 END_PROFILE(SMBsplclose);
5882 return;
5885 if (!CAN_PRINT(conn)) {
5886 reply_force_doserror(req, ERRSRV, ERRerror);
5887 END_PROFILE(SMBsplclose);
5888 return;
5891 DEBUG(3,("printclose fd=%d %s\n",
5892 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5894 status = close_file(req, fsp, NORMAL_CLOSE);
5896 if(!NT_STATUS_IS_OK(status)) {
5897 reply_nterror(req, status);
5898 END_PROFILE(SMBsplclose);
5899 return;
5902 reply_outbuf(req, 0, 0);
5904 END_PROFILE(SMBsplclose);
5905 return;
5908 /****************************************************************************
5909 Reply to a printqueue.
5910 ****************************************************************************/
5912 void reply_printqueue(struct smb_request *req)
5914 connection_struct *conn = req->conn;
5915 int max_count;
5916 int start_index;
5918 START_PROFILE(SMBsplretq);
5920 if (req->wct < 2) {
5921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5922 END_PROFILE(SMBsplretq);
5923 return;
5926 max_count = SVAL(req->vwv+0, 0);
5927 start_index = SVAL(req->vwv+1, 0);
5929 /* we used to allow the client to get the cnum wrong, but that
5930 is really quite gross and only worked when there was only
5931 one printer - I think we should now only accept it if they
5932 get it right (tridge) */
5933 if (!CAN_PRINT(conn)) {
5934 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5935 END_PROFILE(SMBsplretq);
5936 return;
5939 reply_outbuf(req, 2, 3);
5940 SSVAL(req->outbuf,smb_vwv0,0);
5941 SSVAL(req->outbuf,smb_vwv1,0);
5942 SCVAL(smb_buf(req->outbuf),0,1);
5943 SSVAL(smb_buf(req->outbuf),1,0);
5945 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5946 start_index, max_count));
5949 TALLOC_CTX *mem_ctx = talloc_tos();
5950 NTSTATUS status;
5951 WERROR werr;
5952 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5953 struct rpc_pipe_client *cli = NULL;
5954 struct dcerpc_binding_handle *b = NULL;
5955 struct policy_handle handle;
5956 struct spoolss_DevmodeContainer devmode_ctr;
5957 union spoolss_JobInfo *info;
5958 uint32_t count;
5959 uint32_t num_to_get;
5960 uint32_t first;
5961 uint32_t i;
5963 ZERO_STRUCT(handle);
5965 status = rpc_pipe_open_interface(mem_ctx,
5966 &ndr_table_spoolss,
5967 conn->session_info,
5968 conn->sconn->remote_address,
5969 conn->sconn->local_address,
5970 conn->sconn->msg_ctx,
5971 &cli);
5972 if (!NT_STATUS_IS_OK(status)) {
5973 DEBUG(0, ("reply_printqueue: "
5974 "could not connect to spoolss: %s\n",
5975 nt_errstr(status)));
5976 reply_nterror(req, status);
5977 goto out;
5979 b = cli->binding_handle;
5981 ZERO_STRUCT(devmode_ctr);
5983 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5984 sharename,
5985 NULL, devmode_ctr,
5986 SEC_FLAG_MAXIMUM_ALLOWED,
5987 &handle,
5988 &werr);
5989 if (!NT_STATUS_IS_OK(status)) {
5990 reply_nterror(req, status);
5991 goto out;
5993 if (!W_ERROR_IS_OK(werr)) {
5994 reply_nterror(req, werror_to_ntstatus(werr));
5995 goto out;
5998 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5999 &handle,
6000 0, /* firstjob */
6001 0xff, /* numjobs */
6002 2, /* level */
6003 0, /* offered */
6004 &count,
6005 &info);
6006 if (!W_ERROR_IS_OK(werr)) {
6007 reply_nterror(req, werror_to_ntstatus(werr));
6008 goto out;
6011 if (max_count > 0) {
6012 first = start_index;
6013 } else {
6014 first = start_index + max_count + 1;
6017 if (first >= count) {
6018 num_to_get = first;
6019 } else {
6020 num_to_get = first + MIN(ABS(max_count), count - first);
6023 for (i = first; i < num_to_get; i++) {
6024 char blob[28];
6025 char *p = blob;
6026 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6027 int qstatus;
6028 size_t len = 0;
6029 uint16_t qrapjobid = pjobid_to_rap(sharename,
6030 info[i].info2.job_id);
6032 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6033 qstatus = 2;
6034 } else {
6035 qstatus = 3;
6038 srv_put_dos_date2(p, 0, qtime);
6039 SCVAL(p, 4, qstatus);
6040 SSVAL(p, 5, qrapjobid);
6041 SIVAL(p, 7, info[i].info2.size);
6042 SCVAL(p, 11, 0);
6043 status = srvstr_push(blob, req->flags2, p+12,
6044 info[i].info2.notify_name, 16, STR_ASCII, &len);
6045 if (!NT_STATUS_IS_OK(status)) {
6046 reply_nterror(req, status);
6047 goto out;
6049 if (message_push_blob(
6050 &req->outbuf,
6051 data_blob_const(
6052 blob, sizeof(blob))) == -1) {
6053 reply_nterror(req, NT_STATUS_NO_MEMORY);
6054 goto out;
6058 if (count > 0) {
6059 SSVAL(req->outbuf,smb_vwv0,count);
6060 SSVAL(req->outbuf,smb_vwv1,
6061 (max_count>0?first+count:first-1));
6062 SCVAL(smb_buf(req->outbuf),0,1);
6063 SSVAL(smb_buf(req->outbuf),1,28*count);
6067 DEBUG(3, ("%u entries returned in queue\n",
6068 (unsigned)count));
6070 out:
6071 if (b && is_valid_policy_hnd(&handle)) {
6072 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6077 END_PROFILE(SMBsplretq);
6078 return;
6081 /****************************************************************************
6082 Reply to a printwrite.
6083 ****************************************************************************/
6085 void reply_printwrite(struct smb_request *req)
6087 connection_struct *conn = req->conn;
6088 int numtowrite;
6089 const char *data;
6090 files_struct *fsp;
6092 START_PROFILE(SMBsplwr);
6094 if (req->wct < 1) {
6095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6096 END_PROFILE(SMBsplwr);
6097 return;
6100 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6102 if (!check_fsp(conn, req, fsp)) {
6103 END_PROFILE(SMBsplwr);
6104 return;
6107 if (!fsp->print_file) {
6108 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6109 END_PROFILE(SMBsplwr);
6110 return;
6113 if (!CHECK_WRITE(fsp)) {
6114 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6115 END_PROFILE(SMBsplwr);
6116 return;
6119 numtowrite = SVAL(req->buf, 1);
6122 * This already protects us against CVE-2017-12163.
6124 if (req->buflen < numtowrite + 3) {
6125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6126 END_PROFILE(SMBsplwr);
6127 return;
6130 data = (const char *)req->buf + 3;
6132 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6133 reply_nterror(req, map_nt_error_from_unix(errno));
6134 END_PROFILE(SMBsplwr);
6135 return;
6138 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6140 END_PROFILE(SMBsplwr);
6141 return;
6144 /****************************************************************************
6145 Reply to a mkdir.
6146 ****************************************************************************/
6148 void reply_mkdir(struct smb_request *req)
6150 connection_struct *conn = req->conn;
6151 struct smb_filename *smb_dname = NULL;
6152 char *directory = NULL;
6153 NTSTATUS status;
6154 uint32_t ucf_flags;
6155 TALLOC_CTX *ctx = talloc_tos();
6157 START_PROFILE(SMBmkdir);
6159 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6160 STR_TERMINATE, &status);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 reply_nterror(req, status);
6163 goto out;
6166 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6167 status = filename_convert(ctx, conn,
6168 directory,
6169 ucf_flags,
6170 NULL,
6171 &smb_dname);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6174 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6175 ERRSRV, ERRbadpath);
6176 goto out;
6178 reply_nterror(req, status);
6179 goto out;
6182 status = create_directory(conn, req, smb_dname);
6184 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6186 if (!NT_STATUS_IS_OK(status)) {
6188 if (!use_nt_status()
6189 && NT_STATUS_EQUAL(status,
6190 NT_STATUS_OBJECT_NAME_COLLISION)) {
6192 * Yes, in the DOS error code case we get a
6193 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6194 * samba4 torture test.
6196 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6199 reply_nterror(req, status);
6200 goto out;
6203 reply_outbuf(req, 0, 0);
6205 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6206 out:
6207 TALLOC_FREE(smb_dname);
6208 END_PROFILE(SMBmkdir);
6209 return;
6212 /****************************************************************************
6213 Reply to a rmdir.
6214 ****************************************************************************/
6216 void reply_rmdir(struct smb_request *req)
6218 connection_struct *conn = req->conn;
6219 struct smb_filename *smb_dname = NULL;
6220 char *directory = NULL;
6221 NTSTATUS status;
6222 TALLOC_CTX *ctx = talloc_tos();
6223 files_struct *fsp = NULL;
6224 int info = 0;
6225 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6226 struct smbd_server_connection *sconn = req->sconn;
6228 START_PROFILE(SMBrmdir);
6230 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6231 STR_TERMINATE, &status);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 reply_nterror(req, status);
6234 goto out;
6237 status = filename_convert(ctx, conn,
6238 directory,
6239 ucf_flags,
6240 NULL,
6241 &smb_dname);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6244 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6245 ERRSRV, ERRbadpath);
6246 goto out;
6248 reply_nterror(req, status);
6249 goto out;
6252 if (is_ntfs_stream_smb_fname(smb_dname)) {
6253 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6254 goto out;
6257 status = SMB_VFS_CREATE_FILE(
6258 conn, /* conn */
6259 req, /* req */
6260 0, /* root_dir_fid */
6261 smb_dname, /* fname */
6262 DELETE_ACCESS, /* access_mask */
6263 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6264 FILE_SHARE_DELETE),
6265 FILE_OPEN, /* create_disposition*/
6266 FILE_DIRECTORY_FILE, /* create_options */
6267 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6268 0, /* oplock_request */
6269 NULL, /* lease */
6270 0, /* allocation_size */
6271 0, /* private_flags */
6272 NULL, /* sd */
6273 NULL, /* ea_list */
6274 &fsp, /* result */
6275 &info, /* pinfo */
6276 NULL, NULL); /* create context */
6278 if (!NT_STATUS_IS_OK(status)) {
6279 if (open_was_deferred(req->xconn, req->mid)) {
6280 /* We have re-scheduled this call. */
6281 goto out;
6283 reply_nterror(req, status);
6284 goto out;
6287 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 close_file(req, fsp, ERROR_CLOSE);
6290 reply_nterror(req, status);
6291 goto out;
6294 if (!set_delete_on_close(fsp, true,
6295 conn->session_info->security_token,
6296 conn->session_info->unix_token)) {
6297 close_file(req, fsp, ERROR_CLOSE);
6298 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6299 goto out;
6302 status = close_file(req, fsp, NORMAL_CLOSE);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 reply_nterror(req, status);
6305 } else {
6306 reply_outbuf(req, 0, 0);
6309 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6311 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6312 out:
6313 TALLOC_FREE(smb_dname);
6314 END_PROFILE(SMBrmdir);
6315 return;
6318 /*******************************************************************
6319 Resolve wildcards in a filename rename.
6320 ********************************************************************/
6322 static bool resolve_wildcards(TALLOC_CTX *ctx,
6323 const char *name1,
6324 const char *name2,
6325 char **pp_newname)
6327 char *name2_copy = NULL;
6328 char *root1 = NULL;
6329 char *root2 = NULL;
6330 char *ext1 = NULL;
6331 char *ext2 = NULL;
6332 char *p,*p2, *pname1, *pname2;
6334 name2_copy = talloc_strdup(ctx, name2);
6335 if (!name2_copy) {
6336 return False;
6339 pname1 = strrchr_m(name1,'/');
6340 pname2 = strrchr_m(name2_copy,'/');
6342 if (!pname1 || !pname2) {
6343 return False;
6346 /* Truncate the copy of name2 at the last '/' */
6347 *pname2 = '\0';
6349 /* Now go past the '/' */
6350 pname1++;
6351 pname2++;
6353 root1 = talloc_strdup(ctx, pname1);
6354 root2 = talloc_strdup(ctx, pname2);
6356 if (!root1 || !root2) {
6357 return False;
6360 p = strrchr_m(root1,'.');
6361 if (p) {
6362 *p = 0;
6363 ext1 = talloc_strdup(ctx, p+1);
6364 } else {
6365 ext1 = talloc_strdup(ctx, "");
6367 p = strrchr_m(root2,'.');
6368 if (p) {
6369 *p = 0;
6370 ext2 = talloc_strdup(ctx, p+1);
6371 } else {
6372 ext2 = talloc_strdup(ctx, "");
6375 if (!ext1 || !ext2) {
6376 return False;
6379 p = root1;
6380 p2 = root2;
6381 while (*p2) {
6382 if (*p2 == '?') {
6383 /* Hmmm. Should this be mb-aware ? */
6384 *p2 = *p;
6385 p2++;
6386 } else if (*p2 == '*') {
6387 *p2 = '\0';
6388 root2 = talloc_asprintf(ctx, "%s%s",
6389 root2,
6391 if (!root2) {
6392 return False;
6394 break;
6395 } else {
6396 p2++;
6398 if (*p) {
6399 p++;
6403 p = ext1;
6404 p2 = ext2;
6405 while (*p2) {
6406 if (*p2 == '?') {
6407 /* Hmmm. Should this be mb-aware ? */
6408 *p2 = *p;
6409 p2++;
6410 } else if (*p2 == '*') {
6411 *p2 = '\0';
6412 ext2 = talloc_asprintf(ctx, "%s%s",
6413 ext2,
6415 if (!ext2) {
6416 return False;
6418 break;
6419 } else {
6420 p2++;
6422 if (*p) {
6423 p++;
6427 if (*ext2) {
6428 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6429 name2_copy,
6430 root2,
6431 ext2);
6432 } else {
6433 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6434 name2_copy,
6435 root2);
6438 if (!*pp_newname) {
6439 return False;
6442 return True;
6445 /****************************************************************************
6446 Ensure open files have their names updated. Updated to notify other smbd's
6447 asynchronously.
6448 ****************************************************************************/
6450 static void rename_open_files(connection_struct *conn,
6451 struct share_mode_lock *lck,
6452 struct file_id id,
6453 uint32_t orig_name_hash,
6454 const struct smb_filename *smb_fname_dst)
6456 files_struct *fsp;
6457 bool did_rename = False;
6458 NTSTATUS status;
6459 uint32_t new_name_hash = 0;
6461 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6462 fsp = file_find_di_next(fsp)) {
6463 /* fsp_name is a relative path under the fsp. To change this for other
6464 sharepaths we need to manipulate relative paths. */
6465 /* TODO - create the absolute path and manipulate the newname
6466 relative to the sharepath. */
6467 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6468 continue;
6470 if (fsp->name_hash != orig_name_hash) {
6471 continue;
6473 DEBUG(10, ("rename_open_files: renaming file %s "
6474 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6475 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6476 smb_fname_str_dbg(smb_fname_dst)));
6478 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6479 if (NT_STATUS_IS_OK(status)) {
6480 did_rename = True;
6481 new_name_hash = fsp->name_hash;
6485 if (!did_rename) {
6486 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6487 "for %s\n", file_id_string_tos(&id),
6488 smb_fname_str_dbg(smb_fname_dst)));
6491 /* Send messages to all smbd's (not ourself) that the name has changed. */
6492 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6493 orig_name_hash, new_name_hash,
6494 smb_fname_dst);
6498 /****************************************************************************
6499 We need to check if the source path is a parent directory of the destination
6500 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6501 refuse the rename with a sharing violation. Under UNIX the above call can
6502 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6503 probably need to check that the client is a Windows one before disallowing
6504 this as a UNIX client (one with UNIX extensions) can know the source is a
6505 symlink and make this decision intelligently. Found by an excellent bug
6506 report from <AndyLiebman@aol.com>.
6507 ****************************************************************************/
6509 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6510 const struct smb_filename *smb_fname_dst)
6512 const char *psrc = smb_fname_src->base_name;
6513 const char *pdst = smb_fname_dst->base_name;
6514 size_t slen;
6516 if (psrc[0] == '.' && psrc[1] == '/') {
6517 psrc += 2;
6519 if (pdst[0] == '.' && pdst[1] == '/') {
6520 pdst += 2;
6522 if ((slen = strlen(psrc)) > strlen(pdst)) {
6523 return False;
6525 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6529 * Do the notify calls from a rename
6532 static void notify_rename(connection_struct *conn, bool is_dir,
6533 const struct smb_filename *smb_fname_src,
6534 const struct smb_filename *smb_fname_dst)
6536 char *parent_dir_src = NULL;
6537 char *parent_dir_dst = NULL;
6538 uint32_t mask;
6540 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6541 : FILE_NOTIFY_CHANGE_FILE_NAME;
6543 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6544 &parent_dir_src, NULL) ||
6545 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6546 &parent_dir_dst, NULL)) {
6547 goto out;
6550 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6551 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6552 smb_fname_src->base_name);
6553 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6554 smb_fname_dst->base_name);
6556 else {
6557 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6558 smb_fname_src->base_name);
6559 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6560 smb_fname_dst->base_name);
6563 /* this is a strange one. w2k3 gives an additional event for
6564 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6565 files, but not directories */
6566 if (!is_dir) {
6567 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6568 FILE_NOTIFY_CHANGE_ATTRIBUTES
6569 |FILE_NOTIFY_CHANGE_CREATION,
6570 smb_fname_dst->base_name);
6572 out:
6573 TALLOC_FREE(parent_dir_src);
6574 TALLOC_FREE(parent_dir_dst);
6577 /****************************************************************************
6578 Returns an error if the parent directory for a filename is open in an
6579 incompatible way.
6580 ****************************************************************************/
6582 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6583 const struct smb_filename *smb_fname_dst_in)
6585 char *parent_dir = NULL;
6586 struct smb_filename smb_fname_parent;
6587 struct file_id id;
6588 files_struct *fsp = NULL;
6589 int ret;
6591 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6592 &parent_dir, NULL)) {
6593 return NT_STATUS_NO_MEMORY;
6595 ZERO_STRUCT(smb_fname_parent);
6596 smb_fname_parent.base_name = parent_dir;
6598 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6599 if (ret == -1) {
6600 return map_nt_error_from_unix(errno);
6604 * We're only checking on this smbd here, mostly good
6605 * enough.. and will pass tests.
6608 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6609 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6610 fsp = file_find_di_next(fsp)) {
6611 if (fsp->access_mask & DELETE_ACCESS) {
6612 return NT_STATUS_SHARING_VIOLATION;
6615 return NT_STATUS_OK;
6618 /****************************************************************************
6619 Rename an open file - given an fsp.
6620 ****************************************************************************/
6622 NTSTATUS rename_internals_fsp(connection_struct *conn,
6623 files_struct *fsp,
6624 const struct smb_filename *smb_fname_dst_in,
6625 uint32_t attrs,
6626 bool replace_if_exists)
6628 TALLOC_CTX *ctx = talloc_tos();
6629 struct smb_filename *smb_fname_dst = NULL;
6630 NTSTATUS status = NT_STATUS_OK;
6631 struct share_mode_lock *lck = NULL;
6632 uint32_t access_mask = SEC_DIR_ADD_FILE;
6633 bool dst_exists, old_is_stream, new_is_stream;
6635 status = check_name(conn, smb_fname_dst_in);
6636 if (!NT_STATUS_IS_OK(status)) {
6637 return status;
6640 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6641 if (!NT_STATUS_IS_OK(status)) {
6642 return status;
6645 /* Make a copy of the dst smb_fname structs */
6647 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6648 if (smb_fname_dst == NULL) {
6649 status = NT_STATUS_NO_MEMORY;
6650 goto out;
6654 * Check for special case with case preserving and not
6655 * case sensitive. If the new last component differs from the original
6656 * last component only by case, then we should allow
6657 * the rename (user is trying to change the case of the
6658 * filename).
6660 if (!conn->case_sensitive && conn->case_preserve &&
6661 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6662 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6663 char *fname_dst_parent = NULL;
6664 const char *fname_dst_lcomp = NULL;
6665 char *orig_lcomp_path = NULL;
6666 char *orig_lcomp_stream = NULL;
6667 bool ok = true;
6670 * Split off the last component of the processed
6671 * destination name. We will compare this to
6672 * the split components of smb_fname_dst->original_lcomp.
6674 if (!parent_dirname(ctx,
6675 smb_fname_dst->base_name,
6676 &fname_dst_parent,
6677 &fname_dst_lcomp)) {
6678 status = NT_STATUS_NO_MEMORY;
6679 goto out;
6683 * The original_lcomp component contains
6684 * the last_component of the path + stream
6685 * name (if a stream exists).
6687 * Split off the stream name so we
6688 * can check them separately.
6691 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6692 /* POSIX - no stream component. */
6693 orig_lcomp_path = talloc_strdup(ctx,
6694 smb_fname_dst->original_lcomp);
6695 if (orig_lcomp_path == NULL) {
6696 ok = false;
6698 } else {
6699 ok = split_stream_filename(ctx,
6700 smb_fname_dst->original_lcomp,
6701 &orig_lcomp_path,
6702 &orig_lcomp_stream);
6705 if (!ok) {
6706 TALLOC_FREE(fname_dst_parent);
6707 status = NT_STATUS_NO_MEMORY;
6708 goto out;
6711 /* If the base names only differ by case, use original. */
6712 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6713 char *tmp;
6715 * Replace the modified last component with the
6716 * original.
6718 if (!ISDOT(fname_dst_parent)) {
6719 tmp = talloc_asprintf(smb_fname_dst,
6720 "%s/%s",
6721 fname_dst_parent,
6722 orig_lcomp_path);
6723 } else {
6724 tmp = talloc_strdup(smb_fname_dst,
6725 orig_lcomp_path);
6727 if (tmp == NULL) {
6728 status = NT_STATUS_NO_MEMORY;
6729 TALLOC_FREE(fname_dst_parent);
6730 TALLOC_FREE(orig_lcomp_path);
6731 TALLOC_FREE(orig_lcomp_stream);
6732 goto out;
6734 TALLOC_FREE(smb_fname_dst->base_name);
6735 smb_fname_dst->base_name = tmp;
6738 /* If the stream_names only differ by case, use original. */
6739 if(!strcsequal(smb_fname_dst->stream_name,
6740 orig_lcomp_stream)) {
6741 /* Use the original stream. */
6742 char *tmp = talloc_strdup(smb_fname_dst,
6743 orig_lcomp_stream);
6744 if (tmp == NULL) {
6745 status = NT_STATUS_NO_MEMORY;
6746 TALLOC_FREE(fname_dst_parent);
6747 TALLOC_FREE(orig_lcomp_path);
6748 TALLOC_FREE(orig_lcomp_stream);
6749 goto out;
6751 TALLOC_FREE(smb_fname_dst->stream_name);
6752 smb_fname_dst->stream_name = tmp;
6754 TALLOC_FREE(fname_dst_parent);
6755 TALLOC_FREE(orig_lcomp_path);
6756 TALLOC_FREE(orig_lcomp_stream);
6760 * If the src and dest names are identical - including case,
6761 * don't do the rename, just return success.
6764 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6765 strcsequal(fsp->fsp_name->stream_name,
6766 smb_fname_dst->stream_name)) {
6767 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6768 "- returning success\n",
6769 smb_fname_str_dbg(smb_fname_dst)));
6770 status = NT_STATUS_OK;
6771 goto out;
6774 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6775 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6777 /* Return the correct error code if both names aren't streams. */
6778 if (!old_is_stream && new_is_stream) {
6779 status = NT_STATUS_OBJECT_NAME_INVALID;
6780 goto out;
6783 if (old_is_stream && !new_is_stream) {
6784 status = NT_STATUS_INVALID_PARAMETER;
6785 goto out;
6788 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6790 if(!replace_if_exists && dst_exists) {
6791 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6792 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6793 smb_fname_str_dbg(smb_fname_dst)));
6794 status = NT_STATUS_OBJECT_NAME_COLLISION;
6795 goto out;
6798 if (dst_exists) {
6799 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6800 &smb_fname_dst->st);
6801 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6802 fileid);
6803 /* The file can be open when renaming a stream */
6804 if (dst_fsp && !new_is_stream) {
6805 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6806 status = NT_STATUS_ACCESS_DENIED;
6807 goto out;
6811 /* Ensure we have a valid stat struct for the source. */
6812 status = vfs_stat_fsp(fsp);
6813 if (!NT_STATUS_IS_OK(status)) {
6814 goto out;
6817 status = can_rename(conn, fsp, attrs);
6819 if (!NT_STATUS_IS_OK(status)) {
6820 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6821 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6822 smb_fname_str_dbg(smb_fname_dst)));
6823 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6824 status = NT_STATUS_ACCESS_DENIED;
6825 goto out;
6828 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6829 status = NT_STATUS_ACCESS_DENIED;
6830 goto out;
6833 /* Do we have rights to move into the destination ? */
6834 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6835 /* We're moving a directory. */
6836 access_mask = SEC_DIR_ADD_SUBDIR;
6838 status = check_parent_access(conn,
6839 smb_fname_dst,
6840 access_mask);
6841 if (!NT_STATUS_IS_OK(status)) {
6842 DBG_INFO("check_parent_access on "
6843 "dst %s returned %s\n",
6844 smb_fname_str_dbg(smb_fname_dst),
6845 nt_errstr(status));
6846 goto out;
6849 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6852 * We have the file open ourselves, so not being able to get the
6853 * corresponding share mode lock is a fatal error.
6856 SMB_ASSERT(lck != NULL);
6858 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6859 uint32_t create_options = fsp->fh->private_options;
6861 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6862 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6863 smb_fname_str_dbg(smb_fname_dst)));
6865 if (!fsp->is_directory &&
6866 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6867 (lp_map_archive(SNUM(conn)) ||
6868 lp_store_dos_attributes(SNUM(conn)))) {
6869 /* We must set the archive bit on the newly
6870 renamed file. */
6871 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6872 uint32_t old_dosmode = dos_mode(conn,
6873 smb_fname_dst);
6874 file_set_dosmode(conn,
6875 smb_fname_dst,
6876 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6877 NULL,
6878 true);
6882 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6883 smb_fname_dst);
6885 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6886 smb_fname_dst);
6889 * A rename acts as a new file create w.r.t. allowing an initial delete
6890 * on close, probably because in Windows there is a new handle to the
6891 * new file. If initial delete on close was requested but not
6892 * originally set, we need to set it here. This is probably not 100% correct,
6893 * but will work for the CIFSFS client which in non-posix mode
6894 * depends on these semantics. JRA.
6897 if (create_options & FILE_DELETE_ON_CLOSE) {
6898 status = can_set_delete_on_close(fsp, 0);
6900 if (NT_STATUS_IS_OK(status)) {
6901 /* Note that here we set the *inital* delete on close flag,
6902 * not the regular one. The magic gets handled in close. */
6903 fsp->initial_delete_on_close = True;
6906 TALLOC_FREE(lck);
6907 status = NT_STATUS_OK;
6908 goto out;
6911 TALLOC_FREE(lck);
6913 if (errno == ENOTDIR || errno == EISDIR) {
6914 status = NT_STATUS_OBJECT_NAME_COLLISION;
6915 } else {
6916 status = map_nt_error_from_unix(errno);
6919 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6920 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6921 smb_fname_str_dbg(smb_fname_dst)));
6923 out:
6924 TALLOC_FREE(smb_fname_dst);
6926 return status;
6929 /****************************************************************************
6930 The guts of the rename command, split out so it may be called by the NT SMB
6931 code.
6932 ****************************************************************************/
6934 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6935 connection_struct *conn,
6936 struct smb_request *req,
6937 struct smb_filename *smb_fname_src,
6938 struct smb_filename *smb_fname_dst,
6939 uint32_t attrs,
6940 bool replace_if_exists,
6941 bool src_has_wild,
6942 bool dest_has_wild,
6943 uint32_t access_mask)
6945 char *fname_src_dir = NULL;
6946 struct smb_filename *smb_fname_src_dir = NULL;
6947 char *fname_src_mask = NULL;
6948 int count=0;
6949 NTSTATUS status = NT_STATUS_OK;
6950 struct smb_Dir *dir_hnd = NULL;
6951 const char *dname = NULL;
6952 char *talloced = NULL;
6953 long offset = 0;
6954 int create_options = 0;
6955 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6956 int rc;
6959 * Split the old name into directory and last component
6960 * strings. Note that unix_convert may have stripped off a
6961 * leading ./ from both name and newname if the rename is
6962 * at the root of the share. We need to make sure either both
6963 * name and newname contain a / character or neither of them do
6964 * as this is checked in resolve_wildcards().
6967 /* Split up the directory from the filename/mask. */
6968 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6969 &fname_src_dir, &fname_src_mask);
6970 if (!NT_STATUS_IS_OK(status)) {
6971 status = NT_STATUS_NO_MEMORY;
6972 goto out;
6976 * We should only check the mangled cache
6977 * here if unix_convert failed. This means
6978 * that the path in 'mask' doesn't exist
6979 * on the file system and so we need to look
6980 * for a possible mangle. This patch from
6981 * Tine Smukavec <valentin.smukavec@hermes.si>.
6984 if (!VALID_STAT(smb_fname_src->st) &&
6985 mangle_is_mangled(fname_src_mask, conn->params)) {
6986 char *new_mask = NULL;
6987 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6988 conn->params);
6989 if (new_mask) {
6990 TALLOC_FREE(fname_src_mask);
6991 fname_src_mask = new_mask;
6995 if (!src_has_wild) {
6996 files_struct *fsp;
6999 * Only one file needs to be renamed. Append the mask back
7000 * onto the directory.
7002 TALLOC_FREE(smb_fname_src->base_name);
7003 if (ISDOT(fname_src_dir)) {
7004 /* Ensure we use canonical names on open. */
7005 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7006 "%s",
7007 fname_src_mask);
7008 } else {
7009 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7010 "%s/%s",
7011 fname_src_dir,
7012 fname_src_mask);
7014 if (!smb_fname_src->base_name) {
7015 status = NT_STATUS_NO_MEMORY;
7016 goto out;
7019 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7020 "case_preserve = %d, short case preserve = %d, "
7021 "directory = %s, newname = %s, "
7022 "last_component_dest = %s\n",
7023 conn->case_sensitive, conn->case_preserve,
7024 conn->short_case_preserve,
7025 smb_fname_str_dbg(smb_fname_src),
7026 smb_fname_str_dbg(smb_fname_dst),
7027 smb_fname_dst->original_lcomp));
7029 /* The dest name still may have wildcards. */
7030 if (dest_has_wild) {
7031 char *fname_dst_mod = NULL;
7032 if (!resolve_wildcards(smb_fname_dst,
7033 smb_fname_src->base_name,
7034 smb_fname_dst->base_name,
7035 &fname_dst_mod)) {
7036 DEBUG(6, ("rename_internals: resolve_wildcards "
7037 "%s %s failed\n",
7038 smb_fname_src->base_name,
7039 smb_fname_dst->base_name));
7040 status = NT_STATUS_NO_MEMORY;
7041 goto out;
7043 TALLOC_FREE(smb_fname_dst->base_name);
7044 smb_fname_dst->base_name = fname_dst_mod;
7047 ZERO_STRUCT(smb_fname_src->st);
7048 if (posix_pathnames) {
7049 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7050 } else {
7051 rc = SMB_VFS_STAT(conn, smb_fname_src);
7053 if (rc == -1) {
7054 status = map_nt_error_from_unix_common(errno);
7055 goto out;
7058 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7059 create_options |= FILE_DIRECTORY_FILE;
7062 status = SMB_VFS_CREATE_FILE(
7063 conn, /* conn */
7064 req, /* req */
7065 0, /* root_dir_fid */
7066 smb_fname_src, /* fname */
7067 access_mask, /* access_mask */
7068 (FILE_SHARE_READ | /* share_access */
7069 FILE_SHARE_WRITE),
7070 FILE_OPEN, /* create_disposition*/
7071 create_options, /* create_options */
7072 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7073 0, /* oplock_request */
7074 NULL, /* lease */
7075 0, /* allocation_size */
7076 0, /* private_flags */
7077 NULL, /* sd */
7078 NULL, /* ea_list */
7079 &fsp, /* result */
7080 NULL, /* pinfo */
7081 NULL, NULL); /* create context */
7083 if (!NT_STATUS_IS_OK(status)) {
7084 DEBUG(3, ("Could not open rename source %s: %s\n",
7085 smb_fname_str_dbg(smb_fname_src),
7086 nt_errstr(status)));
7087 goto out;
7090 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7091 attrs, replace_if_exists);
7093 close_file(req, fsp, NORMAL_CLOSE);
7095 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7096 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7097 smb_fname_str_dbg(smb_fname_dst)));
7099 goto out;
7103 * Wildcards - process each file that matches.
7105 if (strequal(fname_src_mask, "????????.???")) {
7106 TALLOC_FREE(fname_src_mask);
7107 fname_src_mask = talloc_strdup(ctx, "*");
7108 if (!fname_src_mask) {
7109 status = NT_STATUS_NO_MEMORY;
7110 goto out;
7114 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7115 fname_src_dir,
7116 NULL,
7117 NULL,
7118 smb_fname_src->flags);
7119 if (smb_fname_src_dir == NULL) {
7120 status = NT_STATUS_NO_MEMORY;
7121 goto out;
7124 status = check_name(conn, smb_fname_src_dir);
7125 if (!NT_STATUS_IS_OK(status)) {
7126 goto out;
7129 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
7130 attrs);
7131 if (dir_hnd == NULL) {
7132 status = map_nt_error_from_unix(errno);
7133 goto out;
7136 status = NT_STATUS_NO_SUCH_FILE;
7138 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7139 * - gentest fix. JRA
7142 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7143 &talloced))) {
7144 files_struct *fsp = NULL;
7145 char *destname = NULL;
7146 bool sysdir_entry = False;
7148 /* Quick check for "." and ".." */
7149 if (ISDOT(dname) || ISDOTDOT(dname)) {
7150 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7151 sysdir_entry = True;
7152 } else {
7153 TALLOC_FREE(talloced);
7154 continue;
7158 if (!is_visible_file(conn, fname_src_dir, dname,
7159 &smb_fname_src->st, false)) {
7160 TALLOC_FREE(talloced);
7161 continue;
7164 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7165 TALLOC_FREE(talloced);
7166 continue;
7169 if (sysdir_entry) {
7170 status = NT_STATUS_OBJECT_NAME_INVALID;
7171 break;
7174 TALLOC_FREE(smb_fname_src->base_name);
7175 if (ISDOT(fname_src_dir)) {
7176 /* Ensure we use canonical names on open. */
7177 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7178 "%s",
7179 dname);
7180 } else {
7181 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7182 "%s/%s",
7183 fname_src_dir,
7184 dname);
7186 if (!smb_fname_src->base_name) {
7187 status = NT_STATUS_NO_MEMORY;
7188 goto out;
7191 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7192 smb_fname_dst->base_name,
7193 &destname)) {
7194 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7195 smb_fname_src->base_name, destname));
7196 TALLOC_FREE(talloced);
7197 continue;
7199 if (!destname) {
7200 status = NT_STATUS_NO_MEMORY;
7201 goto out;
7204 TALLOC_FREE(smb_fname_dst->base_name);
7205 smb_fname_dst->base_name = destname;
7207 ZERO_STRUCT(smb_fname_src->st);
7208 if (posix_pathnames) {
7209 SMB_VFS_LSTAT(conn, smb_fname_src);
7210 } else {
7211 SMB_VFS_STAT(conn, smb_fname_src);
7214 create_options = 0;
7216 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7217 create_options |= FILE_DIRECTORY_FILE;
7220 status = SMB_VFS_CREATE_FILE(
7221 conn, /* conn */
7222 req, /* req */
7223 0, /* root_dir_fid */
7224 smb_fname_src, /* fname */
7225 access_mask, /* access_mask */
7226 (FILE_SHARE_READ | /* share_access */
7227 FILE_SHARE_WRITE),
7228 FILE_OPEN, /* create_disposition*/
7229 create_options, /* create_options */
7230 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7231 0, /* oplock_request */
7232 NULL, /* lease */
7233 0, /* allocation_size */
7234 0, /* private_flags */
7235 NULL, /* sd */
7236 NULL, /* ea_list */
7237 &fsp, /* result */
7238 NULL, /* pinfo */
7239 NULL, NULL); /* create context */
7241 if (!NT_STATUS_IS_OK(status)) {
7242 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7243 "returned %s rename %s -> %s\n",
7244 nt_errstr(status),
7245 smb_fname_str_dbg(smb_fname_src),
7246 smb_fname_str_dbg(smb_fname_dst)));
7247 break;
7250 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7251 dname);
7252 if (!smb_fname_dst->original_lcomp) {
7253 status = NT_STATUS_NO_MEMORY;
7254 goto out;
7257 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7258 attrs, replace_if_exists);
7260 close_file(req, fsp, NORMAL_CLOSE);
7262 if (!NT_STATUS_IS_OK(status)) {
7263 DEBUG(3, ("rename_internals_fsp returned %s for "
7264 "rename %s -> %s\n", nt_errstr(status),
7265 smb_fname_str_dbg(smb_fname_src),
7266 smb_fname_str_dbg(smb_fname_dst)));
7267 break;
7270 count++;
7272 DEBUG(3,("rename_internals: doing rename on %s -> "
7273 "%s\n", smb_fname_str_dbg(smb_fname_src),
7274 smb_fname_str_dbg(smb_fname_src)));
7275 TALLOC_FREE(talloced);
7277 TALLOC_FREE(dir_hnd);
7279 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7280 status = map_nt_error_from_unix(errno);
7283 out:
7284 TALLOC_FREE(talloced);
7285 TALLOC_FREE(smb_fname_src_dir);
7286 TALLOC_FREE(fname_src_dir);
7287 TALLOC_FREE(fname_src_mask);
7288 return status;
7291 /****************************************************************************
7292 Reply to a mv.
7293 ****************************************************************************/
7295 void reply_mv(struct smb_request *req)
7297 connection_struct *conn = req->conn;
7298 char *name = NULL;
7299 char *newname = NULL;
7300 const char *p;
7301 uint32_t attrs;
7302 NTSTATUS status;
7303 bool src_has_wcard = False;
7304 bool dest_has_wcard = False;
7305 TALLOC_CTX *ctx = talloc_tos();
7306 struct smb_filename *smb_fname_src = NULL;
7307 struct smb_filename *smb_fname_dst = NULL;
7308 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
7309 (req->posix_pathnames ?
7310 UCF_UNIX_NAME_LOOKUP :
7311 UCF_COND_ALLOW_WCARD_LCOMP);
7312 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
7313 UCF_SAVE_LCOMP |
7314 (req->posix_pathnames ?
7316 UCF_COND_ALLOW_WCARD_LCOMP);
7317 bool stream_rename = false;
7319 START_PROFILE(SMBmv);
7321 if (req->wct < 1) {
7322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7323 goto out;
7326 attrs = SVAL(req->vwv+0, 0);
7328 p = (const char *)req->buf + 1;
7329 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7330 &status, &src_has_wcard);
7331 if (!NT_STATUS_IS_OK(status)) {
7332 reply_nterror(req, status);
7333 goto out;
7335 p++;
7336 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7337 &status, &dest_has_wcard);
7338 if (!NT_STATUS_IS_OK(status)) {
7339 reply_nterror(req, status);
7340 goto out;
7343 if (!req->posix_pathnames) {
7344 /* The newname must begin with a ':' if the
7345 name contains a ':'. */
7346 if (strchr_m(name, ':')) {
7347 if (newname[0] != ':') {
7348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7349 goto out;
7351 stream_rename = true;
7355 status = filename_convert(ctx,
7356 conn,
7357 name,
7358 src_ucf_flags,
7359 &src_has_wcard,
7360 &smb_fname_src);
7362 if (!NT_STATUS_IS_OK(status)) {
7363 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7364 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7365 ERRSRV, ERRbadpath);
7366 goto out;
7368 reply_nterror(req, status);
7369 goto out;
7372 status = filename_convert(ctx,
7373 conn,
7374 newname,
7375 dst_ucf_flags,
7376 &dest_has_wcard,
7377 &smb_fname_dst);
7379 if (!NT_STATUS_IS_OK(status)) {
7380 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7381 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7382 ERRSRV, ERRbadpath);
7383 goto out;
7385 reply_nterror(req, status);
7386 goto out;
7389 if (stream_rename) {
7390 /* smb_fname_dst->base_name must be the same as
7391 smb_fname_src->base_name. */
7392 TALLOC_FREE(smb_fname_dst->base_name);
7393 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7394 smb_fname_src->base_name);
7395 if (!smb_fname_dst->base_name) {
7396 reply_nterror(req, NT_STATUS_NO_MEMORY);
7397 goto out;
7401 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7402 smb_fname_str_dbg(smb_fname_dst)));
7404 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7405 attrs, False, src_has_wcard, dest_has_wcard,
7406 DELETE_ACCESS);
7407 if (!NT_STATUS_IS_OK(status)) {
7408 if (open_was_deferred(req->xconn, req->mid)) {
7409 /* We have re-scheduled this call. */
7410 goto out;
7412 reply_nterror(req, status);
7413 goto out;
7416 reply_outbuf(req, 0, 0);
7417 out:
7418 TALLOC_FREE(smb_fname_src);
7419 TALLOC_FREE(smb_fname_dst);
7420 END_PROFILE(SMBmv);
7421 return;
7424 /*******************************************************************
7425 Copy a file as part of a reply_copy.
7426 ******************************************************************/
7429 * TODO: check error codes on all callers
7432 NTSTATUS copy_file(TALLOC_CTX *ctx,
7433 connection_struct *conn,
7434 struct smb_filename *smb_fname_src,
7435 struct smb_filename *smb_fname_dst,
7436 int ofun,
7437 int count,
7438 bool target_is_directory)
7440 struct smb_filename *smb_fname_dst_tmp = NULL;
7441 off_t ret=-1;
7442 files_struct *fsp1,*fsp2;
7443 uint32_t dosattrs;
7444 uint32_t new_create_disposition;
7445 NTSTATUS status;
7448 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7449 if (smb_fname_dst_tmp == NULL) {
7450 return NT_STATUS_NO_MEMORY;
7454 * If the target is a directory, extract the last component from the
7455 * src filename and append it to the dst filename
7457 if (target_is_directory) {
7458 const char *p;
7460 /* dest/target can't be a stream if it's a directory. */
7461 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7463 p = strrchr_m(smb_fname_src->base_name,'/');
7464 if (p) {
7465 p++;
7466 } else {
7467 p = smb_fname_src->base_name;
7469 smb_fname_dst_tmp->base_name =
7470 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7472 if (!smb_fname_dst_tmp->base_name) {
7473 status = NT_STATUS_NO_MEMORY;
7474 goto out;
7478 status = vfs_file_exist(conn, smb_fname_src);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 goto out;
7483 if (!target_is_directory && count) {
7484 new_create_disposition = FILE_OPEN;
7485 } else {
7486 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7487 0, ofun,
7488 NULL, NULL,
7489 &new_create_disposition,
7490 NULL,
7491 NULL)) {
7492 status = NT_STATUS_INVALID_PARAMETER;
7493 goto out;
7497 /* Open the src file for reading. */
7498 status = SMB_VFS_CREATE_FILE(
7499 conn, /* conn */
7500 NULL, /* req */
7501 0, /* root_dir_fid */
7502 smb_fname_src, /* fname */
7503 FILE_GENERIC_READ, /* access_mask */
7504 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7505 FILE_OPEN, /* create_disposition*/
7506 0, /* create_options */
7507 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7508 INTERNAL_OPEN_ONLY, /* oplock_request */
7509 NULL, /* lease */
7510 0, /* allocation_size */
7511 0, /* private_flags */
7512 NULL, /* sd */
7513 NULL, /* ea_list */
7514 &fsp1, /* result */
7515 NULL, /* psbuf */
7516 NULL, NULL); /* create context */
7518 if (!NT_STATUS_IS_OK(status)) {
7519 goto out;
7522 dosattrs = dos_mode(conn, smb_fname_src);
7524 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7525 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7528 /* Open the dst file for writing. */
7529 status = SMB_VFS_CREATE_FILE(
7530 conn, /* conn */
7531 NULL, /* req */
7532 0, /* root_dir_fid */
7533 smb_fname_dst, /* fname */
7534 FILE_GENERIC_WRITE, /* access_mask */
7535 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7536 new_create_disposition, /* create_disposition*/
7537 0, /* create_options */
7538 dosattrs, /* file_attributes */
7539 INTERNAL_OPEN_ONLY, /* oplock_request */
7540 NULL, /* lease */
7541 0, /* allocation_size */
7542 0, /* private_flags */
7543 NULL, /* sd */
7544 NULL, /* ea_list */
7545 &fsp2, /* result */
7546 NULL, /* psbuf */
7547 NULL, NULL); /* create context */
7549 if (!NT_STATUS_IS_OK(status)) {
7550 close_file(NULL, fsp1, ERROR_CLOSE);
7551 goto out;
7554 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7555 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7556 if (ret == -1) {
7557 DEBUG(0, ("error - vfs lseek returned error %s\n",
7558 strerror(errno)));
7559 status = map_nt_error_from_unix(errno);
7560 close_file(NULL, fsp1, ERROR_CLOSE);
7561 close_file(NULL, fsp2, ERROR_CLOSE);
7562 goto out;
7566 /* Do the actual copy. */
7567 if (smb_fname_src->st.st_ex_size) {
7568 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7569 } else {
7570 ret = 0;
7573 close_file(NULL, fsp1, NORMAL_CLOSE);
7575 /* Ensure the modtime is set correctly on the destination file. */
7576 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7579 * As we are opening fsp1 read-only we only expect
7580 * an error on close on fsp2 if we are out of space.
7581 * Thus we don't look at the error return from the
7582 * close of fsp1.
7584 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7586 if (!NT_STATUS_IS_OK(status)) {
7587 goto out;
7590 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7591 status = NT_STATUS_DISK_FULL;
7592 goto out;
7595 status = NT_STATUS_OK;
7597 out:
7598 TALLOC_FREE(smb_fname_dst_tmp);
7599 return status;
7602 /****************************************************************************
7603 Reply to a file copy.
7604 ****************************************************************************/
7606 void reply_copy(struct smb_request *req)
7608 connection_struct *conn = req->conn;
7609 struct smb_filename *smb_fname_src = NULL;
7610 struct smb_filename *smb_fname_src_dir = NULL;
7611 struct smb_filename *smb_fname_dst = NULL;
7612 char *fname_src = NULL;
7613 char *fname_dst = NULL;
7614 char *fname_src_mask = NULL;
7615 char *fname_src_dir = NULL;
7616 const char *p;
7617 int count=0;
7618 int error = ERRnoaccess;
7619 int tid2;
7620 int ofun;
7621 int flags;
7622 bool target_is_directory=False;
7623 bool source_has_wild = False;
7624 bool dest_has_wild = False;
7625 NTSTATUS status;
7626 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7627 ucf_flags_from_smb_request(req);
7628 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7629 ucf_flags_from_smb_request(req);
7630 TALLOC_CTX *ctx = talloc_tos();
7632 START_PROFILE(SMBcopy);
7634 if (req->wct < 3) {
7635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7636 goto out;
7639 tid2 = SVAL(req->vwv+0, 0);
7640 ofun = SVAL(req->vwv+1, 0);
7641 flags = SVAL(req->vwv+2, 0);
7643 p = (const char *)req->buf;
7644 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7645 &status, &source_has_wild);
7646 if (!NT_STATUS_IS_OK(status)) {
7647 reply_nterror(req, status);
7648 goto out;
7650 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7651 &status, &dest_has_wild);
7652 if (!NT_STATUS_IS_OK(status)) {
7653 reply_nterror(req, status);
7654 goto out;
7657 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7659 if (tid2 != conn->cnum) {
7660 /* can't currently handle inter share copies XXXX */
7661 DEBUG(3,("Rejecting inter-share copy\n"));
7662 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7663 goto out;
7666 status = filename_convert(ctx, conn,
7667 fname_src,
7668 ucf_flags_src,
7669 &source_has_wild,
7670 &smb_fname_src);
7671 if (!NT_STATUS_IS_OK(status)) {
7672 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7673 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7674 ERRSRV, ERRbadpath);
7675 goto out;
7677 reply_nterror(req, status);
7678 goto out;
7681 status = filename_convert(ctx, conn,
7682 fname_dst,
7683 ucf_flags_dst,
7684 &dest_has_wild,
7685 &smb_fname_dst);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7688 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7689 ERRSRV, ERRbadpath);
7690 goto out;
7692 reply_nterror(req, status);
7693 goto out;
7696 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7698 if ((flags&1) && target_is_directory) {
7699 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7700 goto out;
7703 if ((flags&2) && !target_is_directory) {
7704 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7705 goto out;
7708 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7709 /* wants a tree copy! XXXX */
7710 DEBUG(3,("Rejecting tree copy\n"));
7711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7712 goto out;
7715 /* Split up the directory from the filename/mask. */
7716 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7717 &fname_src_dir, &fname_src_mask);
7718 if (!NT_STATUS_IS_OK(status)) {
7719 reply_nterror(req, NT_STATUS_NO_MEMORY);
7720 goto out;
7724 * We should only check the mangled cache
7725 * here if unix_convert failed. This means
7726 * that the path in 'mask' doesn't exist
7727 * on the file system and so we need to look
7728 * for a possible mangle. This patch from
7729 * Tine Smukavec <valentin.smukavec@hermes.si>.
7731 if (!VALID_STAT(smb_fname_src->st) &&
7732 mangle_is_mangled(fname_src_mask, conn->params)) {
7733 char *new_mask = NULL;
7734 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7735 &new_mask, conn->params);
7737 /* Use demangled name if one was successfully found. */
7738 if (new_mask) {
7739 TALLOC_FREE(fname_src_mask);
7740 fname_src_mask = new_mask;
7744 if (!source_has_wild) {
7747 * Only one file needs to be copied. Append the mask back onto
7748 * the directory.
7750 TALLOC_FREE(smb_fname_src->base_name);
7751 if (ISDOT(fname_src_dir)) {
7752 /* Ensure we use canonical names on open. */
7753 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7754 "%s",
7755 fname_src_mask);
7756 } else {
7757 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7758 "%s/%s",
7759 fname_src_dir,
7760 fname_src_mask);
7762 if (!smb_fname_src->base_name) {
7763 reply_nterror(req, NT_STATUS_NO_MEMORY);
7764 goto out;
7767 if (dest_has_wild) {
7768 char *fname_dst_mod = NULL;
7769 if (!resolve_wildcards(smb_fname_dst,
7770 smb_fname_src->base_name,
7771 smb_fname_dst->base_name,
7772 &fname_dst_mod)) {
7773 reply_nterror(req, NT_STATUS_NO_MEMORY);
7774 goto out;
7776 TALLOC_FREE(smb_fname_dst->base_name);
7777 smb_fname_dst->base_name = fname_dst_mod;
7780 status = check_name(conn, smb_fname_src);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 reply_nterror(req, status);
7783 goto out;
7786 status = check_name(conn, smb_fname_dst);
7787 if (!NT_STATUS_IS_OK(status)) {
7788 reply_nterror(req, status);
7789 goto out;
7792 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7793 ofun, count, target_is_directory);
7795 if(!NT_STATUS_IS_OK(status)) {
7796 reply_nterror(req, status);
7797 goto out;
7798 } else {
7799 count++;
7801 } else {
7802 struct smb_Dir *dir_hnd = NULL;
7803 const char *dname = NULL;
7804 char *talloced = NULL;
7805 long offset = 0;
7808 * There is a wildcard that requires us to actually read the
7809 * src dir and copy each file matching the mask to the dst.
7810 * Right now streams won't be copied, but this could
7811 * presumably be added with a nested loop for reach dir entry.
7813 SMB_ASSERT(!smb_fname_src->stream_name);
7814 SMB_ASSERT(!smb_fname_dst->stream_name);
7816 smb_fname_src->stream_name = NULL;
7817 smb_fname_dst->stream_name = NULL;
7819 if (strequal(fname_src_mask,"????????.???")) {
7820 TALLOC_FREE(fname_src_mask);
7821 fname_src_mask = talloc_strdup(ctx, "*");
7822 if (!fname_src_mask) {
7823 reply_nterror(req, NT_STATUS_NO_MEMORY);
7824 goto out;
7828 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
7829 fname_src_dir,
7830 NULL,
7831 NULL,
7832 smb_fname_src->flags);
7833 if (smb_fname_src_dir == NULL) {
7834 reply_nterror(req, NT_STATUS_NO_MEMORY);
7835 goto out;
7838 status = check_name(conn, smb_fname_src_dir);
7839 if (!NT_STATUS_IS_OK(status)) {
7840 reply_nterror(req, status);
7841 goto out;
7844 dir_hnd = OpenDir(ctx,
7845 conn,
7846 smb_fname_src_dir,
7847 fname_src_mask,
7849 if (dir_hnd == NULL) {
7850 status = map_nt_error_from_unix(errno);
7851 reply_nterror(req, status);
7852 goto out;
7855 error = ERRbadfile;
7857 /* Iterate over the src dir copying each entry to the dst. */
7858 while ((dname = ReadDirName(dir_hnd, &offset,
7859 &smb_fname_src->st, &talloced))) {
7860 char *destname = NULL;
7862 if (ISDOT(dname) || ISDOTDOT(dname)) {
7863 TALLOC_FREE(talloced);
7864 continue;
7867 if (!is_visible_file(conn, fname_src_dir, dname,
7868 &smb_fname_src->st, false)) {
7869 TALLOC_FREE(talloced);
7870 continue;
7873 if(!mask_match(dname, fname_src_mask,
7874 conn->case_sensitive)) {
7875 TALLOC_FREE(talloced);
7876 continue;
7879 error = ERRnoaccess;
7881 /* Get the src smb_fname struct setup. */
7882 TALLOC_FREE(smb_fname_src->base_name);
7883 if (ISDOT(fname_src_dir)) {
7884 /* Ensure we use canonical names on open. */
7885 smb_fname_src->base_name =
7886 talloc_asprintf(smb_fname_src, "%s",
7887 dname);
7888 } else {
7889 smb_fname_src->base_name =
7890 talloc_asprintf(smb_fname_src, "%s/%s",
7891 fname_src_dir, dname);
7894 if (!smb_fname_src->base_name) {
7895 TALLOC_FREE(dir_hnd);
7896 TALLOC_FREE(talloced);
7897 reply_nterror(req, NT_STATUS_NO_MEMORY);
7898 goto out;
7901 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7902 smb_fname_dst->base_name,
7903 &destname)) {
7904 TALLOC_FREE(talloced);
7905 continue;
7907 if (!destname) {
7908 TALLOC_FREE(dir_hnd);
7909 TALLOC_FREE(talloced);
7910 reply_nterror(req, NT_STATUS_NO_MEMORY);
7911 goto out;
7914 TALLOC_FREE(smb_fname_dst->base_name);
7915 smb_fname_dst->base_name = destname;
7917 status = check_name(conn, smb_fname_src);
7918 if (!NT_STATUS_IS_OK(status)) {
7919 TALLOC_FREE(dir_hnd);
7920 TALLOC_FREE(talloced);
7921 reply_nterror(req, status);
7922 goto out;
7925 status = check_name(conn, smb_fname_dst);
7926 if (!NT_STATUS_IS_OK(status)) {
7927 TALLOC_FREE(dir_hnd);
7928 TALLOC_FREE(talloced);
7929 reply_nterror(req, status);
7930 goto out;
7933 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7934 smb_fname_src->base_name,
7935 smb_fname_dst->base_name));
7937 status = copy_file(ctx, conn, smb_fname_src,
7938 smb_fname_dst, ofun, count,
7939 target_is_directory);
7940 if (NT_STATUS_IS_OK(status)) {
7941 count++;
7944 TALLOC_FREE(talloced);
7946 TALLOC_FREE(dir_hnd);
7949 if (count == 0) {
7950 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7951 goto out;
7954 reply_outbuf(req, 1, 0);
7955 SSVAL(req->outbuf,smb_vwv0,count);
7956 out:
7957 TALLOC_FREE(smb_fname_src);
7958 TALLOC_FREE(smb_fname_src_dir);
7959 TALLOC_FREE(smb_fname_dst);
7960 TALLOC_FREE(fname_src);
7961 TALLOC_FREE(fname_dst);
7962 TALLOC_FREE(fname_src_mask);
7963 TALLOC_FREE(fname_src_dir);
7965 END_PROFILE(SMBcopy);
7966 return;
7969 #undef DBGC_CLASS
7970 #define DBGC_CLASS DBGC_LOCKING
7972 /****************************************************************************
7973 Get a lock pid, dealing with large count requests.
7974 ****************************************************************************/
7976 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7977 bool large_file_format)
7979 if(!large_file_format)
7980 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7981 else
7982 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7985 /****************************************************************************
7986 Get a lock count, dealing with large count requests.
7987 ****************************************************************************/
7989 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7990 bool large_file_format)
7992 uint64_t count = 0;
7994 if(!large_file_format) {
7995 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7996 } else {
7998 * No BVAL, this is reversed!
8000 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8001 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8004 return count;
8007 /****************************************************************************
8008 Get a lock offset, dealing with large offset requests.
8009 ****************************************************************************/
8011 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8012 bool large_file_format)
8014 uint64_t offset = 0;
8016 if(!large_file_format) {
8017 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8018 } else {
8020 * No BVAL, this is reversed!
8022 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8023 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8026 return offset;
8029 NTSTATUS smbd_do_locking(struct smb_request *req,
8030 files_struct *fsp,
8031 uint8_t type,
8032 int32_t timeout,
8033 uint16_t num_locks,
8034 struct smbd_lock_element *locks,
8035 bool *async)
8037 connection_struct *conn = req->conn;
8038 int i;
8039 NTSTATUS status = NT_STATUS_OK;
8041 *async = false;
8043 /* Setup the timeout in seconds. */
8045 if (!lp_blocking_locks(SNUM(conn))) {
8046 timeout = 0;
8049 for(i = 0; i < (int)num_locks; i++) {
8050 struct smbd_lock_element *e = &locks[i];
8052 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
8053 "%llu, file %s timeout = %d\n",
8054 (double)e->offset,
8055 (double)e->count,
8056 (unsigned long long)e->smblctx,
8057 fsp_str_dbg(fsp),
8058 (int)timeout));
8060 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8061 struct blocking_lock_record *blr = NULL;
8063 if (num_locks > 1) {
8065 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
8066 * if the lock vector contains one entry. When given multiple cancel
8067 * requests in a single PDU we expect the server to return an
8068 * error. Windows servers seem to accept the request but only
8069 * cancel the first lock.
8070 * JRA - Do what Windows does (tm) :-).
8073 #if 0
8074 /* MS-CIFS (2.2.4.32.1) behavior. */
8075 return NT_STATUS_DOS(ERRDOS,
8076 ERRcancelviolation);
8077 #else
8078 /* Windows behavior. */
8079 if (i != 0) {
8080 DEBUG(10,("smbd_do_locking: ignoring subsequent "
8081 "cancel request\n"));
8082 continue;
8084 #endif
8087 if (lp_blocking_locks(SNUM(conn))) {
8089 /* Schedule a message to ourselves to
8090 remove the blocking lock record and
8091 return the right error. */
8093 blr = blocking_lock_cancel_smb1(fsp,
8094 e->smblctx,
8095 e->offset,
8096 e->count,
8097 WINDOWS_LOCK,
8098 type,
8099 NT_STATUS_FILE_LOCK_CONFLICT);
8100 if (blr == NULL) {
8101 return NT_STATUS_DOS(
8102 ERRDOS,
8103 ERRcancelviolation);
8106 /* Remove a matching pending lock. */
8107 status = do_lock_cancel(fsp,
8108 e->smblctx,
8109 e->count,
8110 e->offset,
8111 WINDOWS_LOCK);
8112 } else {
8113 bool blocking_lock = timeout ? true : false;
8114 bool defer_lock = false;
8115 struct byte_range_lock *br_lck;
8116 uint64_t block_smblctx;
8118 br_lck = do_lock(req->sconn->msg_ctx,
8119 fsp,
8120 e->smblctx,
8121 e->count,
8122 e->offset,
8123 e->brltype,
8124 WINDOWS_LOCK,
8125 blocking_lock,
8126 &status,
8127 &block_smblctx);
8129 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8130 /* Windows internal resolution for blocking locks seems
8131 to be about 200ms... Don't wait for less than that. JRA. */
8132 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8133 timeout = lp_lock_spin_time();
8135 defer_lock = true;
8138 /* If a lock sent with timeout of zero would fail, and
8139 * this lock has been requested multiple times,
8140 * according to brl_lock_failed() we convert this
8141 * request to a blocking lock with a timeout of between
8142 * 150 - 300 milliseconds.
8144 * If lp_lock_spin_time() has been set to 0, we skip
8145 * this blocking retry and fail immediately.
8147 * Replacement for do_lock_spin(). JRA. */
8149 if (!req->sconn->using_smb2 &&
8150 br_lck && lp_blocking_locks(SNUM(conn)) &&
8151 lp_lock_spin_time() && !blocking_lock &&
8152 NT_STATUS_EQUAL((status),
8153 NT_STATUS_FILE_LOCK_CONFLICT))
8155 defer_lock = true;
8156 timeout = lp_lock_spin_time();
8159 if (br_lck && defer_lock) {
8161 * A blocking lock was requested. Package up
8162 * this smb into a queued request and push it
8163 * onto the blocking lock queue.
8165 if(push_blocking_lock_request(br_lck,
8166 req,
8167 fsp,
8168 timeout,
8170 e->smblctx,
8171 e->brltype,
8172 WINDOWS_LOCK,
8173 e->offset,
8174 e->count,
8175 block_smblctx)) {
8176 TALLOC_FREE(br_lck);
8177 *async = true;
8178 return NT_STATUS_OK;
8182 TALLOC_FREE(br_lck);
8185 if (!NT_STATUS_IS_OK(status)) {
8186 break;
8190 /* If any of the above locks failed, then we must unlock
8191 all of the previous locks (X/Open spec). */
8193 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8195 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8196 i = -1; /* we want to skip the for loop */
8200 * Ensure we don't do a remove on the lock that just failed,
8201 * as under POSIX rules, if we have a lock already there, we
8202 * will delete it (and we shouldn't) .....
8204 for(i--; i >= 0; i--) {
8205 struct smbd_lock_element *e = &locks[i];
8207 do_unlock(req->sconn->msg_ctx,
8208 fsp,
8209 e->smblctx,
8210 e->count,
8211 e->offset,
8212 WINDOWS_LOCK);
8214 return status;
8217 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8218 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8220 return NT_STATUS_OK;
8223 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8224 files_struct *fsp,
8225 uint16_t num_ulocks,
8226 struct smbd_lock_element *ulocks)
8228 int i;
8230 for(i = 0; i < (int)num_ulocks; i++) {
8231 struct smbd_lock_element *e = &ulocks[i];
8232 NTSTATUS status;
8234 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8235 "pid %u, file %s\n", __func__,
8236 (double)e->offset,
8237 (double)e->count,
8238 (unsigned int)e->smblctx,
8239 fsp_str_dbg(fsp)));
8241 if (e->brltype != UNLOCK_LOCK) {
8242 /* this can only happen with SMB2 */
8243 return NT_STATUS_INVALID_PARAMETER;
8246 status = do_unlock(req->sconn->msg_ctx,
8247 fsp,
8248 e->smblctx,
8249 e->count,
8250 e->offset,
8251 WINDOWS_LOCK);
8253 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8254 nt_errstr(status)));
8256 if (!NT_STATUS_IS_OK(status)) {
8257 return status;
8261 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8262 num_ulocks));
8264 return NT_STATUS_OK;
8267 /****************************************************************************
8268 Reply to a lockingX request.
8269 ****************************************************************************/
8271 void reply_lockingX(struct smb_request *req)
8273 connection_struct *conn = req->conn;
8274 files_struct *fsp;
8275 unsigned char locktype;
8276 unsigned char oplocklevel;
8277 uint16_t num_ulocks;
8278 uint16_t num_locks;
8279 int32_t lock_timeout;
8280 int i;
8281 const uint8_t *data;
8282 bool large_file_format;
8283 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8284 struct smbd_lock_element *ulocks;
8285 struct smbd_lock_element *locks;
8286 bool async = false;
8288 START_PROFILE(SMBlockingX);
8290 if (req->wct < 8) {
8291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8292 END_PROFILE(SMBlockingX);
8293 return;
8296 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8297 locktype = CVAL(req->vwv+3, 0);
8298 oplocklevel = CVAL(req->vwv+3, 1);
8299 num_ulocks = SVAL(req->vwv+6, 0);
8300 num_locks = SVAL(req->vwv+7, 0);
8301 lock_timeout = IVAL(req->vwv+4, 0);
8302 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8304 if (!check_fsp(conn, req, fsp)) {
8305 END_PROFILE(SMBlockingX);
8306 return;
8309 data = req->buf;
8311 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8312 /* we don't support these - and CANCEL_LOCK makes w2k
8313 and XP reboot so I don't really want to be
8314 compatible! (tridge) */
8315 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8316 END_PROFILE(SMBlockingX);
8317 return;
8320 /* Check if this is an oplock break on a file
8321 we have granted an oplock on.
8323 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8324 /* Client can insist on breaking to none. */
8325 bool break_to_none = (oplocklevel == 0);
8326 bool result;
8328 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8329 "for %s\n", (unsigned int)oplocklevel,
8330 fsp_fnum_dbg(fsp)));
8333 * Make sure we have granted an exclusive or batch oplock on
8334 * this file.
8337 if (fsp->oplock_type == 0) {
8339 /* The Samba4 nbench simulator doesn't understand
8340 the difference between break to level2 and break
8341 to none from level2 - it sends oplock break
8342 replies in both cases. Don't keep logging an error
8343 message here - just ignore it. JRA. */
8345 DEBUG(5,("reply_lockingX: Error : oplock break from "
8346 "client for %s (oplock=%d) and no "
8347 "oplock granted on this file (%s).\n",
8348 fsp_fnum_dbg(fsp), fsp->oplock_type,
8349 fsp_str_dbg(fsp)));
8351 /* if this is a pure oplock break request then don't
8352 * send a reply */
8353 if (num_locks == 0 && num_ulocks == 0) {
8354 END_PROFILE(SMBlockingX);
8355 return;
8356 } else {
8357 END_PROFILE(SMBlockingX);
8358 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8359 return;
8363 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8364 (break_to_none)) {
8365 result = remove_oplock(fsp);
8366 } else {
8367 result = downgrade_oplock(fsp);
8370 if (!result) {
8371 DEBUG(0, ("reply_lockingX: error in removing "
8372 "oplock on file %s\n", fsp_str_dbg(fsp)));
8373 /* Hmmm. Is this panic justified? */
8374 smb_panic("internal tdb error");
8377 /* if this is a pure oplock break request then don't send a
8378 * reply */
8379 if (num_locks == 0 && num_ulocks == 0) {
8380 /* Sanity check - ensure a pure oplock break is not a
8381 chained request. */
8382 if (CVAL(req->vwv+0, 0) != 0xff) {
8383 DEBUG(0,("reply_lockingX: Error : pure oplock "
8384 "break is a chained %d request !\n",
8385 (unsigned int)CVAL(req->vwv+0, 0)));
8387 END_PROFILE(SMBlockingX);
8388 return;
8392 if (req->buflen <
8393 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8395 END_PROFILE(SMBlockingX);
8396 return;
8399 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8400 if (ulocks == NULL) {
8401 reply_nterror(req, NT_STATUS_NO_MEMORY);
8402 END_PROFILE(SMBlockingX);
8403 return;
8406 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8407 if (locks == NULL) {
8408 reply_nterror(req, NT_STATUS_NO_MEMORY);
8409 END_PROFILE(SMBlockingX);
8410 return;
8413 /* Data now points at the beginning of the list
8414 of smb_unlkrng structs */
8415 for(i = 0; i < (int)num_ulocks; i++) {
8416 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8417 ulocks[i].count = get_lock_count(data, i, large_file_format);
8418 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8419 ulocks[i].brltype = UNLOCK_LOCK;
8422 /* Now do any requested locks */
8423 data += ((large_file_format ? 20 : 10)*num_ulocks);
8425 /* Data now points at the beginning of the list
8426 of smb_lkrng structs */
8428 for(i = 0; i < (int)num_locks; i++) {
8429 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8430 locks[i].count = get_lock_count(data, i, large_file_format);
8431 locks[i].offset = get_lock_offset(data, i, large_file_format);
8433 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8434 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8435 locks[i].brltype = PENDING_READ_LOCK;
8436 } else {
8437 locks[i].brltype = READ_LOCK;
8439 } else {
8440 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8441 locks[i].brltype = PENDING_WRITE_LOCK;
8442 } else {
8443 locks[i].brltype = WRITE_LOCK;
8448 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8449 if (!NT_STATUS_IS_OK(status)) {
8450 END_PROFILE(SMBlockingX);
8451 reply_nterror(req, status);
8452 return;
8455 status = smbd_do_locking(req, fsp,
8456 locktype, lock_timeout,
8457 num_locks, locks,
8458 &async);
8459 if (!NT_STATUS_IS_OK(status)) {
8460 END_PROFILE(SMBlockingX);
8461 reply_nterror(req, status);
8462 return;
8464 if (async) {
8465 END_PROFILE(SMBlockingX);
8466 return;
8469 reply_outbuf(req, 2, 0);
8470 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8471 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8473 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8474 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8476 END_PROFILE(SMBlockingX);
8479 #undef DBGC_CLASS
8480 #define DBGC_CLASS DBGC_ALL
8482 /****************************************************************************
8483 Reply to a SMBreadbmpx (read block multiplex) request.
8484 Always reply with an error, if someone has a platform really needs this,
8485 please contact vl@samba.org
8486 ****************************************************************************/
8488 void reply_readbmpx(struct smb_request *req)
8490 START_PROFILE(SMBreadBmpx);
8491 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8492 END_PROFILE(SMBreadBmpx);
8493 return;
8496 /****************************************************************************
8497 Reply to a SMBreadbs (read block multiplex secondary) request.
8498 Always reply with an error, if someone has a platform really needs this,
8499 please contact vl@samba.org
8500 ****************************************************************************/
8502 void reply_readbs(struct smb_request *req)
8504 START_PROFILE(SMBreadBs);
8505 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8506 END_PROFILE(SMBreadBs);
8507 return;
8510 /****************************************************************************
8511 Reply to a SMBsetattrE.
8512 ****************************************************************************/
8514 void reply_setattrE(struct smb_request *req)
8516 connection_struct *conn = req->conn;
8517 struct smb_file_time ft;
8518 files_struct *fsp;
8519 NTSTATUS status;
8521 START_PROFILE(SMBsetattrE);
8522 ZERO_STRUCT(ft);
8524 if (req->wct < 7) {
8525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8526 goto out;
8529 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8531 if(!fsp || (fsp->conn != conn)) {
8532 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8533 goto out;
8537 * Convert the DOS times into unix times.
8540 ft.atime = convert_time_t_to_timespec(
8541 srv_make_unix_date2(req->vwv+3));
8542 ft.mtime = convert_time_t_to_timespec(
8543 srv_make_unix_date2(req->vwv+5));
8544 ft.create_time = convert_time_t_to_timespec(
8545 srv_make_unix_date2(req->vwv+1));
8547 reply_outbuf(req, 0, 0);
8550 * Patch from Ray Frush <frush@engr.colostate.edu>
8551 * Sometimes times are sent as zero - ignore them.
8554 /* Ensure we have a valid stat struct for the source. */
8555 status = vfs_stat_fsp(fsp);
8556 if (!NT_STATUS_IS_OK(status)) {
8557 reply_nterror(req, status);
8558 goto out;
8561 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8562 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8563 goto out;
8566 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8567 if (!NT_STATUS_IS_OK(status)) {
8568 reply_nterror(req, status);
8569 goto out;
8572 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8573 " createtime=%u\n",
8574 fsp_fnum_dbg(fsp),
8575 (unsigned int)ft.atime.tv_sec,
8576 (unsigned int)ft.mtime.tv_sec,
8577 (unsigned int)ft.create_time.tv_sec
8579 out:
8580 END_PROFILE(SMBsetattrE);
8581 return;
8585 /* Back from the dead for OS/2..... JRA. */
8587 /****************************************************************************
8588 Reply to a SMBwritebmpx (write block multiplex primary) request.
8589 Always reply with an error, if someone has a platform really needs this,
8590 please contact vl@samba.org
8591 ****************************************************************************/
8593 void reply_writebmpx(struct smb_request *req)
8595 START_PROFILE(SMBwriteBmpx);
8596 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8597 END_PROFILE(SMBwriteBmpx);
8598 return;
8601 /****************************************************************************
8602 Reply to a SMBwritebs (write block multiplex secondary) request.
8603 Always reply with an error, if someone has a platform really needs this,
8604 please contact vl@samba.org
8605 ****************************************************************************/
8607 void reply_writebs(struct smb_request *req)
8609 START_PROFILE(SMBwriteBs);
8610 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8611 END_PROFILE(SMBwriteBs);
8612 return;
8615 /****************************************************************************
8616 Reply to a SMBgetattrE.
8617 ****************************************************************************/
8619 void reply_getattrE(struct smb_request *req)
8621 connection_struct *conn = req->conn;
8622 int mode;
8623 files_struct *fsp;
8624 struct timespec create_ts;
8626 START_PROFILE(SMBgetattrE);
8628 if (req->wct < 1) {
8629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8630 END_PROFILE(SMBgetattrE);
8631 return;
8634 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8636 if(!fsp || (fsp->conn != conn)) {
8637 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8638 END_PROFILE(SMBgetattrE);
8639 return;
8642 /* Do an fstat on this file */
8643 if(fsp_stat(fsp)) {
8644 reply_nterror(req, map_nt_error_from_unix(errno));
8645 END_PROFILE(SMBgetattrE);
8646 return;
8649 mode = dos_mode(conn, fsp->fsp_name);
8652 * Convert the times into dos times. Set create
8653 * date to be last modify date as UNIX doesn't save
8654 * this.
8657 reply_outbuf(req, 11, 0);
8659 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8660 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8661 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8662 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8663 /* Should we check pending modtime here ? JRA */
8664 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8665 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8667 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8668 SIVAL(req->outbuf, smb_vwv6, 0);
8669 SIVAL(req->outbuf, smb_vwv8, 0);
8670 } else {
8671 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8672 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8673 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8675 SSVAL(req->outbuf,smb_vwv10, mode);
8677 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8679 END_PROFILE(SMBgetattrE);
8680 return;