s3: smbd: Ensure srvstr_pull_req_talloc() always NULLs out *dest.
[Samba.git] / source3 / smbd / smb2_reply.c
blobdfcd05d2cae18e7c058566c020410b0b73e61aae
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 "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
43 #include "auth.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
53 #include "source3/lib/substitute.h"
55 /****************************************************************************
56 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
57 path or anything including wildcards.
58 We're assuming here that '/' is not the second byte in any multibyte char
59 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
60 set.
61 ****************************************************************************/
63 /* Custom version for processing POSIX paths. */
64 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
66 NTSTATUS check_path_syntax(char *path, bool posix_path)
68 char *d = path;
69 const char *s = path;
70 NTSTATUS ret = NT_STATUS_OK;
71 bool start_of_name_component = True;
72 bool stream_started = false;
73 bool last_component_contains_wcard = false;
75 while (*s) {
76 if (stream_started) {
77 switch (*s) {
78 case '/':
79 case '\\':
80 return NT_STATUS_OBJECT_NAME_INVALID;
81 case ':':
82 if (s[1] == '\0') {
83 return NT_STATUS_OBJECT_NAME_INVALID;
85 if (strchr_m(&s[1], ':')) {
86 return NT_STATUS_OBJECT_NAME_INVALID;
88 break;
92 if ((*s == ':') && !posix_path && !stream_started) {
93 if (last_component_contains_wcard) {
94 return NT_STATUS_OBJECT_NAME_INVALID;
96 /* Stream names allow more characters than file names.
97 We're overloading posix_path here to allow a wider
98 range of characters. If stream_started is true this
99 is still a Windows path even if posix_path is true.
100 JRA.
102 stream_started = true;
103 start_of_name_component = false;
104 posix_path = true;
106 if (s[1] == '\0') {
107 return NT_STATUS_OBJECT_NAME_INVALID;
111 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
113 * Safe to assume is not the second part of a mb char
114 * as this is handled below.
116 /* Eat multiple '/' or '\\' */
117 while (IS_PATH_SEP(*s,posix_path)) {
118 s++;
120 if ((d != path) && (*s != '\0')) {
121 /* We only care about non-leading or trailing '/' or '\\' */
122 *d++ = '/';
125 start_of_name_component = True;
126 /* New component. */
127 last_component_contains_wcard = false;
128 continue;
131 if (start_of_name_component) {
132 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
133 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
136 * No mb char starts with '.' so we're safe checking the directory separator here.
139 /* If we just added a '/' - delete it */
140 if ((d > path) && (*(d-1) == '/')) {
141 *(d-1) = '\0';
142 d--;
145 /* Are we at the start ? Can't go back further if so. */
146 if (d <= path) {
147 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
148 break;
150 /* Go back one level... */
151 /* We know this is safe as '/' cannot be part of a mb sequence. */
152 /* NOTE - if this assumption is invalid we are not in good shape... */
153 /* Decrement d first as d points to the *next* char to write into. */
154 for (d--; d > path; d--) {
155 if (*d == '/')
156 break;
158 s += 2; /* Else go past the .. */
159 /* We're still at the start of a name component, just the previous one. */
160 continue;
162 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
163 if (posix_path) {
164 /* Eat the '.' */
165 s++;
166 continue;
172 if (!(*s & 0x80)) {
173 if (!posix_path) {
174 if (*s <= 0x1f || *s == '|') {
175 return NT_STATUS_OBJECT_NAME_INVALID;
177 switch (*s) {
178 case '*':
179 case '?':
180 case '<':
181 case '>':
182 case '"':
183 last_component_contains_wcard = true;
184 break;
185 default:
186 break;
189 *d++ = *s++;
190 } else {
191 size_t ch_size;
192 /* Get the size of the next MB character. */
193 next_codepoint(s,&ch_size);
194 switch(ch_size) {
195 case 5:
196 *d++ = *s++;
197 FALL_THROUGH;
198 case 4:
199 *d++ = *s++;
200 FALL_THROUGH;
201 case 3:
202 *d++ = *s++;
203 FALL_THROUGH;
204 case 2:
205 *d++ = *s++;
206 FALL_THROUGH;
207 case 1:
208 *d++ = *s++;
209 break;
210 default:
211 DBG_ERR("character length assumptions invalid !\n");
212 *d = '\0';
213 return NT_STATUS_INVALID_PARAMETER;
216 start_of_name_component = False;
219 *d = '\0';
221 return ret;
224 /****************************************************************************
225 SMB2-only code to strip an MSDFS prefix from an incoming pathname.
226 ****************************************************************************/
228 NTSTATUS smb2_strip_dfs_path(const char *in_path, const char **out_path)
230 const char *path = in_path;
232 /* Match the Windows 2022 behavior for an empty DFS pathname. */
233 if (*path == '\0') {
234 return NT_STATUS_INVALID_PARAMETER;
236 /* Strip any leading '\\' characters - MacOSX client behavior. */
237 while (*path == '\\') {
238 path++;
240 /* We should now be pointing at the server name. Go past it. */
241 for (;;) {
242 if (*path == '\0') {
243 /* End of complete path. Exit OK. */
244 goto out;
246 if (*path == '\\') {
247 /* End of server name. Go past and break. */
248 path++;
249 break;
251 path++; /* Continue looking for end of server name or string. */
254 /* We should now be pointing at the share name. Go past it. */
255 for (;;) {
256 if (*path == '\0') {
257 /* End of complete path. Exit OK. */
258 goto out;
260 if (*path == '\\') {
261 /* End of share name. Go past and break. */
262 path++;
263 break;
265 if (*path == ':') {
266 /* Only invalid character in sharename. */
267 return NT_STATUS_OBJECT_NAME_INVALID;
269 path++; /* Continue looking for end of share name or string. */
272 /* path now points at the start of the real filename (if any). */
274 out:
275 /* We have stripped the DFS path prefix (if any). */
276 *out_path = path;
277 return NT_STATUS_OK;
280 /****************************************************************************
281 Pull a string and check the path allowing a wildcard - provide for error return.
282 Passes in posix flag.
283 ****************************************************************************/
285 static size_t srvstr_get_path_internal(TALLOC_CTX *ctx,
286 const char *base_ptr,
287 uint16_t smb_flags2,
288 char **pp_dest,
289 const char *src,
290 size_t src_len,
291 int flags,
292 bool posix_pathnames,
293 NTSTATUS *err)
295 size_t ret;
296 char *dst = NULL;
298 *pp_dest = NULL;
300 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
301 src_len, flags);
303 if (!*pp_dest) {
304 *err = NT_STATUS_INVALID_PARAMETER;
305 return ret;
308 dst = *pp_dest;
310 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
312 * A valid DFS path looks either like
313 * /server/share
314 * \server\share
315 * (there may be more components after).
316 * Either way it must have at least two separators.
318 * Ensure we end up as /server/share
319 * so we don't need to special case
320 * separator characters elsewhere in
321 * the code.
323 char *server = NULL;
324 char *share = NULL;
325 char *remaining_path = NULL;
326 char path_sep = 0;
327 char *p = NULL;
329 if (posix_pathnames && (dst[0] == '/')) {
330 path_sep = dst[0];
331 } else if (dst[0] == '\\') {
332 path_sep = dst[0];
335 if (path_sep == 0) {
336 goto local_path;
339 * May be a DFS path.
340 * We need some heuristics here,
341 * as clients differ on what constitutes
342 * a well-formed DFS path. If the path
343 * appears malformed, just fall back to
344 * processing as a local path.
346 server = dst;
349 * Cosmetic fix for Linux-only DFS clients.
350 * The Linux kernel SMB1 client has a bug - it sends
351 * DFS pathnames as:
353 * \\server\share\path
355 * Causing us to mis-parse server,share,remaining_path here
356 * and jump into 'goto local_path' at 'share\path' instead
357 * of 'path'.
359 * This doesn't cause an error as the limits on share names
360 * are similar to those on pathnames.
362 * parse_dfs_path() which we call before filename parsing
363 * copes with this by calling trim_char on the leading '\'
364 * characters before processing.
365 * Do the same here so logging of pathnames looks better.
367 if (server[1] == path_sep) {
368 trim_char(&server[1], path_sep, '\0');
372 * Look to see if we also have /share following.
374 share = strchr(server+1, path_sep);
375 if (share == NULL) {
376 goto local_path;
379 * Ensure the server name does not contain
380 * any possible path components by converting
381 * them to _'s.
383 for (p = server + 1; p < share; p++) {
384 if (*p == '/' || *p == '\\') {
385 *p = '_';
389 * It's a well formed DFS path with
390 * at least server and share components.
391 * Replace the slashes with '/' and
392 * pass the remainder to local_path.
394 *server = '/';
395 *share = '/';
397 * Skip past share so we don't pass the
398 * sharename into check_path_syntax().
400 remaining_path = strchr(share+1, path_sep);
401 if (remaining_path == NULL) {
403 * Ensure the share name does not contain
404 * any possible path components by converting
405 * them to _'s.
407 for (p = share + 1; *p; p++) {
408 if (*p == '/' || *p == '\\') {
409 *p = '_';
413 * If no remaining path this was
414 * a bare /server/share path. Just return.
416 *err = NT_STATUS_OK;
417 return ret;
420 * Ensure the share name does not contain
421 * any possible path components by converting
422 * them to _'s.
424 for (p = share + 1; p < remaining_path; p++) {
425 if (*p == '/' || *p == '\\') {
426 *p = '_';
429 *remaining_path = '/';
430 dst = remaining_path + 1;
431 /* dst now points at any following components. */
434 local_path:
436 *err = check_path_syntax(dst, posix_pathnames);
438 return ret;
441 /****************************************************************************
442 Pull a string and check the path - provide for error return.
443 ****************************************************************************/
445 size_t srvstr_get_path(TALLOC_CTX *ctx,
446 const char *base_ptr,
447 uint16_t smb_flags2,
448 char **pp_dest,
449 const char *src,
450 size_t src_len,
451 int flags,
452 NTSTATUS *err)
454 return srvstr_get_path_internal(ctx,
455 base_ptr,
456 smb_flags2,
457 pp_dest,
458 src,
459 src_len,
460 flags,
461 false,
462 err);
465 /****************************************************************************
466 Pull a string and check the path - provide for error return.
467 posix_pathnames version.
468 ****************************************************************************/
470 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
471 const char *base_ptr,
472 uint16_t smb_flags2,
473 char **pp_dest,
474 const char *src,
475 size_t src_len,
476 int flags,
477 NTSTATUS *err)
479 return srvstr_get_path_internal(ctx,
480 base_ptr,
481 smb_flags2,
482 pp_dest,
483 src,
484 src_len,
485 flags,
486 true,
487 err);
491 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
492 char **pp_dest, const char *src, int flags,
493 NTSTATUS *err)
495 ssize_t bufrem = smbreq_bufrem(req, src);
497 if (bufrem == 0) {
498 *err = NT_STATUS_INVALID_PARAMETER;
499 return 0;
502 if (req->posix_pathnames) {
503 return srvstr_get_path_internal(mem_ctx,
504 (const char *)req->inbuf,
505 req->flags2,
506 pp_dest,
507 src,
508 bufrem,
509 flags,
510 true,
511 err);
512 } else {
513 return srvstr_get_path_internal(mem_ctx,
514 (const char *)req->inbuf,
515 req->flags2,
516 pp_dest,
517 src,
518 bufrem,
519 flags,
520 false,
521 err);
526 * pull a string from the smb_buf part of a packet. In this case the
527 * string can either be null terminated or it can be terminated by the
528 * end of the smbbuf area
530 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
531 char **dest, const uint8_t *src, int flags)
533 ssize_t bufrem = smbreq_bufrem(req, src);
535 if (bufrem == 0) {
536 *dest = NULL;
537 return 0;
540 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
541 bufrem, flags);
544 /****************************************************************************
545 Check if we have a correct fsp pointing to a quota fake file. Replacement for
546 the CHECK_NTQUOTA_HANDLE_OK macro.
547 ****************************************************************************/
549 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
550 files_struct *fsp)
552 if ((fsp == NULL) || (conn == NULL)) {
553 return false;
556 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
557 return false;
560 if (fsp->fsp_flags.is_directory) {
561 return false;
564 if (fsp->fake_file_handle == NULL) {
565 return false;
568 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
569 return false;
572 if (fsp->fake_file_handle->private_data == NULL) {
573 return false;
576 return true;
579 /****************************************************************************
580 Return the port number we've bound to on a socket.
581 ****************************************************************************/
583 static int get_socket_port(int fd)
585 struct samba_sockaddr saddr = {
586 .sa_socklen = sizeof(struct sockaddr_storage),
589 if (fd == -1) {
590 return -1;
593 if (getsockname(fd, &saddr.u.sa, &saddr.sa_socklen) < 0) {
594 int level = (errno == ENOTCONN) ? 2 : 0;
595 DEBUG(level, ("getsockname failed. Error was %s\n",
596 strerror(errno)));
597 return -1;
600 #if defined(HAVE_IPV6)
601 if (saddr.u.sa.sa_family == AF_INET6) {
602 return ntohs(saddr.u.in6.sin6_port);
604 #endif
605 if (saddr.u.sa.sa_family == AF_INET) {
606 return ntohs(saddr.u.in.sin_port);
608 return -1;
611 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
612 const char *name, int name_type)
614 char *trim_name;
615 char *trim_name_type;
616 const char *retarget_parm;
617 char *retarget;
618 char *p;
619 int retarget_type = 0x20;
620 int retarget_port = NBT_SMB_PORT;
621 struct sockaddr_storage retarget_addr;
622 struct sockaddr_in *in_addr;
623 bool ret = false;
624 uint8_t outbuf[10];
626 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
627 return false;
630 trim_name = talloc_strdup(talloc_tos(), name);
631 if (trim_name == NULL) {
632 goto fail;
634 trim_char(trim_name, ' ', ' ');
636 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
637 name_type);
638 if (trim_name_type == NULL) {
639 goto fail;
642 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
643 trim_name_type, NULL);
644 if (retarget_parm == NULL) {
645 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
646 trim_name, NULL);
648 if (retarget_parm == NULL) {
649 goto fail;
652 retarget = talloc_strdup(trim_name, retarget_parm);
653 if (retarget == NULL) {
654 goto fail;
657 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
659 p = strchr(retarget, ':');
660 if (p != NULL) {
661 *p++ = '\0';
662 retarget_port = atoi(p);
665 p = strchr_m(retarget, '#');
666 if (p != NULL) {
667 *p++ = '\0';
668 if (sscanf(p, "%x", &retarget_type) != 1) {
669 goto fail;
673 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
674 if (!ret) {
675 DEBUG(10, ("could not resolve %s\n", retarget));
676 goto fail;
679 if (retarget_addr.ss_family != AF_INET) {
680 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
681 goto fail;
684 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
686 _smb_setlen(outbuf, 6);
687 SCVAL(outbuf, 0, 0x84);
688 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
689 *(uint16_t *)(outbuf+8) = htons(retarget_port);
691 if (!smb1_srv_send(xconn, (char *)outbuf, false, 0, false)) {
692 exit_server_cleanly("netbios_session_retarget: smb1_srv_send "
693 "failed.");
696 ret = true;
697 fail:
698 TALLOC_FREE(trim_name);
699 return ret;
702 static void reply_called_name_not_present(char *outbuf)
704 smb_setlen(outbuf, 1);
705 SCVAL(outbuf, 0, 0x83);
706 SCVAL(outbuf, 4, 0x82);
709 /****************************************************************************
710 Reply to a (netbios-level) special message.
711 ****************************************************************************/
713 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
715 struct smbd_server_connection *sconn = xconn->client->sconn;
716 int msg_type = CVAL(inbuf,0);
717 int msg_flags = CVAL(inbuf,1);
719 * We only really use 4 bytes of the outbuf, but for the smb_setlen
720 * calculation & friends (smb1_srv_send uses that) we need the full smb
721 * header.
723 char outbuf[smb_size];
725 memset(outbuf, '\0', sizeof(outbuf));
727 smb_setlen(outbuf,0);
729 switch (msg_type) {
730 case NBSSrequest: /* session request */
732 /* inbuf_size is guaranteed to be at least 4. */
733 fstring name1,name2;
734 int name_type1, name_type2;
735 int name_len1, name_len2;
737 *name1 = *name2 = 0;
739 if (xconn->transport.nbt.got_session) {
740 exit_server_cleanly("multiple session request not permitted");
743 SCVAL(outbuf,0,NBSSpositive);
744 SCVAL(outbuf,3,0);
746 /* inbuf_size is guaranteed to be at least 4. */
747 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
748 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
749 DEBUG(0,("Invalid name length in session request\n"));
750 reply_called_name_not_present(outbuf);
751 break;
753 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
754 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
755 DEBUG(0,("Invalid name length in session request\n"));
756 reply_called_name_not_present(outbuf);
757 break;
760 name_type1 = name_extract((unsigned char *)inbuf,
761 inbuf_size,(unsigned int)4,name1);
762 name_type2 = name_extract((unsigned char *)inbuf,
763 inbuf_size,(unsigned int)(4 + name_len1),name2);
765 if (name_type1 == -1 || name_type2 == -1) {
766 DEBUG(0,("Invalid name type in session request\n"));
767 reply_called_name_not_present(outbuf);
768 break;
771 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
772 name1, name_type1, name2, name_type2));
774 if (netbios_session_retarget(xconn, name1, name_type1)) {
775 exit_server_cleanly("retargeted client");
779 * Windows NT/2k uses "*SMBSERVER" and XP uses
780 * "*SMBSERV" arrggg!!!
782 if (strequal(name1, "*SMBSERVER ")
783 || strequal(name1, "*SMBSERV ")) {
784 char *raddr;
786 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
787 talloc_tos());
788 if (raddr == NULL) {
789 exit_server_cleanly("could not allocate raddr");
792 fstrcpy(name1, raddr);
795 set_local_machine_name(name1, True);
796 set_remote_machine_name(name2, True);
798 if (is_ipaddress(sconn->remote_hostname)) {
799 char *p = discard_const_p(char, sconn->remote_hostname);
801 talloc_free(p);
803 sconn->remote_hostname = talloc_strdup(sconn,
804 get_remote_machine_name());
805 if (sconn->remote_hostname == NULL) {
806 exit_server_cleanly("could not copy remote name");
808 xconn->remote_hostname = sconn->remote_hostname;
811 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
812 get_local_machine_name(), get_remote_machine_name(),
813 name_type2));
815 if (name_type2 == 'R') {
816 /* We are being asked for a pathworks session ---
817 no thanks! */
818 reply_called_name_not_present(outbuf);
819 break;
822 reload_services(sconn, conn_snum_used, true);
823 reopen_logs();
825 xconn->transport.nbt.got_session = true;
826 break;
829 case 0x89: /* session keepalive request
830 (some old clients produce this?) */
831 SCVAL(outbuf,0,NBSSkeepalive);
832 SCVAL(outbuf,3,0);
833 break;
835 case NBSSpositive: /* positive session response */
836 case NBSSnegative: /* negative session response */
837 case NBSSretarget: /* retarget session response */
838 DEBUG(0,("Unexpected session response\n"));
839 break;
841 case NBSSkeepalive: /* session keepalive */
842 default:
843 return;
846 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
847 msg_type, msg_flags));
849 if (!smb1_srv_send(xconn, outbuf, false, 0, false)) {
850 exit_server_cleanly("reply_special: smb1_srv_send failed.");
853 if (CVAL(outbuf, 0) != 0x82) {
854 exit_server_cleanly("invalid netbios session");
856 return;
859 /*******************************************************************
860 * unlink a file with all relevant access checks
861 *******************************************************************/
863 NTSTATUS unlink_internals(connection_struct *conn,
864 struct smb_request *req,
865 uint32_t dirtype,
866 struct files_struct *dirfsp,
867 struct smb_filename *smb_fname)
869 uint32_t fattr;
870 files_struct *fsp;
871 uint32_t dirtype_orig = dirtype;
872 NTSTATUS status;
873 int ret;
874 struct smb2_create_blobs *posx = NULL;
876 if (dirtype == 0) {
877 dirtype = FILE_ATTRIBUTE_NORMAL;
880 DBG_DEBUG("%s, dirtype = %d\n",
881 smb_fname_str_dbg(smb_fname),
882 dirtype);
884 if (!CAN_WRITE(conn)) {
885 return NT_STATUS_MEDIA_WRITE_PROTECTED;
888 ret = vfs_stat(conn, smb_fname);
889 if (ret != 0) {
890 return map_nt_error_from_unix(errno);
893 fattr = fdos_mode(smb_fname->fsp);
895 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
896 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
899 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
900 if (!dirtype) {
901 return NT_STATUS_NO_SUCH_FILE;
904 if (!dir_check_ftype(fattr, dirtype)) {
905 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
906 return NT_STATUS_FILE_IS_A_DIRECTORY;
908 return NT_STATUS_NO_SUCH_FILE;
911 if (dirtype_orig & 0x8000) {
912 /* These will never be set for POSIX. */
913 return NT_STATUS_NO_SUCH_FILE;
916 #if 0
917 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
918 return NT_STATUS_FILE_IS_A_DIRECTORY;
921 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
922 return NT_STATUS_NO_SUCH_FILE;
925 if (dirtype & 0xFF00) {
926 /* These will never be set for POSIX. */
927 return NT_STATUS_NO_SUCH_FILE;
930 dirtype &= 0xFF;
931 if (!dirtype) {
932 return NT_STATUS_NO_SUCH_FILE;
935 /* Can't delete a directory. */
936 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
937 return NT_STATUS_FILE_IS_A_DIRECTORY;
939 #endif
941 #if 0 /* JRATEST */
942 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
943 return NT_STATUS_OBJECT_NAME_INVALID;
944 #endif /* JRATEST */
946 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
947 status = make_smb2_posix_create_ctx(
948 talloc_tos(), &posx, 0777);
949 if (!NT_STATUS_IS_OK(status)) {
950 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
951 nt_errstr(status));
952 return status;
956 /* On open checks the open itself will check the share mode, so
957 don't do it here as we'll get it wrong. */
959 status = SMB_VFS_CREATE_FILE
960 (conn, /* conn */
961 req, /* req */
962 dirfsp, /* dirfsp */
963 smb_fname, /* fname */
964 DELETE_ACCESS, /* access_mask */
965 FILE_SHARE_NONE, /* share_access */
966 FILE_OPEN, /* create_disposition*/
967 FILE_NON_DIRECTORY_FILE, /* create_options */
968 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
969 0, /* oplock_request */
970 NULL, /* lease */
971 0, /* allocation_size */
972 0, /* private_flags */
973 NULL, /* sd */
974 NULL, /* ea_list */
975 &fsp, /* result */
976 NULL, /* pinfo */
977 posx, /* in_context_blobs */
978 NULL); /* out_context_blobs */
980 TALLOC_FREE(posx);
982 if (!NT_STATUS_IS_OK(status)) {
983 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
984 nt_errstr(status));
985 return status;
988 status = can_set_delete_on_close(fsp, fattr);
989 if (!NT_STATUS_IS_OK(status)) {
990 DBG_DEBUG("can_set_delete_on_close for file %s - "
991 "(%s)\n",
992 smb_fname_str_dbg(smb_fname),
993 nt_errstr(status));
994 close_file_free(req, &fsp, NORMAL_CLOSE);
995 return status;
998 /* The set is across all open files on this dev/inode pair. */
999 if (!set_delete_on_close(fsp, True,
1000 conn->session_info->security_token,
1001 conn->session_info->unix_token)) {
1002 close_file_free(req, &fsp, NORMAL_CLOSE);
1003 return NT_STATUS_ACCESS_DENIED;
1006 return close_file_free(req, &fsp, NORMAL_CLOSE);
1009 /****************************************************************************
1010 Fake (read/write) sendfile. Returns -1 on read or write fail.
1011 ****************************************************************************/
1013 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
1014 off_t startpos, size_t nread)
1016 size_t bufsize;
1017 size_t tosend = nread;
1018 char *buf;
1020 if (nread == 0) {
1021 return 0;
1024 bufsize = MIN(nread, 65536);
1026 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
1027 return -1;
1030 while (tosend > 0) {
1031 ssize_t ret;
1032 size_t cur_read;
1034 cur_read = MIN(tosend, bufsize);
1035 ret = read_file(fsp,buf,startpos,cur_read);
1036 if (ret == -1) {
1037 SAFE_FREE(buf);
1038 return -1;
1041 /* If we had a short read, fill with zeros. */
1042 if (ret < cur_read) {
1043 memset(buf + ret, '\0', cur_read - ret);
1046 ret = write_data(xconn->transport.sock, buf, cur_read);
1047 if (ret != cur_read) {
1048 int saved_errno = errno;
1050 * Try and give an error message saying what
1051 * client failed.
1053 DEBUG(0, ("write_data failed for client %s. "
1054 "Error %s\n",
1055 smbXsrv_connection_dbg(xconn),
1056 strerror(saved_errno)));
1057 SAFE_FREE(buf);
1058 errno = saved_errno;
1059 return -1;
1061 tosend -= cur_read;
1062 startpos += cur_read;
1065 SAFE_FREE(buf);
1066 return (ssize_t)nread;
1069 /****************************************************************************
1070 Deal with the case of sendfile reading less bytes from the file than
1071 requested. Fill with zeros (all we can do). Returns 0 on success
1072 ****************************************************************************/
1074 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
1075 files_struct *fsp,
1076 ssize_t nread,
1077 size_t headersize,
1078 size_t smb_maxcnt)
1080 #define SHORT_SEND_BUFSIZE 1024
1081 if (nread < headersize) {
1082 DEBUG(0,("sendfile_short_send: sendfile failed to send "
1083 "header for file %s (%s). Terminating\n",
1084 fsp_str_dbg(fsp), strerror(errno)));
1085 return -1;
1088 nread -= headersize;
1090 if (nread < smb_maxcnt) {
1091 char buf[SHORT_SEND_BUFSIZE] = { 0 };
1093 DEBUG(0,("sendfile_short_send: filling truncated file %s "
1094 "with zeros !\n", fsp_str_dbg(fsp)));
1096 while (nread < smb_maxcnt) {
1098 * We asked for the real file size and told sendfile
1099 * to not go beyond the end of the file. But it can
1100 * happen that in between our fstat call and the
1101 * sendfile call the file was truncated. This is very
1102 * bad because we have already announced the larger
1103 * number of bytes to the client.
1105 * The best we can do now is to send 0-bytes, just as
1106 * a read from a hole in a sparse file would do.
1108 * This should happen rarely enough that I don't care
1109 * about efficiency here :-)
1111 size_t to_write;
1112 ssize_t ret;
1114 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
1115 ret = write_data(xconn->transport.sock, buf, to_write);
1116 if (ret != to_write) {
1117 int saved_errno = errno;
1119 * Try and give an error message saying what
1120 * client failed.
1122 DEBUG(0, ("write_data failed for client %s. "
1123 "Error %s\n",
1124 smbXsrv_connection_dbg(xconn),
1125 strerror(saved_errno)));
1126 errno = saved_errno;
1127 return -1;
1129 nread += to_write;
1133 return 0;
1136 /*******************************************************************
1137 Check if a user is allowed to rename a file.
1138 ********************************************************************/
1140 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1141 uint16_t dirtype)
1143 if (!CAN_WRITE(conn)) {
1144 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1147 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
1148 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1149 /* Only bother to read the DOS attribute if we might deny the
1150 rename on the grounds of attribute mismatch. */
1151 uint32_t fmode = fdos_mode(fsp);
1152 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
1153 return NT_STATUS_NO_SUCH_FILE;
1157 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1158 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
1159 return NT_STATUS_OK;
1162 /* If no pathnames are open below this
1163 directory, allow the rename. */
1165 if (lp_strict_rename(SNUM(conn))) {
1167 * Strict rename, check open file db.
1169 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
1170 return NT_STATUS_ACCESS_DENIED;
1172 } else if (file_find_subpath(fsp)) {
1174 * No strict rename, just look in local process.
1176 return NT_STATUS_ACCESS_DENIED;
1178 return NT_STATUS_OK;
1181 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
1182 return NT_STATUS_OK;
1185 return NT_STATUS_ACCESS_DENIED;
1188 /****************************************************************************
1189 Ensure open files have their names updated. Updated to notify other smbd's
1190 asynchronously.
1191 ****************************************************************************/
1193 static void rename_open_files(connection_struct *conn,
1194 struct share_mode_lock *lck,
1195 struct file_id id,
1196 uint32_t orig_name_hash,
1197 const struct smb_filename *smb_fname_dst)
1199 files_struct *fsp;
1200 bool did_rename = False;
1201 NTSTATUS status;
1202 uint32_t new_name_hash = 0;
1204 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
1205 fsp = file_find_di_next(fsp, false)) {
1206 SMB_STRUCT_STAT fsp_orig_sbuf;
1207 struct file_id_buf idbuf;
1208 /* fsp_name is a relative path under the fsp. To change this for other
1209 sharepaths we need to manipulate relative paths. */
1210 /* TODO - create the absolute path and manipulate the newname
1211 relative to the sharepath. */
1212 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
1213 continue;
1215 if (fsp->name_hash != orig_name_hash) {
1216 continue;
1218 DBG_DEBUG("renaming file %s "
1219 "(file_id %s) from %s -> %s\n",
1220 fsp_fnum_dbg(fsp),
1221 file_id_str_buf(fsp->file_id, &idbuf),
1222 fsp_str_dbg(fsp),
1223 smb_fname_str_dbg(smb_fname_dst));
1226 * The incoming smb_fname_dst here has an
1227 * invalid stat struct (it must not have
1228 * existed for the rename to succeed).
1229 * Preserve the existing stat from the
1230 * open fsp after fsp_set_smb_fname()
1231 * overwrites with the invalid stat.
1233 * We will do an fstat before returning
1234 * any of this metadata to the client anyway.
1236 fsp_orig_sbuf = fsp->fsp_name->st;
1237 status = fsp_set_smb_fname(fsp, smb_fname_dst);
1238 if (NT_STATUS_IS_OK(status)) {
1239 did_rename = True;
1240 new_name_hash = fsp->name_hash;
1241 /* Restore existing stat. */
1242 fsp->fsp_name->st = fsp_orig_sbuf;
1246 if (!did_rename) {
1247 struct file_id_buf idbuf;
1248 DBG_DEBUG("no open files on file_id %s "
1249 "for %s\n",
1250 file_id_str_buf(id, &idbuf),
1251 smb_fname_str_dbg(smb_fname_dst));
1254 /* Send messages to all smbd's (not ourself) that the name has changed. */
1255 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
1256 orig_name_hash, new_name_hash,
1257 smb_fname_dst);
1261 /****************************************************************************
1262 We need to check if the source path is a parent directory of the destination
1263 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
1264 refuse the rename with a sharing violation. Under UNIX the above call can
1265 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
1266 probably need to check that the client is a Windows one before disallowing
1267 this as a UNIX client (one with UNIX extensions) can know the source is a
1268 symlink and make this decision intelligently. Found by an excellent bug
1269 report from <AndyLiebman@aol.com>.
1270 ****************************************************************************/
1272 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
1273 const struct smb_filename *smb_fname_dst)
1275 const char *psrc = smb_fname_src->base_name;
1276 const char *pdst = smb_fname_dst->base_name;
1277 size_t slen;
1279 if (psrc[0] == '.' && psrc[1] == '/') {
1280 psrc += 2;
1282 if (pdst[0] == '.' && pdst[1] == '/') {
1283 pdst += 2;
1285 if ((slen = strlen(psrc)) > strlen(pdst)) {
1286 return False;
1288 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
1292 * Do the notify calls from a rename
1295 static void notify_rename(connection_struct *conn, bool is_dir,
1296 const struct smb_filename *smb_fname_src,
1297 const struct smb_filename *smb_fname_dst)
1299 char *parent_dir_src = NULL;
1300 char *parent_dir_dst = NULL;
1301 uint32_t mask;
1303 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
1304 : FILE_NOTIFY_CHANGE_FILE_NAME;
1306 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
1307 &parent_dir_src, NULL) ||
1308 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
1309 &parent_dir_dst, NULL)) {
1310 goto out;
1313 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
1314 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
1315 smb_fname_src->base_name);
1316 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
1317 smb_fname_dst->base_name);
1319 else {
1320 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
1321 smb_fname_src->base_name);
1322 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
1323 smb_fname_dst->base_name);
1326 /* this is a strange one. w2k3 gives an additional event for
1327 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
1328 files, but not directories */
1329 if (!is_dir) {
1330 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
1331 FILE_NOTIFY_CHANGE_ATTRIBUTES
1332 |FILE_NOTIFY_CHANGE_CREATION,
1333 smb_fname_dst->base_name);
1335 out:
1336 TALLOC_FREE(parent_dir_src);
1337 TALLOC_FREE(parent_dir_dst);
1340 /****************************************************************************
1341 Returns an error if the parent directory for a filename is open in an
1342 incompatible way.
1343 ****************************************************************************/
1345 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
1346 const struct smb_filename *smb_fname_dst_in)
1348 struct smb_filename *smb_fname_parent = NULL;
1349 struct file_id id;
1350 files_struct *fsp = NULL;
1351 int ret;
1352 NTSTATUS status;
1354 status = SMB_VFS_PARENT_PATHNAME(conn,
1355 talloc_tos(),
1356 smb_fname_dst_in,
1357 &smb_fname_parent,
1358 NULL);
1359 if (!NT_STATUS_IS_OK(status)) {
1360 return status;
1363 ret = vfs_stat(conn, smb_fname_parent);
1364 if (ret == -1) {
1365 return map_nt_error_from_unix(errno);
1369 * We're only checking on this smbd here, mostly good
1370 * enough.. and will pass tests.
1373 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
1374 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
1375 fsp = file_find_di_next(fsp, true)) {
1376 if (fsp->access_mask & DELETE_ACCESS) {
1377 return NT_STATUS_SHARING_VIOLATION;
1380 return NT_STATUS_OK;
1383 /****************************************************************************
1384 Rename an open file - given an fsp.
1385 ****************************************************************************/
1387 NTSTATUS rename_internals_fsp(connection_struct *conn,
1388 files_struct *fsp,
1389 struct files_struct *dst_dirfsp,
1390 struct smb_filename *smb_fname_dst_in,
1391 const char *dst_original_lcomp,
1392 uint32_t attrs,
1393 bool replace_if_exists)
1395 TALLOC_CTX *ctx = talloc_tos();
1396 struct smb_filename *parent_dir_fname_dst = NULL;
1397 struct smb_filename *parent_dir_fname_dst_atname = NULL;
1398 struct smb_filename *parent_dir_fname_src = NULL;
1399 struct smb_filename *parent_dir_fname_src_atname = NULL;
1400 struct smb_filename *smb_fname_dst = NULL;
1401 NTSTATUS status = NT_STATUS_OK;
1402 struct share_mode_lock *lck = NULL;
1403 uint32_t access_mask = SEC_DIR_ADD_FILE;
1404 bool dst_exists, old_is_stream, new_is_stream;
1405 int ret;
1406 bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1407 true : conn->case_sensitive;
1408 bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1409 true : conn->case_preserve;
1411 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
1412 if (!NT_STATUS_IS_OK(status)) {
1413 return status;
1416 if (file_has_open_streams(fsp)) {
1417 return NT_STATUS_ACCESS_DENIED;
1420 /* Make a copy of the dst smb_fname structs */
1422 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
1423 if (smb_fname_dst == NULL) {
1424 status = NT_STATUS_NO_MEMORY;
1425 goto out;
1429 * Check for special case with case preserving and not
1430 * case sensitive. If the new last component differs from the original
1431 * last component only by case, then we should allow
1432 * the rename (user is trying to change the case of the
1433 * filename).
1435 if (!case_sensitive && case_preserve &&
1436 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1437 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
1438 char *fname_dst_parent = NULL;
1439 const char *fname_dst_lcomp = NULL;
1440 char *orig_lcomp_path = NULL;
1441 char *orig_lcomp_stream = NULL;
1442 bool ok = true;
1445 * Split off the last component of the processed
1446 * destination name. We will compare this to
1447 * the split components of dst_original_lcomp.
1449 if (!parent_dirname(ctx,
1450 smb_fname_dst->base_name,
1451 &fname_dst_parent,
1452 &fname_dst_lcomp)) {
1453 status = NT_STATUS_NO_MEMORY;
1454 goto out;
1458 * The dst_original_lcomp component contains
1459 * the last_component of the path + stream
1460 * name (if a stream exists).
1462 * Split off the stream name so we
1463 * can check them separately.
1466 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
1467 /* POSIX - no stream component. */
1468 orig_lcomp_path = talloc_strdup(ctx,
1469 dst_original_lcomp);
1470 if (orig_lcomp_path == NULL) {
1471 ok = false;
1473 } else {
1474 ok = split_stream_filename(ctx,
1475 dst_original_lcomp,
1476 &orig_lcomp_path,
1477 &orig_lcomp_stream);
1480 if (!ok) {
1481 TALLOC_FREE(fname_dst_parent);
1482 status = NT_STATUS_NO_MEMORY;
1483 goto out;
1486 /* If the base names only differ by case, use original. */
1487 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
1488 char *tmp;
1490 * Replace the modified last component with the
1491 * original.
1493 if (!ISDOT(fname_dst_parent)) {
1494 tmp = talloc_asprintf(smb_fname_dst,
1495 "%s/%s",
1496 fname_dst_parent,
1497 orig_lcomp_path);
1498 } else {
1499 tmp = talloc_strdup(smb_fname_dst,
1500 orig_lcomp_path);
1502 if (tmp == NULL) {
1503 status = NT_STATUS_NO_MEMORY;
1504 TALLOC_FREE(fname_dst_parent);
1505 TALLOC_FREE(orig_lcomp_path);
1506 TALLOC_FREE(orig_lcomp_stream);
1507 goto out;
1509 TALLOC_FREE(smb_fname_dst->base_name);
1510 smb_fname_dst->base_name = tmp;
1513 /* If the stream_names only differ by case, use original. */
1514 if(!strcsequal(smb_fname_dst->stream_name,
1515 orig_lcomp_stream)) {
1516 /* Use the original stream. */
1517 char *tmp = talloc_strdup(smb_fname_dst,
1518 orig_lcomp_stream);
1519 if (tmp == NULL) {
1520 status = NT_STATUS_NO_MEMORY;
1521 TALLOC_FREE(fname_dst_parent);
1522 TALLOC_FREE(orig_lcomp_path);
1523 TALLOC_FREE(orig_lcomp_stream);
1524 goto out;
1526 TALLOC_FREE(smb_fname_dst->stream_name);
1527 smb_fname_dst->stream_name = tmp;
1529 TALLOC_FREE(fname_dst_parent);
1530 TALLOC_FREE(orig_lcomp_path);
1531 TALLOC_FREE(orig_lcomp_stream);
1535 * If the src and dest names are identical - including case,
1536 * don't do the rename, just return success.
1539 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
1540 strcsequal(fsp->fsp_name->stream_name,
1541 smb_fname_dst->stream_name)) {
1542 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
1543 "- returning success\n",
1544 smb_fname_str_dbg(smb_fname_dst)));
1545 status = NT_STATUS_OK;
1546 goto out;
1549 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
1550 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
1552 /* Return the correct error code if both names aren't streams. */
1553 if (!old_is_stream && new_is_stream) {
1554 status = NT_STATUS_OBJECT_NAME_INVALID;
1555 goto out;
1558 if (old_is_stream && !new_is_stream) {
1559 status = NT_STATUS_INVALID_PARAMETER;
1560 goto out;
1563 dst_exists = vfs_stat(conn, smb_fname_dst) == 0;
1565 if(!replace_if_exists && dst_exists) {
1566 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
1567 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1568 smb_fname_str_dbg(smb_fname_dst)));
1569 status = NT_STATUS_OBJECT_NAME_COLLISION;
1570 goto out;
1574 * Drop the pathref fsp on the destination otherwise we trip upon in in
1575 * the below check for open files check.
1577 if (smb_fname_dst_in->fsp != NULL) {
1578 fd_close(smb_fname_dst_in->fsp);
1579 file_free(NULL, smb_fname_dst_in->fsp);
1580 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
1583 if (dst_exists) {
1584 struct file_id fileid = vfs_file_id_from_sbuf(conn,
1585 &smb_fname_dst->st);
1586 files_struct *dst_fsp = file_find_di_first(conn->sconn,
1587 fileid, true);
1588 /* The file can be open when renaming a stream */
1589 if (dst_fsp && !new_is_stream) {
1590 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
1591 status = NT_STATUS_ACCESS_DENIED;
1592 goto out;
1596 /* Ensure we have a valid stat struct for the source. */
1597 status = vfs_stat_fsp(fsp);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 goto out;
1602 status = can_rename(conn, fsp, attrs);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1606 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1607 smb_fname_str_dbg(smb_fname_dst)));
1608 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
1609 status = NT_STATUS_ACCESS_DENIED;
1610 goto out;
1613 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
1614 status = NT_STATUS_ACCESS_DENIED;
1615 goto out;
1618 /* Do we have rights to move into the destination ? */
1619 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1620 /* We're moving a directory. */
1621 access_mask = SEC_DIR_ADD_SUBDIR;
1625 * Get a pathref on the destination parent directory, so
1626 * we can call check_parent_access_fsp().
1628 status = parent_pathref(ctx,
1629 conn->cwd_fsp,
1630 smb_fname_dst,
1631 &parent_dir_fname_dst,
1632 &parent_dir_fname_dst_atname);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 goto out;
1637 status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
1638 access_mask);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 DBG_INFO("check_parent_access_fsp on "
1641 "dst %s returned %s\n",
1642 smb_fname_str_dbg(smb_fname_dst),
1643 nt_errstr(status));
1644 goto out;
1648 * If the target existed, make sure the destination
1649 * atname has the same stat struct.
1651 parent_dir_fname_dst_atname->st = smb_fname_dst->st;
1654 * It's very common that source and
1655 * destination directories are the same.
1656 * Optimize by not opening the
1657 * second parent_pathref if we know
1658 * this is the case.
1661 status = SMB_VFS_PARENT_PATHNAME(conn,
1662 ctx,
1663 fsp->fsp_name,
1664 &parent_dir_fname_src,
1665 &parent_dir_fname_src_atname);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 goto out;
1671 * We do a case-sensitive string comparison. We want to be *sure*
1672 * this is the same path. The worst that can happen if
1673 * the case doesn't match is we lose out on the optimization,
1674 * the code still works.
1676 * We can ignore twrp fields here. Rename is not allowed on
1677 * shadow copy handles.
1680 if (strcmp(parent_dir_fname_src->base_name,
1681 parent_dir_fname_dst->base_name) == 0) {
1683 * parent directory is the same for source
1684 * and destination.
1686 /* Reparent the src_atname to the parent_dir_dest fname. */
1687 parent_dir_fname_src_atname = talloc_move(
1688 parent_dir_fname_dst,
1689 &parent_dir_fname_src_atname);
1690 /* Free the unneeded duplicate parent name. */
1691 TALLOC_FREE(parent_dir_fname_src);
1693 * And make the source parent name a copy of the
1694 * destination parent name.
1696 parent_dir_fname_src = parent_dir_fname_dst;
1699 * Ensure we have a pathref fsp on the
1700 * parent_dir_fname_src_atname to match the code in the else
1701 * branch where we use parent_pathref().
1703 status = reference_smb_fname_fsp_link(
1704 parent_dir_fname_src_atname,
1705 fsp->fsp_name);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 goto out;
1709 } else {
1711 * source and destination parent directories are
1712 * different.
1714 * Get a pathref on the source parent directory, so
1715 * we can do a relative rename.
1717 TALLOC_FREE(parent_dir_fname_src);
1718 status = parent_pathref(ctx,
1719 conn->cwd_fsp,
1720 fsp->fsp_name,
1721 &parent_dir_fname_src,
1722 &parent_dir_fname_src_atname);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 goto out;
1729 * Some modules depend on the source smb_fname having a valid stat.
1730 * The parent_dir_fname_src_atname is the relative name of the
1731 * currently open file, so just copy the stat from the open fsp.
1733 parent_dir_fname_src_atname->st = fsp->fsp_name->st;
1735 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1738 * We have the file open ourselves, so not being able to get the
1739 * corresponding share mode lock is a fatal error.
1742 SMB_ASSERT(lck != NULL);
1744 ret = SMB_VFS_RENAMEAT(conn,
1745 parent_dir_fname_src->fsp,
1746 parent_dir_fname_src_atname,
1747 parent_dir_fname_dst->fsp,
1748 parent_dir_fname_dst_atname);
1749 if (ret == 0) {
1750 uint32_t create_options = fh_get_private_options(fsp->fh);
1752 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
1753 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
1754 smb_fname_str_dbg(smb_fname_dst)));
1756 notify_rename(conn,
1757 fsp->fsp_flags.is_directory,
1758 fsp->fsp_name,
1759 smb_fname_dst);
1761 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
1762 smb_fname_dst);
1764 if (!fsp->fsp_flags.is_directory &&
1765 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
1766 (lp_map_archive(SNUM(conn)) ||
1767 lp_store_dos_attributes(SNUM(conn))))
1770 * We must set the archive bit on the newly renamed
1771 * file.
1773 status = vfs_stat_fsp(fsp);
1774 if (NT_STATUS_IS_OK(status)) {
1775 uint32_t old_dosmode;
1776 old_dosmode = fdos_mode(fsp);
1778 * We can use fsp->fsp_name here as it has
1779 * already been changed to the new name.
1781 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
1782 file_set_dosmode(conn,
1783 fsp->fsp_name,
1784 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
1785 NULL,
1786 true);
1791 * A rename acts as a new file create w.r.t. allowing an initial delete
1792 * on close, probably because in Windows there is a new handle to the
1793 * new file. If initial delete on close was requested but not
1794 * originally set, we need to set it here. This is probably not 100% correct,
1795 * but will work for the CIFSFS client which in non-posix mode
1796 * depends on these semantics. JRA.
1799 if (create_options & FILE_DELETE_ON_CLOSE) {
1800 status = can_set_delete_on_close(fsp, 0);
1802 if (NT_STATUS_IS_OK(status)) {
1803 /* Note that here we set the *initial* delete on close flag,
1804 * not the regular one. The magic gets handled in close. */
1805 fsp->fsp_flags.initial_delete_on_close = true;
1808 TALLOC_FREE(lck);
1809 status = NT_STATUS_OK;
1810 goto out;
1813 TALLOC_FREE(lck);
1815 if (errno == ENOTDIR || errno == EISDIR) {
1816 status = NT_STATUS_OBJECT_NAME_COLLISION;
1817 } else {
1818 status = map_nt_error_from_unix(errno);
1821 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
1822 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
1823 smb_fname_str_dbg(smb_fname_dst)));
1825 out:
1828 * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
1829 * See the optimization for same source and destination directory
1830 * above. Only free one in that case.
1832 if (parent_dir_fname_src != parent_dir_fname_dst) {
1833 TALLOC_FREE(parent_dir_fname_src);
1835 TALLOC_FREE(parent_dir_fname_dst);
1836 TALLOC_FREE(smb_fname_dst);
1838 return status;
1841 /****************************************************************************
1842 The guts of the rename command, split out so it may be called by the NT SMB
1843 code.
1844 ****************************************************************************/
1846 NTSTATUS rename_internals(TALLOC_CTX *ctx,
1847 connection_struct *conn,
1848 struct smb_request *req,
1849 struct files_struct *src_dirfsp,
1850 struct smb_filename *smb_fname_src,
1851 struct files_struct *dst_dirfsp,
1852 struct smb_filename *smb_fname_dst,
1853 const char *dst_original_lcomp,
1854 uint32_t attrs,
1855 bool replace_if_exists,
1856 uint32_t access_mask)
1858 NTSTATUS status = NT_STATUS_OK;
1859 int create_options = 0;
1860 struct smb2_create_blobs *posx = NULL;
1861 struct files_struct *fsp = NULL;
1862 bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
1863 bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
1864 bool case_preserve = posix_pathname ? true : conn->case_preserve;
1865 bool short_case_preserve = posix_pathname ? true :
1866 conn->short_case_preserve;
1868 if (posix_pathname) {
1869 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
1870 if (!NT_STATUS_IS_OK(status)) {
1871 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
1872 nt_errstr(status));
1873 goto out;
1877 DBG_NOTICE("case_sensitive = %d, "
1878 "case_preserve = %d, short case preserve = %d, "
1879 "directory = %s, newname = %s, "
1880 "last_component_dest = %s\n",
1881 case_sensitive, case_preserve,
1882 short_case_preserve,
1883 smb_fname_str_dbg(smb_fname_src),
1884 smb_fname_str_dbg(smb_fname_dst),
1885 dst_original_lcomp);
1887 ZERO_STRUCT(smb_fname_src->st);
1889 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 if (!NT_STATUS_EQUAL(status,
1892 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1893 goto out;
1896 * Possible symlink src.
1898 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
1899 goto out;
1901 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
1902 goto out;
1906 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
1907 create_options |= FILE_DIRECTORY_FILE;
1910 status = SMB_VFS_CREATE_FILE(
1911 conn, /* conn */
1912 req, /* req */
1913 src_dirfsp, /* dirfsp */
1914 smb_fname_src, /* fname */
1915 access_mask, /* access_mask */
1916 (FILE_SHARE_READ | /* share_access */
1917 FILE_SHARE_WRITE),
1918 FILE_OPEN, /* create_disposition*/
1919 create_options, /* create_options */
1920 0, /* file_attributes */
1921 0, /* oplock_request */
1922 NULL, /* lease */
1923 0, /* allocation_size */
1924 0, /* private_flags */
1925 NULL, /* sd */
1926 NULL, /* ea_list */
1927 &fsp, /* result */
1928 NULL, /* pinfo */
1929 posx, /* in_context_blobs */
1930 NULL); /* out_context_blobs */
1932 if (!NT_STATUS_IS_OK(status)) {
1933 DBG_NOTICE("Could not open rename source %s: %s\n",
1934 smb_fname_str_dbg(smb_fname_src),
1935 nt_errstr(status));
1936 goto out;
1939 status = rename_internals_fsp(conn,
1940 fsp,
1941 dst_dirfsp,
1942 smb_fname_dst,
1943 dst_original_lcomp,
1944 attrs,
1945 replace_if_exists);
1947 close_file_free(req, &fsp, NORMAL_CLOSE);
1949 DBG_NOTICE("Error %s rename %s -> %s\n",
1950 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
1951 smb_fname_str_dbg(smb_fname_dst));
1953 out:
1954 TALLOC_FREE(posx);
1955 return status;
1958 /*******************************************************************
1959 Copy a file as part of a reply_copy.
1960 ******************************************************************/
1963 * TODO: check error codes on all callers
1966 NTSTATUS copy_file(TALLOC_CTX *ctx,
1967 connection_struct *conn,
1968 struct smb_filename *smb_fname_src,
1969 struct smb_filename *smb_fname_dst,
1970 uint32_t new_create_disposition)
1972 struct smb_filename *smb_fname_dst_tmp = NULL;
1973 off_t ret=-1;
1974 files_struct *fsp1,*fsp2;
1975 uint32_t dosattrs;
1976 NTSTATUS status;
1979 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
1980 if (smb_fname_dst_tmp == NULL) {
1981 return NT_STATUS_NO_MEMORY;
1984 status = vfs_file_exist(conn, smb_fname_src);
1985 if (!NT_STATUS_IS_OK(status)) {
1986 goto out;
1989 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
1990 if (!NT_STATUS_IS_OK(status)) {
1991 goto out;
1994 /* Open the src file for reading. */
1995 status = SMB_VFS_CREATE_FILE(
1996 conn, /* conn */
1997 NULL, /* req */
1998 NULL, /* dirfsp */
1999 smb_fname_src, /* fname */
2000 FILE_GENERIC_READ, /* access_mask */
2001 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2002 FILE_OPEN, /* create_disposition*/
2003 0, /* create_options */
2004 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2005 INTERNAL_OPEN_ONLY, /* oplock_request */
2006 NULL, /* lease */
2007 0, /* allocation_size */
2008 0, /* private_flags */
2009 NULL, /* sd */
2010 NULL, /* ea_list */
2011 &fsp1, /* result */
2012 NULL, /* psbuf */
2013 NULL, NULL); /* create context */
2015 if (!NT_STATUS_IS_OK(status)) {
2016 goto out;
2019 dosattrs = fdos_mode(fsp1);
2021 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
2022 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
2025 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
2026 if (!NT_STATUS_IS_OK(status) &&
2027 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
2029 goto out;
2032 /* Open the dst file for writing. */
2033 status = SMB_VFS_CREATE_FILE(
2034 conn, /* conn */
2035 NULL, /* req */
2036 NULL, /* dirfsp */
2037 smb_fname_dst, /* fname */
2038 FILE_GENERIC_WRITE, /* access_mask */
2039 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2040 new_create_disposition, /* create_disposition*/
2041 0, /* create_options */
2042 dosattrs, /* file_attributes */
2043 INTERNAL_OPEN_ONLY, /* oplock_request */
2044 NULL, /* lease */
2045 0, /* allocation_size */
2046 0, /* private_flags */
2047 NULL, /* sd */
2048 NULL, /* ea_list */
2049 &fsp2, /* result */
2050 NULL, /* psbuf */
2051 NULL, NULL); /* create context */
2053 if (!NT_STATUS_IS_OK(status)) {
2054 close_file_free(NULL, &fsp1, ERROR_CLOSE);
2055 goto out;
2058 /* Do the actual copy. */
2059 if (smb_fname_src->st.st_ex_size) {
2060 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
2061 } else {
2062 ret = 0;
2065 close_file_free(NULL, &fsp1, NORMAL_CLOSE);
2067 /* Ensure the modtime is set correctly on the destination file. */
2068 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
2071 * As we are opening fsp1 read-only we only expect
2072 * an error on close on fsp2 if we are out of space.
2073 * Thus we don't look at the error return from the
2074 * close of fsp1.
2076 status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
2078 if (!NT_STATUS_IS_OK(status)) {
2079 goto out;
2082 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
2083 status = NT_STATUS_DISK_FULL;
2084 goto out;
2087 status = NT_STATUS_OK;
2089 out:
2090 TALLOC_FREE(smb_fname_dst_tmp);
2091 return status;
2094 /****************************************************************************
2095 Get a lock offset, dealing with large offset requests.
2096 ****************************************************************************/
2098 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
2099 bool large_file_format)
2101 uint64_t offset = 0;
2103 if(!large_file_format) {
2104 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
2105 } else {
2107 * No BVAL, this is reversed!
2109 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
2110 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
2113 return offset;
2116 struct smbd_do_unlocking_state {
2117 struct files_struct *fsp;
2118 uint16_t num_ulocks;
2119 struct smbd_lock_element *ulocks;
2120 NTSTATUS status;
2123 static void smbd_do_unlocking_fn(
2124 struct share_mode_lock *lck,
2125 void *private_data)
2127 struct smbd_do_unlocking_state *state = private_data;
2128 struct files_struct *fsp = state->fsp;
2129 uint16_t i;
2131 for (i = 0; i < state->num_ulocks; i++) {
2132 struct smbd_lock_element *e = &state->ulocks[i];
2134 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
2135 "pid %"PRIu64", file %s\n",
2136 e->offset,
2137 e->count,
2138 e->smblctx,
2139 fsp_str_dbg(fsp));
2141 if (e->brltype != UNLOCK_LOCK) {
2142 /* this can only happen with SMB2 */
2143 state->status = NT_STATUS_INVALID_PARAMETER;
2144 return;
2147 state->status = do_unlock(
2148 fsp, e->smblctx, e->count, e->offset, e->lock_flav);
2150 DBG_DEBUG("do_unlock returned %s\n",
2151 nt_errstr(state->status));
2153 if (!NT_STATUS_IS_OK(state->status)) {
2154 return;
2158 share_mode_wakeup_waiters(fsp->file_id);
2161 NTSTATUS smbd_do_unlocking(struct smb_request *req,
2162 files_struct *fsp,
2163 uint16_t num_ulocks,
2164 struct smbd_lock_element *ulocks)
2166 struct smbd_do_unlocking_state state = {
2167 .fsp = fsp,
2168 .num_ulocks = num_ulocks,
2169 .ulocks = ulocks,
2171 NTSTATUS status;
2173 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
2175 status = share_mode_do_locked_vfs_allowed(
2176 fsp->file_id, smbd_do_unlocking_fn, &state);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 DBG_DEBUG("share_mode_do_locked_vfs_allowed failed: %s\n",
2180 nt_errstr(status));
2181 return status;
2183 if (!NT_STATUS_IS_OK(state.status)) {
2184 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
2185 nt_errstr(status));
2186 return state.status;
2189 return NT_STATUS_OK;